@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.
Files changed (91) hide show
  1. package/CHANGELOG.md +258 -0
  2. package/dist/components/avatar-group/avatar-group.d.ts.map +1 -1
  3. package/dist/components/avatar-group/avatar-group.js +2 -1
  4. package/dist/components/avatar-group/avatar-group.js.map +1 -1
  5. package/dist/components/card/card.d.ts.map +1 -1
  6. package/dist/components/card/card.js +2 -1
  7. package/dist/components/card/card.js.map +1 -1
  8. package/dist/components/cascader/cascader.d.ts +9 -1
  9. package/dist/components/cascader/cascader.d.ts.map +1 -1
  10. package/dist/components/cascader/cascader.js +19 -1
  11. package/dist/components/cascader/cascader.js.map +1 -1
  12. package/dist/components/combobox/combobox.d.ts +18 -1
  13. package/dist/components/combobox/combobox.d.ts.map +1 -1
  14. package/dist/components/combobox/combobox.js +37 -4
  15. package/dist/components/combobox/combobox.js.map +1 -1
  16. package/dist/components/command/command.d.ts +23 -2
  17. package/dist/components/command/command.d.ts.map +1 -1
  18. package/dist/components/command/command.js +46 -4
  19. package/dist/components/command/command.js.map +1 -1
  20. package/dist/components/context-menu/context-menu.d.ts +14 -1
  21. package/dist/components/context-menu/context-menu.d.ts.map +1 -1
  22. package/dist/components/context-menu/context-menu.js +42 -12
  23. package/dist/components/context-menu/context-menu.js.map +1 -1
  24. package/dist/components/input-group/input-group.d.ts.map +1 -1
  25. package/dist/components/input-group/input-group.js +2 -1
  26. package/dist/components/input-group/input-group.js.map +1 -1
  27. package/dist/components/json-viewer/json-viewer.js.map +1 -1
  28. package/dist/components/kbd/kbd.d.ts.map +1 -1
  29. package/dist/components/kbd/kbd.js +27 -10
  30. package/dist/components/kbd/kbd.js.map +1 -1
  31. package/dist/components/listbox/listbox.d.ts +18 -1
  32. package/dist/components/listbox/listbox.d.ts.map +1 -1
  33. package/dist/components/listbox/listbox.js +37 -4
  34. package/dist/components/listbox/listbox.js.map +1 -1
  35. package/dist/components/mention/mention.d.ts +17 -1
  36. package/dist/components/mention/mention.d.ts.map +1 -1
  37. package/dist/components/mention/mention.js +36 -4
  38. package/dist/components/mention/mention.js.map +1 -1
  39. package/dist/components/menu/menu.d.ts +14 -1
  40. package/dist/components/menu/menu.d.ts.map +1 -1
  41. package/dist/components/menu/menu.js +63 -8
  42. package/dist/components/menu/menu.js.map +1 -1
  43. package/dist/components/menubar/menubar.d.ts +14 -2
  44. package/dist/components/menubar/menubar.d.ts.map +1 -1
  45. package/dist/components/menubar/menubar.js +43 -11
  46. package/dist/components/menubar/menubar.js.map +1 -1
  47. package/dist/components/page-header/page-header.d.ts.map +1 -1
  48. package/dist/components/page-header/page-header.js +2 -1
  49. package/dist/components/page-header/page-header.js.map +1 -1
  50. package/dist/components/pagination/pagination.js.map +1 -1
  51. package/dist/components/reasoning/reasoning.d.ts +1 -1
  52. package/dist/components/select/select.d.ts +18 -1
  53. package/dist/components/select/select.d.ts.map +1 -1
  54. package/dist/components/select/select.js +37 -4
  55. package/dist/components/select/select.js.map +1 -1
  56. package/dist/components/sortable/sortable.d.ts +1 -1
  57. package/dist/components/statistic/statistic.d.ts.map +1 -1
  58. package/dist/components/statistic/statistic.js +2 -1
  59. package/dist/components/statistic/statistic.js.map +1 -1
  60. package/dist/components/table/table.d.ts +2 -2
  61. package/dist/components/table/table.d.ts.map +1 -1
  62. package/dist/components/tag-group/tag-group.js +1 -1
  63. package/dist/components/tag-group/tag-group.js.map +1 -1
  64. package/dist/components/timeline/timeline.d.ts.map +1 -1
  65. package/dist/components/timeline/timeline.js +2 -1
  66. package/dist/components/timeline/timeline.js.map +1 -1
  67. package/dist/components/timer/timer.d.ts +1 -1
  68. package/dist/components/tour/tour.d.ts +1 -1
  69. package/dist/components/transfer/transfer.d.ts +9 -1
  70. package/dist/components/transfer/transfer.d.ts.map +1 -1
  71. package/dist/components/transfer/transfer.js +19 -1
  72. package/dist/components/transfer/transfer.js.map +1 -1
  73. package/dist/components/tree/tree.d.ts +9 -7
  74. package/dist/components/tree/tree.d.ts.map +1 -1
  75. package/dist/components/tree/tree.js +17 -15
  76. package/dist/components/tree/tree.js.map +1 -1
  77. package/dist/components/tree-select/tree-select.d.ts +9 -1
  78. package/dist/components/tree-select/tree-select.d.ts.map +1 -1
  79. package/dist/components/tree-select/tree-select.js +19 -1
  80. package/dist/components/tree-select/tree-select.js.map +1 -1
  81. package/dist/components/typography/typography.d.ts.map +1 -1
  82. package/dist/components/typography/typography.js +2 -1
  83. package/dist/components/typography/typography.js.map +1 -1
  84. package/dist/index.d.ts +13 -13
  85. package/dist/index.js +13 -13
  86. package/dist/package.js +1 -1
  87. package/dist/runtime/use-machine.js +3 -2
  88. package/dist/runtime/use-machine.js.map +1 -1
  89. package/dist/runtime/use-scrollbars.js +3 -1
  90. package/dist/runtime/use-scrollbars.js.map +1 -1
  91. package/package.json +14 -14
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.js","names":["mergeVueProps","mergeProps"],"sources":["../../../src/components/context-menu/context-menu.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// 提供 context menu 相关实现。\n\nimport type { Direction, Placement, Size, Tone } from '@xihan-ui/core'\nimport type { ContextMenuApi, ContextMenuGroupProps, ContextMenuItemProps, ContextMenuNode, ContextMenuNodeMeta, ContextMenuSchema, MenuApi } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { groupAdjacentRuns, mergeProps } from '@xihan-ui/core'\nimport { computed, defineComponent, h, mergeProps as mergeVueProps, onBeforeUnmount, ref, watch } 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 { provideMenu, useMenuContext } from '../menu/context'\nimport { useMenuWithParent } from '../menu/use-menu'\nimport {\n provideContextMenu,\n provideContextMenuGroup,\n provideContextMenuItem,\n provideContextMenuSub,\n useContextMenuContext,\n useContextMenuGroupContext,\n useContextMenuItemContext,\n useContextMenuSubContext,\n} from './context'\nimport { useContextMenu } from './use-context-menu'\n\ntype ContextMenuProps = ContextMenuSchema['props']\n\n/** 默认插槽的载荷:右键菜单的展开态与锚点坐标,以及开合、按坐标展开的命令。 */\nexport type ContextMenuRootSlotProps = Pick<ContextMenuApi, 'open' | 'point' | 'setOpen' | 'openAt'>\n\n/** 子菜单默认插槽的载荷:该层子菜单自己的展开态与开合命令。 */\nexport type ContextMenuSubSlotProps = Pick<MenuApi, 'open' | 'setOpen'>\n\nexport const XhContextMenuRoot = defineComponent({\n name: 'XhContextMenuRoot',\n // 缺省值由 connect 与机器给出;普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ContextMenuNode[]> },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n loop: { type: Boolean, default: undefined },\n typeahead: { type: Boolean, default: undefined },\n translations: { type: Object as PropType<ContextMenuProps['translations']> },\n dir: { type: String as PropType<Direction> },\n longPressDelay: { type: Number },\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n },\n // open-change 携带 { open }、select 携带 { value },update:open 携带裸布尔\n emits: {\n 'open-change': (_details: PayloadOf<ContextMenuProps, 'onOpenChange'>) => true,\n 'select': (_details: PayloadOf<ContextMenuProps, 'onSelect'>) => true,\n 'update:open': (_open: PayloadOf<ContextMenuProps, 'onOpenChange'>['open']) => true,\n },\n slots: Object as SlotsType<{\n default?: (props: ContextMenuRootSlotProps) => VNode[]\n trigger?: () => VNode[]\n item?: (node: ContextMenuNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit, expose }) {\n const notifyOpen: ContextMenuProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const notifySelect: ContextMenuProps['onSelect'] = details => emit('select', details)\n const ctx = useContextMenu(withXhConfig('context-menu', props) as ContextMenuProps, notifyOpen, notifySelect)\n provideContextMenu(ctx)\n // 菜单钉在坐标上,坐标只能由 openAt 交进来。默认插槽那条路从载荷里拿,\n // 只交 collection 的那条路没有载荷,所以同一组命令也从实例上暴露一份。\n expose({\n openAt: (x: number, y: number) => ctx.api.value.openAt(x, y),\n setOpen: (open: boolean) => ctx.api.value.setOpen(open),\n get open() {\n return ctx.api.value.open\n },\n get point() {\n return ctx.api.value.point\n },\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 point: ctx.api.value.point,\n setOpen: ctx.api.value.setOpen,\n openAt: ctx.api.value.openAt,\n })\n : props.collection\n ? renderDefaultTree(ctx.api.value.collection, slots.trigger?.() ?? null, slots.item)\n : [],\n )\n },\n})\n\nexport const XhContextMenuTrigger = defineComponent({\n name: 'XhContextMenuTrigger',\n // 直通属性自己合:Vue 默认把作者的处理器排在部件的后面,这里改成作者先跑\n inheritAttrs: false,\n props: {\n /** 借用作者的子节点作为触发器,不再渲染自己的包裹元素;子节点须恰好一个。 */\n asChild: Boolean,\n },\n setup(props, { slots, attrs }) {\n const ctx = useContextMenuContext()\n // 触发区渲染为 div,语义由 connect 打上的 ARIA 属性给出\n return () => {\n const part = mergePartProps({\n ...ctx.api.value.getTriggerProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.triggerRef.value = el as HTMLElement },\n }, attrs)\n const children = slots.default?.()\n // asChild:把触发器属性合到作者的节点上,不再自己渲染包裹元素\n if (props.asChild) {\n const merged = mergeIntoChild(children, part, 'context-menu')\n if (merged)\n return merged\n }\n return h('div', part, children)\n }\n },\n})\n\nexport const XhContextMenuPositioner = defineComponent({\n name: 'XhContextMenuPositioner',\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 = useContextMenuContext()\n // 条目列表的自绘条:与 content 同级、绝对定位不占布局,壳是这层已经 fixed 的 positioner\n // 浮层里的条子走 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.triggerRef }, () => [\n h('div', {\n ...mergeVueProps(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 XhContextMenuContent = defineComponent({\n name: 'XhContextMenuContent',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\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 XhContextMenuGroup = defineComponent({\n name: 'XhContextMenuGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useContextMenuContext()\n const group = computed<ContextMenuGroupProps>(() => ({ value: props.value }))\n provideContextMenuGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuGroupLabel = defineComponent({\n name: 'XhContextMenuGroupLabel',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { group } = useContextMenuGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuItem = defineComponent({\n name: 'XhContextMenuItem',\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 = useContextMenuContext()\n const item = computed<ContextMenuItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideContextMenuItem({ item })\n // 本条目持有焦点时,value 变更按新值重报焦点条目,卸载时上报焦点丢失\n const itemEl = ref<HTMLElement | null>(null)\n watch(() => props.value, (next, prev) => {\n if (next === prev)\n return\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.FOCUS', value: next })\n })\n onBeforeUnmount(() => {\n const { service } = ctx\n // 根已停机时不再送事件\n if (service.getStatus() !== 'Started')\n return\n // 按「本节点当下正持有焦点」判定,不按 value 比对\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.LOST' })\n })\n return () => h(\n 'div',\n { ...ctx.api.value.getItemProps(item.value) as Record<string, unknown>, ref: itemEl },\n slots.default?.(),\n )\n },\n})\n\n/**\n * 右键菜单中的子菜单:子层运行一台 submenu 模式的 menu 状态机,触发条目由\n * XhContextMenuSubTrigger 渲染为父层条目与子层触发器的双重身份。\n * 子层内部使用 XhMenu 系部件(再往深嵌套即 menu 嵌套 menu)。本身不渲染节点。\n */\nexport const XhContextMenuSub = defineComponent({\n name: 'XhContextMenuSub',\n props: {\n /** 它在父右键菜单中的条目身份。 */\n value: { type: String, required: true },\n disabled: { type: Boolean, default: undefined },\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n loop: { type: Boolean, default: undefined },\n openOnHover: { type: Boolean, default: undefined },\n hoverOpenDelay: { type: Number },\n /** 文字方向;默认继承父层。子层被迁移到浮层落点,无法继承父层的方向。 */\n dir: { type: String as PropType<Direction> },\n /** 语气;默认继承父层。子层是浮层落点下的同级节点,CSS 私有槽无法继承。 */\n tone: { type: String as PropType<Tone> },\n /** 尺寸;默认继承父层,理由同 tone。 */\n size: { type: String as PropType<Size> },\n hoverCloseDelay: { type: Number },\n },\n slots: Object as SlotsType<{\n default?: (props: ContextMenuSubSlotProps) => VNode[]\n }>,\n setup(props, { slots }) {\n const parent = useContextMenuContext()\n const sub = useMenuWithParent(\n {\n ...props,\n submenu: true,\n dir: props.dir ?? parent.service.prop('dir'),\n tone: props.tone ?? parent.service.prop('tone'),\n size: props.size ?? parent.service.prop('size'),\n },\n undefined,\n parent.tree,\n )\n // 子树内的 XhMenu 系部件都归子机器\n provideMenu(sub)\n provideContextMenuSub({ parent, value: props.value, disabled: props.disabled })\n // 父层收起(Escape、外点、选中)时本层跟着收,层层传导\n watch(() => parent.api.value.open, (open) => {\n if (!open)\n sub.api.value.setOpen(false)\n })\n return () => slots.default?.({ open: sub.api.value.open, setOpen: sub.api.value.setOpen })\n },\n})\n\nexport const XhContextMenuSubTrigger = defineComponent({\n name: 'XhContextMenuSubTrigger',\n setup(_, { slots }) {\n const handle = useContextMenuSubContext()\n const sub = useMenuContext()\n return () => h('div', {\n // 合并序=子先父后:父层的 data-scope/data-part 胜出,父层的方向键与选中照常认它\n ...mergeProps(\n sub.api.value.getSubmenuTriggerProps({ value: handle.value, disabled: handle.disabled }) as Record<string, unknown>,\n handle.parent.api.value.getItemProps({ value: handle.value, disabled: handle.disabled }) as Record<string, unknown>,\n ),\n // 子菜单的定位锚点就是这一条\n ref: (el: unknown) => {\n sub.triggerRef.value = el as HTMLElement\n },\n }, slots.default?.())\n },\n})\n\nexport const XhContextMenuItemText = defineComponent({\n name: 'XhContextMenuItemText',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuItemIndicator = defineComponent({\n name: 'XhContextMenuItemIndicator',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目中的副文本,排在文字下一行 */\nexport const XhContextMenuItemDescription = defineComponent({\n name: 'XhContextMenuItemDescription',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemDescriptionProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuSeparator = defineComponent({\n name: 'XhContextMenuSeparator',\n setup() {\n const ctx = useContextMenuContext()\n return () => h('div', ctx.api.value.getSeparatorProps() as Record<string, unknown>)\n },\n})\n\nexport const XhContextMenuArrow = defineComponent({\n name: 'XhContextMenuArrow',\n setup() {\n const ctx = useContextMenuContext()\n return () => h('div', ctx.api.value.getArrowProps() as Record<string, unknown>)\n },\n})\n\n/** 一段连续的同组条目;不分组的条目各自单独成段。 */\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n * 触发区中放置的内容由作者决定,经 trigger 插槽给出。\n */\nfunction renderDefaultTree(\n collection: readonly ContextMenuNodeMeta[],\n trigger: (VNode | string)[] | null,\n itemSlot?: (node: ContextMenuNodeMeta) => VNode[],\n): VNode[] {\n return [\n h(XhContextMenuTrigger, null, () => trigger ?? []),\n h(XhContextMenuPositioner, null, () => [\n h(XhContextMenuContent, null, () => renderNodes(collection, itemSlot)),\n ]),\n ]\n}\n\n/** content 的内容:分组段铺为 group,段首的分隔线落在 group 外面。 */\nfunction renderNodes(\n collection: readonly ContextMenuNodeMeta[],\n itemSlot?: (node: ContextMenuNodeMeta) => VNode[],\n): VNode[] {\n return groupAdjacentRuns(collection, node => node.group).flatMap((run, runIndex) => {\n const head = run[0]\n // 首条上的标记不产出分隔线:菜单开头不留一道空隔\n const lead = runIndex > 0 && head.separatorBefore\n ? [h(XhContextMenuSeparator, { key: `separator:${head.value}` })]\n : []\n if (head.group == null)\n return [...lead, renderItem(head, itemSlot)]\n const groupLabel = run.find(node => node.groupLabel != null)?.groupLabel ?? null\n return [\n ...lead,\n h(XhContextMenuGroup, { key: `group:${head.group}`, value: head.group }, () => [\n ...(groupLabel != null ? [h(XhContextMenuGroupLabel, null, () => groupLabel)] : []),\n ...run.flatMap((node, index) => [\n ...(index > 0 && node.separatorBefore ? [h(XhContextMenuSeparator, { key: `separator:${node.value}` })] : []),\n renderItem(node, itemSlot),\n ]),\n ]),\n ]\n })\n}\n\n/** 单个条目:标记位排在文字前面,未提供标记位时不铺该部件。 */\nfunction renderItem(\n meta: ContextMenuNodeMeta,\n itemSlot?: (node: ContextMenuNodeMeta) => VNode[],\n): VNode {\n return h(XhContextMenuItem, { key: meta.value, value: meta.value }, () => [\n ...(meta.indicator != null ? [h(XhContextMenuItemIndicator, null, () => meta.indicator)] : []),\n h(XhContextMenuItemText, null, () => itemSlot?.(meta) ?? meta.label),\n ...(meta.description != null ? [h(XhContextMenuItemDescription, null, () => meta.description)] : []),\n ])\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"context-menu.js","names":["mergeVueProps","mergeProps"],"sources":["../../../src/components/context-menu/context-menu.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// 提供 context menu 相关实现。\n\nimport type { Direction, Placement, Size, Tone } from '@xihan-ui/core'\nimport type { ContextMenuApi, ContextMenuGroupProps, ContextMenuItemProps, ContextMenuNode, ContextMenuNodeMeta, ContextMenuSchema, MenuApi } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { groupAdjacentRuns, mergeProps } from '@xihan-ui/core'\nimport { computed, defineComponent, h, mergeProps as mergeVueProps, onBeforeUnmount, ref, watch } 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 { provideMenu, useMenuContext } from '../menu/context'\nimport { useMenuWithParent } from '../menu/use-menu'\nimport {\n provideContextMenu,\n provideContextMenuGroup,\n provideContextMenuItem,\n provideContextMenuSub,\n useContextMenuContext,\n useContextMenuGroupContext,\n useContextMenuItemContext,\n useContextMenuSubContext,\n} from './context'\nimport { useContextMenu } from './use-context-menu'\n\ntype ContextMenuProps = ContextMenuSchema['props']\n\n/** 默认插槽的载荷:右键菜单的展开态与锚点坐标,以及开合、按坐标展开的命令。 */\nexport type ContextMenuRootSlotProps = Pick<ContextMenuApi, 'open' | 'point' | 'setOpen' | 'openAt'>\n\n/** 子菜单默认插槽的载荷:该层子菜单自己的展开态与开合命令。 */\nexport type ContextMenuSubSlotProps = Pick<MenuApi, 'open' | 'setOpen'>\n\n/** 代铺条目时可逐槽接管的三个插槽;三个都不写即完全按数据铺。 */\nexport interface ContextMenuItemSlots {\n /** 只填条目的文字槽,其余槽照旧由数据铺。 */\n item?: (node: ContextMenuNodeMeta) => VNode[]\n /** 只接管行首那一格,其余槽照旧由数据铺。 */\n ['item-prefix']?: (node: ContextMenuNodeMeta) => VNode[]\n /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺。 */\n ['item-suffix']?: (node: ContextMenuNodeMeta) => VNode[]\n}\n\nexport const XhContextMenuRoot = defineComponent({\n name: 'XhContextMenuRoot',\n // 缺省值由 connect 与机器给出;普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ContextMenuNode[]> },\n open: { type: Boolean, default: undefined },\n defaultOpen: Boolean,\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n loop: { type: Boolean, default: undefined },\n typeahead: { type: Boolean, default: undefined },\n translations: { type: Object as PropType<ContextMenuProps['translations']> },\n dir: { type: String as PropType<Direction> },\n longPressDelay: { type: Number },\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n },\n // open-change 携带 { open }、select 携带 { value },update:open 携带裸布尔\n emits: {\n 'open-change': (_details: PayloadOf<ContextMenuProps, 'onOpenChange'>) => true,\n 'select': (_details: PayloadOf<ContextMenuProps, 'onSelect'>) => true,\n 'update:open': (_open: PayloadOf<ContextMenuProps, 'onOpenChange'>['open']) => true,\n },\n slots: Object as SlotsType<{\n 'default'?: (props: ContextMenuRootSlotProps) => VNode[]\n 'trigger'?: () => VNode[]\n /** 只填条目的文字槽,标记位、副文本与快捷键照旧由数据铺 */\n 'item'?: (node: ContextMenuNodeMeta) => VNode[]\n /** 只接管行首那一格,其余槽照旧由数据铺 */\n 'item-prefix'?: (node: ContextMenuNodeMeta) => VNode[]\n /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */\n 'item-suffix'?: (node: ContextMenuNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit, expose }) {\n const notifyOpen: ContextMenuProps['onOpenChange'] = (details) => {\n emit('open-change', details)\n emit('update:open', details.open)\n }\n const notifySelect: ContextMenuProps['onSelect'] = details => emit('select', details)\n const ctx = useContextMenu(withXhConfig('context-menu', props) as ContextMenuProps, notifyOpen, notifySelect)\n provideContextMenu(ctx)\n // 菜单钉在坐标上,坐标只能由 openAt 交进来。默认插槽那条路从载荷里拿,\n // 只交 collection 的那条路没有载荷,所以同一组命令也从实例上暴露一份。\n expose({\n openAt: (x: number, y: number) => ctx.api.value.openAt(x, y),\n setOpen: (open: boolean) => ctx.api.value.setOpen(open),\n get open() {\n return ctx.api.value.open\n },\n get point() {\n return ctx.api.value.point\n },\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 point: ctx.api.value.point,\n setOpen: ctx.api.value.setOpen,\n openAt: ctx.api.value.openAt,\n })\n : props.collection\n ? renderDefaultTree(ctx.api.value.collection, slots.trigger?.() ?? null, { 'item': slots.item, 'item-prefix': slots['item-prefix'], 'item-suffix': slots['item-suffix'] })\n : [],\n )\n },\n})\n\nexport const XhContextMenuTrigger = defineComponent({\n name: 'XhContextMenuTrigger',\n // 直通属性自己合:Vue 默认把作者的处理器排在部件的后面,这里改成作者先跑\n inheritAttrs: false,\n props: {\n /** 借用作者的子节点作为触发器,不再渲染自己的包裹元素;子节点须恰好一个。 */\n asChild: Boolean,\n },\n setup(props, { slots, attrs }) {\n const ctx = useContextMenuContext()\n // 触发区渲染为 div,语义由 connect 打上的 ARIA 属性给出\n return () => {\n const part = mergePartProps({\n ...ctx.api.value.getTriggerProps() as Record<string, unknown>,\n ref: (el: unknown) => { ctx.triggerRef.value = el as HTMLElement },\n }, attrs)\n const children = slots.default?.()\n // asChild:把触发器属性合到作者的节点上,不再自己渲染包裹元素\n if (props.asChild) {\n const merged = mergeIntoChild(children, part, 'context-menu')\n if (merged)\n return merged\n }\n return h('div', part, children)\n }\n },\n})\n\nexport const XhContextMenuPositioner = defineComponent({\n name: 'XhContextMenuPositioner',\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 = useContextMenuContext()\n // 条目列表的自绘条:与 content 同级、绝对定位不占布局,壳是这层已经 fixed 的 positioner\n // 浮层里的条子走 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.triggerRef }, () => [\n h('div', {\n ...mergeVueProps(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 XhContextMenuContent = defineComponent({\n name: 'XhContextMenuContent',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\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 XhContextMenuGroup = defineComponent({\n name: 'XhContextMenuGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useContextMenuContext()\n const group = computed<ContextMenuGroupProps>(() => ({ value: props.value }))\n provideContextMenuGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuGroupLabel = defineComponent({\n name: 'XhContextMenuGroupLabel',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { group } = useContextMenuGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuItem = defineComponent({\n name: 'XhContextMenuItem',\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 = useContextMenuContext()\n const item = computed<ContextMenuItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideContextMenuItem({ item })\n // 本条目持有焦点时,value 变更按新值重报焦点条目,卸载时上报焦点丢失\n const itemEl = ref<HTMLElement | null>(null)\n watch(() => props.value, (next, prev) => {\n if (next === prev)\n return\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.FOCUS', value: next })\n })\n onBeforeUnmount(() => {\n const { service } = ctx\n // 根已停机时不再送事件\n if (service.getStatus() !== 'Started')\n return\n // 按「本节点当下正持有焦点」判定,不按 value 比对\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.LOST' })\n })\n return () => h(\n 'div',\n { ...ctx.api.value.getItemProps(item.value) as Record<string, unknown>, ref: itemEl },\n slots.default?.(),\n )\n },\n})\n\n/**\n * 右键菜单中的子菜单:子层运行一台 submenu 模式的 menu 状态机,触发条目由\n * XhContextMenuSubTrigger 渲染为父层条目与子层触发器的双重身份。\n * 子层内部使用 XhMenu 系部件(再往深嵌套即 menu 嵌套 menu)。本身不渲染节点。\n */\nexport const XhContextMenuSub = defineComponent({\n name: 'XhContextMenuSub',\n props: {\n /** 它在父右键菜单中的条目身份。 */\n value: { type: String, required: true },\n disabled: { type: Boolean, default: undefined },\n placement: { type: String as PropType<Placement> },\n offset: { type: Number },\n loop: { type: Boolean, default: undefined },\n openOnHover: { type: Boolean, default: undefined },\n hoverOpenDelay: { type: Number },\n /** 文字方向;默认继承父层。子层被迁移到浮层落点,无法继承父层的方向。 */\n dir: { type: String as PropType<Direction> },\n /** 语气;默认继承父层。子层是浮层落点下的同级节点,CSS 私有槽无法继承。 */\n tone: { type: String as PropType<Tone> },\n /** 尺寸;默认继承父层,理由同 tone。 */\n size: { type: String as PropType<Size> },\n hoverCloseDelay: { type: Number },\n },\n slots: Object as SlotsType<{\n default?: (props: ContextMenuSubSlotProps) => VNode[]\n }>,\n setup(props, { slots }) {\n const parent = useContextMenuContext()\n const sub = useMenuWithParent(\n {\n ...props,\n submenu: true,\n dir: props.dir ?? parent.service.prop('dir'),\n tone: props.tone ?? parent.service.prop('tone'),\n size: props.size ?? parent.service.prop('size'),\n },\n undefined,\n parent.tree,\n )\n // 子树内的 XhMenu 系部件都归子机器\n provideMenu(sub)\n provideContextMenuSub({ parent, value: props.value, disabled: props.disabled })\n // 父层收起(Escape、外点、选中)时本层跟着收,层层传导\n watch(() => parent.api.value.open, (open) => {\n if (!open)\n sub.api.value.setOpen(false)\n })\n return () => slots.default?.({ open: sub.api.value.open, setOpen: sub.api.value.setOpen })\n },\n})\n\nexport const XhContextMenuSubTrigger = defineComponent({\n name: 'XhContextMenuSubTrigger',\n setup(_, { slots }) {\n const handle = useContextMenuSubContext()\n const sub = useMenuContext()\n return () => h('div', {\n // 合并序=子先父后:父层的 data-scope/data-part 胜出,父层的方向键与选中照常认它\n ...mergeProps(\n sub.api.value.getSubmenuTriggerProps({ value: handle.value, disabled: handle.disabled }) as Record<string, unknown>,\n handle.parent.api.value.getItemProps({ value: handle.value, disabled: handle.disabled }) as Record<string, unknown>,\n ),\n // 子菜单的定位锚点就是这一条\n ref: (el: unknown) => {\n sub.triggerRef.value = el as HTMLElement\n },\n }, slots.default?.())\n },\n})\n\nexport const XhContextMenuItemText = defineComponent({\n name: 'XhContextMenuItemText',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuItemIndicator = defineComponent({\n name: 'XhContextMenuItemIndicator',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目中的副文本,排在文字下一行 */\nexport const XhContextMenuItemDescription = defineComponent({\n name: 'XhContextMenuItemDescription',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemDescriptionProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目中的快捷键提示,贴行尾;纯装饰,读屏从条目文字取意 */\nexport const XhContextMenuItemShortcut = defineComponent({\n name: 'XhContextMenuItemShortcut',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemShortcutProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行尾的作者内容(计数、徽标、次级图标);家族只管落位,不规定字号与颜色 */\nexport const XhContextMenuItemSuffix = defineComponent({\n name: 'XhContextMenuItemSuffix',\n setup(_, { slots }) {\n const ctx = useContextMenuContext()\n const { item } = useContextMenuItemContext()\n return () => h('span', ctx.api.value.getItemSuffixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhContextMenuSeparator = defineComponent({\n name: 'XhContextMenuSeparator',\n setup() {\n const ctx = useContextMenuContext()\n return () => h('div', ctx.api.value.getSeparatorProps() as Record<string, unknown>)\n },\n})\n\nexport const XhContextMenuArrow = defineComponent({\n name: 'XhContextMenuArrow',\n setup() {\n const ctx = useContextMenuContext()\n return () => h('div', ctx.api.value.getArrowProps() as Record<string, unknown>)\n },\n})\n\n/** 一段连续的同组条目;不分组的条目各自单独成段。 */\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。\n * 触发区中放置的内容由作者决定,经 trigger 插槽给出。\n */\nfunction renderDefaultTree(\n collection: readonly ContextMenuNodeMeta[],\n trigger: (VNode | string)[] | null,\n itemSlots: ContextMenuItemSlots,\n): VNode[] {\n return [\n h(XhContextMenuTrigger, null, () => trigger ?? []),\n h(XhContextMenuPositioner, null, () => [\n h(XhContextMenuContent, null, () => renderNodes(collection, itemSlots)),\n ]),\n ]\n}\n\n/** content 的内容:分组段铺为 group,段首的分隔线落在 group 外面。 */\nfunction renderNodes(\n collection: readonly ContextMenuNodeMeta[],\n itemSlots: ContextMenuItemSlots,\n): VNode[] {\n return groupAdjacentRuns(collection, node => node.group).flatMap((run, runIndex) => {\n const head = run[0]\n // 首条上的标记不产出分隔线:菜单开头不留一道空隔\n const lead = runIndex > 0 && head.separatorBefore\n ? [h(XhContextMenuSeparator, { key: `separator:${head.value}` })]\n : []\n if (head.group == null)\n return [...lead, renderItem(head, itemSlots)]\n const groupLabel = run.find(node => node.groupLabel != null)?.groupLabel ?? null\n return [\n ...lead,\n h(XhContextMenuGroup, { key: `group:${head.group}`, value: head.group }, () => [\n ...(groupLabel != null ? [h(XhContextMenuGroupLabel, null, () => groupLabel)] : []),\n ...run.flatMap((node, index) => [\n ...(index > 0 && node.separatorBefore ? [h(XhContextMenuSeparator, { key: `separator:${node.value}` })] : []),\n renderItem(node, itemSlots),\n ]),\n ]),\n ]\n })\n}\n\n/**\n * 单个条目:标记位排在文字前面,未提供标记位时不铺该部件。\n * `item-prefix` / `item-suffix` 插槽各接管首尾一格,其余槽照旧由数据铺;\n * 行首那一格与数据里的 `indicator` 同一个部件,插槽在场时以它为准。\n */\nfunction renderItem(\n meta: ContextMenuNodeMeta,\n itemSlots: ContextMenuItemSlots,\n): VNode {\n const prefix = itemSlots['item-prefix']\n const suffix = itemSlots['item-suffix']\n return h(XhContextMenuItem, { key: meta.value, value: meta.value }, () => [\n ...(prefix\n ? [h(XhContextMenuItemIndicator, null, () => prefix(meta))]\n : meta.indicator != null ? [h(XhContextMenuItemIndicator, null, () => meta.indicator)] : []),\n h(XhContextMenuItemText, null, () => itemSlots.item?.(meta) ?? meta.label),\n ...(meta.description != null ? [h(XhContextMenuItemDescription, null, () => meta.description)] : []),\n ...(meta.shortcut != null ? [h(XhContextMenuItemShortcut, null, () => meta.shortcut)] : []),\n ...(suffix ? [h(XhContextMenuItemSuffix, null, () => suffix(meta))] : []),\n ])\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"input-group.d.ts","names":[],"sources":["../../../src/components/input-group/input-group.ts"],"mappings":";;;cAgBa,gCAAgB,8BAAA;EAIN,SAAA,SAAS;;IACJ,MAAA,SAAS;;;;;EADd,SAAA,SAAS;;IACJ,MAAA,SAAS;;MAQnC,oDAAA;cAEW,gCAAgB,wCAAA,oBAAA,4BAAA;;8BAO3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
1
+ {"version":3,"file":"input-group.d.ts","names":[],"sources":["../../../src/components/input-group/input-group.ts"],"mappings":";;;cAgBa,gCAAgB,8BAAA;EAIN,SAAA,SAAS;;IACJ,MAAA,SAAS;;;;;EADd,SAAA,SAAS;;IACJ,MAAA,SAAS;;MAUnC,oDAAA;cAEW,gCAAgB,wCAAA,oBAAA,4BAAA;;8BAO3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
@@ -11,7 +11,8 @@ const XhInputGroupRoot = defineComponent({
11
11
  size: { type: String }
12
12
  },
13
13
  setup(props, { slots }) {
14
- const api = computed(() => connectInputGroup(withXhConfig("input-group", props), vueNormalize));
14
+ const configured = withXhConfig("input-group", props);
15
+ const api = computed(() => connectInputGroup(configured, vueNormalize));
15
16
  provideInputGroup({ api });
16
17
  return () => h("div", api.value.getRootProps(), slots.default?.());
17
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"input-group.js","names":[],"sources":["../../../src/components/input-group/input-group.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// 提供 input group 相关实现。\n\nimport type { ControlVariant, Size } from '@xihan-ui/core'\nimport type { InputGroupProps } from '@xihan-ui/headless'\nimport type { PropType } from 'vue'\nimport { connectInputGroup } from '@xihan-ui/headless'\nimport { computed, defineComponent, h } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { vueNormalize } from '../../runtime/normalize-props'\nimport { provideInputGroup, useInputGroupContext } from './context'\n\nexport const XhInputGroupRoot = defineComponent({\n name: 'XhInputGroupRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n variant: String as PropType<ControlVariant>,\n size: { type: String as PropType<Size> },\n },\n setup(props, { slots }) {\n const api = computed(() => connectInputGroup(withXhConfig('input-group', props) as InputGroupProps, vueNormalize))\n provideInputGroup({ api })\n // 组内每一段是作者放进插槽的控件,直接当直接子节点摆\n return () => h('div', api.value.getRootProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhInputGroupItem = defineComponent({\n name: 'XhInputGroupItem',\n setup(_, { slots }) {\n const ctx = useInputGroupContext()\n // 前后缀文本由作者写进插槽\n return () => h('span', ctx.api.value.getItemProps() as Record<string, unknown>, slots.default?.())\n },\n})\n"],"mappings":";;;;;;AAgBA,MAAa,mBAAmB,gBAAgB;CAC9C,MAAM;CAEN,OAAO;EACL,SAAS;EACT,MAAM,EAAE,MAAM,OAAyB;CACzC;CACA,MAAM,OAAO,EAAE,SAAS;EACtB,MAAM,MAAM,eAAe,kBAAkB,aAAa,eAAe,KAAK,GAAsB,YAAY,CAAC;EACjH,kBAAkB,EAAE,IAAI,CAAC;EAEzB,aAAa,EAAE,OAAO,IAAI,MAAM,aAAa,GAA8B,MAAM,UAAU,CAAC;CAC9F;AACF,CAAC;AAED,MAAa,mBAAmB,gBAAgB;CAC9C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,qBAAqB;EAEjC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,aAAa,GAA8B,MAAM,UAAU,CAAC;CACnG;AACF,CAAC"}
1
+ {"version":3,"file":"input-group.js","names":[],"sources":["../../../src/components/input-group/input-group.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// 提供 input group 相关实现。\n\nimport type { ControlVariant, Size } from '@xihan-ui/core'\nimport type { InputGroupProps } from '@xihan-ui/headless'\nimport type { PropType } from 'vue'\nimport { connectInputGroup } from '@xihan-ui/headless'\nimport { computed, defineComponent, h } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { vueNormalize } from '../../runtime/normalize-props'\nimport { provideInputGroup, useInputGroupContext } from './context'\n\nexport const XhInputGroupRoot = defineComponent({\n name: 'XhInputGroupRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n variant: String as PropType<ControlVariant>,\n size: { type: String as PropType<Size> },\n },\n setup(props, { slots }) {\n // withXhConfig 只能在 setup 期调,连接层在渲染期读这份代理\n const configured = withXhConfig('input-group', props)\n const api = computed(() => connectInputGroup(configured as InputGroupProps, vueNormalize))\n provideInputGroup({ api })\n // 组内每一段是作者放进插槽的控件,直接当直接子节点摆\n return () => h('div', api.value.getRootProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhInputGroupItem = defineComponent({\n name: 'XhInputGroupItem',\n setup(_, { slots }) {\n const ctx = useInputGroupContext()\n // 前后缀文本由作者写进插槽\n return () => h('span', ctx.api.value.getItemProps() as Record<string, unknown>, slots.default?.())\n },\n})\n"],"mappings":";;;;;;AAgBA,MAAa,mBAAmB,gBAAgB;CAC9C,MAAM;CAEN,OAAO;EACL,SAAS;EACT,MAAM,EAAE,MAAM,OAAyB;CACzC;CACA,MAAM,OAAO,EAAE,SAAS;EAEtB,MAAM,aAAa,aAAa,eAAe,KAAK;EACpD,MAAM,MAAM,eAAe,kBAAkB,YAA+B,YAAY,CAAC;EACzF,kBAAkB,EAAE,IAAI,CAAC;EAEzB,aAAa,EAAE,OAAO,IAAI,MAAM,aAAa,GAA8B,MAAM,UAAU,CAAC;CAC9F;AACF,CAAC;AAED,MAAa,mBAAmB,gBAAgB;CAC9C,MAAM;CACN,MAAM,GAAG,EAAE,SAAS;EAClB,MAAM,MAAM,qBAAqB;EAEjC,aAAa,EAAE,QAAQ,IAAI,IAAI,MAAM,aAAa,GAA8B,MAAM,UAAU,CAAC;CACnG;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"json-viewer.js","names":[],"sources":["../../../src/components/json-viewer/json-viewer.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// 提供 json viewer 相关实现。\n\nimport type { ControlVariant, Direction, Size } from '@xihan-ui/core'\nimport type { JsonViewerApi, JsonViewerNode, JsonViewerSchema, JsonViewerTranslations, JsonViewerView } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { groupJsonViewerNodesByParent } from '@xihan-ui/headless'\nimport { defineComponent, h } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { useJsonViewer } from './use-json-viewer'\n\ntype JsonViewerProps = JsonViewerSchema['props']\n\nfunction renderRows(\n api: JsonViewerApi,\n children: Map<string | null, JsonViewerNode[]>,\n parent: string | null,\n): VNode[] {\n return (children.get(parent) ?? []).map(node => renderRow(api, children, node))\n}\n\n/**\n * 一行:标量是 item(键名 + 值),对象与数组是 branch(控制行 + 子层)。\n * 没有键名的行(根行、截断占位)不渲染键名部件,避免多出一个空盒子。\n */\nfunction renderRow(\n api: JsonViewerApi,\n children: Map<string | null, JsonViewerNode[]>,\n node: JsonViewerNode,\n): VNode {\n const ref = { value: node.value }\n\n if (!node.branch) {\n const parts: VNode[] = []\n if (node.key != null)\n parts.push(h('span', api.getItemKeyProps(ref) as Record<string, unknown>, node.key))\n parts.push(h('span', api.getItemValueProps(ref) as Record<string, unknown>, api.valueText(node)))\n return h('div', { ...api.getItemProps(ref) as Record<string, unknown>, key: node.value }, parts)\n }\n\n const control: VNode[] = [\n h('span', api.getBranchTriggerProps(ref) as Record<string, unknown>, [\n h('span', api.getBranchIndicatorProps(ref) as Record<string, unknown>),\n ]),\n ]\n if (node.key != null)\n control.push(h('span', api.getBranchTextProps(ref) as Record<string, unknown>, node.key))\n control.push(h('span', api.getPreviewProps(ref) as Record<string, unknown>, api.previewText(node)))\n\n const parts: VNode[] = [h('div', api.getBranchControlProps(ref) as Record<string, unknown>, control)]\n // 收起的子层不渲染:一份大 JSON 全铺出来会把页面压住,展开集合本来也是逐层放开的\n if (api.isExpanded(node.value)) {\n parts.push(h(\n 'div',\n api.getBranchContentProps(ref) as Record<string, unknown>,\n renderRows(api, children, node.value),\n ))\n }\n return h('div', { ...api.getBranchProps(ref) as Record<string, unknown>, key: node.value }, parts)\n}\n\nexport const XhJsonViewerRoot = defineComponent({\n name: 'XhJsonViewerRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n // 任意形状都收,类型检查交给使用方\n value: { type: null as unknown as PropType<unknown>, default: undefined as unknown },\n view: { type: String as PropType<JsonViewerView> },\n /** 外框形态:outline 带描边与底色(默认),subtle 淡底无描边,ghost 去掉描边与底色只保留内容。 */\n variant: { type: String as PropType<ControlVariant> },\n expandedValue: { type: Array as PropType<string[]> },\n defaultExpandedValue: { type: Array as PropType<string[]> },\n defaultExpandedDepth: { type: Number },\n maxStringLength: { type: Number },\n maxItems: { type: Number },\n sortKeys: { type: Boolean, default: undefined },\n loop: { type: Boolean, default: undefined },\n dir: { type: String as PropType<Direction> },\n size: { type: String as PropType<Size> },\n translations: { type: Object as PropType<Partial<JsonViewerTranslations>> },\n },\n // 空态那一格的内容:不写即铺 translations 里的兜底文案\n slots: Object as SlotsType<{\n empty?: () => VNode[]\n }>,\n // expanded-change 携带 { value },update:expandedValue 携带裸集合\n emits: {\n 'expanded-value-change': (_details: PayloadOf<JsonViewerProps, 'onExpandedValueChange'>) => true,\n 'update:expandedValue': (_value: PayloadOf<JsonViewerProps, 'onExpandedValueChange'>['value']) => true,\n },\n setup(props, { emit, slots }) {\n const notify: JsonViewerProps['onExpandedValueChange'] = (details) => {\n emit('expanded-value-change', details)\n emit('update:expandedValue', details.value)\n }\n const ctx = useJsonViewer(withXhConfig('json-viewer', props) as JsonViewerProps, notify)\n // 两档容器是页内结构容器(与 Tree 同类):滚动条走 reset 层的原生细条,不接自绘条(§6.6)\n // 行是按数据摊出来的,作者写不出也不必写:整棵树由组件自己铺\n // 空态与滚动层同级:一行也摊不出来时由它说话,有行可摊时 connect 给它打 hidden\n const renderEmpty = (api: JsonViewerApi): VNode => h(\n 'div',\n api.getEmptyProps() as Record<string, unknown>,\n slots.empty?.() ?? api.emptyText,\n )\n return () => {\n const api = ctx.api.value\n // 原文档不铺行:整块文本交给 pre,框选与复制才拿得到与后端一字不差的那份\n if (api.view === 'text') {\n return h('div', api.getRootProps() as Record<string, unknown>, [\n h('pre', api.getTextProps() as Record<string, unknown>, api.text),\n renderEmpty(api),\n ])\n }\n\n const children = groupJsonViewerNodesByParent(api.visibleNodes)\n return h('div', api.getRootProps() as Record<string, unknown>, [\n h('div', api.getTreeProps() as Record<string, unknown>, renderRows(api, children, null)),\n renderEmpty(api),\n ])\n }\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"json-viewer.js","names":[],"sources":["../../../src/components/json-viewer/json-viewer.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// 提供 json viewer 相关实现。\n\nimport type { ControlVariant, Direction, Size } from '@xihan-ui/core'\nimport type { JsonViewerApi, JsonViewerNode, JsonViewerSchema, JsonViewerTranslations, JsonViewerView } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { groupJsonViewerNodesByParent } from '@xihan-ui/headless'\nimport { defineComponent, h } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { useJsonViewer } from './use-json-viewer'\n\ntype JsonViewerProps = JsonViewerSchema['props']\n\nfunction renderRows(\n api: JsonViewerApi,\n children: Map<string | null, JsonViewerNode[]>,\n parent: string | null,\n): VNode[] {\n return (children.get(parent) ?? []).map(node => renderRow(api, children, node))\n}\n\n/**\n * 一行:标量是 item(键名 + 值),对象与数组是 branch(控制行 + 子层)。\n * 没有键名的行(根行、截断占位)不渲染键名部件,避免多出一个空盒子。\n */\nfunction renderRow(\n api: JsonViewerApi,\n children: Map<string | null, JsonViewerNode[]>,\n node: JsonViewerNode,\n): VNode {\n const ref = { value: node.value }\n\n if (!node.branch) {\n const parts: VNode[] = []\n if (node.key != null)\n parts.push(h('span', api.getItemKeyProps(ref) as Record<string, unknown>, node.key))\n parts.push(h('span', api.getItemValueProps(ref) as Record<string, unknown>, api.valueText(node)))\n return h('div', { ...api.getItemProps(ref) as Record<string, unknown>, key: node.value }, parts)\n }\n\n const control: VNode[] = [\n h('span', api.getBranchTriggerProps(ref) as Record<string, unknown>, [\n h('span', api.getBranchIndicatorProps(ref) as Record<string, unknown>),\n ]),\n ]\n if (node.key != null)\n control.push(h('span', api.getBranchTextProps(ref) as Record<string, unknown>, node.key))\n control.push(h('span', api.getPreviewProps(ref) as Record<string, unknown>, api.previewText(node)))\n\n const parts: VNode[] = [h('div', api.getBranchControlProps(ref) as Record<string, unknown>, control)]\n // 收起的子层不渲染:一份大 JSON 全铺出来会把页面压住,展开集合本来也是逐层放开的\n if (api.isExpanded(node.value)) {\n parts.push(h(\n 'div',\n api.getBranchContentProps(ref) as Record<string, unknown>,\n renderRows(api, children, node.value),\n ))\n }\n return h('div', { ...api.getBranchProps(ref) as Record<string, unknown>, key: node.value }, parts)\n}\n\nexport const XhJsonViewerRoot = defineComponent({\n name: 'XhJsonViewerRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n // 任意形状都收,类型检查交给使用方\n value: { type: null as unknown as PropType<unknown>, default: undefined as unknown },\n view: { type: String as PropType<JsonViewerView> },\n /** 外框形态:outline 带描边与底色(默认),subtle 淡底无描边,ghost 去掉描边与底色只保留内容。 */\n variant: { type: String as PropType<ControlVariant> },\n expandedValue: { type: Array as PropType<string[]> },\n defaultExpandedValue: { type: Array as PropType<string[]> },\n defaultExpandedDepth: { type: Number },\n maxStringLength: { type: Number },\n maxItems: { type: Number },\n sortKeys: { type: Boolean, default: undefined },\n loop: { type: Boolean, default: undefined },\n dir: { type: String as PropType<Direction> },\n size: { type: String as PropType<Size> },\n translations: { type: Object as PropType<Partial<JsonViewerTranslations>> },\n },\n // 空态那一格的内容:不写即铺 translations 里的兜底文案\n slots: Object as SlotsType<{\n empty?: () => VNode[]\n }>,\n // expanded-change 携带 { value },update:expandedValue 携带裸集合\n emits: {\n 'expanded-value-change': (_details: PayloadOf<JsonViewerProps, 'onExpandedValueChange'>) => true,\n 'update:expandedValue': (_value: PayloadOf<JsonViewerProps, 'onExpandedValueChange'>['value']) => true,\n },\n setup(props, { emit, slots }) {\n const notify: JsonViewerProps['onExpandedValueChange'] = (details) => {\n emit('expanded-value-change', details)\n emit('update:expandedValue', details.value)\n }\n const ctx = useJsonViewer(withXhConfig('json-viewer', props) as JsonViewerProps, notify)\n // 两档容器是页内结构容器(与 Tree 同类):滚动条走 reset 层的原生细条,不接自绘条\n // 行是按数据摊出来的,作者写不出也不必写:整棵树由组件自己铺\n // 空态与滚动层同级:一行也摊不出来时由它说话,有行可摊时 connect 给它打 hidden\n const renderEmpty = (api: JsonViewerApi): VNode => h(\n 'div',\n api.getEmptyProps() as Record<string, unknown>,\n slots.empty?.() ?? api.emptyText,\n )\n return () => {\n const api = ctx.api.value\n // 原文档不铺行:整块文本交给 pre,框选与复制才拿得到与后端一字不差的那份\n if (api.view === 'text') {\n return h('div', api.getRootProps() as Record<string, unknown>, [\n h('pre', api.getTextProps() as Record<string, unknown>, api.text),\n renderEmpty(api),\n ])\n }\n\n const children = groupJsonViewerNodesByParent(api.visibleNodes)\n return h('div', api.getRootProps() as Record<string, unknown>, [\n h('div', api.getTreeProps() as Record<string, unknown>, renderRows(api, children, null)),\n renderEmpty(api),\n ])\n }\n },\n})\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"kbd.d.ts","names":[],"sources":["../../../src/components/kbd/kbd.ts"],"mappings":";;;;cAgBa,qBAAK,8BAAA;;IAGS,MAAA;;;;IACK,MAAA,SAAS;;;IACV,MAAA,SAAS;;;;;;;IAEE,MAAA,SAAS;;;;;;;;;;;IAGf,MAAA,SAAS,QAAQ;;;;;EAG3B,YAAA,UAAA,UAAU;;;IAVT,MAAA;;;;IACK,MAAA,SAAS;;;IACV,MAAA,SAAS;;;;;;;IAEE,MAAA,SAAS;;;;;;;;;;;IAGf,MAAA,SAAS,QAAQ;;;;;;;;qCAwCnD"}
1
+ {"version":3,"file":"kbd.d.ts","names":[],"sources":["../../../src/components/kbd/kbd.ts"],"mappings":";;;;cAgBa,qBAAK,8BAAA;;IAGS,MAAA;;;;IACK,MAAA,SAAS;;;IACV,MAAA,SAAS;;;;;;;IAEE,MAAA,SAAS;;;;;;;;;;;IAGf,MAAA,SAAS,QAAQ;;;;;EAG3B,YAAA,UAAA,UAAU;;;IAVT,MAAA;;;;IACK,MAAA,SAAS;;;IACV,MAAA,SAAS;;;;;;;IAEE,MAAA,SAAS;;;;;;;;;;;IAGf,MAAA,SAAS,QAAQ;;;;;;;;qCA8DnD"}
@@ -31,17 +31,34 @@ const XhKbd = defineComponent({
31
31
  emits: { "hot-key": (_details) => true },
32
32
  setup(props, { emit }) {
33
33
  const detected = useKbdPlatform();
34
- const api = computed(() => connectKbd(withXhConfig("kbd", {
35
- keys: props.keys,
36
- platform: props.platform && props.platform !== "auto" ? props.platform : detected.value,
37
- variant: props.variant,
38
- register: props.register,
39
- target: props.target,
40
- preventDefault: props.preventDefault,
41
- enabled: props.enabled,
42
- translations: props.translations,
34
+ const configured = withXhConfig("kbd", {
35
+ get keys() {
36
+ return props.keys;
37
+ },
38
+ get platform() {
39
+ return props.platform && props.platform !== "auto" ? props.platform : detected.value;
40
+ },
41
+ get variant() {
42
+ return props.variant;
43
+ },
44
+ get register() {
45
+ return props.register;
46
+ },
47
+ get target() {
48
+ return props.target;
49
+ },
50
+ get preventDefault() {
51
+ return props.preventDefault;
52
+ },
53
+ get enabled() {
54
+ return props.enabled;
55
+ },
56
+ get translations() {
57
+ return props.translations;
58
+ },
43
59
  onHotKey: (details) => emit("hot-key", details)
44
- }), vueNormalize));
60
+ });
61
+ const api = computed(() => connectKbd(configured, vueNormalize));
45
62
  const onKeyDown = (event) => api.value.handleKeyDown(event);
46
63
  let bound = null;
47
64
  const stop = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"kbd.js","names":[],"sources":["../../../src/components/kbd/kbd.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// 提供 kbd 展示与快捷键注册实现。\n\nimport type { KbdPlatform, KbdProps, KbdTarget, KbdTranslations, KbdVariant } from '@xihan-ui/headless'\nimport type { PropType } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { connectKbd } from '@xihan-ui/headless'\nimport { computed, defineComponent, h, onBeforeUnmount, watchEffect } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { vueNormalize } from '../../runtime/normalize-props'\nimport { useKbdPlatform } from './use-kbd-platform'\n\nexport const XhKbd = defineComponent({\n name: 'XhKbd',\n props: {\n keys: { type: Array as PropType<string[]>, required: true },\n platform: { type: String as PropType<KbdPlatform> },\n variant: { type: String as PropType<KbdVariant> },\n register: { type: Boolean, default: undefined },\n target: { type: [String, Function] as PropType<KbdTarget> },\n preventDefault: { type: Boolean, default: undefined },\n enabled: { type: Boolean, default: undefined },\n translations: { type: Object as PropType<Partial<KbdTranslations>> },\n },\n emits: {\n 'hot-key': (_details: PayloadOf<KbdProps, 'onHotKey'>) => true,\n },\n setup(props, { emit }) {\n const detected = useKbdPlatform()\n const api = computed(() => connectKbd(withXhConfig('kbd', {\n keys: props.keys,\n platform: props.platform && props.platform !== 'auto' ? props.platform : detected.value,\n variant: props.variant,\n register: props.register,\n target: props.target,\n preventDefault: props.preventDefault,\n enabled: props.enabled,\n translations: props.translations,\n onHotKey: details => emit('hot-key', details),\n }) as KbdProps, vueNormalize))\n const onKeyDown = (event: Event): void => api.value.handleKeyDown(event as KeyboardEvent)\n let bound: EventTarget | null = null\n const stop = (): void => {\n bound?.removeEventListener('keydown', onKeyDown)\n bound = null\n }\n watchEffect(() => {\n const next = api.value.resolveTarget(typeof document === 'undefined' ? null : document)\n if (next === bound)\n return\n stop()\n bound = next\n bound?.addEventListener('keydown', onKeyDown)\n })\n onBeforeUnmount(stop)\n\n return () => h('kbd', api.value.getRootProps() as Record<string, unknown>, api.value.segments.map((segment, index) => h(\n 'span',\n { ...api.value.getKeyProps({ value: segment.source }) as Record<string, unknown>, key: `${segment.source}-${index}` },\n segment.label,\n )))\n },\n})\n"],"mappings":";;;;;;AAgBA,MAAa,QAAQ,gBAAgB;CACnC,MAAM;CACN,OAAO;EACL,MAAM;GAAE,MAAM;GAA6B,UAAU;EAAK;EAC1D,UAAU,EAAE,MAAM,OAAgC;EAClD,SAAS,EAAE,MAAM,OAA+B;EAChD,UAAU;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ,QAAQ,EAAyB;EAC1D,gBAAgB;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EACpD,SAAS;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC7C,cAAc,EAAE,MAAM,OAA6C;CACrE;CACA,OAAO,EACL,YAAY,aAA8C,KAC5D;CACA,MAAM,OAAO,EAAE,QAAQ;EACrB,MAAM,WAAW,eAAe;EAChC,MAAM,MAAM,eAAe,WAAW,aAAa,OAAO;GACxD,MAAM,MAAM;GACZ,UAAU,MAAM,YAAY,MAAM,aAAa,SAAS,MAAM,WAAW,SAAS;GAClF,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,QAAQ,MAAM;GACd,gBAAgB,MAAM;GACtB,SAAS,MAAM;GACf,cAAc,MAAM;GACpB,WAAU,YAAW,KAAK,WAAW,OAAO;EAC9C,CAAC,GAAe,YAAY,CAAC;EAC7B,MAAM,aAAa,UAAuB,IAAI,MAAM,cAAc,KAAsB;EACxF,IAAI,QAA4B;EAChC,MAAM,aAAmB;GACvB,OAAO,oBAAoB,WAAW,SAAS;GAC/C,QAAQ;EACV;EACA,kBAAkB;GAChB,MAAM,OAAO,IAAI,MAAM,cAAc,OAAO,aAAa,cAAc,OAAO,QAAQ;GACtF,IAAI,SAAS,OACX;GACF,KAAK;GACL,QAAQ;GACR,OAAO,iBAAiB,WAAW,SAAS;EAC9C,CAAC;EACD,gBAAgB,IAAI;EAEpB,aAAa,EAAE,OAAO,IAAI,MAAM,aAAa,GAA8B,IAAI,MAAM,SAAS,KAAK,SAAS,UAAU,EACpH,QACA;GAAE,GAAG,IAAI,MAAM,YAAY,EAAE,OAAO,QAAQ,OAAO,CAAC;GAA8B,KAAK,GAAG,QAAQ,OAAO,GAAG;EAAQ,GACpH,QAAQ,KACV,CAAC,CAAC;CACJ;AACF,CAAC"}
1
+ {"version":3,"file":"kbd.js","names":[],"sources":["../../../src/components/kbd/kbd.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// 提供 kbd 展示与快捷键注册实现。\n\nimport type { KbdPlatform, KbdProps, KbdTarget, KbdTranslations, KbdVariant } from '@xihan-ui/headless'\nimport type { PropType } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { connectKbd } from '@xihan-ui/headless'\nimport { computed, defineComponent, h, onBeforeUnmount, watchEffect } from 'vue'\nimport { withXhConfig } from '../../config/config'\nimport { vueNormalize } from '../../runtime/normalize-props'\nimport { useKbdPlatform } from './use-kbd-platform'\n\nexport const XhKbd = defineComponent({\n name: 'XhKbd',\n props: {\n keys: { type: Array as PropType<string[]>, required: true },\n platform: { type: String as PropType<KbdPlatform> },\n variant: { type: String as PropType<KbdVariant> },\n register: { type: Boolean, default: undefined },\n target: { type: [String, Function] as PropType<KbdTarget> },\n preventDefault: { type: Boolean, default: undefined },\n enabled: { type: Boolean, default: undefined },\n translations: { type: Object as PropType<Partial<KbdTranslations>> },\n },\n emits: {\n 'hot-key': (_details: PayloadOf<KbdProps, 'onHotKey'>) => true,\n },\n setup(props, { emit }) {\n const detected = useKbdPlatform()\n // withXhConfig 只能在 setup 期调,连接层在渲染期读这份代理。\n // 本组件不能把它写进 computed:useKbdPlatform 在 onMounted 改写平台会让 api 失效,\n // 下一次求值发生在下面 watchEffect 的作业里,那时已不在组件上下文中,inject 拿不到\n // 全局配置,translations 与 locale 会被静默丢回内建英文。\n // 代理包的是一组取值函数:props 与 detected 仍在求值期被追踪,响应性不变。\n const configured = withXhConfig('kbd', {\n get keys() {\n return props.keys\n },\n get platform() {\n return props.platform && props.platform !== 'auto' ? props.platform : detected.value\n },\n get variant() {\n return props.variant\n },\n get register() {\n return props.register\n },\n get target() {\n return props.target\n },\n get preventDefault() {\n return props.preventDefault\n },\n get enabled() {\n return props.enabled\n },\n get translations() {\n return props.translations\n },\n onHotKey: (details: PayloadOf<KbdProps, 'onHotKey'>) => emit('hot-key', details),\n }) as KbdProps\n const api = computed(() => connectKbd(configured, vueNormalize))\n const onKeyDown = (event: Event): void => api.value.handleKeyDown(event as KeyboardEvent)\n let bound: EventTarget | null = null\n const stop = (): void => {\n bound?.removeEventListener('keydown', onKeyDown)\n bound = null\n }\n watchEffect(() => {\n const next = api.value.resolveTarget(typeof document === 'undefined' ? null : document)\n if (next === bound)\n return\n stop()\n bound = next\n bound?.addEventListener('keydown', onKeyDown)\n })\n onBeforeUnmount(stop)\n\n return () => h('kbd', api.value.getRootProps() as Record<string, unknown>, api.value.segments.map((segment, index) => h(\n 'span',\n { ...api.value.getKeyProps({ value: segment.source }) as Record<string, unknown>, key: `${segment.source}-${index}` },\n segment.label,\n )))\n },\n})\n"],"mappings":";;;;;;AAgBA,MAAa,QAAQ,gBAAgB;CACnC,MAAM;CACN,OAAO;EACL,MAAM;GAAE,MAAM;GAA6B,UAAU;EAAK;EAC1D,UAAU,EAAE,MAAM,OAAgC;EAClD,SAAS,EAAE,MAAM,OAA+B;EAChD,UAAU;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ,QAAQ,EAAyB;EAC1D,gBAAgB;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EACpD,SAAS;GAAE,MAAM;GAAS,SAAS,KAAA;EAAU;EAC7C,cAAc,EAAE,MAAM,OAA6C;CACrE;CACA,OAAO,EACL,YAAY,aAA8C,KAC5D;CACA,MAAM,OAAO,EAAE,QAAQ;EACrB,MAAM,WAAW,eAAe;EAMhC,MAAM,aAAa,aAAa,OAAO;GACrC,IAAI,OAAO;IACT,OAAO,MAAM;GACf;GACA,IAAI,WAAW;IACb,OAAO,MAAM,YAAY,MAAM,aAAa,SAAS,MAAM,WAAW,SAAS;GACjF;GACA,IAAI,UAAU;IACZ,OAAO,MAAM;GACf;GACA,IAAI,WAAW;IACb,OAAO,MAAM;GACf;GACA,IAAI,SAAS;IACX,OAAO,MAAM;GACf;GACA,IAAI,iBAAiB;IACnB,OAAO,MAAM;GACf;GACA,IAAI,UAAU;IACZ,OAAO,MAAM;GACf;GACA,IAAI,eAAe;IACjB,OAAO,MAAM;GACf;GACA,WAAW,YAA6C,KAAK,WAAW,OAAO;EACjF,CAAC;EACD,MAAM,MAAM,eAAe,WAAW,YAAY,YAAY,CAAC;EAC/D,MAAM,aAAa,UAAuB,IAAI,MAAM,cAAc,KAAsB;EACxF,IAAI,QAA4B;EAChC,MAAM,aAAmB;GACvB,OAAO,oBAAoB,WAAW,SAAS;GAC/C,QAAQ;EACV;EACA,kBAAkB;GAChB,MAAM,OAAO,IAAI,MAAM,cAAc,OAAO,aAAa,cAAc,OAAO,QAAQ;GACtF,IAAI,SAAS,OACX;GACF,KAAK;GACL,QAAQ;GACR,OAAO,iBAAiB,WAAW,SAAS;EAC9C,CAAC;EACD,gBAAgB,IAAI;EAEpB,aAAa,EAAE,OAAO,IAAI,MAAM,aAAa,GAA8B,IAAI,MAAM,SAAS,KAAK,SAAS,UAAU,EACpH,QACA;GAAE,GAAG,IAAI,MAAM,YAAY,EAAE,OAAO,QAAQ,OAAO,CAAC;GAA8B,KAAK,GAAG,QAAQ,OAAO,GAAG;EAAQ,GACpH,QAAQ,KACV,CAAC,CAAC;CACJ;AACF,CAAC"}
@@ -124,7 +124,12 @@ declare const XhListboxRoot: import("vue").DefineComponent<import("vue").Extract
124
124
  }, SlotsType<{
125
125
  default?: (props: ListboxRootSlotProps) => VNode[];
126
126
  label?: () => VNode[];
127
+ /** 只填条目的文字槽,副文本与首尾两格照旧各归各的 */
127
128
  item?: (node: ListboxNodeMeta) => VNode[];
129
+ /** 只接管行首那一格,其余槽照旧由数据铺 */
130
+ 'item-prefix'?: (node: ListboxNodeMeta) => VNode[];
131
+ /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */
132
+ 'item-suffix'?: (node: ListboxNodeMeta) => VNode[];
128
133
  }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
129
134
  declare const XhListboxLabel: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
130
135
  [key: string]: any;
@@ -183,9 +188,21 @@ declare const XhListboxItem: import("vue").DefineComponent<import("vue").Extract
183
188
  declare const XhListboxItemText: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
184
189
  [key: string]: any;
185
190
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
191
+ /** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
192
+ declare const XhListboxItemPrefix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
193
+ [key: string]: any;
194
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
195
+ /** 条目行尾的作者内容(计数、徽标) */
196
+ declare const XhListboxItemSuffix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
197
+ [key: string]: any;
198
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
199
+ /** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
200
+ declare const XhListboxItemDescription: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
201
+ [key: string]: any;
202
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
186
203
  declare const XhListboxItemIndicator: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
187
204
  [key: string]: any;
188
205
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
189
206
  //#endregion
190
- export { ListboxRootSlotProps, XhListboxContent, XhListboxEmpty, XhListboxGroup, XhListboxGroupLabel, XhListboxItem, XhListboxItemIndicator, XhListboxItemText, XhListboxLabel, XhListboxLoadMoreTrigger, XhListboxLoading, XhListboxRoot };
207
+ export { ListboxRootSlotProps, XhListboxContent, XhListboxEmpty, XhListboxGroup, XhListboxGroupLabel, XhListboxItem, XhListboxItemDescription, XhListboxItemIndicator, XhListboxItemPrefix, XhListboxItemSuffix, XhListboxItemText, XhListboxLabel, XhListboxLoadMoreTrigger, XhListboxLoading, XhListboxRoot };
191
208
  //# sourceMappingURL=listbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listbox.d.ts","names":[],"sources":["../../../src/components/listbox/listbox.ts"],"mappings":";;;;;KAwBK,eAAe;;KAGR,uBAAuB,KACjC;cAIW,6BAAa,8BAAA;;IAIO,MAAA,SAAS;;;;;;;IAGJ,MAAA;;;IACO,MAAA;;;IACR,MAAA,SAAS;;;;;;;;;;;;;;;;IAKlB,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;IAGV,MAAA,SAAS;;;IACD,MAAA,SAAS;;;;;EAIb,iBAAA,UAAA,UAAU;EACZ,iBAAA,QAAA,UAAU;;;IApBN,MAAA,SAAS;;;;;;;IAGJ,MAAA;;;IACO,MAAA;;;IACR,MAAA,SAAS;;;;;;;;;;;;;;;;IAKlB,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;IAGV,MAAA,SAAS;;;IACD,MAAA,SAAS;;;;;;;;;;;;;EAQ9B,WAAC,OAAO,yBAAyB;EACnC,cAAM;EACP,QAAC,MAAM,oBAAoB;kCA6BpC;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;gCA0B3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAQzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAO3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,wCAAwB,0BAAA,oBAAA,4BAAA;;8BAOnC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,8BAAA;;;;;;;;;;;;MAWzB,oDAAA;cAEW,mCAAmB,0BAAA,oBAAA,4BAAA;;8BAO9B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAoCxB;cAEW,iCAAiB,0BAAA,oBAAA,4BAAA;;8BAO5B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,sCAAsB,0BAAA,oBAAA,4BAAA;;8BAOjC,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
1
+ {"version":3,"file":"listbox.d.ts","names":[],"sources":["../../../src/components/listbox/listbox.ts"],"mappings":";;;;;KAwBK,eAAe;;KAGR,uBAAuB,KACjC;cAIW,6BAAa,8BAAA;;IAIO,MAAA,SAAS;;;;;;;IAGJ,MAAA;;;IACO,MAAA;;;IACR,MAAA,SAAS;;;;;;;;;;;;;;;;IAKlB,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;IAGV,MAAA,SAAS;;;IACD,MAAA,SAAS;;;;;EAIb,iBAAA,UAAA,UAAU;EACZ,iBAAA,QAAA,UAAU;;;IApBN,MAAA,SAAS;;;;;;;IAGJ,MAAA;;;IACO,MAAA;;;IACR,MAAA,SAAS;;;;;;;;;;;;;;;;IAKlB,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;IAGV,MAAA,SAAS;;;IACD,MAAA,SAAS;;;;;;;;;;;;;EAQ5B,WAAC,OAAO,yBAAyB;EACnC,cAAM;;EAEP,QAAC,MAAM,oBAAoB;;EAEpB,iBAAC,MAAM,oBAAoB;;EAE3B,iBAAC,MAAM,oBAAoB;kCA+B7C;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;gCA0B3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAQzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAO3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,wCAAwB,0BAAA,oBAAA,4BAAA;;8BAOnC,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,8BAAc,8BAAA;;;;;;;;;;;;MAWzB,oDAAA;cAEW,mCAAmB,0BAAA,oBAAA,4BAAA;;8BAO9B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAoCxB;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;cAEW,sCAAsB,0BAAA,oBAAA,4BAAA;;8BAOjC,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
@@ -59,7 +59,7 @@ const XhListboxRoot = defineComponent({
59
59
  setValue: ctx.api.value.setValue,
60
60
  select: ctx.api.value.select,
61
61
  toggle: ctx.api.value.toggle
62
- }) ?? [] : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.label?.() ?? (props.label != null ? [props.label] : null), slots.item) : []]);
62
+ }) ?? [] : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.label?.() ?? (props.label != null ? [props.label] : null), slots.item, slots["item-prefix"], slots["item-suffix"]) : []]);
63
63
  }
64
64
  });
65
65
  const XhListboxLabel = defineComponent({
@@ -180,6 +180,33 @@ const XhListboxItemText = defineComponent({
180
180
  return () => h("span", ctx.api.value.getItemTextProps(item.value), slots.default?.());
181
181
  }
182
182
  });
183
+ /** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
184
+ const XhListboxItemPrefix = defineComponent({
185
+ name: "XhListboxItemPrefix",
186
+ setup(_, { slots }) {
187
+ const ctx = useListboxContext();
188
+ const { item } = useListboxItemContext();
189
+ return () => h("span", ctx.api.value.getItemPrefixProps(item.value), slots.default?.());
190
+ }
191
+ });
192
+ /** 条目行尾的作者内容(计数、徽标) */
193
+ const XhListboxItemSuffix = defineComponent({
194
+ name: "XhListboxItemSuffix",
195
+ setup(_, { slots }) {
196
+ const ctx = useListboxContext();
197
+ const { item } = useListboxItemContext();
198
+ return () => h("span", ctx.api.value.getItemSuffixProps(item.value), slots.default?.());
199
+ }
200
+ });
201
+ /** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
202
+ const XhListboxItemDescription = defineComponent({
203
+ name: "XhListboxItemDescription",
204
+ setup(_, { slots }) {
205
+ const ctx = useListboxContext();
206
+ const { item } = useListboxItemContext();
207
+ return () => h("span", ctx.api.value.getItemDescriptionProps(item.value), slots.default?.());
208
+ }
209
+ });
183
210
  const XhListboxItemIndicator = defineComponent({
184
211
  name: "XhListboxItemIndicator",
185
212
  setup(_, { slots }) {
@@ -192,13 +219,19 @@ const XhListboxItemIndicator = defineComponent({
192
219
  * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。
193
220
  * 与手写部件产出的 DOM 完全一致,需要修改结构(分组、条目外的节点)时写默认插槽。
194
221
  */
195
- function renderDefaultTree(collection, label, itemSlot) {
222
+ function renderDefaultTree(collection, label, itemSlot, prefixSlot, suffixSlot) {
196
223
  return [...label ? [h(XhListboxLabel, null, () => label)] : [], h(XhListboxContent, null, () => collection.map((node) => h(XhListboxItem, {
197
224
  key: node.value,
198
225
  value: node.value
199
- }, () => [h(XhListboxItemText, null, () => itemSlot?.(node) ?? node.label), h(XhListboxItemIndicator)])))];
226
+ }, () => [
227
+ ...prefixSlot ? [h(XhListboxItemPrefix, null, () => prefixSlot(node))] : [],
228
+ h(XhListboxItemText, null, () => itemSlot?.(node) ?? node.label),
229
+ ...node.description != null ? [h(XhListboxItemDescription, null, () => node.description)] : [],
230
+ ...suffixSlot ? [h(XhListboxItemSuffix, null, () => suffixSlot(node))] : [],
231
+ h(XhListboxItemIndicator)
232
+ ])))];
200
233
  }
201
234
  //#endregion
202
- export { XhListboxContent, XhListboxEmpty, XhListboxGroup, XhListboxGroupLabel, XhListboxItem, XhListboxItemIndicator, XhListboxItemText, XhListboxLabel, XhListboxLoadMoreTrigger, XhListboxLoading, XhListboxRoot };
235
+ export { XhListboxContent, XhListboxEmpty, XhListboxGroup, XhListboxGroupLabel, XhListboxItem, XhListboxItemDescription, XhListboxItemIndicator, XhListboxItemPrefix, XhListboxItemSuffix, XhListboxItemText, XhListboxLabel, XhListboxLoadMoreTrigger, XhListboxLoading, XhListboxRoot };
203
236
 
204
237
  //# sourceMappingURL=listbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"listbox.js","names":[],"sources":["../../../src/components/listbox/listbox.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// 提供 listbox 相关实现。\n\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/core'\nimport type { ListboxApi, ListboxGroupProps, ListboxItemProps, ListboxNode, ListboxNodeMeta, ListboxSchema, ListboxSelectionMode } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { computed, defineComponent, h, mergeProps, onBeforeUnmount, onUpdated, ref, watch } from 'vue'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport { useFormControlProps } from '../form/use-form-control'\nimport {\n provideListbox,\n provideListboxItem,\n provideListboxItemGroup,\n useListboxContext,\n useListboxItemContext,\n useListboxItemGroupContext,\n} from './context'\nimport { useListbox } from './use-listbox'\n\ntype ListboxProps = ListboxSchema['props']\n\n/** 默认插槽的载荷:选中集合、选择模式与焦点锚点,以及判定选中与整份赋值、单选、切换的命令。 */\nexport type ListboxRootSlotProps = Pick<\n ListboxApi,\n 'value' | 'selectionMode' | 'focusedValue' | 'isSelected' | 'setValue' | 'select' | 'toggle'\n>\n\nexport const XhListboxRoot = defineComponent({\n name: 'XhListboxRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ListboxNode[]> },\n /** 标题文字。提供后不必再写 label 部件;需要放置其他内容时改用 label 插槽。 */\n label: { type: String },\n value: { type: [String, Array] as PropType<string | string[]> },\n defaultValue: { type: [String, Array] as PropType<string | string[]> },\n selectionMode: { type: String as PropType<ListboxSelectionMode> },\n disabled: { type: Boolean, default: undefined },\n readOnly: { type: Boolean, default: undefined },\n invalid: { type: Boolean, default: undefined },\n loading: Boolean,\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n loop: { type: Boolean, default: undefined },\n typeahead: { type: Boolean, default: undefined },\n dir: { type: String as PropType<Direction> },\n orientation: { type: String as PropType<Orientation> },\n },\n // value-change 携带 { value },update:value 携带裸集合;回传值恒为数组,单选时长度 ≤ 1\n emits: {\n 'value-change': (_details: PayloadOf<ListboxProps, 'onValueChange'>) => true,\n 'update:value': (_value: PayloadOf<ListboxProps, 'onValueChange'>['value']) => true,\n },\n slots: Object as SlotsType<{\n default?: (props: ListboxRootSlotProps) => VNode[]\n label?: () => VNode[]\n item?: (node: ListboxNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notify: ListboxProps['onValueChange'] = (details) => {\n emit('value-change', details)\n emit('update:value', details.value)\n }\n const ctx = useListbox(useFormControlProps(props) as ListboxProps, notify)\n provideListbox(ctx)\n return () => h('div', ctx.api.value.getRootProps() as Record<string, unknown>, [\n ...(slots.default\n ? slots.default({\n value: ctx.api.value.value,\n selectionMode: ctx.api.value.selectionMode,\n focusedValue: ctx.api.value.focusedValue,\n isSelected: ctx.api.value.isSelected,\n setValue: ctx.api.value.setValue,\n select: ctx.api.value.select,\n toggle: ctx.api.value.toggle,\n }) ?? []\n : props.collection\n ? renderDefaultTree(\n ctx.api.value.collection,\n slots.label?.() ?? (props.label != null ? [props.label] : null),\n slots.item,\n )\n : []),\n ])\n },\n})\n\nexport const XhListboxLabel = defineComponent({\n name: 'XhListboxLabel',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n return () => h('span', ctx.api.value.getLabelProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxContent = defineComponent({\n name: 'XhListboxContent',\n // 根是片段(列表节点 + 贴层的条子),Vue 不会把直通属性合上去:作者写的 class、style 与 data-* 自己接住落到列表节点上\n inheritAttrs: false,\n setup(_, { slots, attrs }) {\n const ctx = useListboxContext()\n const contentRef = ref<HTMLElement | null>(null)\n // 定高小列表走自绘条(§6.6):条子是 content 的兄弟、挂在 root 这个定位盒上,贴在 content 自己的盒子上\n // (root 里还有标题与占位,贴壳边会盖到它们);两条轴都摆——皮肤给的是两轴 overflow: auto。\n // 页内宿主走 6px 缺省档;横条的正负按排版方向算,把机器里那份 dir 交过去\n const bars = useScrollbars({\n scrollable: () => contentRef.value,\n axes: ['vertical', 'horizontal'],\n anchor: 'layer',\n props: () => ({ dir: ctx.service.prop('dir') }),\n })\n // 条目增减、占位显隐都会挪动列表在壳内的位置与尺寸:每次更新后重量一次偏移盒\n onUpdated(() => bars.measure())\n return () => [\n h('div', {\n ...mergeProps(ctx.api.value.getContentProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { contentRef.value = el as HTMLElement | null },\n }, slots.default?.()),\n ...bars.render(),\n ]\n },\n})\n\nexport const XhListboxEmpty = defineComponent({\n name: 'XhListboxEmpty',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 空态占位:写在 root 里、content 的兄弟,不进列表框的拥有关系。\n // 给了 collection 时收放归连接层,条目手写时归作者\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxLoading = defineComponent({\n name: 'XhListboxLoading',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxLoadMoreTrigger = defineComponent({\n name: 'XhListboxLoadMoreTrigger',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 取下一页的入口:点了做什么归作者,这里只把在途与禁用两档焊成点不动\n return () => h('button', ctx.api.value.getLoadMoreTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxGroup = defineComponent({\n name: 'XhListboxGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useListboxContext()\n const group = computed<ListboxGroupProps>(() => ({ value: props.value }))\n provideListboxItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxGroupLabel = defineComponent({\n name: 'XhListboxGroupLabel',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { group } = useListboxItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxItem = defineComponent({\n name: 'XhListboxItem',\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 = useListboxContext()\n const item = computed<ListboxItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideListboxItem({ item })\n // 本条目持有焦点时,value 变更重报焦点条目,卸载时上报列表失焦\n const itemEl = ref<HTMLElement | null>(null)\n watch(() => props.value, (next, prev) => {\n if (next === prev)\n return\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.FOCUS', value: next })\n })\n onBeforeUnmount(() => {\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n // 按「本节点当下正持有焦点」判定,不按 value 比对\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'LIST.BLUR' })\n })\n return () => h(\n 'div',\n { ...ctx.api.value.getItemProps(item.value) as Record<string, unknown>, ref: itemEl },\n slots.default?.(),\n )\n },\n})\n\nexport const XhListboxItemText = defineComponent({\n name: 'XhListboxItemText',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxItemIndicator = defineComponent({\n name: 'XhListboxItemIndicator',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构(分组、条目外的节点)时写默认插槽。\n */\nfunction renderDefaultTree(\n collection: readonly ListboxNodeMeta[],\n label: (VNode | string)[] | null,\n itemSlot?: (node: ListboxNodeMeta) => VNode[],\n): VNode[] {\n return [\n ...(label ? [h(XhListboxLabel, null, () => label)] : []),\n h(XhListboxContent, null, () => collection.map(node =>\n h(XhListboxItem, { key: node.value, value: node.value }, () => [\n h(XhListboxItemText, null, () => itemSlot?.(node) ?? node.label),\n h(XhListboxItemIndicator),\n ]),\n )),\n ]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"listbox.js","names":[],"sources":["../../../src/components/listbox/listbox.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// 提供 listbox 相关实现。\n\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/core'\nimport type { ListboxApi, ListboxGroupProps, ListboxItemProps, ListboxNode, ListboxNodeMeta, ListboxSchema, ListboxSelectionMode } from '@xihan-ui/headless'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport type { PayloadOf } from '../../runtime/payload'\nimport { computed, defineComponent, h, mergeProps, onBeforeUnmount, onUpdated, ref, watch } from 'vue'\nimport { useScrollbars } from '../../runtime/use-scrollbars'\nimport { useFormControlProps } from '../form/use-form-control'\nimport {\n provideListbox,\n provideListboxItem,\n provideListboxItemGroup,\n useListboxContext,\n useListboxItemContext,\n useListboxItemGroupContext,\n} from './context'\nimport { useListbox } from './use-listbox'\n\ntype ListboxProps = ListboxSchema['props']\n\n/** 默认插槽的载荷:选中集合、选择模式与焦点锚点,以及判定选中与整份赋值、单选、切换的命令。 */\nexport type ListboxRootSlotProps = Pick<\n ListboxApi,\n 'value' | 'selectionMode' | 'focusedValue' | 'isSelected' | 'setValue' | 'select' | 'toggle'\n>\n\nexport const XhListboxRoot = defineComponent({\n name: 'XhListboxRoot',\n // 有 connect 兜底的 prop:普通类型省略 default,Boolean 显式保留 undefined\n props: {\n collection: { type: Array as PropType<ListboxNode[]> },\n /** 标题文字。提供后不必再写 label 部件;需要放置其他内容时改用 label 插槽。 */\n label: { type: String },\n value: { type: [String, Array] as PropType<string | string[]> },\n defaultValue: { type: [String, Array] as PropType<string | string[]> },\n selectionMode: { type: String as PropType<ListboxSelectionMode> },\n disabled: { type: Boolean, default: undefined },\n readOnly: { type: Boolean, default: undefined },\n invalid: { type: Boolean, default: undefined },\n loading: Boolean,\n tone: { type: String as PropType<Tone> },\n size: { type: String as PropType<Size> },\n loop: { type: Boolean, default: undefined },\n typeahead: { type: Boolean, default: undefined },\n dir: { type: String as PropType<Direction> },\n orientation: { type: String as PropType<Orientation> },\n },\n // value-change 携带 { value },update:value 携带裸集合;回传值恒为数组,单选时长度 ≤ 1\n emits: {\n 'value-change': (_details: PayloadOf<ListboxProps, 'onValueChange'>) => true,\n 'update:value': (_value: PayloadOf<ListboxProps, 'onValueChange'>['value']) => true,\n },\n slots: Object as SlotsType<{\n 'default'?: (props: ListboxRootSlotProps) => VNode[]\n 'label'?: () => VNode[]\n /** 只填条目的文字槽,副文本与首尾两格照旧各归各的 */\n 'item'?: (node: ListboxNodeMeta) => VNode[]\n /** 只接管行首那一格,其余槽照旧由数据铺 */\n 'item-prefix'?: (node: ListboxNodeMeta) => VNode[]\n /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */\n 'item-suffix'?: (node: ListboxNodeMeta) => VNode[]\n }>,\n setup(props, { slots, emit }) {\n const notify: ListboxProps['onValueChange'] = (details) => {\n emit('value-change', details)\n emit('update:value', details.value)\n }\n const ctx = useListbox(useFormControlProps(props) as ListboxProps, notify)\n provideListbox(ctx)\n return () => h('div', ctx.api.value.getRootProps() as Record<string, unknown>, [\n ...(slots.default\n ? slots.default({\n value: ctx.api.value.value,\n selectionMode: ctx.api.value.selectionMode,\n focusedValue: ctx.api.value.focusedValue,\n isSelected: ctx.api.value.isSelected,\n setValue: ctx.api.value.setValue,\n select: ctx.api.value.select,\n toggle: ctx.api.value.toggle,\n }) ?? []\n : props.collection\n ? renderDefaultTree(\n ctx.api.value.collection,\n slots.label?.() ?? (props.label != null ? [props.label] : null),\n slots.item,\n slots['item-prefix'],\n slots['item-suffix'],\n )\n : []),\n ])\n },\n})\n\nexport const XhListboxLabel = defineComponent({\n name: 'XhListboxLabel',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n return () => h('span', ctx.api.value.getLabelProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxContent = defineComponent({\n name: 'XhListboxContent',\n // 根是片段(列表节点 + 贴层的条子),Vue 不会把直通属性合上去:作者写的 class、style 与 data-* 自己接住落到列表节点上\n inheritAttrs: false,\n setup(_, { slots, attrs }) {\n const ctx = useListboxContext()\n const contentRef = ref<HTMLElement | null>(null)\n // 定高小列表走自绘条:条子是 content 的兄弟、挂在 root 这个定位盒上,贴在 content 自己的盒子上\n // (root 里还有标题与占位,贴壳边会盖到它们);两条轴都摆——皮肤给的是两轴 overflow: auto。\n // 页内宿主走 6px 缺省档;横条的正负按排版方向算,把机器里那份 dir 交过去\n const bars = useScrollbars({\n scrollable: () => contentRef.value,\n axes: ['vertical', 'horizontal'],\n anchor: 'layer',\n props: () => ({ dir: ctx.service.prop('dir') }),\n })\n // 条目增减、占位显隐都会挪动列表在壳内的位置与尺寸:每次更新后重量一次偏移盒\n onUpdated(() => bars.measure())\n return () => [\n h('div', {\n ...mergeProps(ctx.api.value.getContentProps() as Record<string, unknown>, attrs),\n ref: (el: unknown) => { contentRef.value = el as HTMLElement | null },\n }, slots.default?.()),\n ...bars.render(),\n ]\n },\n})\n\nexport const XhListboxEmpty = defineComponent({\n name: 'XhListboxEmpty',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 空态占位:写在 root 里、content 的兄弟,不进列表框的拥有关系。\n // 给了 collection 时收放归连接层,条目手写时归作者\n return () => h('div', ctx.api.value.getEmptyProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxLoading = defineComponent({\n name: 'XhListboxLoading',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 在途占位:与空态占位同一个位置,取数期间顶上来\n return () => h('div', ctx.api.value.getLoadingProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxLoadMoreTrigger = defineComponent({\n name: 'XhListboxLoadMoreTrigger',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n // 取下一页的入口:点了做什么归作者,这里只把在途与禁用两档焊成点不动\n return () => h('button', ctx.api.value.getLoadMoreTriggerProps() as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxGroup = defineComponent({\n name: 'XhListboxGroup',\n props: {\n value: { type: String, required: true },\n },\n setup(props, { slots }) {\n const ctx = useListboxContext()\n const group = computed<ListboxGroupProps>(() => ({ value: props.value }))\n provideListboxItemGroup({ group })\n return () => h('div', ctx.api.value.getGroupProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxGroupLabel = defineComponent({\n name: 'XhListboxGroupLabel',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { group } = useListboxItemGroupContext()\n return () => h('span', ctx.api.value.getGroupLabelProps(group.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxItem = defineComponent({\n name: 'XhListboxItem',\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 = useListboxContext()\n const item = computed<ListboxItemProps>(() => ({ value: props.value, disabled: props.disabled }))\n provideListboxItem({ item })\n // 本条目持有焦点时,value 变更重报焦点条目,卸载时上报列表失焦\n const itemEl = ref<HTMLElement | null>(null)\n watch(() => props.value, (next, prev) => {\n if (next === prev)\n return\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'ITEM.FOCUS', value: next })\n })\n onBeforeUnmount(() => {\n const { service } = ctx\n if (service.getStatus() !== 'Started')\n return\n // 按「本节点当下正持有焦点」判定,不按 value 比对\n if (itemEl.value && service.scope.getActiveElement() === itemEl.value)\n service.send({ type: 'LIST.BLUR' })\n })\n return () => h(\n 'div',\n { ...ctx.api.value.getItemProps(item.value) as Record<string, unknown>, ref: itemEl },\n slots.default?.(),\n )\n },\n})\n\nexport const XhListboxItemText = defineComponent({\n name: 'XhListboxItemText',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemTextProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */\nexport const XhListboxItemPrefix = defineComponent({\n name: 'XhListboxItemPrefix',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemPrefixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目行尾的作者内容(计数、徽标) */\nexport const XhListboxItemSuffix = defineComponent({\n name: 'XhListboxItemSuffix',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemSuffixProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/** 条目的第 2 行副文本,跨文字槽、走 muted 档 */\nexport const XhListboxItemDescription = defineComponent({\n name: 'XhListboxItemDescription',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemDescriptionProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\nexport const XhListboxItemIndicator = defineComponent({\n name: 'XhListboxItemIndicator',\n setup(_, { slots }) {\n const ctx = useListboxContext()\n const { item } = useListboxItemContext()\n return () => h('span', ctx.api.value.getItemIndicatorProps(item.value) as Record<string, unknown>, slots.default?.())\n },\n})\n\n/**\n * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。\n * 与手写部件产出的 DOM 完全一致,需要修改结构(分组、条目外的节点)时写默认插槽。\n */\nfunction renderDefaultTree(\n collection: readonly ListboxNodeMeta[],\n label: (VNode | string)[] | null,\n itemSlot?: (node: ListboxNodeMeta) => VNode[],\n prefixSlot?: (node: ListboxNodeMeta) => VNode[],\n suffixSlot?: (node: ListboxNodeMeta) => VNode[],\n): VNode[] {\n return [\n ...(label ? [h(XhListboxLabel, null, () => label)] : []),\n h(XhListboxContent, null, () => collection.map(node =>\n h(XhListboxItem, { key: node.value, value: node.value }, () => [\n ...(prefixSlot ? [h(XhListboxItemPrefix, null, () => prefixSlot(node))] : []),\n h(XhListboxItemText, null, () => itemSlot?.(node) ?? node.label),\n ...(node.description != null ? [h(XhListboxItemDescription, null, () => node.description)] : []),\n ...(suffixSlot ? [h(XhListboxItemSuffix, null, () => suffixSlot(node))] : []),\n h(XhListboxItemIndicator),\n ]),\n )),\n ]\n}\n"],"mappings":"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"}
@@ -146,6 +146,10 @@ declare const XhMentionRoot: import("vue").DefineComponent<import("vue").Extract
146
146
  default?: (props: MentionRootSlotProps) => VNode[];
147
147
  /** 铺开 collection 时每条候选的文本插槽。 */
148
148
  item?: (props: MentionNodeMeta) => VNode[];
149
+ /** 只接管行首那一格,其余槽照旧由数据铺 */
150
+ 'item-prefix'?: (props: MentionNodeMeta) => VNode[];
151
+ /** 只接管行尾那一格(计数、徽标、次级图标),其余槽照旧由数据铺 */
152
+ 'item-suffix'?: (props: MentionNodeMeta) => VNode[];
149
153
  /** 铺开 collection 时空态中的文案;未写时使用内建英文。 */
150
154
  empty?: () => VNode[];
151
155
  }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -207,6 +211,18 @@ declare const XhMentionItem: import("vue").DefineComponent<import("vue").Extract
207
211
  declare const XhMentionItemText: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
208
212
  [key: string]: any;
209
213
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
214
+ /** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
215
+ declare const XhMentionItemPrefix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
216
+ [key: string]: any;
217
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
218
+ /** 条目行尾的作者内容(计数、徽标) */
219
+ declare const XhMentionItemSuffix: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
220
+ [key: string]: any;
221
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
222
+ /** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
223
+ declare const XhMentionItemDescription: import("vue").DefineComponent<{}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
224
+ [key: string]: any;
225
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
210
226
  //#endregion
211
- export { MentionRootSlotProps, XhMentionContent, XhMentionEmpty, XhMentionInput, XhMentionItem, XhMentionItemText, XhMentionLabel, XhMentionLoading, XhMentionPositioner, XhMentionRoot };
227
+ export { MentionRootSlotProps, XhMentionContent, XhMentionEmpty, XhMentionInput, XhMentionItem, XhMentionItemDescription, XhMentionItemPrefix, XhMentionItemSuffix, XhMentionItemText, XhMentionLabel, XhMentionLoading, XhMentionPositioner, XhMentionRoot };
212
228
  //# sourceMappingURL=mention.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mention.d.ts","names":[],"sources":["../../../src/components/mention/mention.ts"],"mappings":";;;;;KAoBK,eAAe;;KAGR,uBAAuB,KACjC;cAUW,6BAAa,8BAAA;;IAIoB,MAAA;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUT,MAAA,SAAS;;;;;;;IAGf,MAAA,SAAS;;;IACA,MAAA,SAAS;;;IACd,MAAA,SAAS;;;IACZ,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;EAIN,iBAAA,UAAA,UAAU;EACV,iBAAA,UAAA,UAAU;EAChB,SAAA,UAAA,UAAU;EACL,gBAAA,UAAA,UAAU;EACX,iBAAA,QAAA,UAAU;;;IA1BO,MAAA;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUT,MAAA,SAAS;;;;;;;IAGf,MAAA,SAAS;;;IACA,MAAA,SAAS;;;IACd,MAAA,SAAS;;;IACZ,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;;;;;EAWvB,WAAC,OAAO,yBAAyB;;EAEpC,QAAC,OAAO,oBAAoB;;EAE3B,cAAM;kCAyChB;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAczB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,mCAAmB,8BAAA;;;IAIC,MAAA,SAAS;;;;;;;IAAT,MAAA,SAAS;;MAgBxC,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAY3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAM3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAkBxB;cAEW,iCAAiB,0BAAA,oBAAA,4BAAA;;8BAO5B,qCAAA,iDAAA,aAAA,eAAA,oDAAA"}
1
+ {"version":3,"file":"mention.d.ts","names":[],"sources":["../../../src/components/mention/mention.ts"],"mappings":";;;;;KAoBK,eAAe;;KAGR,uBAAuB,KACjC;cAUW,6BAAa,8BAAA;;IAIoB,MAAA;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUT,MAAA,SAAS;;;;;;;IAGf,MAAA,SAAS;;;IACA,MAAA,SAAS;;;IACd,MAAA,SAAS;;;IACZ,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;EAIN,iBAAA,UAAA,UAAU;EACV,iBAAA,UAAA,UAAU;EAChB,SAAA,UAAA,UAAU;EACL,gBAAA,UAAA,UAAU;EACX,iBAAA,QAAA,UAAU;;;IA1BO,MAAA;;;IACb,MAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUT,MAAA,SAAS;;;;;;;IAGf,MAAA,SAAS;;;IACA,MAAA,SAAS;;;IACd,MAAA,SAAS;;;IACZ,MAAA,SAAS;;;IACT,MAAA,SAAS;;;;;;;;;;;;;;;EAWrB,WAAC,OAAO,yBAAyB;;EAEpC,QAAC,OAAO,oBAAoB;;EAErB,iBAAC,OAAO,oBAAoB;;EAE5B,iBAAC,OAAO,oBAAoB;;EAElC,cAAM;kCAyClB;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAczB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,mCAAmB,8BAAA;;;IAIC,MAAA,SAAS;;;;;;;IAAT,MAAA,SAAS;;MAgBxC,oDAAA;cAEW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAY3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,8BAAc,0BAAA,oBAAA,4BAAA;;8BAMzB,qCAAA,iDAAA,aAAA,eAAA,oDAAA;;cAGW,gCAAgB,0BAAA,oBAAA,4BAAA;;8BAM3B,qCAAA,iDAAA,aAAA,eAAA,oDAAA;cAEW,6BAAa,8BAAA;;;;;;;;;;;;;;;;;;;;;;qCAkBxB;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"}
@@ -75,7 +75,7 @@ const XhMentionRoot = defineComponent({
75
75
  highlightedValue: ctx.api.value.highlightedValue,
76
76
  setValue: ctx.api.value.setValue,
77
77
  close: ctx.api.value.close
78
- }) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.item, slots.empty) : []);
78
+ }) : props.collection ? renderDefaultTree(ctx.api.value.collection, slots.item, slots["item-prefix"], slots["item-suffix"], slots.empty) : []);
79
79
  }
80
80
  });
81
81
  /** 标题;必须是原生 label,getLabelProps 的 for 恒指向输入框。 */
@@ -187,19 +187,51 @@ const XhMentionItemText = defineComponent({
187
187
  return () => h("span", ctx.api.value.getItemTextProps(item.value), slots.default?.());
188
188
  }
189
189
  });
190
+ /** 条目行首的作者内容(图标、色块、头像),对读屏隐藏 */
191
+ const XhMentionItemPrefix = defineComponent({
192
+ name: "XhMentionItemPrefix",
193
+ setup(_, { slots }) {
194
+ const ctx = useMentionContext();
195
+ const { item } = useMentionItemContext();
196
+ return () => h("span", ctx.api.value.getItemPrefixProps(item.value), slots.default?.());
197
+ }
198
+ });
199
+ /** 条目行尾的作者内容(计数、徽标) */
200
+ const XhMentionItemSuffix = defineComponent({
201
+ name: "XhMentionItemSuffix",
202
+ setup(_, { slots }) {
203
+ const ctx = useMentionContext();
204
+ const { item } = useMentionItemContext();
205
+ return () => h("span", ctx.api.value.getItemSuffixProps(item.value), slots.default?.());
206
+ }
207
+ });
208
+ /** 条目的第 2 行副文本,跨文字槽、走 muted 档 */
209
+ const XhMentionItemDescription = defineComponent({
210
+ name: "XhMentionItemDescription",
211
+ setup(_, { slots }) {
212
+ const ctx = useMentionContext();
213
+ const { item } = useMentionItemContext();
214
+ return () => h("span", ctx.api.value.getItemDescriptionProps(item.value), slots.default?.());
215
+ }
216
+ });
190
217
  /**
191
218
  * 未写默认插槽时按 collection 铺开的整套结构,作者只提供数据。
192
219
  * 与手写部件产出的 DOM 完全一致,需要修改结构时写默认插槽,行为不变。
193
220
  * 过滤仍归调用方:collection 就是当前应显示的候选。
194
221
  */
195
- function renderDefaultTree(collection, itemSlot, emptySlot) {
222
+ function renderDefaultTree(collection, itemSlot, prefixSlot, suffixSlot, emptySlot) {
196
223
  const emptyText = emptySlot?.() ?? "No results";
197
224
  return [h(XhMentionInput), h(XhMentionPositioner, null, () => [h(XhMentionContent, null, () => collection.map((node) => h(XhMentionItem, {
198
225
  key: node.value,
199
226
  value: node.value
200
- }, () => [h(XhMentionItemText, null, () => itemSlot?.(node) ?? node.label)]))), h(XhMentionEmpty, null, () => emptyText)])];
227
+ }, () => [
228
+ ...prefixSlot ? [h(XhMentionItemPrefix, null, () => prefixSlot(node))] : [],
229
+ h(XhMentionItemText, null, () => itemSlot?.(node) ?? node.label),
230
+ ...node.description != null ? [h(XhMentionItemDescription, null, () => node.description)] : [],
231
+ ...suffixSlot ? [h(XhMentionItemSuffix, null, () => suffixSlot(node))] : []
232
+ ]))), h(XhMentionEmpty, null, () => emptyText)])];
201
233
  }
202
234
  //#endregion
203
- export { XhMentionContent, XhMentionEmpty, XhMentionInput, XhMentionItem, XhMentionItemText, XhMentionLabel, XhMentionLoading, XhMentionPositioner, XhMentionRoot };
235
+ export { XhMentionContent, XhMentionEmpty, XhMentionInput, XhMentionItem, XhMentionItemDescription, XhMentionItemPrefix, XhMentionItemSuffix, XhMentionItemText, XhMentionLabel, XhMentionLoading, XhMentionPositioner, XhMentionRoot };
204
236
 
205
237
  //# sourceMappingURL=mention.js.map