@xihan-ui/vue 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +258 -0
- package/dist/components/avatar-group/avatar-group.d.ts.map +1 -1
- package/dist/components/avatar-group/avatar-group.js +2 -1
- package/dist/components/avatar-group/avatar-group.js.map +1 -1
- package/dist/components/card/card.d.ts.map +1 -1
- package/dist/components/card/card.js +2 -1
- package/dist/components/card/card.js.map +1 -1
- package/dist/components/cascader/cascader.d.ts +9 -1
- package/dist/components/cascader/cascader.d.ts.map +1 -1
- package/dist/components/cascader/cascader.js +19 -1
- package/dist/components/cascader/cascader.js.map +1 -1
- package/dist/components/combobox/combobox.d.ts +18 -1
- package/dist/components/combobox/combobox.d.ts.map +1 -1
- package/dist/components/combobox/combobox.js +37 -4
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/command/command.d.ts +23 -2
- package/dist/components/command/command.d.ts.map +1 -1
- package/dist/components/command/command.js +46 -4
- package/dist/components/command/command.js.map +1 -1
- package/dist/components/context-menu/context-menu.d.ts +14 -1
- package/dist/components/context-menu/context-menu.d.ts.map +1 -1
- package/dist/components/context-menu/context-menu.js +42 -12
- package/dist/components/context-menu/context-menu.js.map +1 -1
- package/dist/components/input-group/input-group.d.ts.map +1 -1
- package/dist/components/input-group/input-group.js +2 -1
- package/dist/components/input-group/input-group.js.map +1 -1
- package/dist/components/json-viewer/json-viewer.js.map +1 -1
- package/dist/components/kbd/kbd.d.ts.map +1 -1
- package/dist/components/kbd/kbd.js +27 -10
- package/dist/components/kbd/kbd.js.map +1 -1
- package/dist/components/listbox/listbox.d.ts +18 -1
- package/dist/components/listbox/listbox.d.ts.map +1 -1
- package/dist/components/listbox/listbox.js +37 -4
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/mention/mention.d.ts +17 -1
- package/dist/components/mention/mention.d.ts.map +1 -1
- package/dist/components/mention/mention.js +36 -4
- package/dist/components/mention/mention.js.map +1 -1
- package/dist/components/menu/menu.d.ts +14 -1
- package/dist/components/menu/menu.d.ts.map +1 -1
- package/dist/components/menu/menu.js +63 -8
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/menubar/menubar.d.ts +14 -2
- package/dist/components/menubar/menubar.d.ts.map +1 -1
- package/dist/components/menubar/menubar.js +43 -11
- package/dist/components/menubar/menubar.js.map +1 -1
- package/dist/components/page-header/page-header.d.ts.map +1 -1
- package/dist/components/page-header/page-header.js +2 -1
- package/dist/components/page-header/page-header.js.map +1 -1
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/reasoning/reasoning.d.ts +1 -1
- package/dist/components/select/select.d.ts +18 -1
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/select/select.js +37 -4
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/sortable/sortable.d.ts +1 -1
- package/dist/components/statistic/statistic.d.ts.map +1 -1
- package/dist/components/statistic/statistic.js +2 -1
- package/dist/components/statistic/statistic.js.map +1 -1
- package/dist/components/table/table.d.ts +2 -2
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/tag-group/tag-group.js +1 -1
- package/dist/components/tag-group/tag-group.js.map +1 -1
- package/dist/components/timeline/timeline.d.ts.map +1 -1
- package/dist/components/timeline/timeline.js +2 -1
- package/dist/components/timeline/timeline.js.map +1 -1
- package/dist/components/timer/timer.d.ts +1 -1
- package/dist/components/tour/tour.d.ts +1 -1
- package/dist/components/transfer/transfer.d.ts +9 -1
- package/dist/components/transfer/transfer.d.ts.map +1 -1
- package/dist/components/transfer/transfer.js +19 -1
- package/dist/components/transfer/transfer.js.map +1 -1
- package/dist/components/tree/tree.d.ts +9 -7
- package/dist/components/tree/tree.d.ts.map +1 -1
- package/dist/components/tree/tree.js +17 -15
- package/dist/components/tree/tree.js.map +1 -1
- package/dist/components/tree-select/tree-select.d.ts +9 -1
- package/dist/components/tree-select/tree-select.d.ts.map +1 -1
- package/dist/components/tree-select/tree-select.js +19 -1
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/components/typography/typography.d.ts.map +1 -1
- package/dist/components/typography/typography.js +2 -1
- package/dist/components/typography/typography.js.map +1 -1
- package/dist/index.d.ts +13 -13
- package/dist/index.js +13 -13
- package/dist/package.js +1 -1
- package/dist/runtime/use-machine.js +3 -2
- package/dist/runtime/use-machine.js.map +1 -1
- package/dist/runtime/use-scrollbars.js +3 -1
- package/dist/runtime/use-scrollbars.js.map +1 -1
- package/package.json +14 -14
|
@@ -101,7 +101,7 @@ const XhComboboxRoot = defineComponent({
|
|
|
101
101
|
setValue: ctx.api.value.setValue,
|
|
102
102
|
setInputValue: ctx.api.value.setInputValue,
|
|
103
103
|
clear: ctx.api.value.clear
|
|
104
|
-
}) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.label?.() ?? (props.label != null ? [props.label] : null), slots.empty?.() ?? (props.empty != null ? [props.empty] : null), slots.item, props.clearable) : []);
|
|
104
|
+
}) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.label?.() ?? (props.label != null ? [props.label] : null), slots.empty?.() ?? (props.empty != null ? [props.empty] : null), slots.item, props.clearable, slots["item-prefix"], slots["item-suffix"]) : []);
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
const XhComboboxLabel = defineComponent({
|
|
@@ -251,6 +251,33 @@ const XhComboboxItemText = defineComponent({
|
|
|
251
251
|
return () => h("span", ctx.api.value.getItemTextProps(item.value), slots.default?.());
|
|
252
252
|
}
|
|
253
253
|
});
|
|
254
|
+
/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
|
|
255
|
+
const XhComboboxItemPrefix = defineComponent({
|
|
256
|
+
name: "XhComboboxItemPrefix",
|
|
257
|
+
setup(_, { slots }) {
|
|
258
|
+
const ctx = useComboboxContext();
|
|
259
|
+
const { item } = useComboboxItemContext();
|
|
260
|
+
return () => h("span", ctx.api.value.getItemPrefixProps(item.value), slots.default?.());
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
/** 条目行尾的作者内容(计数、徽标) */
|
|
264
|
+
const XhComboboxItemSuffix = defineComponent({
|
|
265
|
+
name: "XhComboboxItemSuffix",
|
|
266
|
+
setup(_, { slots }) {
|
|
267
|
+
const ctx = useComboboxContext();
|
|
268
|
+
const { item } = useComboboxItemContext();
|
|
269
|
+
return () => h("span", ctx.api.value.getItemSuffixProps(item.value), slots.default?.());
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
|
|
273
|
+
const XhComboboxItemDescription = defineComponent({
|
|
274
|
+
name: "XhComboboxItemDescription",
|
|
275
|
+
setup(_, { slots }) {
|
|
276
|
+
const ctx = useComboboxContext();
|
|
277
|
+
const { item } = useComboboxItemContext();
|
|
278
|
+
return () => h("span", ctx.api.value.getItemDescriptionProps(item.value), slots.default?.());
|
|
279
|
+
}
|
|
280
|
+
});
|
|
254
281
|
const XhComboboxItemIndicator = defineComponent({
|
|
255
282
|
name: "XhComboboxItemIndicator",
|
|
256
283
|
setup(_, { slots }) {
|
|
@@ -290,7 +317,7 @@ const XhComboboxLoading = defineComponent({
|
|
|
290
317
|
* 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。
|
|
291
318
|
* 过滤仍归调用方:collection 就是当前应显示的候选。
|
|
292
319
|
*/
|
|
293
|
-
function renderDefaultTree(collection, label, empty, itemSlot, clearable) {
|
|
320
|
+
function renderDefaultTree(collection, label, empty, itemSlot, clearable, prefixSlot, suffixSlot) {
|
|
294
321
|
return [
|
|
295
322
|
...label ? [h(XhComboboxLabel, null, () => label)] : [],
|
|
296
323
|
h(XhComboboxControl, null, () => [
|
|
@@ -301,10 +328,16 @@ function renderDefaultTree(collection, label, empty, itemSlot, clearable) {
|
|
|
301
328
|
h(XhComboboxPositioner, null, () => [h(XhComboboxContent, null, () => collection.map((node) => h(XhComboboxItem, {
|
|
302
329
|
key: node.value,
|
|
303
330
|
value: node.value
|
|
304
|
-
}, () => [
|
|
331
|
+
}, () => [
|
|
332
|
+
...prefixSlot ? [h(XhComboboxItemPrefix, null, () => prefixSlot(node))] : [],
|
|
333
|
+
h(XhComboboxItemText, null, () => itemSlot?.(node) ?? node.label),
|
|
334
|
+
...node.description != null ? [h(XhComboboxItemDescription, null, () => node.description)] : [],
|
|
335
|
+
...suffixSlot ? [h(XhComboboxItemSuffix, null, () => suffixSlot(node))] : [],
|
|
336
|
+
h(XhComboboxItemIndicator)
|
|
337
|
+
]))), h(XhComboboxEmpty, null, () => empty ?? [])])
|
|
305
338
|
];
|
|
306
339
|
}
|
|
307
340
|
//#endregion
|
|
308
|
-
export { XhComboboxClearTrigger, XhComboboxContent, XhComboboxControl, XhComboboxEmpty, XhComboboxGroup, XhComboboxGroupLabel, XhComboboxHiddenInput, XhComboboxInput, XhComboboxItem, XhComboboxItemIndicator, XhComboboxItemText, XhComboboxLabel, XhComboboxLoading, XhComboboxPositioner, XhComboboxRoot, XhComboboxTrigger };
|
|
341
|
+
export { XhComboboxClearTrigger, XhComboboxContent, XhComboboxControl, XhComboboxEmpty, XhComboboxGroup, XhComboboxGroupLabel, XhComboboxHiddenInput, XhComboboxInput, XhComboboxItem, XhComboboxItemDescription, XhComboboxItemIndicator, XhComboboxItemPrefix, XhComboboxItemSuffix, XhComboboxItemText, XhComboboxLabel, XhComboboxLoading, XhComboboxPositioner, XhComboboxRoot, XhComboboxTrigger };
|
|
309
342
|
|
|
310
343
|
//# sourceMappingURL=combobox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.js","names":[],"sources":["../../../src/components/combobox/combobox.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-Present XiHanFun and contributors.\n * Licensed under the MIT License. See LICENSE in the project root for license information.\n */\n\n// 提供 combobox 相关实现。\n\nimport type { ControlVariant, Direction, Placement, Size, Tone } from '@xihan-ui/core'\nimport type { ComboboxApi, ComboboxGroupProps, ComboboxInputBehavior, ComboboxInputEl, ComboboxInputHost, ComboboxItemProps, ComboboxNode, ComboboxNodeMeta, ComboboxSchema } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { computed, defineComponent, h, mergeProps, onMounted, onUnmounted, onUpdated, watch } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { XhPortal } from '../../runtime/portal'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport { useFieldLabelWiring, useFieldStateWiring } from '../field/use-field-control'\nimport { useFormControlProps } from '../form/use-form-control'\nimport {\n provideCombobox,\n provideComboboxItem,\n provideComboboxItemGroup,\n useComboboxContext,\n useComboboxItemContext,\n useComboboxItemGroupContext,\n} from './context'\nimport { useCombobox } from './use-combobox'\n\ntype ComboboxProps = ComboboxSchema['props']\n\n/** 默认插槽的载荷:展开状态、选中值、输入串、高亮候选、空态,以及修改它们的命令。 */\nexport type ComboboxRootSlotProps = Pick<\n ComboboxApi,\n 'open' | 'value' | 'inputValue' | 'highlightedValue' | 'empty' | 'isSelected' | 'setOpen' | 'setValue' | 'setInputValue' | 'clear'\n>\n\nexport const XhComboboxRoot = defineComponent({\n name: 'XhComboboxRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ComboboxNode[]> },\n /** 标题文字。提供后不必再写 label 部件;需要放置其他内容时改用 label 插槽。 */\n label: { type: String },\n /** 无匹配时的提示语。提供后不必再写 empty 部件;需要放置其他内容时改用 empty 插槽。 */\n empty: { type: String },\n value: { type: [String, Array] as PropType<string | string[]> },\n defaultValue: { type: [String, Array] as PropType<string | string[]> },\n inputValue: { type: String },\n defaultInputValue: { type: String },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n /** 表单字段名;提供后 hidden-input 才带 name 并参与提交 */\n name: { type: String },\n form: { type: String },\n multiple: Boolean,\n disabled: { type: Boolean, default: undefined },\n readOnly: { type: Boolean, default: undefined },\n invalid: { type: Boolean, default: undefined },\n loading: Boolean,\n loop: { type: Boolean, default: undefined },\n placeholder: { type: String },\n /** 自动铺开时是否渲染清空按钮;手写部件模式不使用它,写了节点即可清空 */\n clearable: Boolean,\n translations: { type: Object as PropType<ComboboxProps['translations']> },\n allowCustomValue: Boolean,\n openOnClick: Boolean,\n inputBehavior: { type: String as PropType<ComboboxInputBehavior> },\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n /** 文字方向;浮层迁移到落点后无法继承作者子树上的方向,需要 RTL 时显式提供。 */\n dir: { type: String as PropType<Direction> },\n variant: { type: String as PropType<ControlVariant> },\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n },\n // *-change 携带 details 对象,update:* 携带裸值\n emits: {\n 'value-change': (_details: PayloadOf<ComboboxProps, 'onValueChange'>) => true,\n 'input-value-change': (_details: PayloadOf<ComboboxProps, 'onInputValueChange'>) => true,\n 'open-change': (_details: PayloadOf<ComboboxProps, 'onOpenChange'>) => true,\n 'update:value': (_value: PayloadOf<ComboboxProps, 'onValueChange'>['value']) => true,\n 'update:inputValue': (_inputValue: PayloadOf<ComboboxProps, 'onInputValueChange'>['inputValue']) => true,\n 'update:open': (_open: PayloadOf<ComboboxProps, 'onOpenChange'>['open']) => true,\n },\n slots: Object as SlotsType<{\n default?: (props: ComboboxRootSlotProps) => VNode[]\n label?: () => VNode[]\n empty?: () => VNode[]\n item?: (node: ComboboxNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notifyValue: ComboboxProps['onValueChange'] = (details) => {\n emit('value-change', details)\n emit('update:value', details.value)\n }\n const notifyInputValue: ComboboxProps['onInputValueChange'] = (details) => {\n emit('input-value-change', details)\n emit('update:inputValue', details.inputValue)\n }\n const notifyOpen: ComboboxProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const ctx = useCombobox(withXhConfig('combobox', useFormControlProps(props)) as ComboboxProps, {\n onValueChange: notifyValue,\n onInputValueChange: notifyInputValue,\n onOpenChange: notifyOpen,\n })\n provideCombobox(ctx)\n\n // 首帧结算一次候选条数供空态节点判断,之后的增删由条目自己上报\n onMounted(ctx.syncItems)\n onUpdated(ctx.syncItems)\n\n return () => h(\n 'div',\n ctx.api.value.getRootProps() as Record<string, unknown>,\n slots.default\n ? slots.default({\n open: ctx.api.value.open,\n value: ctx.api.value.value,\n inputValue: ctx.api.value.inputValue,\n highlightedValue: ctx.api.value.highlightedValue,\n empty: ctx.api.value.empty,\n isSelected: ctx.api.value.isSelected,\n setOpen: ctx.api.value.setOpen,\n setValue: ctx.api.value.setValue,\n setInputValue: ctx.api.value.setInputValue,\n clear: ctx.api.value.clear,\n })\n : props.collection\n ? renderDefaultTree(\n ctx.api.value.collection,\n slots.label?.() ?? (props.label != null ? [props.label] : null),\n slots.empty?.() ?? (props.empty != null ? [props.empty] : null),\n slots.item,\n props.clearable,\n )\n : [],\n )\n },\n})\n\nexport const XhComboboxLabel = defineComponent({\n name: 'XhComboboxLabel',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 用原生 label,connect 给的 for 指向输入框\n return () => h('label', ctx.api.value.getLabelProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxControl = defineComponent({\n name: 'XhComboboxControl',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('div', {\n ...ctx.api.value.getControlProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.controlRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhComboboxInput = defineComponent({\n name: 'XhComboboxInput',\n props: {\n /**\n * 输入框渲染为哪个标签,默认 input。\n * 写 textarea 即多行宿主:connect 随之撤销 type、role 与 aria-expanded。\n */\n as: { type: String as PropType<ComboboxInputHost>, default: 'input' },\n },\n setup(props) {\n // 字段的说明与校验状态要落在真控件上,不能停在封装根的 div 上\n const fieldWiring = useFieldStateWiring()\n // 字段的标签也得并进名字链:控件自带的那条指的是它自己那个没渲染的 label 部件\n const fieldLabel = useFieldLabelWiring()\n const ctx = useComboboxContext()\n return () => h(props.as, fieldLabel.value({\n ...fieldWiring.value,\n ...ctx.api.value.getInputProps({ as: props.as }) as Record<string, unknown>,\n ref: (el: unknown) => { ctx.inputRef.value = el as ComboboxInputEl },\n }))\n },\n})\n\nexport const XhComboboxTrigger = defineComponent({\n name: 'XhComboboxTrigger',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('button', ctx.api.value.getTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxClearTrigger = defineComponent({\n name: 'XhComboboxClearTrigger',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('button', ctx.api.value.getClearTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxPositioner = defineComponent({\n name: 'XhComboboxPositioner',\n props: {\n /** 本实例的 Portal 容器;优先于应用级配置。 */\n container: { type: Object as PropType<Element> },\n },\n // 根是 Teleport,Vue 不会把直通属性合上去,作者写的 class 与 style 得自己接住落到 positioner 上\n inheritAttrs: false,\n setup(props, { slots, attrs }) {\n const ctx = useComboboxContext()\n // 候选列表的自绘条:与 content 同级、绝对定位不占布局,壳是这层已经 fixed 的 positioner,条子走浮层 4px 档\n const bars = useScrollbars({ scrollable: () => ctx.contentRef.value, props: { size: 'sm' } })\n // 搬到 portal 落点:留在原地的话,宿主祖先只要建了层叠上下文就能盖住浮层\n return () => h(XhPortal, { to: props.container ?? ctx.portalTarget.value, source: ctx.controlRef }, () => [\n h('div', {\n ...mergeProps(ctx.api.value.getPositionerProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { ctx.positionerRef.value = el as HTMLElement },\n }, [...(slots.default?.() ?? []), ...bars.render()]),\n ])\n },\n})\n\nexport const XhComboboxContent = defineComponent({\n name: 'XhComboboxContent',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('div', {\n ...ctx.api.value.getContentProps() as Record<string, unknown>,\n // 收起跟着退场闸门走:皮肤刻意没给 content 补 [hidden]{display:none}(补了退场\n // 就一帧都播不出来),所以真正的收起落成内联 display——节点始终留在原地\n style: ctx.visible.value ? undefined : { display: 'none' },\n ref: (el: unknown) => { ctx.contentRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhComboboxGroup = defineComponent({\n name: 'XhComboboxGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useComboboxContext()\n const group = computed<ComboboxGroupProps>(() => ({ value: props.value }))\n provideComboboxItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxGroupLabel = defineComponent({\n name: 'XhComboboxGroupLabel',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { group } = useComboboxItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItem = defineComponent({\n name: 'XhComboboxItem',\n props: {\n value: { type: String, required: true },\n // 缺省交给 connect 回 collection 里查,写死 false 会盖掉数据里的禁用\n disabled: { type: Boolean, default: undefined },\n },\n setup(props, { slots }) {\n const ctx = useComboboxContext()\n const item = computed<ComboboxItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideComboboxItem({ item })\n // 候选的进出与改名由条目自己上报,机器据此结算条数并摘掉悬空高亮\n onMounted(ctx.syncItems)\n onUnmounted(ctx.syncItems)\n // 节点就地复用时数量不变但身份换了,需按 value 另行上报\n watch(() => props.value, ctx.syncItems)\n return () => h('div', ctx.api.value.getItemProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItemText = defineComponent({\n name: 'XhComboboxItemText',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItemIndicator = defineComponent({\n name: 'XhComboboxItemIndicator',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxHiddenInput = defineComponent({\n name: 'XhComboboxHiddenInput',\n inheritAttrs: false,\n setup(_, { attrs }) {\n const ctx = useComboboxContext()\n // 表单出口,不写这个部件即不参与表单提交\n return () => ctx.api.value.value.map(value => h('input', {\n ...ctx.api.value.getHiddenInputProps({ value }) as Record<string, unknown>,\n ...attrs,\n key: value,\n }))\n },\n})\n\nexport const XhComboboxEmpty = defineComponent({\n name: 'XhComboboxEmpty',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 放在 positioner 里作 content 的兄弟节点,不进 role=listbox\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxLoading = defineComponent({\n name: 'XhComboboxLoading',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n * 过滤仍归调用方:collection 就是当前应显示的候选。\n */\nfunction renderDefaultTree(\n collection: readonly ComboboxNodeMeta[],\n label: (VNode | string)[] | null,\n empty: (VNode | string)[] | null,\n itemSlot: ((node: ComboboxNodeMeta) => VNode[]) | undefined,\n clearable: boolean,\n): VNode[] {\n return [\n ...(label ? [h(XhComboboxLabel, null, () => label)] : []),\n h(XhComboboxControl, null, () => [\n h(XhComboboxInput),\n ...(clearable ? [h(XhComboboxClearTrigger)] : []),\n h(XhComboboxTrigger),\n ]),\n h(XhComboboxPositioner, null, () => [\n h(XhComboboxContent, null, () => collection.map(node =>\n h(XhComboboxItem, { key: node.value, value: node.value }, () => [\n h(XhComboboxItemText, null, () => itemSlot?.(node) ?? node.label),\n h(XhComboboxItemIndicator),\n ]),\n )),\n // 空态节点是 content 的兄弟,不进 role=listbox\n h(XhComboboxEmpty, null, () => empty ?? []),\n ]),\n ]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"combobox.js","names":[],"sources":["../../../src/components/combobox/combobox.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-Present XiHanFun and contributors.\n * Licensed under the MIT License. See LICENSE in the project root for license information.\n */\n\n// 提供 combobox 相关实现。\n\nimport type { ControlVariant, Direction, Placement, Size, Tone } from '@xihan-ui/core'\nimport type { ComboboxApi, ComboboxGroupProps, ComboboxInputBehavior, ComboboxInputEl, ComboboxInputHost, ComboboxItemProps, ComboboxNode, ComboboxNodeMeta, ComboboxSchema } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { computed, defineComponent, h, mergeProps, onMounted, onUnmounted, onUpdated, watch } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { XhPortal } from '../../runtime/portal'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport { useFieldLabelWiring, useFieldStateWiring } from '../field/use-field-control'\nimport { useFormControlProps } from '../form/use-form-control'\nimport {\n provideCombobox,\n provideComboboxItem,\n provideComboboxItemGroup,\n useComboboxContext,\n useComboboxItemContext,\n useComboboxItemGroupContext,\n} from './context'\nimport { useCombobox } from './use-combobox'\n\ntype ComboboxProps = ComboboxSchema['props']\n\n/** 默认插槽的载荷:展开状态、选中值、输入串、高亮候选、空态,以及修改它们的命令。 */\nexport type ComboboxRootSlotProps = Pick<\n ComboboxApi,\n 'open' | 'value' | 'inputValue' | 'highlightedValue' | 'empty' | 'isSelected' | 'setOpen' | 'setValue' | 'setInputValue' | 'clear'\n>\n\nexport const XhComboboxRoot = defineComponent({\n name: 'XhComboboxRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ComboboxNode[]> },\n /** 标题文字。提供后不必再写 label 部件;需要放置其他内容时改用 label 插槽。 */\n label: { type: String },\n /** 无匹配时的提示语。提供后不必再写 empty 部件;需要放置其他内容时改用 empty 插槽。 */\n empty: { type: String },\n value: { type: [String, Array] as PropType<string | string[]> },\n defaultValue: { type: [String, Array] as PropType<string | string[]> },\n inputValue: { type: String },\n defaultInputValue: { type: String },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n /** 表单字段名;提供后 hidden-input 才带 name 并参与提交 */\n name: { type: String },\n form: { type: String },\n multiple: Boolean,\n disabled: { type: Boolean, default: undefined },\n readOnly: { type: Boolean, default: undefined },\n invalid: { type: Boolean, default: undefined },\n loading: Boolean,\n loop: { type: Boolean, default: undefined },\n placeholder: { type: String },\n /** 自动铺开时是否渲染清空按钮;手写部件模式不使用它,写了节点即可清空 */\n clearable: Boolean,\n translations: { type: Object as PropType<ComboboxProps['translations']> },\n allowCustomValue: Boolean,\n openOnClick: Boolean,\n inputBehavior: { type: String as PropType<ComboboxInputBehavior> },\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n /** 文字方向;浮层迁移到落点后无法继承作者子树上的方向,需要 RTL 时显式提供。 */\n dir: { type: String as PropType<Direction> },\n variant: { type: String as PropType<ControlVariant> },\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n },\n // *-change 携带 details 对象,update:* 携带裸值\n emits: {\n 'value-change': (_details: PayloadOf<ComboboxProps, 'onValueChange'>) => true,\n 'input-value-change': (_details: PayloadOf<ComboboxProps, 'onInputValueChange'>) => true,\n 'open-change': (_details: PayloadOf<ComboboxProps, 'onOpenChange'>) => true,\n 'update:value': (_value: PayloadOf<ComboboxProps, 'onValueChange'>['value']) => true,\n 'update:inputValue': (_inputValue: PayloadOf<ComboboxProps, 'onInputValueChange'>['inputValue']) => true,\n 'update:open': (_open: PayloadOf<ComboboxProps, 'onOpenChange'>['open']) => true,\n },\n slots: Object as SlotsType<{\n 'default'?: (props: ComboboxRootSlotProps) => VNode[]\n 'label'?: () => VNode[]\n 'empty'?: () => VNode[]\n /** 只填条目的文字槽,副文本与首尾两格照旧各归各的 */\n 'item'?: (node: ComboboxNodeMeta) => VNode[]\n /** 只接管行首那一格,其余槽照旧由数据铺 */\n 'item-prefix'?: (node: ComboboxNodeMeta) => VNode[]\n /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */\n 'item-suffix'?: (node: ComboboxNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notifyValue: ComboboxProps['onValueChange'] = (details) => {\n emit('value-change', details)\n emit('update:value', details.value)\n }\n const notifyInputValue: ComboboxProps['onInputValueChange'] = (details) => {\n emit('input-value-change', details)\n emit('update:inputValue', details.inputValue)\n }\n const notifyOpen: ComboboxProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const ctx = useCombobox(withXhConfig('combobox', useFormControlProps(props)) as ComboboxProps, {\n onValueChange: notifyValue,\n onInputValueChange: notifyInputValue,\n onOpenChange: notifyOpen,\n })\n provideCombobox(ctx)\n\n // 首帧结算一次候选条数供空态节点判断,之后的增删由条目自己上报\n onMounted(ctx.syncItems)\n onUpdated(ctx.syncItems)\n\n return () => h(\n 'div',\n ctx.api.value.getRootProps() as Record<string, unknown>,\n slots.default\n ? slots.default({\n open: ctx.api.value.open,\n value: ctx.api.value.value,\n inputValue: ctx.api.value.inputValue,\n highlightedValue: ctx.api.value.highlightedValue,\n empty: ctx.api.value.empty,\n isSelected: ctx.api.value.isSelected,\n setOpen: ctx.api.value.setOpen,\n setValue: ctx.api.value.setValue,\n setInputValue: ctx.api.value.setInputValue,\n clear: ctx.api.value.clear,\n })\n : props.collection\n ? renderDefaultTree(\n ctx.api.value.collection,\n slots.label?.() ?? (props.label != null ? [props.label] : null),\n slots.empty?.() ?? (props.empty != null ? [props.empty] : null),\n slots.item,\n props.clearable,\n slots['item-prefix'],\n slots['item-suffix'],\n )\n : [],\n )\n },\n})\n\nexport const XhComboboxLabel = defineComponent({\n name: 'XhComboboxLabel',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 用原生 label,connect 给的 for 指向输入框\n return () => h('label', ctx.api.value.getLabelProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxControl = defineComponent({\n name: 'XhComboboxControl',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('div', {\n ...ctx.api.value.getControlProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.controlRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhComboboxInput = defineComponent({\n name: 'XhComboboxInput',\n props: {\n /**\n * 输入框渲染为哪个标签,默认 input。\n * 写 textarea 即多行宿主:connect 随之撤销 type、role 与 aria-expanded。\n */\n as: { type: String as PropType<ComboboxInputHost>, default: 'input' },\n },\n setup(props) {\n // 字段的说明与校验状态要落在真控件上,不能停在封装根的 div 上\n const fieldWiring = useFieldStateWiring()\n // 字段的标签也得并进名字链:控件自带的那条指的是它自己那个没渲染的 label 部件\n const fieldLabel = useFieldLabelWiring()\n const ctx = useComboboxContext()\n return () => h(props.as, fieldLabel.value({\n ...fieldWiring.value,\n ...ctx.api.value.getInputProps({ as: props.as }) as Record<string, unknown>,\n ref: (el: unknown) => { ctx.inputRef.value = el as ComboboxInputEl },\n }))\n },\n})\n\nexport const XhComboboxTrigger = defineComponent({\n name: 'XhComboboxTrigger',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('button', ctx.api.value.getTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxClearTrigger = defineComponent({\n name: 'XhComboboxClearTrigger',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('button', ctx.api.value.getClearTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxPositioner = defineComponent({\n name: 'XhComboboxPositioner',\n props: {\n /** 本实例的 Portal 容器;优先于应用级配置。 */\n container: { type: Object as PropType<Element> },\n },\n // 根是 Teleport,Vue 不会把直通属性合上去,作者写的 class 与 style 得自己接住落到 positioner 上\n inheritAttrs: false,\n setup(props, { slots, attrs }) {\n const ctx = useComboboxContext()\n // 候选列表的自绘条:与 content 同级、绝对定位不占布局,壳是这层已经 fixed 的 positioner,条子走浮层 4px 档\n const bars = useScrollbars({ scrollable: () => ctx.contentRef.value, props: { size: 'sm' } })\n // 搬到 portal 落点:留在原地的话,宿主祖先只要建了层叠上下文就能盖住浮层\n return () => h(XhPortal, { to: props.container ?? ctx.portalTarget.value, source: ctx.controlRef }, () => [\n h('div', {\n ...mergeProps(ctx.api.value.getPositionerProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { ctx.positionerRef.value = el as HTMLElement },\n }, [...(slots.default?.() ?? []), ...bars.render()]),\n ])\n },\n})\n\nexport const XhComboboxContent = defineComponent({\n name: 'XhComboboxContent',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n return () => h('div', {\n ...ctx.api.value.getContentProps() as Record<string, unknown>,\n // 收起跟着退场闸门走:皮肤刻意没给 content 补 [hidden]{display:none}(补了退场\n // 就一帧都播不出来),所以真正的收起落成内联 display——节点始终留在原地\n style: ctx.visible.value ? undefined : { display: 'none' },\n ref: (el: unknown) => { ctx.contentRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhComboboxGroup = defineComponent({\n name: 'XhComboboxGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useComboboxContext()\n const group = computed<ComboboxGroupProps>(() => ({ value: props.value }))\n provideComboboxItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxGroupLabel = defineComponent({\n name: 'XhComboboxGroupLabel',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { group } = useComboboxItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItem = defineComponent({\n name: 'XhComboboxItem',\n props: {\n value: { type: String, required: true },\n // 缺省交给 connect 回 collection 里查,写死 false 会盖掉数据里的禁用\n disabled: { type: Boolean, default: undefined },\n },\n setup(props, { slots }) {\n const ctx = useComboboxContext()\n const item = computed<ComboboxItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideComboboxItem({ item })\n // 候选的进出与改名由条目自己上报,机器据此结算条数并摘掉悬空高亮\n onMounted(ctx.syncItems)\n onUnmounted(ctx.syncItems)\n // 节点就地复用时数量不变但身份换了,需按 value 另行上报\n watch(() => props.value, ctx.syncItems)\n return () => h('div', ctx.api.value.getItemProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItemText = defineComponent({\n name: 'XhComboboxItemText',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */\nexport const XhComboboxItemPrefix = defineComponent({\n name: 'XhComboboxItemPrefix',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemPrefixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行尾的作者内容(计数、徽标) */\nexport const XhComboboxItemSuffix = defineComponent({\n name: 'XhComboboxItemSuffix',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemSuffixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */\nexport const XhComboboxItemDescription = defineComponent({\n name: 'XhComboboxItemDescription',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemDescriptionProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxItemIndicator = defineComponent({\n name: 'XhComboboxItemIndicator',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n const { item } = useComboboxItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxHiddenInput = defineComponent({\n name: 'XhComboboxHiddenInput',\n inheritAttrs: false,\n setup(_, { attrs }) {\n const ctx = useComboboxContext()\n // 表单出口,不写这个部件即不参与表单提交\n return () => ctx.api.value.value.map(value => h('input', {\n ...ctx.api.value.getHiddenInputProps({ value }) as Record<string, unknown>,\n ...attrs,\n key: value,\n }))\n },\n})\n\nexport const XhComboboxEmpty = defineComponent({\n name: 'XhComboboxEmpty',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 放在 positioner 里作 content 的兄弟节点,不进 role=listbox\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhComboboxLoading = defineComponent({\n name: 'XhComboboxLoading',\n setup(_, { slots }) {\n const ctx = useComboboxContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n * 过滤仍归调用方:collection 就是当前应显示的候选。\n */\nfunction renderDefaultTree(\n collection: readonly ComboboxNodeMeta[],\n label: (VNode | string)[] | null,\n empty: (VNode | string)[] | null,\n itemSlot: ((node: ComboboxNodeMeta) => VNode[]) | undefined,\n clearable: boolean,\n prefixSlot?: (node: ComboboxNodeMeta) => VNode[],\n suffixSlot?: (node: ComboboxNodeMeta) => VNode[],\n): VNode[] {\n return [\n ...(label ? [h(XhComboboxLabel, null, () => label)] : []),\n h(XhComboboxControl, null, () => [\n h(XhComboboxInput),\n ...(clearable ? [h(XhComboboxClearTrigger)] : []),\n h(XhComboboxTrigger),\n ]),\n h(XhComboboxPositioner, null, () => [\n h(XhComboboxContent, null, () => collection.map(node =>\n h(XhComboboxItem, { key: node.value, value: node.value }, () => [\n ...(prefixSlot ? [h(XhComboboxItemPrefix, null, () => prefixSlot(node))] : []),\n h(XhComboboxItemText, null, () => itemSlot?.(node) ?? node.label),\n ...(node.description != null ? [h(XhComboboxItemDescription, null, () => node.description)] : []),\n ...(suffixSlot ? [h(XhComboboxItemSuffix, null, () => suffixSlot(node))] : []),\n h(XhComboboxItemIndicator),\n ]),\n )),\n // 空态节点是 content 的兄弟,不进 role=listbox\n h(XhComboboxEmpty, null, () => empty ?? []),\n ]),\n ]\n}\n"],"mappings":";;;;;;;;;AAmCA,MAAa,iBAAiB,gBAAgB;CAC5C,MAAM;CAEN,OAAO;EACL,YAAY,EAAE,MAAM,MAAkC;;EAEtD,OAAO,EAAE,MAAM,OAAO;;EAEtB,OAAO,EAAE,MAAM,OAAO;EACtB,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,EAAiC;EAC9D,cAAc,EAAE,MAAM,CAAC,QAAQ,KAAK,EAAiC;EACrE,YAAY,EAAE,MAAM,OAAO;EAC3B,mBAAmB,EAAE,MAAM,OAAO;EAClC,MAAM;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC1C,aAAa;;EAEb,MAAM,EAAE,MAAM,OAAO;EACrB,MAAM,EAAE,MAAM,OAAO;EACrB,UAAU;EACV,UAAU;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC9C,UAAU;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC9C,SAAS;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC7C,SAAS;EACT,MAAM;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC1C,aAAa,EAAE,MAAM,OAAO;;EAE5B,WAAW;EACX,cAAc,EAAE,MAAM,OAAkD;EACxE,kBAAkB;EAClB,aAAa;EACb,eAAe,EAAE,MAAM,OAA0C;EACjE,WAAW,EAAE,MAAM,OAA8B;EACjD,QAAQ,EAAE,MAAM,OAAO;;EAEvB,KAAK,EAAE,MAAM,OAA8B;EAC3C,SAAS,EAAE,MAAM,OAAmC;EACpD,MAAM,EAAE,MAAM,OAAyB;EACvC,MAAM,EAAE,MAAM,OAAyB;CACzC;CAEA,OAAO;EACL,iBAAiB,aAAwD;EACzE,uBAAuB,aAA6D;EACpF,gBAAgB,aAAuD;EACvE,iBAAiB,WAA+D;EAChF,sBAAsB,gBAA8E;EACpG,gBAAgB,UAA4D;CAC9E;CACA,OAAO;CAWP,MAAM,OAAO,EAAE,OAAO,QAAQ;EAC5B,MAAM,eAA+C,YAAY;GAC/D,KAAK,gBAAgB,OAAO;GAC5B,KAAK,gBAAgB,QAAQ,KAAK;EACpC;EACA,MAAM,oBAAyD,YAAY;GACzE,KAAK,sBAAsB,OAAO;GAClC,KAAK,qBAAqB,QAAQ,UAAU;EAC9C;EACA,MAAM,cAA6C,YAAY;GAC7D,KAAK,eAAe,OAAO;GAC3B,KAAK,eAAe,QAAQ,IAAI;EAClC;EACA,MAAM,MAAM,YAAY,aAAa,YAAY,oBAAoB,KAAK,CAAC,GAAoB;GAC7F,eAAe;GACf,oBAAoB;GACpB,cAAc;EAChB,CAAC;EACD,gBAAgB,GAAG;EAGnB,UAAU,IAAI,SAAS;EACvB,UAAU,IAAI,SAAS;EAEvB,aAAa,EACX,OACA,IAAI,IAAI,MAAM,aAAa,GAC3B,MAAM,UACF,MAAM,QAAQ;GACZ,MAAM,IAAI,IAAI,MAAM;GACpB,OAAO,IAAI,IAAI,MAAM;GACrB,YAAY,IAAI,IAAI,MAAM;GAC1B,kBAAkB,IAAI,IAAI,MAAM;GAChC,OAAO,IAAI,IAAI,MAAM;GACrB,YAAY,IAAI,IAAI,MAAM;GAC1B,SAAS,IAAI,IAAI,MAAM;GACvB,UAAU,IAAI,IAAI,MAAM;GACxB,eAAe,IAAI,IAAI,MAAM;GAC7B,OAAO,IAAI,IAAI,MAAM;EACvB,CAAC,IACD,MAAM,aACJ,kBACE,IAAI,IAAI,MAAM,YACd,MAAM,QAAQ,MAAM,MAAM,SAAS,OAAO,CAAC,MAAM,KAAK,IAAI,OAC1D,MAAM,QAAQ,MAAM,MAAM,SAAS,OAAO,CAAC,MAAM,KAAK,IAAI,OAC1D,MAAM,MACN,MAAM,WACN,MAAM,gBACN,MAAM,cACR,IACA,CAAC,CACT;CACF;AACF,CAAC;AAED,MAAa,kBAAkB,gBAAgB;CAC7C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAE/B,aAAa,EAAE,SAAS,IAAI,IAAI,MAAM,cAAc,GAA8B,MAAM,UAAU,CAAC;CACrG;AACF,CAAC;AAED,MAAa,oBAAoB,gBAAgB;CAC/C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,aAAa,EAAE,OAAO;GACpB,GAAG,IAAI,IAAI,MAAM,gBAAgB;GACjC,MAAM,OAAgB;IAAE,IAAI,WAAW,QAAQ;GAAkB;EACnE,GAAG,MAAM,UAAU,CAAC;CACtB;AACF,CAAC;AAED,MAAa,kBAAkB,gBAAgB;CAC7C,MAAM;CACN,OAAO;;;;;AAKL,IAAI;EAAE,MAAM;EAAuC,SAAS;CAAQ,EACtE;CACA,MAAM,OAAO;EAEX,MAAM,cAAc,oBAAoB;EAExC,MAAM,aAAa,oBAAoB;EACvC,MAAM,MAAM,mBAAmB;EAC/B,aAAa,EAAE,MAAM,IAAI,WAAW,MAAM;GACxC,GAAG,YAAY;GACf,GAAG,IAAI,IAAI,MAAM,cAAc,EAAE,IAAI,MAAM,GAAG,CAAC;GAC/C,MAAM,OAAgB;IAAE,IAAI,SAAS,QAAQ;GAAsB;EACrE,CAAC,CAAC;CACJ;AACF,CAAC;AAED,MAAa,oBAAoB,gBAAgB;CAC/C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,aAAa,EAAE,UAAU,IAAI,IAAI,MAAM,gBAAgB,GAA8B,MAAM,UAAU,CAAC;CACxG;AACF,CAAC;AAED,MAAa,yBAAyB,gBAAgB;CACpD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,aAAa,EAAE,UAAU,IAAI,IAAI,MAAM,qBAAqB,GAA8B,MAAM,UAAU,CAAC;CAC7G;AACF,CAAC;AAED,MAAa,uBAAuB,gBAAgB;CAClD,MAAM;CACN,OAAO;;AAEL,WAAW,EAAE,MAAM,OAA4B,EACjD;CAEA,cAAc;CACd,MAAM,OAAO,EAAE,OAAO,SAAS;EAC7B,MAAM,MAAM,mBAAmB;EAE/B,MAAM,OAAO,cAAc;GAAE,kBAAkB,IAAI,WAAW;GAAO,OAAO,EAAE,MAAM,KAAK;EAAE,CAAC;EAE5F,aAAa,EAAE,UAAU;GAAE,IAAI,MAAM,aAAa,IAAI,aAAa;GAAO,QAAQ,IAAI;EAAW,SAAS,CACxG,EAAE,OAAO;GACP,GAAG,WAAW,IAAI,IAAI,MAAM,mBAAmB,GAA8B,KAAK;GAClF,MAAM,OAAgB;IAAE,IAAI,cAAc,QAAQ;GAAkB;EACtE,GAAG,CAAC,GAAI,MAAM,UAAU,KAAK,CAAC,GAAI,GAAG,KAAK,OAAO,CAAC,CAAC,CACrD,CAAC;CACH;AACF,CAAC;AAED,MAAa,oBAAoB,gBAAgB;CAC/C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,aAAa,EAAE,OAAO;GACpB,GAAG,IAAI,IAAI,MAAM,gBAAgB;GAGjC,OAAO,IAAI,QAAQ,QAAQ,KAAA,IAAY,EAAE,SAAS,OAAO;GACzD,MAAM,OAAgB;IAAE,IAAI,WAAW,QAAQ;GAAkB;EACnE,GAAG,MAAM,UAAU,CAAC;CACtB;AACF,CAAC;AAED,MAAa,kBAAkB,gBAAgB;CAC7C,MAAM;CACN,OAAO,EACL,OAAO;EAAE,MAAM;EAAQ,UAAU;CAAK,EACxC;CACA,MAAM,OAAO,EAAE,SAAS;EACtB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,QAAQ,gBAAoC,EAAE,OAAO,MAAM,MAAM,EAAE;EACzE,yBAAyB,EAAE,MAAM,CAAC;EAClC,aAAa,EAAE,OAAO,IAAI,IAAI,MAAM,cAAc,MAAM,KAAK,GAA8B,MAAM,UAAU,CAAC;CAC9G;AACF,CAAC;AAED,MAAa,uBAAuB,gBAAgB;CAClD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,UAAU,4BAA4B;EAC9C,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,mBAAmB,MAAM,KAAK,GAA8B,MAAM,UAAU,CAAC;CACpH;AACF,CAAC;AAED,MAAa,iBAAiB,gBAAgB;CAC5C,MAAM;CACN,OAAO;EACL,OAAO;GAAE,MAAM;GAAQ,UAAU;EAAK;EAEtC,UAAU;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;CAChD;CACA,MAAM,OAAO,EAAE,SAAS;EACtB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,OAAO,gBAAmC;GAAE,OAAO,MAAM;GAAO,UAAU,MAAM;EAAS,EAAE;EACjG,oBAAoB,EAAE,KAAK,CAAC;EAE5B,UAAU,IAAI,SAAS;EACvB,YAAY,IAAI,SAAS;EAEzB,YAAY,MAAM,OAAO,IAAI,SAAS;EACtC,aAAa,EAAE,OAAO,IAAI,IAAI,MAAM,aAAa,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CAC5G;AACF,CAAC;AAED,MAAa,qBAAqB,gBAAgB;CAChD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,SAAS,uBAAuB;EACxC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,iBAAiB,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CACjH;AACF,CAAC;;AAGD,MAAa,uBAAuB,gBAAgB;CAClD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,SAAS,uBAAuB;EACxC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,mBAAmB,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CACnH;AACF,CAAC;;AAGD,MAAa,uBAAuB,gBAAgB;CAClD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,SAAS,uBAAuB;EACxC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,mBAAmB,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CACnH;AACF,CAAC;;AAGD,MAAa,4BAA4B,gBAAgB;CACvD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,SAAS,uBAAuB;EACxC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,wBAAwB,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CACxH;AACF,CAAC;AAED,MAAa,0BAA0B,gBAAgB;CACrD,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAC/B,MAAM,EAAE,SAAS,uBAAuB;EACxC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,sBAAsB,KAAK,KAAK,GAA8B,MAAM,UAAU,CAAC;CACtH;AACF,CAAC;AAED,MAAa,wBAAwB,gBAAgB;CACnD,MAAM;CACN,cAAc;CACd,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAE/B,aAAa,IAAI,IAAI,MAAM,MAAM,KAAI,UAAS,EAAE,SAAS;GACvD,GAAG,IAAI,IAAI,MAAM,oBAAoB,EAAE,MAAM,CAAC;GAC9C,GAAG;GACH,KAAK;EACP,CAAC,CAAC;CACJ;AACF,CAAC;AAED,MAAa,kBAAkB,gBAAgB;CAC7C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAE/B,aAAa,EAAE,OAAO,IAAI,IAAI,MAAM,cAAc,GAA8B,MAAM,UAAU,CAAC;CACnG;AACF,CAAC;AAED,MAAa,oBAAoB,gBAAgB;CAC/C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,mBAAmB;EAE/B,aAAa,EAAE,OAAO,IAAI,IAAI,MAAM,gBAAgB,GAA8B,MAAM,UAAU,CAAC;CACrG;AACF,CAAC;;;;;;AAOD,SAAS,kBACP,YACA,OACA,OACA,UACA,WACA,YACA,YACS;CACT,OAAO;EACL,GAAI,QAAQ,CAAC,EAAE,iBAAiB,YAAY,KAAK,CAAC,IAAI,CAAC;EACvD,EAAE,mBAAmB,YAAY;GAC/B,EAAE,eAAe;GACjB,GAAI,YAAY,CAAC,EAAE,sBAAsB,CAAC,IAAI,CAAC;GAC/C,EAAE,iBAAiB;EACrB,CAAC;EACD,EAAE,sBAAsB,YAAY,CAClC,EAAE,mBAAmB,YAAY,WAAW,KAAI,SAC9C,EAAE,gBAAgB;GAAE,KAAK,KAAK;GAAO,OAAO,KAAK;EAAM,SAAS;GAC9D,GAAI,aAAa,CAAC,EAAE,sBAAsB,YAAY,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;GAC5E,EAAE,oBAAoB,YAAY,WAAW,IAAI,KAAK,KAAK,KAAK;GAChE,GAAI,KAAK,eAAe,OAAO,CAAC,EAAE,2BAA2B,YAAY,KAAK,WAAW,CAAC,IAAI,CAAC;GAC/F,GAAI,aAAa,CAAC,EAAE,sBAAsB,YAAY,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;GAC5E,EAAE,uBAAuB;EAC3B,CAAC,CACH,CAAC,GAED,EAAE,iBAAiB,YAAY,SAAS,CAAC,CAAC,CAC5C,CAAC;CACH;AACF"}
|
|
@@ -164,8 +164,8 @@ declare const XhCommandRoot: import("vue").DefineComponent<import("vue").Extract
|
|
|
164
164
|
open: boolean;
|
|
165
165
|
defaultOpen: boolean;
|
|
166
166
|
loading: boolean;
|
|
167
|
-
closeOnSelect: boolean;
|
|
168
167
|
caseSensitive: boolean;
|
|
168
|
+
closeOnSelect: boolean;
|
|
169
169
|
modal: boolean;
|
|
170
170
|
closeOnEscape: boolean;
|
|
171
171
|
closeOnInteractOutside: boolean;
|
|
@@ -174,7 +174,12 @@ declare const XhCommandRoot: import("vue").DefineComponent<import("vue").Extract
|
|
|
174
174
|
default?: (props: CommandRootSlotProps) => VNode[];
|
|
175
175
|
/** 铺开时的触发按钮内容;未提供时不渲染触发器(面板改由快捷键或 v-model:open 唤起)。 */
|
|
176
176
|
trigger?: () => VNode[];
|
|
177
|
+
/** 只填条目的文字槽,副文本与首尾两格照旧各归各的 */
|
|
177
178
|
item?: (node: CommandNodeMeta) => VNode[];
|
|
179
|
+
/** 只接管行首那一格,其余槽照旧由数据铺 */
|
|
180
|
+
'item-prefix'?: (node: CommandNodeMeta) => VNode[];
|
|
181
|
+
/** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */
|
|
182
|
+
'item-suffix'?: (node: CommandNodeMeta) => VNode[];
|
|
178
183
|
empty?: () => VNode[];
|
|
179
184
|
footer?: () => VNode[];
|
|
180
185
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -250,6 +255,22 @@ declare const XhCommandItem: import("vue").DefineComponent<import("vue").Extract
|
|
|
250
255
|
declare const XhCommandItemText: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
251
256
|
[key: string]: any;
|
|
252
257
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
258
|
+
/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
|
|
259
|
+
declare const XhCommandItemPrefix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
260
|
+
[key: string]: any;
|
|
261
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
262
|
+
/** 条目行尾的作者内容(计数、徽标) */
|
|
263
|
+
declare const XhCommandItemSuffix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
264
|
+
[key: string]: any;
|
|
265
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
266
|
+
/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
|
|
267
|
+
declare const XhCommandItemDescription: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
268
|
+
[key: string]: any;
|
|
269
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
270
|
+
/** 命令行尾的快捷键提示,与说明同档同色;纯装饰 */
|
|
271
|
+
declare const XhCommandItemShortcut: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
272
|
+
[key: string]: any;
|
|
273
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
253
274
|
declare const XhCommandEmpty: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
254
275
|
[key: string]: any;
|
|
255
276
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -260,5 +281,5 @@ declare const XhCommandFooter: import("vue").DefineComponent<{}, () => VNode<imp
|
|
|
260
281
|
[key: string]: any;
|
|
261
282
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
262
283
|
//#endregion
|
|
263
|
-
export { CommandRootSlotProps, XhCommandContent, XhCommandEmpty, XhCommandFooter, XhCommandGroup, XhCommandGroupLabel, XhCommandInput, XhCommandItem, XhCommandItemText, XhCommandList, XhCommandLoading, XhCommandRoot, XhCommandTrigger };
|
|
284
|
+
export { CommandRootSlotProps, XhCommandContent, XhCommandEmpty, XhCommandFooter, XhCommandGroup, XhCommandGroupLabel, XhCommandInput, XhCommandItem, XhCommandItemDescription, XhCommandItemPrefix, XhCommandItemShortcut, XhCommandItemSuffix, XhCommandItemText, XhCommandList, XhCommandLoading, XhCommandRoot, XhCommandTrigger };
|
|
264
285
|
//# sourceMappingURL=command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","names":[],"sources":["../../../src/components/command/command.ts"],"mappings":";;;;;KA4BK,eAAe;;KAGR,uBAAuB,KACjC;cAIW,6BAAa,8BAAA;;IAIO,MAAA,SAAS;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBX,MAAA,SAAS;;;IACR,MAAA,SAAS;;;IACN,MAAA,SAAS;;;IACJ,MAAA,SAAS;;;;;EAIf,gBAAA,UAAA,UAAU;EACH,uBAAA,UAAA,UAAU;EACtB,SAAA,UAAA,UAAU;EACR,gBAAA,OAAA,UAAU;EACE,sBAAA,aAAA,UAAU;;;IA/BhB,MAAA,SAAS;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBX,MAAA,SAAS;;;IACR,MAAA,SAAS;;;IACN,MAAA,SAAS;;;IACJ,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"command.d.ts","names":[],"sources":["../../../src/components/command/command.ts"],"mappings":";;;;;KA4BK,eAAe;;KAGR,uBAAuB,KACjC;cAIW,6BAAa,8BAAA;;IAIO,MAAA,SAAS;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBX,MAAA,SAAS;;;IACR,MAAA,SAAS;;;IACN,MAAA,SAAS;;;IACJ,MAAA,SAAS;;;;;EAIf,gBAAA,UAAA,UAAU;EACH,uBAAA,UAAA,UAAU;EACtB,SAAA,UAAA,UAAU;EACR,gBAAA,OAAA,UAAU;EACE,sBAAA,aAAA,UAAU;;;IA/BhB,MAAA,SAAS;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBX,MAAA,SAAS;;;IACR,MAAA,SAAS;;;IACN,MAAA,SAAS;;;IACJ,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;EAW7B,WAAC,OAAO,yBAAyB;;EAEjC,gBAAM;;EAET,QAAC,MAAM,oBAAoB;;EAEpB,iBAAC,MAAM,oBAAoB;;EAE3B,iBAAC,MAAM,oBAAoB;EACjC,cAAM;EACL,eAAM;kCAuDnB;cAEW,gCAAgB,8BAAA;;;;;;;;;;qCAsB3B;cAEW,gCAAgB,8BAAA;;;IAII,MAAA,SAAS;;;;;;;IAAT,MAAA,SAAS;;MA+BxC,oDAAA;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BASzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,0BAAA,oBAAA,4BAAA;;8BASxB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,8BAAA;;;;;;;;;;;;MAWzB,oDAAA;cAEW,mCAAmB,0BAAA,oBAAA,4BAAA;;8BAO9B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAaxB;cAEW,iCAAiB,0BAAA,oBAAA,4BAAA;;8BAO5B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,mCAAmB,0BAAA,oBAAA,4BAAA;;8BAO9B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,mCAAmB,0BAAA,oBAAA,4BAAA;;8BAO9B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,wCAAwB,0BAAA,oBAAA,4BAAA;;8BAOnC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,qCAAqB,0BAAA,oBAAA,4BAAA;;8BAOhC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAOzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAO3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,+BAAe,0BAAA,oBAAA,4BAAA;;8BAM1B,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
|
|
@@ -101,7 +101,7 @@ const XhCommandRoot = defineComponent({
|
|
|
101
101
|
setInputValue: api.setInputValue,
|
|
102
102
|
select: api.select
|
|
103
103
|
});
|
|
104
|
-
return renderDefaultTree(fullTree.value, slots.trigger, slots.item, slots.empty?.() ?? (props.empty != null ? [props.empty] : null), slots.footer?.());
|
|
104
|
+
return renderDefaultTree(fullTree.value, slots.trigger, slots.item, slots.empty?.() ?? (props.empty != null ? [props.empty] : null), slots.footer?.(), slots["item-prefix"], slots["item-suffix"]);
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
});
|
|
@@ -229,6 +229,42 @@ const XhCommandItemText = defineComponent({
|
|
|
229
229
|
return () => h("span", ctx.api.value.getItemTextProps(item.value), slots.default?.());
|
|
230
230
|
}
|
|
231
231
|
});
|
|
232
|
+
/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
|
|
233
|
+
const XhCommandItemPrefix = defineComponent({
|
|
234
|
+
name: "XhCommandItemPrefix",
|
|
235
|
+
setup(_, { slots }) {
|
|
236
|
+
const ctx = useCommandContext();
|
|
237
|
+
const { item } = useCommandItemContext();
|
|
238
|
+
return () => h("span", ctx.api.value.getItemPrefixProps(item.value), slots.default?.());
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
/** 条目行尾的作者内容(计数、徽标) */
|
|
242
|
+
const XhCommandItemSuffix = defineComponent({
|
|
243
|
+
name: "XhCommandItemSuffix",
|
|
244
|
+
setup(_, { slots }) {
|
|
245
|
+
const ctx = useCommandContext();
|
|
246
|
+
const { item } = useCommandItemContext();
|
|
247
|
+
return () => h("span", ctx.api.value.getItemSuffixProps(item.value), slots.default?.());
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
|
|
251
|
+
const XhCommandItemDescription = defineComponent({
|
|
252
|
+
name: "XhCommandItemDescription",
|
|
253
|
+
setup(_, { slots }) {
|
|
254
|
+
const ctx = useCommandContext();
|
|
255
|
+
const { item } = useCommandItemContext();
|
|
256
|
+
return () => h("span", ctx.api.value.getItemDescriptionProps(item.value), slots.default?.());
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
/** 命令行尾的快捷键提示,与说明同档同色;纯装饰 */
|
|
260
|
+
const XhCommandItemShortcut = defineComponent({
|
|
261
|
+
name: "XhCommandItemShortcut",
|
|
262
|
+
setup(_, { slots }) {
|
|
263
|
+
const ctx = useCommandContext();
|
|
264
|
+
const { item } = useCommandItemContext();
|
|
265
|
+
return () => h("span", ctx.api.value.getItemShortcutProps(item.value), slots.default?.());
|
|
266
|
+
}
|
|
267
|
+
});
|
|
232
268
|
const XhCommandEmpty = defineComponent({
|
|
233
269
|
name: "XhCommandEmpty",
|
|
234
270
|
setup(_, { slots }) {
|
|
@@ -254,11 +290,17 @@ const XhCommandFooter = defineComponent({
|
|
|
254
290
|
* 未写默认插槽时按清单铺开的整套结构,作者只提供数据。
|
|
255
291
|
* 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。
|
|
256
292
|
*/
|
|
257
|
-
function renderDefaultTree(tree, triggerSlot, itemSlot, empty, footer) {
|
|
293
|
+
function renderDefaultTree(tree, triggerSlot, itemSlot, empty, footer, prefixSlot, suffixSlot) {
|
|
258
294
|
const renderItem = (node) => h(XhCommandItem, {
|
|
259
295
|
key: node.value,
|
|
260
296
|
value: node.value
|
|
261
|
-
}, () => [
|
|
297
|
+
}, () => [
|
|
298
|
+
...prefixSlot ? [h(XhCommandItemPrefix, null, () => prefixSlot(node))] : [],
|
|
299
|
+
h(XhCommandItemText, null, () => itemSlot?.(node) ?? node.label),
|
|
300
|
+
...node.description != null ? [h(XhCommandItemDescription, null, () => node.description)] : [],
|
|
301
|
+
...node.shortcut != null ? [h(XhCommandItemShortcut, null, () => node.shortcut)] : [],
|
|
302
|
+
...suffixSlot ? [h(XhCommandItemSuffix, null, () => suffixSlot(node))] : []
|
|
303
|
+
]);
|
|
262
304
|
return [...triggerSlot ? [h(XhCommandTrigger, null, triggerSlot)] : [], h(XhCommandContent, null, () => [
|
|
263
305
|
h(XhCommandInput),
|
|
264
306
|
h(XhCommandList, null, () => tree.map((group) => group.value === COMMAND_UNGROUPED ? group.items.map(renderItem) : h(XhCommandGroup, {
|
|
@@ -271,6 +313,6 @@ function renderDefaultTree(tree, triggerSlot, itemSlot, empty, footer) {
|
|
|
271
313
|
])];
|
|
272
314
|
}
|
|
273
315
|
//#endregion
|
|
274
|
-
export { XhCommandContent, XhCommandEmpty, XhCommandFooter, XhCommandGroup, XhCommandGroupLabel, XhCommandInput, XhCommandItem, XhCommandItemText, XhCommandList, XhCommandLoading, XhCommandRoot, XhCommandTrigger };
|
|
316
|
+
export { XhCommandContent, XhCommandEmpty, XhCommandFooter, XhCommandGroup, XhCommandGroupLabel, XhCommandInput, XhCommandItem, XhCommandItemDescription, XhCommandItemPrefix, XhCommandItemShortcut, XhCommandItemSuffix, XhCommandItemText, XhCommandList, XhCommandLoading, XhCommandRoot, XhCommandTrigger };
|
|
275
317
|
|
|
276
318
|
//# sourceMappingURL=command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","names":[],"sources":["../../../src/components/command/command.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-Present XiHanFun and contributors.\n * Licensed under the MIT License. See LICENSE in the project root for license information.\n */\n\n// 提供 command 相关实现。\n\nimport type { Direction, OverlayBackdropVariant, Size } from '@xihan-ui/core'\nimport type { CommandApi, CommandGroup, CommandGroupMeta, CommandGroupProps, CommandItemProps, CommandNode, CommandNodeMeta, CommandSchema } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { COMMAND_UNGROUPED, resolveCommandGroups } from '@xihan-ui/headless'\nimport { computed, defineComponent, h, mergeProps } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { mergeIntoChild } from '../../runtime/as-child'\nimport { mergePartProps } from '../../runtime/merge-props'\nimport { XhPortal } from '../../runtime/portal'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport {\n provideCommand,\n provideCommandItem,\n provideCommandItemGroup,\n useCommandContext,\n useCommandItemContext,\n useCommandItemGroupContext,\n} from './context'\nimport { useCommand } from './use-command'\n\ntype CommandProps = CommandSchema['props']\n\n/** 默认插槽的载荷:开合、检索串、结果与锚点,以及修改它们的命令。 */\nexport type CommandRootSlotProps = Pick<\n CommandApi,\n 'open' | 'inputValue' | 'groups' | 'results' | 'highlightedValue' | 'empty' | 'setOpen' | 'setInputValue' | 'select'\n>\n\nexport const XhCommandRoot = defineComponent({\n name: 'XhCommandRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<CommandNode[]> },\n groups: { type: Array as PropType<CommandGroup[]> },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n inputValue: { type: String },\n defaultInputValue: { type: String },\n /** 内置过滤,默认开启;关闭后由调用方自行筛选 */\n filter: { type: Boolean, default: undefined },\n caseSensitive: Boolean,\n closeOnSelect: { type: Boolean, default: undefined },\n modal: { type: Boolean, default: true },\n closeOnEscape: { type: Boolean, default: true },\n closeOnInteractOutside: { type: Boolean, default: undefined },\n restoreFocus: { type: Boolean, default: true },\n loop: { type: Boolean, default: undefined },\n loading: Boolean,\n placeholder: { type: String },\n /** 无匹配时的提示语。提供后不必再写 empty 部件;需要放置其他内容时改用 empty 插槽。 */\n empty: { type: String },\n /** 文字方向;浮层迁移到落点后无法继承作者子树上的方向,需要 RTL 时显式提供。 */\n dir: { type: String as PropType<Direction> },\n size: { type: String as PropType<Size> },\n variant: { type: String as PropType<OverlayBackdropVariant> },\n translations: { type: Object as PropType<CommandProps['translations']> },\n },\n // *-change 携带 details 对象,update:* 携带裸值\n emits: {\n 'open-change': (_details: PayloadOf<CommandProps, 'onOpenChange'>) => true,\n 'input-value-change': (_details: PayloadOf<CommandProps, 'onInputValueChange'>) => true,\n 'select': (_details: PayloadOf<CommandProps, 'onSelect'>) => true,\n 'update:open': (_open: PayloadOf<CommandProps, 'onOpenChange'>['open']) => true,\n 'update:inputValue': (_inputValue: PayloadOf<CommandProps, 'onInputValueChange'>['inputValue']) => true,\n },\n slots: Object as SlotsType<{\n default?: (props: CommandRootSlotProps) => VNode[]\n /** 铺开时的触发按钮内容;未提供时不渲染触发器(面板改由快捷键或 v-model:open 唤起)。 */\n trigger?: () => VNode[]\n item?: (node: CommandNodeMeta) => VNode[]\n empty?: () => VNode[]\n footer?: () => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notifyOpen: CommandProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const notifyInputValue: CommandProps['onInputValueChange'] = (details) => {\n emit('input-value-change', details)\n emit('update:inputValue', details.inputValue)\n }\n const notifySelect: CommandProps['onSelect'] = details => emit('select', details)\n\n const ctx = useCommand(withXhConfig('command', props) as CommandProps, {\n onOpenChange: notifyOpen,\n onInputValueChange: notifyInputValue,\n onSelect: notifySelect,\n })\n provideCommand(ctx)\n\n // 铺开的是整份清单,不是过滤后那几条:此刻该不该露面由 connect 打在条目上的 hidden 说了算。\n // 只渲染命中的那几条会让「铺开」与「手写部件」产出两棵不同的 DOM\n const fullTree = computed(() => resolveCommandGroups(\n props.collection ?? [],\n props.groups ?? [],\n '',\n { filter: false, caseSensitive: false },\n ))\n\n return () => {\n const api = ctx.api.value\n if (slots.default) {\n return slots.default({\n open: api.open,\n inputValue: api.inputValue,\n groups: api.groups,\n results: api.results,\n highlightedValue: api.highlightedValue,\n empty: api.empty,\n setOpen: api.setOpen,\n setInputValue: api.setInputValue,\n select: api.select,\n })\n }\n return renderDefaultTree(\n fullTree.value,\n slots.trigger,\n slots.item,\n slots.empty?.() ?? (props.empty != null ? [props.empty] : null),\n slots.footer?.(),\n )\n }\n },\n})\n\nexport const XhCommandTrigger = defineComponent({\n name: 'XhCommandTrigger',\n // 直通属性自己合:Vue 默认把作者的处理器排在部件的后面,这里改成作者先跑\n inheritAttrs: false,\n props: {\n /** 借用作者的子节点作为触发器,不再渲染自己的包裹元素;子节点须恰好一个。 */\n asChild: Boolean,\n },\n setup(props, { slots, attrs }) {\n const ctx = useCommandContext()\n return () => {\n const part = mergePartProps(ctx.api.value.getTriggerProps() as Record<string, unknown>, attrs)\n const children = slots.default?.()\n // asChild:把触发器属性合到作者的节点上,不再自己渲染包裹元素\n if (props.asChild) {\n const merged = mergeIntoChild(children, part, 'command')\n if (merged)\n return merged\n }\n return h('button', part, children)\n }\n },\n})\n\nexport const XhCommandContent = defineComponent({\n name: 'XhCommandContent',\n props: {\n /** 本实例的 Portal 容器;优先于应用级配置。 */\n container: { type: Object as PropType<Element> },\n },\n // 根是 Teleport,Vue 不会把直通属性合上去,作者写的 class 与 style 得自己接住落到 content 上\n inheritAttrs: false,\n setup(props, { slots, attrs }) {\n const ctx = useCommandContext()\n // 结果列表的自绘条:与 list 同级、绝对定位不占布局,壳是面板自己(content 已经 relative);\n // 模态浮层里的条子走 4px 档\n const bars = useScrollbars({ scrollable: () => ctx.listRef.value, props: { size: 'sm' } })\n return () => {\n if (!ctx.rendered.value)\n return null\n const api = ctx.api.value\n const backdrop = api.getBackdropProps() as Record<string, unknown>\n // 搬到 portal 落点:留在原地的话,宿主祖先只要建了层叠上下文就能盖住浮层\n return h(XhPortal, { to: props.container ?? ctx.portalTarget.value }, () => [\n !backdrop.hidden\n ? h('div', {\n ...backdrop,\n ref: (el: unknown) => { ctx.backdropRef.value = el as HTMLElement },\n })\n : null,\n h('div', api.getPositionerProps() as Record<string, unknown>, [\n h('div', {\n ...mergeProps(api.getContentProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { ctx.contentRef.value = el as HTMLElement },\n }, [...(slots.default?.() ?? []), ...bars.render()]),\n ]),\n ])\n }\n },\n})\n\nexport const XhCommandInput = defineComponent({\n name: 'XhCommandInput',\n setup() {\n const ctx = useCommandContext()\n return () => h('input', {\n ...ctx.api.value.getInputProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.inputRef.value = el as HTMLInputElement },\n })\n },\n})\n\nexport const XhCommandList = defineComponent({\n name: 'XhCommandList',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n return () => h('div', {\n ...ctx.api.value.getListProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.listRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhCommandGroup = defineComponent({\n name: 'XhCommandGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useCommandContext()\n const group = computed<CommandGroupProps>(() => ({ value: props.value }))\n provideCommandItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandGroupLabel = defineComponent({\n name: 'XhCommandGroupLabel',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { group } = useCommandItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandItem = defineComponent({\n name: 'XhCommandItem',\n props: {\n value: { type: String, required: true },\n // 缺省交给 connect 回清单里查,写死 false 会盖掉数据里的禁用\n disabled: { type: Boolean, default: undefined },\n },\n setup(props, { slots }) {\n const ctx = useCommandContext()\n const item = computed<CommandItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideCommandItem({ item })\n return () => h('div', ctx.api.value.getItemProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandItemText = defineComponent({\n name: 'XhCommandItemText',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandEmpty = defineComponent({\n name: 'XhCommandEmpty',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n // 放在 content 里作 list 的兄弟节点,不进 role=listbox\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandLoading = defineComponent({\n name: 'XhCommandLoading',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandFooter = defineComponent({\n name: 'XhCommandFooter',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n return () => h('footer', ctx.api.value.getFooterProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按清单铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n */\nfunction renderDefaultTree(\n tree: readonly CommandGroupMeta[],\n triggerSlot: (() => VNode[]) | undefined,\n itemSlot: ((node: CommandNodeMeta) => VNode[]) | undefined,\n empty: (VNode | string)[] | null,\n footer: VNode[] | undefined,\n): VNode[] {\n const renderItem = (node: CommandNodeMeta): VNode =>\n h(XhCommandItem, { key: node.value, value: node.value }, () => [\n h(XhCommandItemText, null, () => itemSlot?.(node) ?? node.label),\n ])\n\n return [\n ...(triggerSlot ? [h(XhCommandTrigger, null, triggerSlot)] : []),\n h(XhCommandContent, null, () => [\n h(XhCommandInput),\n h(XhCommandList, null, () => tree.map(group =>\n // 没归组的那批直接铺条目,不套分组外壳——空标题的分组只会在列表里留一道白\n group.value === COMMAND_UNGROUPED\n ? group.items.map(renderItem)\n : h(XhCommandGroup, { key: group.value, value: group.value }, () => [\n h(XhCommandGroupLabel, null, () => group.label),\n ...group.items.map(renderItem),\n ]),\n )),\n // 空态与在途占位都是 list 的兄弟,不进 role=listbox\n h(XhCommandEmpty, null, () => empty ?? []),\n h(XhCommandLoading),\n ...(footer ? [h(XhCommandFooter, null, () => footer)] : []),\n ]),\n ]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"command.js","names":[],"sources":["../../../src/components/command/command.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-Present XiHanFun and contributors.\n * Licensed under the MIT License. See LICENSE in the project root for license information.\n */\n\n// 提供 command 相关实现。\n\nimport type { Direction, OverlayBackdropVariant, Size } from '@xihan-ui/core'\nimport type { CommandApi, CommandGroup, CommandGroupMeta, CommandGroupProps, CommandItemProps, CommandNode, CommandNodeMeta, CommandSchema } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { COMMAND_UNGROUPED, resolveCommandGroups } from '@xihan-ui/headless'\nimport { computed, defineComponent, h, mergeProps } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { mergeIntoChild } from '../../runtime/as-child'\nimport { mergePartProps } from '../../runtime/merge-props'\nimport { XhPortal } from '../../runtime/portal'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport {\n provideCommand,\n provideCommandItem,\n provideCommandItemGroup,\n useCommandContext,\n useCommandItemContext,\n useCommandItemGroupContext,\n} from './context'\nimport { useCommand } from './use-command'\n\ntype CommandProps = CommandSchema['props']\n\n/** 默认插槽的载荷:开合、检索串、结果与锚点,以及修改它们的命令。 */\nexport type CommandRootSlotProps = Pick<\n CommandApi,\n 'open' | 'inputValue' | 'groups' | 'results' | 'highlightedValue' | 'empty' | 'setOpen' | 'setInputValue' | 'select'\n>\n\nexport const XhCommandRoot = defineComponent({\n name: 'XhCommandRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<CommandNode[]> },\n groups: { type: Array as PropType<CommandGroup[]> },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n inputValue: { type: String },\n defaultInputValue: { type: String },\n /** 内置过滤,默认开启;关闭后由调用方自行筛选 */\n filter: { type: Boolean, default: undefined },\n caseSensitive: Boolean,\n closeOnSelect: { type: Boolean, default: undefined },\n modal: { type: Boolean, default: true },\n closeOnEscape: { type: Boolean, default: true },\n closeOnInteractOutside: { type: Boolean, default: undefined },\n restoreFocus: { type: Boolean, default: true },\n loop: { type: Boolean, default: undefined },\n loading: Boolean,\n placeholder: { type: String },\n /** 无匹配时的提示语。提供后不必再写 empty 部件;需要放置其他内容时改用 empty 插槽。 */\n empty: { type: String },\n /** 文字方向;浮层迁移到落点后无法继承作者子树上的方向,需要 RTL 时显式提供。 */\n dir: { type: String as PropType<Direction> },\n size: { type: String as PropType<Size> },\n variant: { type: String as PropType<OverlayBackdropVariant> },\n translations: { type: Object as PropType<CommandProps['translations']> },\n },\n // *-change 携带 details 对象,update:* 携带裸值\n emits: {\n 'open-change': (_details: PayloadOf<CommandProps, 'onOpenChange'>) => true,\n 'input-value-change': (_details: PayloadOf<CommandProps, 'onInputValueChange'>) => true,\n 'select': (_details: PayloadOf<CommandProps, 'onSelect'>) => true,\n 'update:open': (_open: PayloadOf<CommandProps, 'onOpenChange'>['open']) => true,\n 'update:inputValue': (_inputValue: PayloadOf<CommandProps, 'onInputValueChange'>['inputValue']) => true,\n },\n slots: Object as SlotsType<{\n 'default'?: (props: CommandRootSlotProps) => VNode[]\n /** 铺开时的触发按钮内容;未提供时不渲染触发器(面板改由快捷键或 v-model:open 唤起)。 */\n 'trigger'?: () => VNode[]\n /** 只填条目的文字槽,副文本与首尾两格照旧各归各的 */\n 'item'?: (node: CommandNodeMeta) => VNode[]\n /** 只接管行首那一格,其余槽照旧由数据铺 */\n 'item-prefix'?: (node: CommandNodeMeta) => VNode[]\n /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */\n 'item-suffix'?: (node: CommandNodeMeta) => VNode[]\n 'empty'?: () => VNode[]\n 'footer'?: () => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notifyOpen: CommandProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const notifyInputValue: CommandProps['onInputValueChange'] = (details) => {\n emit('input-value-change', details)\n emit('update:inputValue', details.inputValue)\n }\n const notifySelect: CommandProps['onSelect'] = details => emit('select', details)\n\n const ctx = useCommand(withXhConfig('command', props) as CommandProps, {\n onOpenChange: notifyOpen,\n onInputValueChange: notifyInputValue,\n onSelect: notifySelect,\n })\n provideCommand(ctx)\n\n // 铺开的是整份清单,不是过滤后那几条:此刻该不该露面由 connect 打在条目上的 hidden 说了算。\n // 只渲染命中的那几条会让「铺开」与「手写部件」产出两棵不同的 DOM\n const fullTree = computed(() => resolveCommandGroups(\n props.collection ?? [],\n props.groups ?? [],\n '',\n { filter: false, caseSensitive: false },\n ))\n\n return () => {\n const api = ctx.api.value\n if (slots.default) {\n return slots.default({\n open: api.open,\n inputValue: api.inputValue,\n groups: api.groups,\n results: api.results,\n highlightedValue: api.highlightedValue,\n empty: api.empty,\n setOpen: api.setOpen,\n setInputValue: api.setInputValue,\n select: api.select,\n })\n }\n return renderDefaultTree(\n fullTree.value,\n slots.trigger,\n slots.item,\n slots.empty?.() ?? (props.empty != null ? [props.empty] : null),\n slots.footer?.(),\n slots['item-prefix'],\n slots['item-suffix'],\n )\n }\n },\n})\n\nexport const XhCommandTrigger = defineComponent({\n name: 'XhCommandTrigger',\n // 直通属性自己合:Vue 默认把作者的处理器排在部件的后面,这里改成作者先跑\n inheritAttrs: false,\n props: {\n /** 借用作者的子节点作为触发器,不再渲染自己的包裹元素;子节点须恰好一个。 */\n asChild: Boolean,\n },\n setup(props, { slots, attrs }) {\n const ctx = useCommandContext()\n return () => {\n const part = mergePartProps(ctx.api.value.getTriggerProps() as Record<string, unknown>, attrs)\n const children = slots.default?.()\n // asChild:把触发器属性合到作者的节点上,不再自己渲染包裹元素\n if (props.asChild) {\n const merged = mergeIntoChild(children, part, 'command')\n if (merged)\n return merged\n }\n return h('button', part, children)\n }\n },\n})\n\nexport const XhCommandContent = defineComponent({\n name: 'XhCommandContent',\n props: {\n /** 本实例的 Portal 容器;优先于应用级配置。 */\n container: { type: Object as PropType<Element> },\n },\n // 根是 Teleport,Vue 不会把直通属性合上去,作者写的 class 与 style 得自己接住落到 content 上\n inheritAttrs: false,\n setup(props, { slots, attrs }) {\n const ctx = useCommandContext()\n // 结果列表的自绘条:与 list 同级、绝对定位不占布局,壳是面板自己(content 已经 relative);\n // 模态浮层里的条子走 4px 档\n const bars = useScrollbars({ scrollable: () => ctx.listRef.value, props: { size: 'sm' } })\n return () => {\n if (!ctx.rendered.value)\n return null\n const api = ctx.api.value\n const backdrop = api.getBackdropProps() as Record<string, unknown>\n // 搬到 portal 落点:留在原地的话,宿主祖先只要建了层叠上下文就能盖住浮层\n return h(XhPortal, { to: props.container ?? ctx.portalTarget.value }, () => [\n !backdrop.hidden\n ? h('div', {\n ...backdrop,\n ref: (el: unknown) => { ctx.backdropRef.value = el as HTMLElement },\n })\n : null,\n h('div', api.getPositionerProps() as Record<string, unknown>, [\n h('div', {\n ...mergeProps(api.getContentProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { ctx.contentRef.value = el as HTMLElement },\n }, [...(slots.default?.() ?? []), ...bars.render()]),\n ]),\n ])\n }\n },\n})\n\nexport const XhCommandInput = defineComponent({\n name: 'XhCommandInput',\n setup() {\n const ctx = useCommandContext()\n return () => h('input', {\n ...ctx.api.value.getInputProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.inputRef.value = el as HTMLInputElement },\n })\n },\n})\n\nexport const XhCommandList = defineComponent({\n name: 'XhCommandList',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n return () => h('div', {\n ...ctx.api.value.getListProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.listRef.value = el as HTMLElement },\n }, slots.default?.())\n },\n})\n\nexport const XhCommandGroup = defineComponent({\n name: 'XhCommandGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useCommandContext()\n const group = computed<CommandGroupProps>(() => ({ value: props.value }))\n provideCommandItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandGroupLabel = defineComponent({\n name: 'XhCommandGroupLabel',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { group } = useCommandItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandItem = defineComponent({\n name: 'XhCommandItem',\n props: {\n value: { type: String, required: true },\n // 缺省交给 connect 回清单里查,写死 false 会盖掉数据里的禁用\n disabled: { type: Boolean, default: undefined },\n },\n setup(props, { slots }) {\n const ctx = useCommandContext()\n const item = computed<CommandItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideCommandItem({ item })\n return () => h('div', ctx.api.value.getItemProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandItemText = defineComponent({\n name: 'XhCommandItemText',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */\nexport const XhCommandItemPrefix = defineComponent({\n name: 'XhCommandItemPrefix',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemPrefixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行尾的作者内容(计数、徽标) */\nexport const XhCommandItemSuffix = defineComponent({\n name: 'XhCommandItemSuffix',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemSuffixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */\nexport const XhCommandItemDescription = defineComponent({\n name: 'XhCommandItemDescription',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemDescriptionProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 命令行尾的快捷键提示,与说明同档同色;纯装饰 */\nexport const XhCommandItemShortcut = defineComponent({\n name: 'XhCommandItemShortcut',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n const { item } = useCommandItemContext()\n return () => h('span', ctx.api.value.getItemShortcutProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandEmpty = defineComponent({\n name: 'XhCommandEmpty',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n // 放在 content 里作 list 的兄弟节点,不进 role=listbox\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandLoading = defineComponent({\n name: 'XhCommandLoading',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhCommandFooter = defineComponent({\n name: 'XhCommandFooter',\n setup(_, { slots }) {\n const ctx = useCommandContext()\n return () => h('footer', ctx.api.value.getFooterProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按清单铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n */\nfunction renderDefaultTree(\n tree: readonly CommandGroupMeta[],\n triggerSlot: (() => VNode[]) | undefined,\n itemSlot: ((node: CommandNodeMeta) => VNode[]) | undefined,\n empty: (VNode | string)[] | null,\n footer: VNode[] | undefined,\n prefixSlot?: (node: CommandNodeMeta) => VNode[],\n suffixSlot?: (node: CommandNodeMeta) => VNode[],\n): VNode[] {\n const renderItem = (node: CommandNodeMeta): VNode =>\n h(XhCommandItem, { key: node.value, value: node.value }, () => [\n ...(prefixSlot ? [h(XhCommandItemPrefix, null, () => prefixSlot(node))] : []),\n h(XhCommandItemText, null, () => itemSlot?.(node) ?? node.label),\n ...(node.description != null ? [h(XhCommandItemDescription, null, () => node.description)] : []),\n ...(node.shortcut != null ? [h(XhCommandItemShortcut, null, () => node.shortcut)] : []),\n ...(suffixSlot ? [h(XhCommandItemSuffix, null, () => suffixSlot(node))] : []),\n ])\n\n return [\n ...(triggerSlot ? [h(XhCommandTrigger, null, triggerSlot)] : []),\n h(XhCommandContent, null, () => [\n h(XhCommandInput),\n h(XhCommandList, null, () => tree.map(group =>\n // 没归组的那批直接铺条目,不套分组外壳——空标题的分组只会在列表里留一道白\n group.value === COMMAND_UNGROUPED\n ? group.items.map(renderItem)\n : h(XhCommandGroup, { key: group.value, value: group.value }, () => [\n h(XhCommandGroupLabel, null, () => group.label),\n ...group.items.map(renderItem),\n ]),\n )),\n // 空态与在途占位都是 list 的兄弟,不进 role=listbox\n h(XhCommandEmpty, null, () => empty ?? []),\n h(XhCommandLoading),\n ...(footer ? [h(XhCommandFooter, null, () => footer)] : []),\n ]),\n ]\n}\n"],"mappings":"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"}
|
|
@@ -102,7 +102,12 @@ declare const XhContextMenuRoot: import("vue").DefineComponent<import("vue").Ext
|
|
|
102
102
|
}, SlotsType<{
|
|
103
103
|
default?: (props: ContextMenuRootSlotProps) => VNode[];
|
|
104
104
|
trigger?: () => VNode[];
|
|
105
|
+
/** 只填条目的文字槽,标记位、副文本与快捷键照旧由数据铺 */
|
|
105
106
|
item?: (node: ContextMenuNodeMeta) => VNode[];
|
|
107
|
+
/** 只接管行首那一格,其余槽照旧由数据铺 */
|
|
108
|
+
'item-prefix'?: (node: ContextMenuNodeMeta) => VNode[];
|
|
109
|
+
/** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */
|
|
110
|
+
'item-suffix'?: (node: ContextMenuNodeMeta) => VNode[];
|
|
106
111
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
107
112
|
declare const XhContextMenuTrigger: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
108
113
|
/** 借用作者的子节点作为触发器,不再渲染自己的包裹元素;子节点须恰好一个。 */
|
|
@@ -281,6 +286,14 @@ declare const XhContextMenuItemIndicator: import("vue").DefineComponent<{}, () =
|
|
|
281
286
|
declare const XhContextMenuItemDescription: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
282
287
|
[key: string]: any;
|
|
283
288
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
289
|
+
/** 条目中的快捷键提示,贴行尾;纯装饰,读屏从条目文字取意 */
|
|
290
|
+
declare const XhContextMenuItemShortcut: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
291
|
+
[key: string]: any;
|
|
292
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
293
|
+
/** 条目行尾的作者内容(计数、徽标、次级图标);家族只管落位,不规定字号与颜色 */
|
|
294
|
+
declare const XhContextMenuItemSuffix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
295
|
+
[key: string]: any;
|
|
296
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
284
297
|
declare const XhContextMenuSeparator: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
285
298
|
[key: string]: any;
|
|
286
299
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -288,5 +301,5 @@ declare const XhContextMenuArrow: import("vue").DefineComponent<{}, () => VNode<
|
|
|
288
301
|
[key: string]: any;
|
|
289
302
|
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
290
303
|
//#endregion
|
|
291
|
-
export { ContextMenuRootSlotProps, ContextMenuSubSlotProps, XhContextMenuArrow, XhContextMenuContent, XhContextMenuGroup, XhContextMenuGroupLabel, XhContextMenuItem, XhContextMenuItemDescription, XhContextMenuItemIndicator, XhContextMenuItemText, XhContextMenuPositioner, XhContextMenuRoot, XhContextMenuSeparator, XhContextMenuSub, XhContextMenuSubTrigger, XhContextMenuTrigger };
|
|
304
|
+
export { ContextMenuRootSlotProps, ContextMenuSubSlotProps, XhContextMenuArrow, XhContextMenuContent, XhContextMenuGroup, XhContextMenuGroupLabel, XhContextMenuItem, XhContextMenuItemDescription, XhContextMenuItemIndicator, XhContextMenuItemShortcut, XhContextMenuItemSuffix, XhContextMenuItemText, XhContextMenuPositioner, XhContextMenuRoot, XhContextMenuSeparator, XhContextMenuSub, XhContextMenuSubTrigger, XhContextMenuTrigger };
|
|
292
305
|
//# sourceMappingURL=context-menu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-menu.d.ts","names":[],"sources":["../../../src/components/context-menu/context-menu.ts"],"mappings":";;;;;KAgCK,mBAAmB;;KAGZ,2BAA2B,KAAK;;KAGhC,0BAA0B,KAAK;
|
|
1
|
+
{"version":3,"file":"context-menu.d.ts","names":[],"sources":["../../../src/components/context-menu/context-menu.ts"],"mappings":";;;;;KAgCK,mBAAmB;;KAGZ,2BAA2B,KAAK;;KAGhC,0BAA0B,KAAK;cAY9B,iCAAiB,8BAAA;;IAIG,MAAA,SAAS;;;;;;;;IAGT,MAAA,SAAS;;;;;;;;;;;;;;IAIN,MAAA,SAAS;;;IAClB,MAAA,SAAS;;;;;;IAER,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;EAIP,gBAAA,UAAA,UAAU;EACf,SAAA,UAAA,UAAU;EACR,gBAAA,OAAA,UAAU;;;IAjBJ,MAAA,SAAS;;;;;;;;IAGT,MAAA,SAAS;;;;;;;;;;;;;;IAIN,MAAA,SAAS;;;IAClB,MAAA,SAAS;;;;;;IAER,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;;EASrB,WAAC,OAAO,6BAA6B;EACrC,gBAAM;;EAET,QAAC,MAAM,wBAAwB;;EAExB,iBAAC,MAAM,wBAAwB;;EAE/B,iBAAC,MAAM,wBAAwB;kCAqCjD;cAEW,oCAAoB,8BAAA;;;;;;;;;;qCA0B/B;cAEW,uCAAuB,8BAAA;;;IAIH,MAAA,SAAS;;;;;;;IAAT,MAAA,SAAS;;MAiBxC,oDAAA;cAEW,oCAAoB,0BAAA,oBAAA,4BAAA;;8BAY/B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,kCAAkB,8BAAA;;;;;;;;;;;;MAW7B,oDAAA;cAEW,uCAAuB,0BAAA,oBAAA,4BAAA;;8BAOlC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,iCAAiB,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAqC5B;;;;;;cAOW,gCAAgB,8BAAA;;;;;;;;;;;IAMI,MAAA,SAAS;;;;;;;;;;;;;;;;;;IAMf,MAAA,SAAS;;;;IAER,MAAA,SAAS;;;;IAET,MAAA,SAAS;;;;;;;;;;;;;;;;;;IAVJ,MAAA,SAAS;;;;;;;;;;;;;;;;;;IAMf,MAAA,SAAS;;;;IAER,MAAA,SAAS;;;;IAET,MAAA,SAAS;;;;;;;;;;EAIvB,WAAC,OAAO,4BAA4B;kCAyBhD;cAEW,uCAAuB,0BAAA,oBAAA,4BAAA;;8BAiBlC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,qCAAqB,0BAAA,oBAAA,4BAAA;;8BAOhC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,0CAA0B,0BAAA,oBAAA,4BAAA;;8BAOrC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,4CAA4B,0BAAA,oBAAA,4BAAA;;8BAOvC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,yCAAyB,0BAAA,oBAAA,4BAAA;;8BAOpC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,uCAAuB,0BAAA,oBAAA,4BAAA;;8BAOlC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,sCAAsB,0BAAA,oBAAA,4BAAA;;8BAMjC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,kCAAkB,0BAAA,oBAAA,4BAAA;;8BAM7B,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
|
|
@@ -64,7 +64,11 @@ const XhContextMenuRoot = defineComponent({
|
|
|
64
64
|
point: ctx.api.value.point,
|
|
65
65
|
setOpen: ctx.api.value.setOpen,
|
|
66
66
|
openAt: ctx.api.value.openAt
|
|
67
|
-
}) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.trigger?.() ?? null,
|
|
67
|
+
}) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.trigger?.() ?? null, {
|
|
68
|
+
"item": slots.item,
|
|
69
|
+
"item-prefix": slots["item-prefix"],
|
|
70
|
+
"item-suffix": slots["item-suffix"]
|
|
71
|
+
}) : []);
|
|
68
72
|
}
|
|
69
73
|
});
|
|
70
74
|
const XhContextMenuTrigger = defineComponent({
|
|
@@ -293,6 +297,24 @@ const XhContextMenuItemDescription = defineComponent({
|
|
|
293
297
|
return () => h("span", ctx.api.value.getItemDescriptionProps(item.value), slots.default?.());
|
|
294
298
|
}
|
|
295
299
|
});
|
|
300
|
+
/** 条目中的快捷键提示,贴行尾;纯装饰,读屏从条目文字取意 */
|
|
301
|
+
const XhContextMenuItemShortcut = defineComponent({
|
|
302
|
+
name: "XhContextMenuItemShortcut",
|
|
303
|
+
setup(_, { slots }) {
|
|
304
|
+
const ctx = useContextMenuContext();
|
|
305
|
+
const { item } = useContextMenuItemContext();
|
|
306
|
+
return () => h("span", ctx.api.value.getItemShortcutProps(item.value), slots.default?.());
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
/** 条目行尾的作者内容(计数、徽标、次级图标);家族只管落位,不规定字号与颜色 */
|
|
310
|
+
const XhContextMenuItemSuffix = defineComponent({
|
|
311
|
+
name: "XhContextMenuItemSuffix",
|
|
312
|
+
setup(_, { slots }) {
|
|
313
|
+
const ctx = useContextMenuContext();
|
|
314
|
+
const { item } = useContextMenuItemContext();
|
|
315
|
+
return () => h("span", ctx.api.value.getItemSuffixProps(item.value), slots.default?.());
|
|
316
|
+
}
|
|
317
|
+
});
|
|
296
318
|
const XhContextMenuSeparator = defineComponent({
|
|
297
319
|
name: "XhContextMenuSeparator",
|
|
298
320
|
setup() {
|
|
@@ -313,34 +335,42 @@ const XhContextMenuArrow = defineComponent({
|
|
|
313
335
|
* 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。
|
|
314
336
|
* 触发区中放置的内容由作者决定,经 trigger 插槽给出。
|
|
315
337
|
*/
|
|
316
|
-
function renderDefaultTree(collection, trigger,
|
|
317
|
-
return [h(XhContextMenuTrigger, null, () => trigger ?? []), h(XhContextMenuPositioner, null, () => [h(XhContextMenuContent, null, () => renderNodes(collection,
|
|
338
|
+
function renderDefaultTree(collection, trigger, itemSlots) {
|
|
339
|
+
return [h(XhContextMenuTrigger, null, () => trigger ?? []), h(XhContextMenuPositioner, null, () => [h(XhContextMenuContent, null, () => renderNodes(collection, itemSlots))])];
|
|
318
340
|
}
|
|
319
341
|
/** content 的内容:分组段铺为 group,段首的分隔线落在 group 外面。 */
|
|
320
|
-
function renderNodes(collection,
|
|
342
|
+
function renderNodes(collection, itemSlots) {
|
|
321
343
|
return groupAdjacentRuns(collection, (node) => node.group).flatMap((run, runIndex) => {
|
|
322
344
|
const head = run[0];
|
|
323
345
|
const lead = runIndex > 0 && head.separatorBefore ? [h(XhContextMenuSeparator, { key: `separator:${head.value}` })] : [];
|
|
324
|
-
if (head.group == null) return [...lead, renderItem(head,
|
|
346
|
+
if (head.group == null) return [...lead, renderItem(head, itemSlots)];
|
|
325
347
|
const groupLabel = run.find((node) => node.groupLabel != null)?.groupLabel ?? null;
|
|
326
348
|
return [...lead, h(XhContextMenuGroup, {
|
|
327
349
|
key: `group:${head.group}`,
|
|
328
350
|
value: head.group
|
|
329
|
-
}, () => [...groupLabel != null ? [h(XhContextMenuGroupLabel, null, () => groupLabel)] : [], ...run.flatMap((node, index) => [...index > 0 && node.separatorBefore ? [h(XhContextMenuSeparator, { key: `separator:${node.value}` })] : [], renderItem(node,
|
|
351
|
+
}, () => [...groupLabel != null ? [h(XhContextMenuGroupLabel, null, () => groupLabel)] : [], ...run.flatMap((node, index) => [...index > 0 && node.separatorBefore ? [h(XhContextMenuSeparator, { key: `separator:${node.value}` })] : [], renderItem(node, itemSlots)])])];
|
|
330
352
|
});
|
|
331
353
|
}
|
|
332
|
-
/**
|
|
333
|
-
|
|
354
|
+
/**
|
|
355
|
+
* 单个条目:标记位排在文字前面,未提供标记位时不铺该部件。
|
|
356
|
+
* `item-prefix` / `item-suffix` 插槽各接管首尾一格,其余槽照旧由数据铺;
|
|
357
|
+
* 行首那一格与数据里的 `indicator` 同一个部件,插槽在场时以它为准。
|
|
358
|
+
*/
|
|
359
|
+
function renderItem(meta, itemSlots) {
|
|
360
|
+
const prefix = itemSlots["item-prefix"];
|
|
361
|
+
const suffix = itemSlots["item-suffix"];
|
|
334
362
|
return h(XhContextMenuItem, {
|
|
335
363
|
key: meta.value,
|
|
336
364
|
value: meta.value
|
|
337
365
|
}, () => [
|
|
338
|
-
...meta.indicator != null ? [h(XhContextMenuItemIndicator, null, () => meta.indicator)] : [],
|
|
339
|
-
h(XhContextMenuItemText, null, () =>
|
|
340
|
-
...meta.description != null ? [h(XhContextMenuItemDescription, null, () => meta.description)] : []
|
|
366
|
+
...prefix ? [h(XhContextMenuItemIndicator, null, () => prefix(meta))] : meta.indicator != null ? [h(XhContextMenuItemIndicator, null, () => meta.indicator)] : [],
|
|
367
|
+
h(XhContextMenuItemText, null, () => itemSlots.item?.(meta) ?? meta.label),
|
|
368
|
+
...meta.description != null ? [h(XhContextMenuItemDescription, null, () => meta.description)] : [],
|
|
369
|
+
...meta.shortcut != null ? [h(XhContextMenuItemShortcut, null, () => meta.shortcut)] : [],
|
|
370
|
+
...suffix ? [h(XhContextMenuItemSuffix, null, () => suffix(meta))] : []
|
|
341
371
|
]);
|
|
342
372
|
}
|
|
343
373
|
//#endregion
|
|
344
|
-
export { XhContextMenuArrow, XhContextMenuContent, XhContextMenuGroup, XhContextMenuGroupLabel, XhContextMenuItem, XhContextMenuItemDescription, XhContextMenuItemIndicator, XhContextMenuItemText, XhContextMenuPositioner, XhContextMenuRoot, XhContextMenuSeparator, XhContextMenuSub, XhContextMenuSubTrigger, XhContextMenuTrigger };
|
|
374
|
+
export { XhContextMenuArrow, XhContextMenuContent, XhContextMenuGroup, XhContextMenuGroupLabel, XhContextMenuItem, XhContextMenuItemDescription, XhContextMenuItemIndicator, XhContextMenuItemShortcut, XhContextMenuItemSuffix, XhContextMenuItemText, XhContextMenuPositioner, XhContextMenuRoot, XhContextMenuSeparator, XhContextMenuSub, XhContextMenuSubTrigger, XhContextMenuTrigger };
|
|
345
375
|
|
|
346
376
|
//# sourceMappingURL=context-menu.js.map
|