Skip to content

Latest commit

 

History

History
387 lines (352 loc) · 7.87 KB

withSettings.module.md

File metadata and controls

387 lines (352 loc) · 7.87 KB

withSetting Module

快速实现小组件可视化配置

类型:

/**
 * @returns 仅在小组件中运行时返回 ListWidget
 */
export function withSettings(options: Options): Promise<ListWidget | undefined>

/** 参数 */
interface Options {
  /** 主页 URL 地址,用于右上角分享 */
  homePage?: string
  /** 在页面顶部插入 HTML */
  head?: string
  /** 表单配置,看下文 */
  formItems: FormItem[]
  /** 
   * 创建小组件
   * @returns 必须返回创建的 ListWidget,支持异步(Promise)
   */
  render(config: {
    /** 用户填写的配置,看下文 */
    settings: Settings,
    /** 组件大小 */
    family?: "small" | "medium" | "large" | "extraLarge" | "accessoryRectangular" | "accessoryInline" | "accessoryCircular"
  }): ListWidget | Promise<ListWidget>
  /**
   * 单项点击事件回调
   * @param item 单项表单配置
   */
  onItemClick?: (item: FormItem) => void
}

/** 表单支持多种类型 */
type FormItem = NormalFormItem | GroupFormItem | PageFormItem

/** 一般表单类型 */
interface NormalFormItem {
  /** 表单名(字段名),唯一 */
  name: string
  /** 标签文本 */
  label: string
  /**
   * 表单类型
   * - `text`: 文本输入框
   * - `number`: 数字输入框
   * - `color`: 颜色选择器
   * - `date`: 日期选择器
   * - `select`: 选择器
   * - `switch`: 开关
   * - `cell`: 可点击项
   */
  type: 'text' | 'number' | 'color' | 'date' | 'select' | 'switch' | 'cell'
  /**
   * 用于区分不同主题的配置
   * 配置此属性后仅满足条件时才显示此表单项
   */
  media: '(prefers-color-scheme: light)' | '(prefers-color-scheme: dark)'
  /** 默认值 */
  default?: unknown
  /**
   * 选择器的选项列表,仅当 type 配置为 `select` 时需传递此参数
   */
  options?: {
    /** 选项显示文本 */
    label: string
    /** 选项值 */
    value: unknown
  }[]
}

/** 将表单分组显示 */
interface GroupFormItem {
  /** 固定 type */
  type: 'group'
  /** 表单名(字段名),唯一 */
  name: string
  /** 标签文本,组名 */
  label: string
  items: FormItem[]
}

/** 单独一页的配置 */
interface PageFormItem {
  /** 固定 type */
  type: 'page'
  /** 唯一 */
  name: string
  /** 标签文本 */
  label: string
  /** 表单配置 */
  formItems: FormItem[]
  /**
   * 单项点击事件回调
   * @param item 单项表单配置
   */
  onItemClick?: (item: FormItem) => void
}

/** 用户配置 */
interface Settings {
  /** 是否使用 iCloud 同步配置 */
  useICloud: boolean
  /**
   * 背景图路径
   *
   * 仅当用户配置了背景图才有值
   */
  backgroundImage?: string
  /** 浅色背景颜色,十六进制 */
  backgroundColorLight?: string
  /** 深色背景颜色,十六进制 */
  backgroundColorDark?: string
  [key: string]: unknown
}

示例:

示例1:基本示例。无自定义配置

const { withSettings } = importModule('withSettings.module')

const createWidget = (text) => {
  const widget = new ListWidget()
  widget.addText(text)
  return widget
}
const createSmallWidget = () => createWidget('这是小号组件')
const createMediumWidget = () => createWidget('这是中号组件')

await withSettings({
  formItems: [],
  render ({ family }) {
    if (family === 'small') {
      return createSmallWidget()
    }
    if (family === 'medium') {
      return createMediumWidget()
    }
  }
})

示例2:一般配置

const { withSettings } = importModule('withSettings.module')

const createWidget = (settings) => {
  const { name, age, color } = settings
  const widget = new ListWidget()
  widget.addText(`姓名:${name}`)
  widget.addText(`年龄:${age}`)
  widget.addText(`喜欢的颜色:${color}`)
  return widget
}

await withSettings({
  formItems: [
    {
      label: '姓名',
      name: 'name',
      type: 'text'
    },
    {
      label: '年龄',
      name: 'age',
      type: 'number'
    },
    {
      label: '喜欢的颜色',
      name: 'color',
      type: 'color'
    }
  ],
  render ({ settings }) {
    return createWidget(settings)
  }
})

示例3:分组配置

const { withSettings } = importModule('withSettings.module')

const createWidget = (settings) => {
  const { userName, familyName } = settings
  const widget = new ListWidget()
  widget.addText(`你的姓名:${userName}`)
  widget.addText(`你家人的姓名:${familyName}`)
  return widget
}

await withSettings({
  formItems: [
    {
      label: '个人',
      name: 'user',
      type: 'group',
      items: [
        {
          label: '姓名',
          name: 'userName',
          type: 'text'
        },
        {
          label: '年龄',
          name: 'userAge',
          type: 'number'
        }
      ]
    },
    {
      label: '家人',
      name: 'family',
      type: 'group',
      items: [
        {
          label: '姓名',
          name: 'familyName',
          type: 'text'
        },
        {
          label: '年龄',
          name: 'familyAge',
          type: 'number'
        }
      ]
    }
  ],
  render ({ settings }) {
    return createWidget(settings)
  }
})

示例4:单独一页的配置

const { withSettings } = importModule('withSettings.module')

const createWidget = (settings) => {
  const { userName, familyName } = settings
  const widget = new ListWidget()
  widget.addText(`你的姓名:${userName}`)
  widget.addText(`你家人的姓名:${familyName}`)
  return widget
}

await withSettings({
  formItems: [
    {
      label: '个人',
      name: 'user',
      type: 'group',
      items: [
        {
          label: '姓名',
          name: 'userName',
          type: 'text'
        },
        {
          label: '年龄',
          name: 'userAge',
          type: 'number'
        }
      ]
    },
    {
      label: '家人',
      name: 'family',
      type: 'page',
      formItems: [
        {
          label: '姓名',
          name: 'familyName',
          type: 'text'
        },
        {
          label: '年龄',
          name: 'familyAge',
          type: 'number'
        }
      ]
    }
  ],
  render ({ settings }) {
    return createWidget(settings)
  }
})

示例5:自定义顶部 HTML

const { withSettings } = importModule('withSettings.module')

const createWidget = (settings) => {
  const { userName, familyName } = settings
  const widget = new ListWidget()
  widget.addText(`你的姓名:${userName}`)
  widget.addText(`你家人的姓名:${familyName}`)
  return widget
}

await withSettings({
  head: `<section>
    <h1>可视化配置</h1>
    <style>
      h1 {
        padding: 0 20px;
      }
    </style>
  </section>`,
  formItems: [
    {
      label: '个人',
      name: 'user',
      type: 'group',
      items: [
        {
          label: '姓名',
          name: 'userName',
          type: 'text'
        },
        {
          label: '年龄',
          name: 'userAge',
          type: 'number'
        }
      ]
    }
  ],
  render ({ settings }) {
    return createWidget(settings)
  }
})

示例5:区分主题配置

const { withSettings } = importModule('withSettings.module')

const preference = {
  colorLight: '#333333',
  colorDark: '#ffffff'
}

const createWidget = () => {
  const { colorLight, colorDark } = preference
  const widget = new ListWidget()
  const text = widget.addText('Hello World!')
  text.textColor = Color.dynamic(new Color(colorLight), new Color(colorDark))
  return widget
}

await withSettings({
  formItems: [
    {
      label: '文字颜色', // 日间颜色
      name: 'colorLight',
      type: 'color',
      media: '(prefers-color-scheme: light)',
      default: preference.colorLight
    },
    {
      label: '文字颜色', // 夜间颜色
      name: 'colorDark',
      type: 'color',
      media: '(prefers-color-scheme: dark)',
      default: preference.colorDark
    }
  ],
  render ({ settings }) {
    Object.assign(preference, settings)
    return createWidget()
  }
})