@xihan-ui/web-components 1.0.0-alpha.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.js","names":["ITEM_SELECTOR","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","authorFlag","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","declaredIndex","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","ITEM_SELECTOR","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","#paint","#painted","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","declaredIndex","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","declaredIndex","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","declaredIndex","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","NUMBER_CONVERTER","TRISTATE_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","declaredIndex","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","#paint","#painted","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","SVG_NS","#glyphOwned","#ownsGlyph","#paint","#report","#painted","STRING_CONVERTER","NUMBER_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","authorDisabled","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","ARRAY_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","#paint","#painted","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","NUMBER_LIST_CONVERTER","STRING_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","ITEM_SELECTOR","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","#paintText","#painted","STRING_CONVERTER","BOOLEAN_CONVERTER","HOUR_CYCLE_CONVERTER","SEGMENT_TYPES","declaredSegment","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","ITEM_SELECTOR","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","BOOLEAN_CONVERTER","ITEM_SELECTOR","BRANCH_SELECTOR","STRING_CONVERTER","NUMBER_CONVERTER","BOOLEAN_CONVERTER","STRING_CONVERTER","NUMBER_CONVERTER","VERSION"],"sources":["../src/dom/part-contract.ts","../src/element-base.ts","../src/elements/accordion.ts","../src/elements/affix.ts","../src/elements/alert.ts","../src/elements/anchor.ts","../src/elements/avatar.ts","../src/elements/avatar-group.ts","../src/elements/back-top.ts","../src/elements/badge.ts","../src/elements/breadcrumb.ts","../src/elements/button.ts","../src/elements/button-group.ts","../src/elements/calendar.ts","../src/elements/card.ts","../src/elements/carousel.ts","../src/elements/cascader.ts","../src/elements/checkbox.ts","../src/dom/declared-disabled.ts","../src/elements/checkbox-group.ts","../src/elements/clipboard.ts","../src/elements/code-block.ts","../src/elements/collapsible.ts","../src/elements/color-picker.ts","../src/elements/combobox.ts","../src/elements/composer.ts","../src/elements/context-menu.ts","../src/elements/countdown.ts","../src/elements/date-field.ts","../src/elements/date-picker.ts","../src/elements/descriptions.ts","../src/elements/dialog.ts","../src/elements/drawer.ts","../src/elements/dynamic-input.ts","../src/elements/editable.ts","../src/elements/ellipsis.ts","../src/elements/empty-state.ts","../src/elements/field.ts","../src/elements/file-upload.ts","../src/elements/flex.ts","../src/elements/float-button.ts","../src/elements/form.ts","../src/elements/gradient-text.ts","../src/elements/grid.ts","../src/elements/highlight.ts","../src/elements/hover-card.ts","../src/elements/icon.ts","../src/elements/icon-wrapper.ts","../src/elements/image.ts","../src/elements/infinite-scroll.ts","../src/elements/layout.ts","../src/elements/list.ts","../src/elements/listbox.ts","../src/elements/loading-bar.ts","../src/elements/log.ts","../src/elements/marquee.ts","../src/elements/mention.ts","../src/elements/menu.ts","../src/elements/menubar.ts","../src/elements/navigation-menu.ts","../src/elements/number-animation.ts","../src/elements/number-field.ts","../src/elements/page-header.ts","../src/elements/pagination.ts","../src/elements/pin-input.ts","../src/elements/popconfirm.ts","../src/elements/popover.ts","../src/elements/popselect.ts","../src/elements/progress.ts","../src/elements/qr-code.ts","../src/elements/radio-group.ts","../src/elements/rating.ts","../src/elements/result.ts","../src/elements/scroll-area.ts","../src/elements/select.ts","../src/elements/separator.ts","../src/elements/skeleton.ts","../src/elements/slider.ts","../src/elements/spinner.ts","../src/elements/splitter.ts","../src/elements/statistic.ts","../src/elements/steps.ts","../src/elements/switch.ts","../src/elements/table.ts","../src/elements/tabs.ts","../src/elements/tags-input.ts","../src/elements/text-field.ts","../src/elements/thread.ts","../src/elements/time.ts","../src/elements/time-field.ts","../src/elements/time-picker.ts","../src/elements/timeline.ts","../src/elements/toast.ts","../src/elements/toaster.ts","../src/elements/toggle.ts","../src/elements/toggle-group.ts","../src/elements/toolbar.ts","../src/elements/tooltip.ts","../src/elements/tour.ts","../src/elements/transfer.ts","../src/elements/tree.ts","../src/elements/tree-select.ts","../src/elements/typography.ts","../src/elements/virtualizer.ts","../src/elements/watermark.ts","../src/define.ts"],"sourcesContent":["// 角色节点契约校验:作者写的 Light DOM 与组件解剖对不上时投递诊断。\nimport type { ComponentMeta } from '@xihan-ui/headless'\nimport { DIAGNOSTIC_CODES, getDiagnostics, reportDiagnostic } from '@xihan-ui/kernel'\n\n/** 只取校验用得上的两项,避免把 `Anatomy<具体 part 联合>` 收窄成 `Anatomy<string>` 时不可赋值。 */\nexport interface PartContract {\n readonly anatomy: { readonly name: string, readonly parts: readonly string[] }\n readonly meta: ComponentMeta\n /**\n * 部件必须用的标签名。只登记「写错了会静默失效」的那些——\n * 比如 field 的 label 不是原生 `<label>` 时,`for` 整条失效,点标签不再聚焦控件。\n */\n readonly tags?: Readonly<Record<string, readonly string[]>>\n /**\n * 委派出去的内嵌部件解剖。\n *\n * 有的宿主把内嵌部件的 DOM 摊在自己的 Light DOM 里接线(date-picker 之于 date-field 与\n * calendar 就是这样),这些角色节点归内嵌部件的 scope 管,本就不该出现在宿主自己的解剖里。\n * 不登记的话它们会被当成解剖外的野节点逐个报警,而它们恰恰是被正常接线的。\n */\n readonly delegates?: readonly { readonly name: string, readonly parts: readonly string[] }[]\n}\n\n/**\n * 比对已发现的角色节点与契约:缺必需 part 报 error,出现解剖外的 part 名报 warn。\n * 通道静默时直接返回,不做扫描。\n */\nexport function validatePartContract(\n contract: PartContract,\n parts: ReadonlyMap<string, HTMLElement[]>,\n host: HTMLElement,\n instanceId: string,\n): void {\n if (getDiagnostics().getLevel() === 'silent')\n return\n\n const scope = contract.anatomy.name\n\n for (const part of contract.meta.requiredParts) {\n if (parts.has(part))\n continue\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.wcMissingPart,\n level: 'error',\n message: `缺少必需的角色节点 data-xh-part=\"${part}\",该部件不会被接线`,\n scope,\n instanceId,\n part,\n node: host,\n detail: { tag: host.tagName.toLowerCase(), requiredParts: contract.meta.requiredParts },\n })\n }\n\n const known = new Set<string>(contract.anatomy.parts)\n for (const delegate of contract.delegates ?? []) {\n for (const part of delegate.parts)\n known.add(part)\n }\n for (const part of parts.keys()) {\n if (known.has(part))\n continue\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.wcUnknownPart,\n level: 'warn',\n message: `角色节点 data-xh-part=\"${part}\" 不在 ${scope} 的解剖内,不会被接线`,\n scope,\n instanceId,\n part,\n node: parts.get(part)?.[0] ?? host,\n detail: { tag: host.tagName.toLowerCase(), knownParts: contract.anatomy.parts },\n })\n }\n\n for (const [part, allowed] of Object.entries(contract.tags ?? {})) {\n for (const el of parts.get(part) ?? []) {\n const tag = el.tagName.toLowerCase()\n if (allowed.includes(tag))\n continue\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.wcWrongPartTag,\n level: 'warn',\n message: `角色节点 data-xh-part=\"${part}\" 是 <${tag}>,须是 ${allowed.map(t => `<${t}>`).join(' 或 ')},否则原生语义静默失效`,\n scope,\n instanceId,\n part,\n node: el,\n detail: { tag, allowed },\n })\n }\n }\n}\n","import type { PartContract } from './dom/part-contract'\nimport type { Spreader } from './dom/spread'\nimport { validatePartContract } from './dom/part-contract'\nimport { containsPart, discoverParts } from './dom/parts'\nimport { createSpreader } from './dom/spread'\nimport { XhReactiveElement } from './reactive'\n\nlet instanceSeq = 0\n\n/**\n * 变动里是否真有角色节点进出。只认\"进出的元素自身是角色节点、或其子树里有角色节点\":\n * 业务内容(图表、虚拟列表、面板里的业务 DOM)的增删与 part 集合无关,不该引发重新接线;\n * 更要紧的是断掉一条死循环——角色节点若本身是会在属性变化时改写自身子节点的自定义元素,\n * \"宿主重新接线 → 写属性 → 该节点改子节点 → 又命中观察器\" 会闭成环。\n */\nfunction touchesParts(record: MutationRecord): boolean {\n for (const list of [record.addedNodes, record.removedNodes]) {\n for (const node of Array.from(list)) {\n if (node.nodeType === 1 && containsPart(node as Element))\n return true\n }\n }\n return false\n}\n\n/**\n * 角色节点上属于作者的\"声明\"(与机器写上去的\"状态\"分属两侧),改了就等于换了一个条目,必须重新接线。\n * 只盯这几个而不是所有属性:wire() 每帧都往角色节点写 aria- 与 data-,全量观察等于自己触发自己。\n */\nconst AUTHORED_ATTRS = ['value', 'disabled', 'aria-disabled'] as const\n\nfunction rewritesDeclaration(record: MutationRecord): boolean {\n if (record.type !== 'attributes' || !record.attributeName)\n return false\n const el = record.target as Element\n return containsPart(el) && (AUTHORED_ATTRS as readonly string[]).includes(record.attributeName)\n}\n\n// Light-DOM 行为宿主基类:不渲染结构,发现用户写的 data-xh-part 角色节点并往上打属性/事件。\nexport abstract class XhElement extends XhReactiveElement {\n /** 子类声明所属组件的解剖与元数据,接线后据它校验作者写的角色节点。 */\n static partContract?: PartContract\n\n protected readonly spreader: Spreader = createSpreader()\n protected partMap: Map<string, HTMLElement[]> = new Map()\n private partObserver: MutationObserver | undefined\n private readonly instanceId = `${++instanceSeq}`\n\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n return this // Light DOM,不建 shadowRoot\n }\n\n // 取角色节点,命名避开 HTMLElement.part。\n protected getPart(name: string, index = 0): HTMLElement | null {\n return this.partMap.get(name)?.[index] ?? null\n }\n\n protected getParts(name: string): HTMLElement[] {\n return this.partMap.get(name) ?? []\n }\n\n /** 接管前记下角色节点上作者写的内联 display。 */\n private readonly authorDisplay = new WeakMap<HTMLElement, string>()\n\n /**\n * 用内联 display 兜住收起态:作者层若给这个 part 声明了 display,会盖过 UA 的 `[hidden]{display:none}`,\n * 光靠 hidden 属性收不起来。展开时还回作者原本的内联值而不是清成 ''——后者会把作者写在该节点上的\n * `style=\"display:grid\"` 一并抹掉,且再也回不来。\n */\n protected setPartHidden(el: HTMLElement | null, hidden: boolean): void {\n if (!el)\n return\n if (!this.authorDisplay.has(el))\n this.authorDisplay.set(el, el.style.display)\n el.style.display = hidden ? 'none' : (this.authorDisplay.get(el) ?? '')\n }\n\n protected refreshParts(): void {\n const next = discoverParts(this as unknown as HTMLElement)\n const live = new Set<HTMLElement>()\n for (const els of next.values()) {\n for (const el of els) live.add(el)\n }\n const gone: HTMLElement[] = []\n for (const els of this.partMap.values()) {\n for (const el of els) {\n if (!live.has(el))\n gone.push(el)\n }\n }\n // 先知会子类再交还:release 会撤掉本机器写过的属性,身份标记(data-value 等)一并消失,之后就认不出离场的是哪个条目\n if (gone.length)\n this.onPartsReleased(gone)\n // 离开本宿主的角色节点必须交还:否则它带着本机器的属性与监听器走,被挪进另一台同类元素后\n // 会同时挂上两台机器的处理器(一次点击驱动两台);单纯被移除的节点也仍能派事件、改本组状态\n for (const el of gone) this.spreader.release(el)\n this.partMap = next\n }\n\n /**\n * 角色节点即将离开本宿主时的回调,交还前调用(节点上还带着本机器写的标记)。\n * 承载焦点的节点被移除时浏览器不派 focusout(Chrome 如此),机器读不到这件事,需要焦点语义的子类在此如实上报。\n */\n protected onPartsReleased(_nodes: readonly HTMLElement[]): void {}\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.observeParts()\n // 重连(元素在 DOM 中被移动)时 controller 会重建机器,但重建前后状态相同、cell 不 bump 版本,\n // 于是不会自动排更新——wire 不再跑,角色节点上仍挂着指向已停机器的处理器(送事件会被静默丢弃,等于全是死的)。\n // 这里显式排一次;首帧与基类的初次更新合并,不多跑一帧\n this.requestUpdate()\n }\n\n /** 已排了断开后的交还,还没跑到。 */\n private releaseScheduled = false\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.partObserver?.disconnect()\n this.partObserver = undefined\n this.scheduleRelease()\n }\n\n /**\n * 排一次断开后的交还,到微任务里再按 isConnected 决定跑不跑。\n * 元素被移动(remove 后同步 append 到别处)走的也是 disconnect,延到微任务才分得清移动与真离场。\n */\n private scheduleRelease(): void {\n if (this.releaseScheduled)\n return\n this.releaseScheduled = true\n queueMicrotask(() => {\n this.releaseScheduled = false\n if (!this.isConnected)\n this.releaseAllParts()\n })\n }\n\n /**\n * 交还全部角色节点并清空 partMap,重连时由 refreshParts 重新发现。\n * 宿主离场后没有观察器再触发更新,refreshParts 那条交还路径够不着,没摘的监听器会经节点钉住整台宿主。\n */\n private releaseAllParts(): void {\n const gone: HTMLElement[] = []\n for (const els of this.partMap.values()) gone.push(...els)\n if (!gone.length)\n return\n this.onPartsReleased(gone)\n for (const el of gone) this.spreader.release(el)\n this.partMap = new Map()\n }\n\n /** 标记 wire() 正在写属性。 */\n private wiring = false\n\n /**\n * 作者在运行期改动 Light DOM 后重新接线,两类改动都要接住:增删角色节点(漏掉会留下没有\n * data-scope/data-part 与处理器的\"死条目\");原地改写节点上的声明(列表换数据复用节点时就是这形状,\n * 漏掉会留着上一轮写的 aria-selected=\"true\",而它自称的 value 已经变了,读屏念出的选中项就不是真的选中项)。\n */\n private observeParts(): void {\n if (this.partObserver)\n return\n this.partObserver = new MutationObserver((records) => {\n if (this.wiring)\n return\n const hit = records.some(r => (touchesParts(r) || rewritesDeclaration(r)) && this.ownsSubtree(r.target))\n if (hit)\n this.requestUpdate()\n })\n this.partObserver.observe(this, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [...AUTHORED_ATTRS],\n })\n }\n\n /** 目标是否归本宿主管:嵌套 xh-* 子树归内层元素自己管,外层不替它重跑 wire(discoverParts 本来也跳过它们)。 */\n private ownsSubtree(target: Node): boolean {\n for (let node: Node | null = target; node; node = node.parentNode) {\n if (node === this)\n return true\n const tag = (node as Element).tagName\n if (typeof tag === 'string' && tag.toLowerCase().startsWith('xh-'))\n return false\n }\n return false\n }\n\n protected override updated(changed: Map<PropertyKey, unknown>): void {\n super.updated(changed)\n // 断开的宿主机器已停机,再接线只会把指向死机器的监听器挂回去、覆盖已接管这些节点的存活宿主;\n // 重连时 connectedCallback 会排一轮补上\n if (!this.isConnected)\n return\n this.refreshParts()\n const contract = (this.constructor as typeof XhElement).partContract\n if (contract)\n validatePartContract(contract, this.partMap, this as unknown as HTMLElement, this.instanceId)\n // 观察器与 wire() 写的是同一批节点,不圈出本区间会自己触发自己;观察器回调是微任务,故圈到微任务排空为止。\n this.wiring = true\n try {\n this.wire()\n }\n finally {\n queueMicrotask(() => {\n this.wiring = false\n })\n }\n }\n\n /** 子类实现:把 connect 产出打到角色节点上。 */\n protected abstract wire(): void\n}\n","import type { AccordionItemProps, AccordionNode, AccordionSchema, AccordionValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport { isItemDisabled } from '@xihan-ui/behavior'\nimport { accordionAnatomy, accordionMachine, accordionMeta, connectAccordion } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n\n/**\n * `<xh-accordion>` —— 手风琴行为宿主,条目身份写在 item 节点的 value 属性上。\n *\n * @customElement xh-accordion\n * @attr {'ltr'|'rtl'} dir - 文字方向,影响水平轴左右键语义\n * @attr {boolean} multiple - 允许多项同时展开\n * @attr {boolean} collapsible - 允许把最后一个展开项收起\n * @attr {'horizontal'|'vertical'} orientation - 方向键轴向,默认 vertical\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 展开集合变化;detail 为 `{ value: string[] }`\n * @csspart root - 手风琴根容器\n * @csspart item - 单个条目容器,作者在此写 value 与可选 disabled\n * @csspart header - 条目标题\n * @csspart trigger - 展开/收起按钮\n * @csspart content - 条目面板,收起时带 hidden\n * @csspart indicator - 展开方向指示符\n */\nexport class XhAccordionElement extends XhElement {\n static override partContract = { anatomy: accordionAnatomy, meta: accordionMeta }\n\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的标题文本与禁用即以数据为准\n collection: { attribute: false },\n // 展开集合是字符串数组,只走 property\n value: { attribute: false },\n defaultValue: { attribute: false },\n multiple: { type: Boolean },\n collapsible: { type: Boolean },\n orientation: {},\n // property 另起名字,避开 HTMLElement 自带的 dir 存取器\n textDir: { attribute: 'dir' },\n tone: {},\n size: {},\n }\n\n declare collection?: AccordionNode[]\n declare value?: string[]\n declare defaultValue?: string[]\n declare multiple?: boolean\n declare collapsible?: boolean\n declare orientation?: Orientation\n declare textDir?: Direction\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: AccordionValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<AccordionSchema>(\n this,\n accordionMachine,\n () => this.machineProps(),\n )\n\n private machineProps(): Partial<AccordionSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n multiple: this.multiple ?? false,\n collapsible: this.collapsible ?? false,\n orientation: this.orientation,\n dir: this.textDir,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n /** 取角色节点所属条目的 value 与 disabled,向上找本宿主内的 item,没有则读节点自身。 */\n private itemProps(el: HTMLElement): AccordionItemProps {\n const owner = el.closest<HTMLElement>(ITEM_SELECTOR)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n // 节点上没写禁用就报 undefined,交给 connect 回 collection 里查\n return { value: source.getAttribute('value') ?? '', disabled: isItemDisabled(source) || undefined }\n }\n\n protected wire(): void {\n const api = connectAccordion(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 集合类 part 逐个 spread,身份由节点自报,不依赖下标。\n const putAll = (name: string, get: (item: AccordionItemProps) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(this.itemProps(el)) as Record<string, unknown>)\n }\n putAll('item', item => api.getItemProps(item))\n putAll('header', item => api.getHeaderProps(item))\n putAll('trigger', item => api.getTriggerProps(item))\n // content 收起靠 connect 给的 hidden 属性\n putAll('content', item => api.getContentProps(item))\n putAll('indicator', item => api.getIndicatorProps(item))\n }\n}\n","import type { AffixChangeDetails, AffixSchema } from '@xihan-ui/headless'\nimport type { Service } from '@xihan-ui/machine'\nimport { affixAnatomy, affixMachine, affixMeta, connectAffix } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-affix>` —— 吸附行为宿主:滚过判定线就把 content 钉在滚动容器可视区的边上。\n *\n * root 是占位盒,content 吸住时脱离常规流,root 留在原位撑住那块空间,页面不跳。\n * 判定与量测都在机器的效应里做:挂载后推迟一拍量一次,此后跟着 scroll 与 resize 走。\n * 钉住的落位(top / bottom / left / width)由机器量好写进 content 的内联样式,\n * 皮肤只按 data-affixed 给 position 与层级。\n *\n * @customElement xh-affix\n * @attr {number} offset-top - 吸住后距滚动容器可视区上边的距离(px),默认 0\n * @attr {number} offset-bottom - 吸住后距可视区下边的距离(px);给了它就改贴下边\n * @fires affix-change - 吸附状态变化;detail 为 `{ affixed: boolean }`\n * @csspart root - 占位盒,吸住时带上冻结的高度\n * @csspart content - 真正被钉住的那块内容,吸住时带 data-affixed\n */\nexport class XhAffixElement extends XhElement {\n static override partContract = { anatomy: affixAnatomy, meta: affixMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // offsetTop / offsetBottom 撞 HTMLElement 的原生只读属性,字段改名,属性名不变\n topOffset: { converter: NUMBER_CONVERTER, attribute: 'offset-top' },\n bottomOffset: { converter: NUMBER_CONVERTER, attribute: 'offset-bottom' },\n // 滚动容器是 DOM 句柄,只走 property;不给即整页滚动\n target: { attribute: false },\n }\n\n declare topOffset?: number\n declare bottomOffset?: number\n declare target?: HTMLElement | null\n\n private readonly notify = (details: AffixChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('affix-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<AffixSchema>(\n this,\n affixMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<AffixSchema['props']> {\n return {\n offsetTop: this.topOffset,\n offsetBottom: this.bottomOffset,\n onAffixChange: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n // 取值口惰性读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n private injectRefs(svc: Service<AffixSchema>): void {\n svc.refs.set('getRootEl', () => this.getPart('root'))\n svc.refs.set('getTargetEl', () => this.target ?? null)\n }\n\n protected wire(): void {\n const api = connectAffix(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n }\n}\n","import type { AlertOpenChangeDetails, AlertSchema } from '@xihan-ui/headless'\nimport type { Tone } from '@xihan-ui/kernel'\nimport { alertAnatomy, alertMachine, alertMeta, connectAlert } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-alert>` —— Light-DOM 行为宿主,把 alert 机器打到 root/icon/title/description/close-trigger\n * 角色节点,收起时用内联 style.display 隐藏 root。\n *\n * @customElement xh-alert\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定实时区级别与配色\n * @attr {boolean} closable - 关闭按钮是否可用,缺省为真\n * @attr {boolean} open - 受控显隐;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始显隐,缺省为显示\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 提示根容器(实时区所在)\n * @csspart icon - 语气图标(对读屏隐藏)\n * @csspart title - 标题(root 的 aria-labelledby 指向它)\n * @csspart description - 说明(root 的 aria-describedby 指向它)\n * @csspart close-trigger - 关闭按钮\n */\nexport class XhAlertElement extends XhElement {\n static override partContract = { anatomy: alertAnatomy, meta: alertMeta }\n\n // 三个布尔都用三态转换器:属性缺席翻成 undefined,缺省值由机器与 connect 决定;\n // 用 Lit 自带的 Boolean 转换器的话,缺省为真的 closable / default-open 永远关不掉\n static override properties = {\n tone: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n closable: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n open: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n defaultOpen: {\n attribute: 'default-open',\n converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') },\n },\n // 文案是对象,只能走 property\n translations: { attribute: false },\n }\n\n declare tone?: Tone\n declare closable?: boolean\n declare open?: boolean\n declare defaultOpen?: boolean\n declare translations?: AlertSchema['props']['translations']\n\n private readonly notify = (details: AlertOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<AlertSchema>(\n this,\n alertMachine,\n () => this.machineProps(),\n )\n\n private machineProps(): Partial<AlertSchema['props']> {\n return {\n tone: this.tone,\n closable: this.closable,\n open: this.open,\n defaultOpen: this.defaultOpen,\n translations: this.translations,\n onOpenChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectAlert(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('icon', api.getIconProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n\n // 收起时用内联 display 隐藏整块提示\n this.setPartHidden(this.getPart('root'), !api.open)\n }\n}\n","import type { AnchorSchema, AnchorTranslations, AnchorValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { anchorAnatomy, anchorMachine, anchorMeta, connectAnchor } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined、在场=true、显式写 \"false\"=false\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-anchor>` —— 锚点导航行为宿主,激活项由机器的滚动观察器结算,\n * 目标区块按 link 上的 value 属性(或 targets 清单)里的 id 现查。\n *\n * 作者须写对标签:root 是 `<nav>`,list 是 `<ul>`,item 是 `<li>`,link 是 `<a>`;\n * href 由元素按 value 派生。\n *\n * @customElement xh-anchor\n * @attr {string} value - 受控激活项;缺省该属性即非受控\n * @attr {string} default-value - 非受控的初始激活项\n * @attr {number} offset - 判定线距滚动容器视口顶边的距离(px),默认 0\n * @attr {boolean} smooth - 点链接时平滑滚动到目标,默认关闭\n * @attr {'horizontal'|'vertical'} orientation - 列表轴向,默认 vertical\n * @attr {'ltr'|'rtl'} dir - 文字方向;不给则继承祖先\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 激活项变化;detail 为 `{ value: string | null }`\n * @csspart root - nav 地标,承载 aria-label\n * @csspart list - ul 容器,同时是指示条定位的参照系\n * @csspart item - li 条目\n * @csspart link - a 链接,须自带 value 属性标识目标区块 id;当前那条报 aria-current=\"location\"\n * @csspart indicator - 指示条,须写成 `<li>` 并住在 list 里;对读屏隐藏,\n * 位置由机器量好写成内联样式,无激活项时 hidden\n */\nexport class XhAnchorElement extends XhElement {\n static override partContract = { anatomy: anchorAnatomy, meta: anchorMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n offset: { converter: NUMBER_CONVERTER },\n smooth: { converter: BOOLEAN_CONVERTER },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 清单与文案是对象,只走 property\n targets: { attribute: false },\n translations: { attribute: false },\n // 滚动容器是 DOM 句柄,只走 property;不给即挂在窗口上\n scrollElement: { attribute: false },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare offset?: number\n declare smooth?: boolean\n declare orientation?: Orientation\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n declare targets?: readonly string[]\n declare translations?: Partial<AnchorTranslations>\n declare scrollElement?: HTMLElement | null\n\n private readonly notify = (details: AnchorValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<AnchorSchema>(\n this,\n anchorMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<AnchorSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n targets: this.targets,\n offset: this.offset,\n smooth: this.smooth,\n orientation: this.orientation,\n dir: this.direction,\n translations: this.translations,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<AnchorSchema>): void {\n svc.refs.set('getListEl', () => this.getPart('list'))\n svc.refs.set('getScrollEl', () => this.scrollElement ?? null)\n }\n\n protected wire(): void {\n const api = connectAnchor(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('list', api.getListProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps() as Record<string, unknown>)\n\n // 逐个打 link,身份取作者写的 value(即目标区块的 id)\n for (const el of this.getParts('link')) {\n const props = api.getLinkProps({ value: el.getAttribute('value') ?? '' })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n const indicator = this.getPart('indicator')\n if (indicator) {\n const props = api.getIndicatorProps() as Record<string, unknown>\n this.spreader.spread(indicator, props)\n // 按本帧产出的 hidden 用内联 display 收起\n this.setPartHidden(indicator, props.hidden === true)\n }\n }\n}\n","import type { AvatarSchema, AvatarStatus, AvatarStatusChangeDetails } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { avatarAnatomy, avatarMachine, avatarMeta, connectAvatar } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-avatar>` —— 头像行为宿主,src/alt 写进 image 节点,加载成败回送机器,image 与 fallback 互斥显隐。\n *\n * @customElement xh-avatar\n * @attr {string} src - 图片地址;缺省即直接落回退态\n * @attr {string} alt - 图片替代文本,原样写到 image 节点上\n * @attr {'sm'|'md'|'lg'} size - 尺寸档位,缺省 md\n * @fires status-change - 加载状态变化;detail 为 `{ status: 'loading' | 'loaded' | 'error' }`\n * @csspart root - 头像根容器,承载 data-status/data-size\n * @csspart image - 图片节点,必须是原生 img;src/alt 由宿主写入,未就绪时带 hidden\n * @csspart fallback - 图片之外的回退内容,图片就绪后带 hidden\n */\nexport class XhAvatarElement extends XhElement {\n static override partContract = { anatomy: avatarAnatomy, meta: avatarMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n src: { converter: STRING_CONVERTER },\n alt: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare src?: string\n declare alt?: string\n declare size?: Size\n\n private readonly notify = (details: AvatarStatusChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('status-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<AvatarSchema>(this, avatarMachine, () => this.machineProps())\n\n private machineProps(): Partial<AvatarSchema['props']> {\n return {\n src: this.src,\n alt: this.alt,\n size: this.size,\n onStatusChange: this.notify,\n }\n }\n\n /** 图片在监听器挂上之前就已就绪时补报一次 IMAGE.LOAD。 */\n private syncSettledImage(status: AvatarStatus): void {\n // 只在 loading 补报:idle 期间补会被随后落地的来源决议踢回 loading\n if (status !== 'loading')\n return\n const { getStatus, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n const image = this.getPart('image') as HTMLImageElement | null\n // 三个条件缺一不可:complete 排除还在路上的请求,naturalWidth 排除加载失败,\n // currentSrc === src 排除换图那一瞬(此刻旧图仍是 complete 的)\n if (image?.complete && image.naturalWidth > 0 && image.currentSrc === image.src)\n send({ type: 'IMAGE.LOAD' })\n }\n\n protected wire(): void {\n const api = connectAvatar(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('image', api.getImageProps() as Record<string, unknown>)\n put('fallback', api.getFallbackProps() as Record<string, unknown>)\n\n // 用内联 display 互斥显隐\n this.setPartHidden(this.getPart('image'), !api.loaded)\n this.setPartHidden(this.getPart('fallback'), api.loaded)\n\n // 属性与监听器落到 image 之后,再判断它是否早已加载完\n this.syncSettledImage(api.status)\n }\n}\n","import type { AvatarGroupProps } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { avatarGroupAnatomy, avatarGroupMeta, connectAvatarGroup } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-avatar-group>` —— Light-DOM 行为宿主,无状态机,把 connectAvatarGroup 产出打到各角色节点。\n *\n * 组内每一枚头像是作者自己的节点,不是本组件的角色节点:尺寸写在根上,\n * 皮肤把它翻成 `--xh-avatar-*` 槽位,沿继承流给每一枚。\n * overflow 可缺省:没超出上限时就没有「+N」。\n *\n * @customElement xh-avatar-group\n * @attr {number} max - 展示上限,如实落成根上的 data-max;裁剪与计数由作者做\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定组内每一枚的直径与字号\n * @csspart root - 组容器,承载 data-size 与 data-max\n * @csspart overflow - 溢出计数位,内容(「+N」)由作者写\n */\nexport class XhAvatarGroupElement extends XhElement {\n static override partContract = { anatomy: avatarGroupAnatomy, meta: avatarGroupMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n max: { type: Number },\n size: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n }\n\n declare max?: number\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectAvatarGroup({\n max: this.max,\n size: this.size,\n } satisfies AvatarGroupProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('overflow', api.getOverflowProps() as Record<string, unknown>)\n }\n}\n","import type { BackTopBehavior, BackTopSchema, BackTopTranslations, BackTopVisibleChangeDetails } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { backTopAnatomy, backTopMachine, backTopMeta, connectBackTop } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-back-top>` —— 回到顶部行为宿主:滚动量过线时露出按钮,点它滚回顶部。\n *\n * 作者须把 trigger 写成 `<button>`:激活与 Tab 停靠由平台提供,元素不接管任何按键。\n * 收起时整个 root 带 hidden,按钮一并退出 Tab 序列与无障碍树——\n * 靠不透明度藏起来的按钮仍然可聚焦、仍然被读屏念到。\n *\n * @customElement xh-back-top\n * @attr {number} visibility-height - 滚过这么多像素按钮才露面,默认 200\n * @attr {'auto'|'smooth'} behavior - 滚回顶部的方式,默认 smooth\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires visible-change - 露面与否变化;detail 为 `{ visible: boolean }`\n * @csspart root - 定位壳,承载 data-visible / data-tone / data-size;收起时带 hidden\n * @csspart trigger - 按钮,须写成 `<button>`;可及名字由 translations.trigger 给\n */\nexport class XhBackTopElement extends XhElement {\n static override partContract = { anatomy: backTopAnatomy, meta: backTopMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n visibilityHeight: { converter: NUMBER_CONVERTER, attribute: 'visibility-height' },\n behavior: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,只走 property\n translations: { attribute: false },\n // 滚动容器是 DOM 句柄,只走 property;不给即整页滚动\n target: { attribute: false },\n }\n\n declare visibilityHeight?: number\n declare behavior?: BackTopBehavior\n declare tone?: Tone\n declare size?: Size\n declare translations?: Partial<BackTopTranslations>\n declare target?: HTMLElement | null\n\n private readonly notify = (details: BackTopVisibleChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('visible-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<BackTopSchema>(\n this,\n backTopMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<BackTopSchema['props']> {\n return {\n visibilityHeight: this.visibilityHeight,\n behavior: this.behavior,\n translations: this.translations,\n tone: this.tone,\n size: this.size,\n onVisibleChange: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<BackTopSchema>): void {\n svc.refs.set('getTargetEl', () => this.target ?? null)\n }\n\n protected wire(): void {\n const api = connectBackTop(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root) {\n const props = api.getRootProps() as Record<string, unknown>\n this.spreader.spread(root, props)\n // Light DOM 常驻,WC 自管可见性:作者层若给这个 part 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来\n this.setPartHidden(root, props.hidden === true)\n }\n\n const trigger = this.getPart('trigger')\n if (trigger)\n this.spreader.spread(trigger, api.getTriggerProps() as Record<string, unknown>)\n }\n}\n","import type { BadgeProps, BadgeVariant } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { badgeAnatomy, badgeMeta, connectBadge } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-badge>` —— 徽标展示宿主,无状态机,外观来自 variant 属性。\n *\n * @customElement xh-badge\n * @attr {'solid'|'subtle'|'outline'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @csspart root - 承载 data-scope/data-part/data-* 的展示节点\n */\nexport class XhBadgeElement extends XhElement {\n static override partContract = { anatomy: badgeAnatomy, meta: badgeMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n variant: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n tone: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n size: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n }\n\n declare variant?: BadgeVariant\n declare tone?: Tone\n declare size?: Size\n\n protected wire(): void {\n const root = this.getPart('root')\n if (!root)\n return\n // 读响应式 property,不回读 DOM 特性\n const api = connectBadge({ variant: this.variant, tone: this.tone, size: this.size } as BadgeProps, wcNormalize)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { BreadcrumbProps, BreadcrumbTranslations } from '@xihan-ui/headless'\nimport type { Direction, Size, Tone } from '@xihan-ui/kernel'\nimport { breadcrumbAnatomy, breadcrumbMeta, connectBreadcrumb } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/** 读作者写在角色节点上的布尔声明:属性缺席或 =\"false\" 为假,其余为真。 */\nfunction authorFlag(el: HTMLElement, name: string): boolean {\n const raw = el.getAttribute(name)\n return raw != null && raw !== 'false'\n}\n\n/**\n * `<xh-breadcrumb>` —— 面包屑行为宿主,无状态机,把 connectBreadcrumb 产出的 aria-* 打到角色节点上。\n *\n * 标签要求:root 为 `<nav>`,list 为 `<ol>`,item / separator / ellipsis 为 `<li>`,link 为 `<a>`。\n * 运行期改写 link 上的 `current` 属性不触发重新接线,需作者自行 requestUpdate。\n *\n * @customElement xh-breadcrumb\n * @attr {'ltr'|'rtl'} dir - 文字方向,写到 root 上;不给则继承祖先\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @csspart root - nav 地标,承载 aria-label\n * @csspart list - ol 容器\n * @csspart item - li 条目\n * @csspart link - a 链接;写 current 属性的那条得到 aria-current=\"page\" 并拦住点击\n * @csspart separator - li 分隔符,对读屏隐藏\n * @csspart ellipsis - li 折叠占位,对读屏隐藏\n */\nexport class XhBreadcrumbElement extends XhElement {\n static override partContract = { anatomy: breadcrumbAnatomy, meta: breadcrumbMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,只走 property\n translations: { attribute: false },\n }\n\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n declare translations?: Partial<BreadcrumbTranslations>\n\n protected wire(): void {\n const props: BreadcrumbProps = {\n dir: this.direction,\n translations: this.translations,\n tone: this.tone,\n size: this.size,\n }\n const api = connectBreadcrumb(props, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('list', api.getListProps() as Record<string, unknown>)\n\n // 多实例 part 逐个打,link 的身份取作者写的 current。\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps() as Record<string, unknown>)\n\n for (const el of this.getParts('link')) {\n const attrs = api.getLinkProps({ current: authorFlag(el, 'current') })\n this.spreader.spread(el, attrs as Record<string, unknown>)\n }\n\n for (const el of this.getParts('separator'))\n this.spreader.spread(el, api.getSeparatorProps() as Record<string, unknown>)\n\n for (const el of this.getParts('ellipsis'))\n this.spreader.spread(el, api.getEllipsisProps() as Record<string, unknown>)\n }\n}\n","import type { ButtonProps } from '@xihan-ui/headless'\nimport type { ActionVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { buttonAnatomy, buttonMeta, connectButton } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-button>` —— 按钮行为宿主,无状态机,宿主属性即 button props。\n *\n * @customElement xh-button\n * @attr {'button'|'submit'|'reset'} type - 原生按钮类型,默认 button\n * @attr {boolean} disabled - 禁用(原生 disabled,丢焦点)\n * @attr {boolean} loading - 加载中(aria-disabled,保留焦点并拦截点击)\n * @attr {'solid'|'subtle'|'outline'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @csspart root - 承载 data-scope/data-part/data-* 的原生 button\n */\nexport class XhButtonElement extends XhElement {\n static override partContract = { anatomy: buttonAnatomy, meta: buttonMeta }\n\n static override properties = {\n type: {},\n disabled: { type: Boolean },\n loading: { type: Boolean },\n variant: {},\n tone: {},\n size: {},\n }\n\n declare type?: 'button' | 'submit' | 'reset'\n declare disabled?: boolean\n declare loading?: boolean\n declare variant?: ActionVariant\n declare tone?: Tone\n declare size?: Size\n\n protected wire(): void {\n const root = this.getPart('root')\n if (!root)\n return\n const api = connectButton(this as unknown as ButtonProps, wcNormalize)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // label / prefix / suffix / indicator 都是可选角色节点,作者写了才接\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('prefix', api.getPrefixProps() as Record<string, unknown>)\n put('suffix', api.getSuffixProps() as Record<string, unknown>)\n put('indicator', api.getIndicatorProps() as Record<string, unknown>)\n }\n}\n","import type { ButtonGroupProps } from '@xihan-ui/headless'\nimport type { ActionVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { buttonGroupAnatomy, buttonGroupMeta, connectButtonGroup } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-button-group>` —— Light-DOM 行为宿主,无状态机,把 connectButtonGroup 产出打到 root 角色节点。\n *\n * 组内每一段是作者自己的按钮,不是本组件的角色节点:三个视觉轴写在根上,\n * 皮肤把它们翻成 `--xh-button-*` 槽位,沿继承流给每一段。\n *\n * @customElement xh-button-group\n * @attr {'horizontal'|'vertical'} orientation - 排布,决定相邻两段在哪个轴上合边,默认 horizontal\n * @attr {'solid'|'subtle'|'outline'|'ghost'} variant - 形态,决定底色、描边与前景怎么用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定用哪族颜色\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定各段的高度、内边距与字号\n * @csspart root - 组容器,承载 role=group 与 data-orientation / data-variant / data-tone / data-size\n */\nexport class XhButtonGroupElement extends XhElement {\n static override partContract = { anatomy: buttonGroupAnatomy, meta: buttonGroupMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n orientation: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n variant: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n tone: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n size: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n }\n\n declare orientation?: string\n declare variant?: ActionVariant\n declare tone?: Tone\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectButtonGroup({\n orientation: this.orientation as ButtonGroupProps['orientation'],\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n } satisfies ButtonGroupProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type {\n CalendarDay,\n CalendarFocusChangeDetails,\n CalendarSchema,\n CalendarSelectionMode,\n CalendarValueChangeDetails,\n CalendarWeekDay,\n CalendarWeekdayFormat,\n} from '@xihan-ui/headless'\nimport { calendarAnatomy, calendarMachine, calendarMeta, connectCalendar } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-calendar>` —— 日历行为宿主。\n *\n * 网格由作者渲染,元素不生成节点:读 `weeks` / `weekDays` / `headingLabel` 三个只读属性,\n * 听 `focused-value-change` 重画(须在收到事件的同一拍内完成)。日期身份取 cell 上的\n * `value`(ISO 串),cell-trigger 跟随所在 cell;表头列取 week-day 上的 `value`(列序 0-6)。\n * 翻月按钮的可及名字由作者给。\n *\n * @customElement xh-calendar\n * @attr {string} value - 受控选中值(单选简写,ISO 串);缺省即非受控,多选/区间用 property\n * @attr {string} default-value - 非受控初始选中值\n * @attr {'single'|'multiple'|'range'} selection-mode - 选择模式,默认 single\n * @attr {string} focused-value - 受控聚焦日(ISO 串),同时决定展示哪个月\n * @attr {string} default-focused-value - 非受控初始聚焦日;缺省时退回首个选中值,再退回今天\n * @attr {string} min - 可选范围下界(含当天),界外的日子转 aria-disabled 但仍可聚焦\n * @attr {string} max - 可选范围上界(含当天)\n * @attr {string} locale - 决定周首日与文案,默认 zh-CN\n * @attr {string} time-zone - 判定今天与格式化用的时区,默认宿主本地时区\n * @attr {boolean} disabled - 整张禁用:翻月按钮转原生 disabled,格子全转 aria-disabled\n * @attr {boolean} read-only - 只读:翻月与移动焦点照常,只是选不动值\n * @attr {'narrow'|'short'} weekday-format - 表头缩写粒度,默认 short\n * @attr {boolean} fixed-weeks - 恒渲染六行\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @fires focused-value-change - 聚焦日变化;detail 为 `{ focusedValue: string }`\n * @csspart root - 组件根容器\n * @csspart header - 标题栏外壳\n * @csspart prev-trigger - 上一月;越过 min 时转原生 disabled\n * @csspart next-trigger - 下一月;越过 max 时转原生 disabled\n * @csspart heading - 展示月标题(grid 的 aria-labelledby 目标)\n * @csspart grid - role=grid 容器,键盘在此收口\n * @csspart grid-head - role=rowgroup 表头组,里面套一个 week-row\n * @csspart week-day - role=columnheader 列头,须自带 value 属性标明列序 0-6\n * @csspart grid-body - role=rowgroup 日期组\n * @csspart week-row - role=row 周行,表头与日期行共用\n * @csspart cell - role=gridcell 日期格,承载 aria-selected;须自带 value 属性(ISO 串)标明是哪一天\n * @csspart cell-trigger - 可点可聚焦层,承载 aria-disabled 与 roving tabindex\n */\nexport class XhCalendarElement extends XhElement {\n static override partContract = { anatomy: calendarAnatomy, meta: calendarMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n selectionMode: { converter: STRING_CONVERTER, attribute: 'selection-mode' },\n focusedValue: { converter: STRING_CONVERTER, attribute: 'focused-value' },\n defaultFocusedValue: { converter: STRING_CONVERTER, attribute: 'default-focused-value' },\n min: { converter: STRING_CONVERTER },\n max: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n timeZone: { converter: STRING_CONVERTER, attribute: 'time-zone' },\n weekdayFormat: { converter: STRING_CONVERTER, attribute: 'weekday-format' },\n // 三个开关缺省为假,属性在场即真\n disabled: { type: Boolean },\n readOnly: { type: Boolean, attribute: 'read-only' },\n fixedWeeks: { type: Boolean, attribute: 'fixed-weeks' },\n // 判定函数只走 property\n isDateUnavailable: { attribute: false },\n }\n\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare selectionMode?: CalendarSelectionMode\n declare focusedValue?: string\n declare defaultFocusedValue?: string\n declare min?: string\n declare max?: string\n declare locale?: string\n declare timeZone?: string\n declare weekdayFormat?: CalendarWeekdayFormat\n declare disabled?: boolean\n declare readOnly?: boolean\n declare fixedWeeks?: boolean\n declare isDateUnavailable?: (value: string) => boolean\n\n private readonly notifyValue = (details: CalendarValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyFocus = (details: CalendarFocusChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('focused-value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CalendarSchema>(\n this,\n calendarMachine,\n () => this.machineProps(),\n {\n // 机器跨月后靠它把焦点送进重画出来的格子\n onBuilt: (service) => {\n service.refs.set('getGridEl', () => this.getPart('grid'))\n },\n },\n )\n\n private machineProps(): Partial<CalendarSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n selectionMode: this.selectionMode,\n focusedValue: this.focusedValue,\n defaultFocusedValue: this.defaultFocusedValue,\n min: this.min,\n max: this.max,\n isDateUnavailable: this.isDateUnavailable,\n locale: this.locale,\n timeZone: this.timeZone,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n weekdayFormat: this.weekdayFormat,\n fixedWeeks: this.fixedWeeks ?? false,\n onValueChange: this.notifyValue,\n onFocusedValueChange: this.notifyFocus,\n }\n }\n\n /** 当前展示月的日期矩阵,作者照它重画网格。机器尚未建起时给空数组。 */\n get weeks(): CalendarDay[][] {\n return this.ctrl.service ? connectCalendar(this.ctrl.service, wcNormalize).weeks : []\n }\n\n /** 七列表头(缩写 + 全称),列序与 weeks 的列序一致。 */\n get weekDays(): CalendarWeekDay[] {\n return this.ctrl.service ? connectCalendar(this.ctrl.service, wcNormalize).weekDays : []\n }\n\n /** 展示月标题文案,作者写进 heading 节点。 */\n get headingLabel(): string {\n return this.ctrl.service ? connectCalendar(this.ctrl.service, wcNormalize).headingLabel : ''\n }\n\n /** 取指定角色节点在 owner 子树内的实例。 */\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectCalendar(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('header', api.getHeaderProps() as Record<string, unknown>)\n put('prev-trigger', api.getPrevTriggerProps() as Record<string, unknown>)\n put('next-trigger', api.getNextTriggerProps() as Record<string, unknown>)\n put('heading', api.getHeadingProps() as Record<string, unknown>)\n put('grid', api.getGridProps() as Record<string, unknown>)\n put('grid-head', api.getGridHeadProps() as Record<string, unknown>)\n put('grid-body', api.getGridBodyProps() as Record<string, unknown>)\n\n // 表头行与日期行共用 role=row,一并打\n for (const el of this.getParts('week-row'))\n this.spreader.spread(el, api.getWeekRowProps() as Record<string, unknown>)\n\n // 列头身份取作者写的 value(列序 0-6);漏写给 NaN,不写 aria-label\n for (const el of this.getParts('week-day')) {\n const raw = el.getAttribute('value')\n const index = raw == null || raw === '' ? Number.NaN : Number(raw)\n this.spreader.spread(el, api.getWeekDayProps({ value: index }) as Record<string, unknown>)\n }\n\n // 日期格逐个打,身份取 cell 上的 value,格内 trigger 跟着同一份声明走\n for (const el of this.getParts('cell')) {\n const cell = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getCellProps(cell) as Record<string, unknown>)\n for (const trigger of this.partsIn(el, 'cell-trigger'))\n this.spreader.spread(trigger, api.getCellTriggerProps(cell) as Record<string, unknown>)\n }\n }\n}\n","import type { CardProps, CardVariant } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { cardAnatomy, cardMeta, connectCard } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-card>` —— Light-DOM 行为宿主,无状态机,把 connectCard 产出打到各角色节点。\n * 除 root 外的部件全部可缺省:封面、头、身、脚按需摆,一个不写也是一张合法的卡片。\n *\n * 根上不写 role:卡片是不是地标、要不要可及名字,由里面放了什么内容决定,作者自己声明。\n *\n * @customElement xh-card\n * @attr {'outline'|'subtle'|'elevated'|'ghost'} variant - 形态,决定描边、底色与投影怎么用\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定各段的内边距与标题字号\n * @attr {boolean} hoverable - 指针悬停时抬起\n * @attr {boolean} segmented - 在头、身、脚之间画分隔线\n * @csspart root - 卡片根容器,承载 data-variant / data-size / data-hoverable / data-segmented\n * @csspart cover - 封面位,通常放图片,压在头部之上\n * @csspart header - 头部,装标题与描述\n * @csspart title - 标题\n * @csspart description - 标题下的说明\n * @csspart body - 主体内容\n * @csspart footer - 底部,通常放操作\n */\nexport class XhCardElement extends XhElement {\n static override partContract = { anatomy: cardAnatomy, meta: cardMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n variant: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n size: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n hoverable: { type: Boolean },\n segmented: { type: Boolean },\n }\n\n declare variant?: CardVariant\n declare size?: Size\n declare hoverable?: boolean\n declare segmented?: boolean\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectCard({\n variant: this.variant,\n size: this.size,\n hoverable: this.hoverable ?? false,\n segmented: this.segmented ?? false,\n } satisfies CardProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('cover', api.getCoverProps() as Record<string, unknown>)\n put('header', api.getHeaderProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('body', api.getBodyProps() as Record<string, unknown>)\n put('footer', api.getFooterProps() as Record<string, unknown>)\n }\n}\n","import type { CarouselPageChangeDetails, CarouselSchema, CarouselTranslations } from '@xihan-ui/headless'\nimport type { Direction, Orientation } from '@xihan-ui/kernel'\nimport { carouselAnatomy, carouselMachine, carouselMeta, connectCarousel } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席,避免 Number('') 落成页码 0\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席 = undefined,=\"false\" = false,其余 = true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * autoplay 布尔或毫秒两用:缺席 = undefined,`autoplay` / `autoplay=\"true\"` = 默认间隔,\n * `autoplay=\"false\"` = 关,`autoplay=\"3000\"` = 3 秒一张,念不成数的串按开着处理。\n */\nconst AUTOPLAY_CONVERTER = {\n fromAttribute: (v: string | null): boolean | number | undefined => {\n if (v == null)\n return undefined\n if (v === '' || v === 'true')\n return true\n if (v === 'false')\n return false\n const ms = Number(v)\n return Number.isFinite(ms) ? ms : true\n },\n}\n\n/** 读作者写在部件上的下标,缺席或写坏了退回文档序。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-carousel>` —— 走马灯行为宿主。\n *\n * 条目总数由 `slide-count` 声明,不从 DOM 数。指示点一页一个,页数由 `slide-count` 与\n * `slides-per-page` / `slides-per-move` 算出,由作者照着渲染节点,元素不生成节点。\n * 轨道位移写在 item-group 的内联 transform 上,样式层不得再碰那条轴。\n *\n * @customElement xh-carousel\n * @attr {number} page - 受控页码,0 基;缺省该属性即非受控\n * @attr {number} default-page - 非受控初始页,默认 0\n * @attr {number} slide-count - 条目总数\n * @attr {number} slides-per-page - 一屏放几张,默认 1\n * @attr {number} slides-per-move - 一次翻几张,默认跟随 slides-per-page\n * @attr {'horizontal'|'vertical'} orientation - 轨道方向,默认 horizontal\n * @attr {'ltr'|'rtl'} dir - 文字方向;水平轴上同时决定位移方向\n * @attr {boolean} loop - 走到尽头回绕,默认关闭\n * @attr {boolean|number} autoplay - 自动播放:属性在即开,写数值即间隔毫秒\n * @attr {boolean} allow-pointer-drag - 允许指针拖拽切页,默认关闭\n * @attr {string} spacing - 张与张之间的间距(任意 CSS 长度)\n * @fires page-change - 页码变化;detail 为 `{ page: number }`\n * @csspart root - region 地标,承载 aria-roledescription=\"carousel\" 与名字\n * @csspart viewport - 裁切窗口,兼作读屏活区\n * @csspart item-group - 被位移的轨道;transform 由元素写入,样式层别碰\n * @csspart item - 一张幻灯片,可自带 index 属性声明下标,缺省按文档序\n * @csspart prev-trigger - 上一张;首页且不回绕时转原生 disabled\n * @csspart next-trigger - 下一张;末页且不回绕时转原生 disabled\n * @csspart indicator-group - 指示点容器(role=group)\n * @csspart indicator - 一页一个的指示点,可自带 index 属性;当前页带 aria-current=\"true\"\n */\nexport class XhCarouselElement extends XhElement {\n static override partContract = { anatomy: carouselAnatomy, meta: carouselMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n page: { converter: NUMBER_CONVERTER },\n defaultPage: { converter: NUMBER_CONVERTER, attribute: 'default-page' },\n slideCount: { converter: NUMBER_CONVERTER, attribute: 'slide-count' },\n slidesPerPage: { converter: NUMBER_CONVERTER, attribute: 'slides-per-page' },\n slidesPerMove: { converter: NUMBER_CONVERTER, attribute: 'slides-per-move' },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n loop: { converter: BOOLEAN_CONVERTER },\n autoplay: { converter: AUTOPLAY_CONVERTER },\n allowPointerDrag: { converter: BOOLEAN_CONVERTER, attribute: 'allow-pointer-drag' },\n spacing: { converter: STRING_CONVERTER },\n // 文案是对象,只走 property\n translations: { attribute: false },\n }\n\n declare page?: number\n declare defaultPage?: number\n declare slideCount?: number\n declare slidesPerPage?: number\n declare slidesPerMove?: number\n declare orientation?: Orientation\n declare direction?: Direction\n declare loop?: boolean\n declare autoplay?: boolean | number\n declare allowPointerDrag?: boolean\n declare spacing?: string\n declare translations?: Partial<CarouselTranslations>\n\n private readonly notify = (details: CarouselPageChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('page-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 机器只有计时器一个副作用,controller 只带 props。\n private readonly ctrl = new MachineController<CarouselSchema>(this, carouselMachine, () => this.machineProps())\n\n private machineProps(): Partial<CarouselSchema['props']> {\n return {\n page: this.page,\n defaultPage: this.defaultPage,\n slideCount: this.slideCount,\n slidesPerPage: this.slidesPerPage,\n slidesPerMove: this.slidesPerMove,\n orientation: this.orientation,\n dir: this.direction,\n // 布尔缺席即 undefined,缺省交回 connect\n loop: this.loop,\n autoplay: this.autoplay,\n allowPointerDrag: this.allowPointerDrag,\n spacing: this.spacing,\n translations: this.translations,\n onPageChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectCarousel(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('viewport', api.getViewportProps() as Record<string, unknown>)\n put('item-group', api.getItemGroupProps() as Record<string, unknown>)\n put('prev-trigger', api.getPrevTriggerProps() as Record<string, unknown>)\n put('next-trigger', api.getNextTriggerProps() as Record<string, unknown>)\n put('indicator-group', api.getIndicatorGroupProps() as Record<string, unknown>)\n\n // 条目与指示点是多实例 part,逐个打:身份取作者写的 index,缺省按文档序。\n this.getParts('item').forEach((el, position) => {\n this.spreader.spread(el, api.getItemProps({ index: declaredIndex(el, position) }) as Record<string, unknown>)\n })\n\n this.getParts('indicator').forEach((el, position) => {\n this.spreader.spread(el, api.getIndicatorProps({ index: declaredIndex(el, position) }) as Record<string, unknown>)\n })\n }\n}\n","import type {\n CascaderExpandTrigger,\n CascaderItemProps,\n CascaderNode,\n CascaderOpenChangeDetails,\n CascaderSchema,\n CascaderValue,\n CascaderValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { cascaderAnatomy, cascaderMachine, cascaderMeta, connectCascader } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定;Lit 自带转换器会把缺席落成 null/false,表达不了\"未指定\"。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 默认的 Boolean 转换器是 v !== null,写 loop=\"false\" 照样是真,缺省为真的开关就关不掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 条目一系的归属容器:文本与勾选标记向上找最近的那个条目。 */\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n\n/**\n * `<xh-cascader>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content 与\n * 每一级一个 column、层内每个节点一个 item,元素跑 cascader 机器并把 connect 产出打上去。\n * 浮层定位引擎在本元素里建好、经 refs 注入机器,锚点取 trigger、被定位的浮层取 positioner;\n * 机器只认端口,不认识具体引擎。\n *\n * 标记是静态的:列按树的深度写满(第 L 列装第 L 层的全部节点),当下该露面的哪些\n * 由元素加 hidden 收口,作者节点一个都不卸载。可先取 `cascaderBuildLevels(collection)` 照着写。\n *\n * 所在列、整条路径、禁用与显示文本都查 `collection` 这份树数据,不从 DOM 反推。\n * collection 必须与标记同源且 value 全树唯一。\n *\n * value-text 的显示文字由元素代填;作者在该节点里写了内容就归作者,元素不再改写。\n *\n * 树数据与选中路径都是数组,只走 property(`el.collection = [...]`、\n * `el.value = ['zhejiang','hangzhou']`)。\n *\n * @customElement xh-cascader\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {'click'|'hover'} expand-trigger - 子列由点还是悬停展开,默认 click\n * @attr {boolean} change-on-select - 中间层(分支)也能落值\n * @attr {boolean} multiple - 多选:选中后浮层不收起,焦点留在列里\n * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,浮层展不开\n * @attr {boolean} read-only - 只读:浮层照常展开、列照常浏览,但选中值改不动、也清不掉\n * @attr {boolean} invalid - 校验失败标注\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @attr {string} placeholder - 无选中时 value-text 显示的占位文字\n * @attr {string} separator - 路径回显的连接符,默认 \" / \"\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} loop - 列内上下键走到首尾回绕,默认开;写 loop=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的进子列/回上一列语义,默认 ltr\n * @fires value-change - 选中路径集合变化;detail 为 `{ value: string[][] }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly/data-invalid)\n * @csspart label - 标题(aria-labelledby 目标)\n * @csspart trigger - role=combobox 的触发按钮,同时是定位锚点,须是原生 button\n * @csspart value-text - 整条路径的显示位;留空即由元素填入,作者写了内容则归作者\n * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)\n * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - 浮层壳(焦点域与消解层的根节点),键盘在此收口,收起时带 hidden\n * @csspart column - role=listbox 的一列,须自带 level 属性标识它是第几列;砍掉时带 hidden\n * @csspart item - role=option 的条目,须自带 value 属性标识身份;不在当前列里时带 hidden\n * @csspart item-text - 条目文本\n * @csspart item-indicator - 条目选中标记(aria-hidden)\n */\nexport class XhCascaderElement extends XhElement {\n static override partContract = { anatomy: cascaderAnatomy, meta: cascaderMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n collection: { attribute: false },\n value: { attribute: false },\n defaultValue: { attribute: false },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n expandTrigger: { converter: STRING_CONVERTER, attribute: 'expand-trigger' },\n changeOnSelect: { converter: BOOLEAN_CONVERTER, attribute: 'change-on-select' },\n multiple: { type: Boolean },\n disabled: { type: Boolean },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n separator: { converter: STRING_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n }\n\n declare collection?: CascaderNode[]\n declare value?: CascaderValue\n declare defaultValue?: CascaderValue\n declare open?: boolean\n declare defaultOpen?: boolean\n declare expandTrigger?: CascaderExpandTrigger\n declare changeOnSelect?: boolean\n declare multiple?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n declare placeholder?: string\n declare separator?: string\n declare placement?: Placement\n declare offset?: number\n declare loop?: boolean\n declare direction?: Direction\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly cascaderScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n /** value-text 是否归元素填:首次见到该节点时定,之后不再回读(回读到的会是自己写的字)。 */\n private readonly ownsValueText = new WeakMap<HTMLElement, boolean>()\n\n private readonly notifyValue = (details: CascaderValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: CascaderOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CascaderSchema>(\n this,\n cascaderMachine,\n () => this.machineProps(),\n { scope: this.cascaderScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<CascaderSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n expandTrigger: this.expandTrigger,\n changeOnSelect: this.changeOnSelect ?? false,\n multiple: this.multiple ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n placeholder: this.placeholder,\n separator: this.separator,\n placement: this.placement,\n offset: this.offset,\n loop: this.loop,\n dir: this.direction,\n onValueChange: this.notifyValue,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.cascaderScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<CascaderSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /** 提前发现一次角色节点,让 default-open 时机器在 hostConnected 里就取得到 content。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时上报 ITEM.LOST,让机器按当前数据重挑锚点。\n * 判据是「焦点已不在浮层内」且离场的正是持有锚点的那个条目。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, scope, send } = this.ctrl.service\n // 宿主断开时机器已停机\n if (getStatus() !== 'Started')\n return\n // 收起态无锚点\n const focusedPath = context.get('focusedPath')\n const focusedValue = focusedPath?.[focusedPath.length - 1]\n if (focusedValue == null)\n return\n const content = this.getPart('content')\n const active = scope.getActiveElement()\n if (content && active && content.contains(active))\n return\n // data-value 只写在 item 上,列内的文本与标记离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'ITEM.LOST' })\n }\n\n /**\n * 取角色节点所属的条目身份:value 写在 item 上,行内文本与勾选标记向上找本宿主内最近的 item,\n * 没有则读节点自身。\n */\n private itemOf(el: HTMLElement): CascaderItemProps {\n const owner = el.closest<HTMLElement>(ITEM_SELECTOR)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n return { value: source.getAttribute('value') ?? '' }\n }\n\n /** 列自报的层号,没写或写歪了按它在 column 序列里的位置兜底。 */\n private levelOf(el: HTMLElement, position: number): number {\n const raw = Number(el.getAttribute('level'))\n return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : position\n }\n\n /** 摘掉作者写在条目上的原生 disabled,条目禁用一律由 collection 决定并以 aria-disabled 表达。 */\n private stripNativeDisabled(el: HTMLElement): void {\n if (el.hasAttribute('disabled'))\n el.removeAttribute('disabled')\n }\n\n /** 把整条路径的文字填进 value-text;首次见到该节点时若已有内容则判为归作者,之后一概不碰。 */\n private fillValueText(el: HTMLElement, text: string): void {\n let owned = this.ownsValueText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsValueText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n const api = connectCascader(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('indicator', api.getIndicatorProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 属性先落,显示文字随后\n const valueText = this.getPart('value-text')\n if (valueText) {\n this.spreader.spread(valueText, api.getValueTextProps() as Record<string, unknown>)\n this.fillValueText(valueText, api.displayText)\n }\n\n // 集合类 part 逐个 spread,身份由节点自报,不依赖下标。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供连接层现查。\n this.getParts('column').forEach((el, position) => {\n this.spreader.spread(el, api.getColumnProps({ level: this.levelOf(el, position) }) as Record<string, unknown>)\n })\n for (const el of this.getParts('item')) {\n this.stripNativeDisabled(el)\n this.spreader.spread(el, api.getItemProps(this.itemOf(el)) as Record<string, unknown>)\n }\n for (const el of this.getParts('item-text'))\n this.spreader.spread(el, api.getItemTextProps(this.itemOf(el)) as Record<string, unknown>)\n for (const el of this.getParts('item-indicator'))\n this.spreader.spread(el, api.getItemIndicatorProps(this.itemOf(el)) as Record<string, unknown>)\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n this.getParts('column').forEach((el, position) => {\n this.setPartHidden(el, this.levelOf(el, position) >= api.columns.length)\n })\n for (const el of this.getParts('item'))\n this.setPartHidden(el, !api.isVisible(this.itemOf(el).value))\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { CheckboxCheckedChangeDetails, CheckboxCheckedState, CheckboxSchema } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { checkboxAnatomy, checkboxMachine, checkboxMeta, connectCheckbox } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-checkbox>` —— Light-DOM 行为宿主,跑 checkbox 机器并把 connect 产出打到 root/indicator 角色节点。\n *\n * @customElement xh-checkbox\n * @attr {boolean|'indeterminate'} checked - 受控选中;写 indeterminate 为半选,缺省该属性即非受控\n * @attr {boolean|'indeterminate'} default-checked - 非受控初值\n * @attr {boolean} disabled - 禁用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires checked-change - checked 状态变化;detail 为 `{ checked: boolean }`\n * @csspart root - role=checkbox 的按钮(承载 aria-checked / data-state)\n * @csspart indicator - 选中标记\n */\nexport class XhCheckboxElement extends XhElement {\n static override partContract = { anatomy: checkboxAnatomy, meta: checkboxMeta }\n\n static override properties = {\n // 三态:写 checked=\"indeterminate\" 表示半选;缺席即非受控\n checked: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v === 'indeterminate' ? 'indeterminate' : v !== 'false') } },\n defaultChecked: { attribute: 'default-checked', converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v === 'indeterminate' ? 'indeterminate' : v !== 'false') } },\n disabled: { type: Boolean },\n tone: {},\n size: {},\n }\n\n declare checked?: CheckboxCheckedState\n declare defaultChecked?: CheckboxCheckedState\n declare disabled?: boolean\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: CheckboxCheckedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('checked-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CheckboxSchema>(this, checkboxMachine, () => this.machineProps())\n\n private machineProps(): Partial<CheckboxSchema['props']> {\n return {\n checked: this.checked,\n defaultChecked: this.defaultChecked ?? false,\n disabled: this.disabled ?? false,\n tone: this.tone,\n size: this.size,\n onCheckedChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectCheckbox(this.ctrl.service, wcNormalize)\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n const indicator = this.getPart('indicator')\n if (indicator)\n this.spreader.spread(indicator, api.getIndicatorProps() as Record<string, unknown>)\n }\n}\n","import { declaredItemDisabled } from '@xihan-ui/behavior'\n\n/**\n * 作者在标记里声明的条目禁用,按元素记住头一回见到的那一份。\n *\n * connect 每帧把 aria-disabled 写回条目,第二帧起现读分不清是作者写的还是自己上一帧写的;\n * 记下首见那一份,「作者没写」才表达得出 undefined,collection 里的禁用才轮得到生效。\n */\nexport function createDeclaredDisabled(): (el: HTMLElement) => boolean | undefined {\n const seen = new WeakMap<HTMLElement, boolean | undefined>()\n return (el) => {\n if (!seen.has(el))\n seen.set(el, declaredItemDisabled(el))\n return seen.get(el)\n }\n}\n","import type { CheckboxGroupItemProps, CheckboxGroupNode, CheckboxGroupSchema, CheckboxGroupValueChangeDetails } from '@xihan-ui/headless'\nimport type { Orientation } from '@xihan-ui/kernel'\nimport { isItemDisabled } from '@xihan-ui/behavior'\nimport { checkboxGroupAnatomy, checkboxGroupMachine, checkboxGroupMeta, connectCheckboxGroup } from '@xihan-ui/headless'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n// 三态布尔:缺席=undefined(走机器默认值)、=\"false\"=false、其余为真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n// 值集合走逗号分隔(value=\"a,b\"):空串是空集合,只有 null 才翻成 undefined。\n// 条目值里不能带逗号,用 property 赋值则不受限。\nconst LIST_CONVERTER = {\n fromAttribute: (v: string | null) => (v === null ? undefined : v.split(',').map(s => s.trim()).filter(Boolean)),\n}\n\n/**\n * `<xh-checkbox-group>` —— Light-DOM 行为宿主:作者写 root/label 与若干 item 角色节点,\n * 每个 item 内自带 item-hidden-input/item-control/item-text,元素跑 checkbox-group 机器\n * 并把 connect 产出打上去。条目身份取自条目节点上的 value 属性。\n *\n * 不做 roving tabindex:组内每一项都是独立的 Tab 停靠点(禁用项也保留),容器自己不占位。\n *\n * @customElement xh-checkbox-group\n * @attr {string} value - 受控选中值,逗号分隔;缺省该属性即非受控\n * @attr {string} default-value - 非受控初始选中值,逗号分隔\n * @attr {string} item-values - 组内全部条目的值,逗号分隔;trigger 据此分辨全选与半选\n * @attr {boolean} disabled - 整组禁用\n * @attr {boolean} read-only - 只读:可聚焦可朗读,改不动\n * @attr {boolean} invalid - 校验失败标注\n * @attr {'horizontal'|'vertical'} orientation - 视觉排布,默认 vertical\n * @attr {string} name - 表单字段名;给定后隐藏输入才带 name 并参与提交\n * @fires value-change - 选中值变化;detail 为 `{ value: string[] }`\n * @csspart root - role=group 容器\n * @csspart label - 组标题(aria-labelledby 目标)\n * @csspart item - role=checkbox 条目,作者用 value 属性声明身份\n * @csspart item-control - 条目的视觉方框(对读屏隐藏)\n * @csspart item-text - 条目文本,条目的可及名来源\n * @csspart item-hidden-input - 条目的表单影子输入(必须是原生 input)\n * @csspart trigger - 全选/半选的父复选框,须写在 root 之内\n */\nexport class XhCheckboxGroupElement extends XhElement {\n static override partContract = { anatomy: checkboxGroupAnatomy, meta: checkboxGroupMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: LIST_CONVERTER },\n defaultValue: { converter: LIST_CONVERTER, attribute: 'default-value' },\n itemValues: { converter: LIST_CONVERTER, attribute: 'item-values' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n orientation: { converter: STRING_CONVERTER },\n name: { converter: STRING_CONVERTER },\n }\n\n declare collection?: CheckboxGroupNode[]\n declare value?: string[]\n declare defaultValue?: string[]\n declare itemValues?: string[]\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare orientation?: Orientation\n declare name?: string\n\n /** 条目自身 disabled 声明的快照,整组禁用期间 DOM 上的 aria-disabled 不可信。 */\n private readonly declaredDisabled = new WeakMap<HTMLElement, boolean>()\n /** 上一帧是否整组禁用;解禁当帧 DOM 上仍留着机器写回的 aria-disabled。 */\n private wasGroupDisabled = false\n\n private readonly notify = (details: CheckboxGroupValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CheckboxGroupSchema>(this, checkboxGroupMachine, () => this.machineProps())\n\n private machineProps(): Partial<CheckboxGroupSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n itemValues: this.itemValues,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n orientation: this.orientation,\n name: this.name,\n onValueChange: this.notify,\n }\n }\n\n /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */\n private readonly declaredItemDisabled = createDeclaredDisabled()\n\n private itemProps(el: HTMLElement): CheckboxGroupItemProps {\n const value = el.getAttribute('value') ?? ''\n // 给了 collection 就以数据为事实源:现读会读到 connect 上一帧写回的 aria-disabled,\n // 「作者没写」表达不出 undefined,数据里的禁用就永远轮不到生效。\n if (this.collection)\n return { value, disabled: this.declaredItemDisabled(el) }\n const groupDisabled = !!this.disabled\n // 首次见到该条目时 DOM 上只有作者写的东西,此刻现读即真声明\n if (!this.declaredDisabled.has(el)) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 本帧与上一帧都未整组禁用时,节点上的 aria-disabled 才等于作者声明\n if (!groupDisabled && !this.wasGroupDisabled) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 整组禁用期间与解禁当帧只认快照\n return { value, disabled: this.declaredDisabled.get(el)! }\n }\n\n /** 取指定角色节点在 item 子树内的实例。 */\n private partsIn(item: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => item.contains(el))\n }\n\n // checked 单独落成 DOM property:spread 见到 false 只会 removeAttribute,关不掉选中态。\n private spreadHiddenInput(input: HTMLInputElement, props: Record<string, unknown>): void {\n const { checked, ...rest } = props\n this.spreader.spread(input, rest)\n input.checked = checked === true\n }\n\n protected wire(): void {\n const api = connectCheckboxGroup(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n // trigger 是多实例 part,逐个接线;root/label 只认头一个(label 的 id 是 aria-labelledby 的唯一目标)\n for (const el of this.getParts('trigger'))\n this.spreader.spread(el, api.getTriggerProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item')) {\n const item = this.itemProps(el)\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const input of this.partsIn(el, 'item-hidden-input'))\n this.spreadHiddenInput(input as HTMLInputElement, api.getItemHiddenInputProps(item) as Record<string, unknown>)\n for (const control of this.partsIn(el, 'item-control'))\n this.spreader.spread(control, api.getItemControlProps(item) as Record<string, unknown>)\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n }\n\n this.wasGroupDisabled = !!this.disabled\n }\n}\n","import type { ClipboardCopyErrorDetails, ClipboardSchema, ClipboardStatusChangeDetails } from '@xihan-ui/headless'\nimport { clipboardAnatomy, clipboardMachine, clipboardMeta, connectClipboard } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-clipboard>` —— Light-DOM 行为宿主,跑 clipboard 机器并把 connect 产出打到角色节点上。\n *\n * 复制走 `navigator.clipboard.writeText`(要求安全上下文):在途为 copying,成功转 copied,\n * 失败回 idle 并派 `copy-error`。\n *\n * 两个 indicator 都常挂,各自用 `copied` 属性声明属于哪一侧,由宿主按状态互斥收起。\n *\n * @customElement xh-clipboard\n * @attr {string} value - 要复制的文本;缺省即复制空串\n * @attr {number} timeout - 复制成功后指示器保持的毫秒数,默认 3000;<=0 表示不自动回落\n * @fires status-change - 状态变化;detail 为 `{ status: 'copying' | 'copied' | 'idle' }`\n * @fires copy-error - 写入失败;detail 为 `{ error, value }`,此刻状态已经回到 idle\n * @csspart root - 组件根容器(承载 data-state / data-copied)\n * @csspart label - 标题,须是原生 `<label>`;`for` 恒写向 input\n * @csspart control - 输入框与按钮的包裹层,只承载 data-state\n * @csspart input - 展示要复制文本的只读输入框,须是原生 `<input>`;聚焦即全选\n * @csspart trigger - 复制按钮,须是原生 `<button>`\n * @csspart indicator - 状态标记;写 `copied` 属性的那个是成功侧,不写的是平时那侧\n */\nexport class XhClipboardElement extends XhElement {\n static override partContract = { anatomy: clipboardAnatomy, meta: clipboardMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n timeout: { converter: NUMBER_CONVERTER },\n }\n\n declare value?: string\n declare timeout?: number\n\n private readonly notifyStatus = (details: ClipboardStatusChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('status-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyError = (details: ClipboardCopyErrorDetails): void => {\n this.dispatchEvent(new CustomEvent('copy-error', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ClipboardSchema>(this, clipboardMachine, () => this.machineProps())\n\n private machineProps(): Partial<ClipboardSchema['props']> {\n return {\n value: this.value,\n timeout: this.timeout,\n onStatusChange: this.notifyStatus,\n onCopyError: this.notifyError,\n }\n }\n\n protected wire(): void {\n const api = connectClipboard(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n\n // 指示器是多实例 part,逐个打:身份取作者写的 copied 属性\n for (const el of this.getParts('indicator')) {\n const indicator = { copied: el.hasAttribute('copied') }\n this.spreader.spread(el, api.getIndicatorProps(indicator) as Record<string, unknown>)\n // 用内联 display 收起非当前侧\n this.setPartHidden(el, indicator.copied !== api.copied)\n }\n }\n}\n","import type { CodeToken, HighlighterPort } from '@xihan-ui/kernel'\nimport { createHighlighter } from '@xihan-ui/code-highlight'\nimport { codeBlockAnatomy, codeBlockMeta, connectCodeBlock } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/** 默认着色实现全元素共用一份:它无状态,没必要每个块建一个。 */\nconst defaultHighlighter = createHighlighter()\n\n// 属性缺席翻成 undefined,缺省值由 connect 给出\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席为 undefined、\"false\" 为 false、其余为 true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-code-block>` —— Light-DOM 行为宿主,无状态机:wire 时算出 connectCodeBlock 的产出,\n * 打到四类角色节点上。显示的代码文本由作者写在 code 角色节点里,元素不改其子节点。\n * 复制按钮由 `<xh-clipboard>` 组合提供。\n *\n * @customElement xh-code-block\n * @attr {string} code - 代码原文,只用于数行数预撑高度\n * @attr {string} code-lang - 围栏语言标注,空白时按 plaintext 处理\n * @attr {boolean} complete - 代码块是否已闭合\n * @csspart root - 外壳,承载 data-lang / data-complete\n * @csspart lang-label - 语言角标,纯装饰且对读屏隐藏\n * @csspart pre - 横向滚动容器;tabindex=0,最小高度按行数写进内联样式\n * @csspart code - 代码文本本身,承载 data-lang\n * @csspart token - 着色生效时的一个记号,承载 data-kind\n */\nexport class XhCodeBlockElement extends XhElement {\n static override partContract = { anatomy: codeBlockAnatomy, meta: codeBlockMeta }\n\n // 属性名用 code-lang,避开 HTML 全局属性 lang 与 HTMLElement 原生 lang 访问器。\n // 描述符逐个写全,不用对象展开,CEM 分析器的 lit 插件读不了展开元素的名字。\n static override properties = {\n code: { converter: STRING_CONVERTER },\n codeLang: { converter: STRING_CONVERTER, attribute: 'code-lang' },\n complete: { converter: BOOLEAN_CONVERTER },\n highlightWhileStreaming: { converter: BOOLEAN_CONVERTER, attribute: 'highlight-while-streaming' },\n }\n\n declare code?: string\n declare codeLang?: string\n declare complete?: boolean\n declare highlightWhileStreaming?: boolean\n\n /** 换一个着色实现(典型是接 Shiki);置 null 关掉着色。只走 property,属性表达不了对象。 */\n highlighter?: HighlighterPort | null\n\n /** 上一次铺进 code 部件的那串记号,用来判断要不要重铺。 */\n #painted?: string\n\n protected wire(): void {\n const api = connectCodeBlock({\n code: this.code ?? '',\n lang: this.codeLang,\n complete: this.complete,\n highlighter: this.highlighter === null ? undefined : this.highlighter ?? defaultHighlighter,\n highlightWhileStreaming: this.highlightWhileStreaming,\n }, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('lang-label', api.getLangLabelProps() as Record<string, unknown>)\n put('pre', api.getPreProps() as Record<string, unknown>)\n put('code', api.getCodeProps() as Record<string, unknown>)\n\n this.#paint(api.tokens, token => api.getTokenProps(token) as Record<string, unknown>)\n }\n\n /**\n * 着色生效时接管 code 部件的内容。\n * 本元素其余各处都不替作者生成节点,这里是**唯一的例外**:记号是算出来的派生数据,\n * 作者没法自己写。没有记号时一个节点都不动,作者写的代码文本原样留着。\n * 内容没变就不重铺——每次更新都重建节点会把用户正在拖的选区弄没。\n */\n #paint(tokens: readonly CodeToken[], propsOf: (token: CodeToken) => Record<string, unknown>): void {\n const host = this.getPart('code')\n if (!host || tokens.length === 0) {\n this.#painted = undefined\n return\n }\n const signature = tokens.map(token => `${token.kind}\u0000${token.text}`).join('\u0001')\n if (signature === this.#painted)\n return\n this.#painted = signature\n\n const doc = host.ownerDocument\n const frame = doc.createDocumentFragment()\n for (const token of tokens) {\n const span = doc.createElement('span')\n this.spreader.spread(span, propsOf(token))\n span.textContent = token.text\n frame.appendChild(span)\n }\n host.replaceChildren(frame)\n }\n}\n","import type { CollapsibleOpenChangeDetails, CollapsibleSchema } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { collapsibleAnatomy, collapsibleMachine, collapsibleMeta, connectCollapsible } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-collapsible>` —— Light-DOM 行为宿主,跑 collapsible 机器打到 root/trigger/content 角色节点,\n * 收起时用内联 style.display 隐藏 content。\n *\n * @customElement xh-collapsible\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} disabled - 禁用 trigger 切换\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 披露根容器\n * @csspart trigger - 触发按钮(aria-expanded/aria-controls 所在)\n * @csspart content - 可折叠内容(收起时隐藏)\n */\nexport class XhCollapsibleElement extends XhElement {\n static override partContract = { anatomy: collapsibleAnatomy, meta: collapsibleMeta }\n\n static override properties = {\n open: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n disabled: { type: Boolean },\n size: {},\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare disabled?: boolean\n declare size?: Size\n\n private readonly notify = (details: CollapsibleOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CollapsibleSchema>(\n this,\n collapsibleMachine,\n () => this.machineProps(),\n )\n\n private machineProps(): Partial<CollapsibleSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n disabled: this.disabled ?? false,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n protected wire(): void {\n const svc = this.ctrl.service\n const api = connectCollapsible(svc, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 收起时用内联 display 隐藏 content\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, this.ctrl.service.state.get() !== 'open')\n }\n}\n","import type {\n ColorPickerChannel,\n ColorPickerFormat,\n ColorPickerOpenChangeDetails,\n ColorPickerSchema,\n ColorPickerTranslations,\n ColorPickerValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { colorPickerAnatomy, colorPickerMachine, colorPickerMeta, colorPickerToChannel, colorPickerToInputChannel, connectColorPicker } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n/** 预设色板写成逗号分隔(swatches=\"#ff0000,#00ff00\"),空串当没写。 */\nconst STRING_LIST_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v == null || v.trim() === '')\n return undefined\n const out = v.split(',').map(item => item.trim()).filter(Boolean)\n return out.length ? out : undefined\n },\n}\n\n/**\n * `<xh-color-picker>` —— Light-DOM 行为宿主:作者写 root/label/trigger/value-text/swatch/\n * positioner/content/area/area-thumb/channel-slider/channel-input/swatch-item 等角色节点,\n * 元素跑 color-picker 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 trigger,被定位的浮层取 positioner。\n *\n * 工作色恒是 HSVA(取色区两轴为饱和度与明度),对外的值串按 format 序列化。\n * 取色区与通道滑杆的矩形只在指针事件那一刻才量。\n *\n * 通道滑杆与数值框用 channel 属性写明自己调哪一路(`channel=\"hue\"` / `channel=\"r\"`),\n * 滑杆内的轨道与拇指跟随所在滑杆的通道;预设色板每格用 value 属性写明颜色。\n *\n * @customElement xh-color-picker\n * @attr {string} value - 受控颜色值串;缺省该属性即非受控\n * @attr {string} default-value - 非受控初值,默认 #000000\n * @attr {'hex'|'rgba'|'hsla'} format - 值串写法,默认 hex\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} disabled - 禁用:触发器与按钮走原生 disabled,取色区与滑杆退出 Tab 序列\n * @attr {boolean} read-only - 只读:浮层照开,进去只是改不动\n * @attr {boolean} alpha - 带透明度,默认关;关掉时透明度那条滑杆与输入框整条禁用\n * @attr {string} swatches - 预设色板,逗号分隔(如 \"#ff0000,#00ff00\")\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写横轴上左右两键与指针的语义,默认 ltr\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @fires value-change - 颜色变化;detail 为 `{ value: string }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly)\n * @csspart label - 组标题(触发器 aria-labelledby 的目标之一)\n * @csspart trigger - 触发按钮,须是原生 button;同时是浮层的定位锚点\n * @csspart value-text - 当前值串的显示位;留空即由元素填入,作者写了内容则归作者\n * @csspart swatch - 当前颜色的色块(aria-hidden,背景由连接层写成内联样式)\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=dialog 容器(焦点域与消解层的根节点),收起时带 hidden\n * @csspart area - 二维取色区,横轴饱和度、纵轴明度;底色是当前色相\n * @csspart area-thumb - role=slider 的取色区拇指,两条轴的位置由连接层写成内联样式\n * @csspart channel-slider - 一条通道滑杆的外框,须自带 channel 属性(hue / alpha)\n * @csspart channel-slider-track - 通道轨道,值与坐标的换算以它的矩形为准\n * @csspart channel-slider-thumb - role=slider 的通道拇指\n * @csspart channel-input - 数值输入框,须是原生 input 且自带 channel 属性(hex / r / g / b / a)\n * @csspart eye-dropper-trigger - 屏幕取色按钮,须是原生 button;环境不支持时自动禁用\n * @csspart swatch-group - role=group 的预设色板容器\n * @csspart swatch-item - 预设色板一格,须是原生 button 且自带 value 属性\n */\nexport class XhColorPickerElement extends XhElement {\n static override partContract = { anatomy: colorPickerAnatomy, meta: colorPickerMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n format: { converter: STRING_CONVERTER },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n alpha: { converter: BOOLEAN_CONVERTER },\n swatches: { converter: STRING_LIST_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n // 文案表是对象,只走 property\n translations: { attribute: false },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare format?: ColorPickerFormat\n declare open?: boolean\n declare defaultOpen?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare alpha?: boolean\n declare swatches?: string[]\n declare direction?: Direction\n declare placement?: Placement\n declare offset?: number\n declare translations?: Partial<ColorPickerTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly pickerScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: ColorPickerValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: ColorPickerOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ColorPickerSchema>(\n this,\n colorPickerMachine,\n () => this.machineProps(),\n { scope: this.pickerScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<ColorPickerSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n format: this.format,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n alpha: this.alpha ?? false,\n swatches: this.swatches,\n dir: this.direction,\n placement: this.placement,\n offset: this.offset,\n translations: this.translations,\n onValueChange: this.notifyValue,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.pickerScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 触发器记为本层分支:点它算层内交互,开合交给它自己切换。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n /** 某条通道的轨道:先按 channel 属性找到那条滑杆,再取它自己那条轨道。 */\n private channelTrack(channel: ColorPickerChannel): HTMLElement | null {\n const slider = this.getParts('channel-slider')\n .find(el => colorPickerToChannel(el.getAttribute('channel') ?? undefined) === channel)\n if (!slider)\n return null\n return this.getParts('channel-slider-track').find(el => slider.contains(el)) ?? null\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入;节点一律懒读,建机器时 partMap 还空着。\n private injectRefs(svc: Service<ColorPickerSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n svc.refs.set('getAreaEl', () => this.getPart('area'))\n svc.refs.set('getChannelTrackEl', channel => this.channelTrack(channel))\n }\n\n /** 提前发现一次角色节点,让 default-open 时机器在 hostConnected 里就取得到 content。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /** value-text 是否归元素填:首次见到该节点时定,之后不再回读(读到的会是自己写的字)。 */\n private readonly ownsValueText = new WeakMap<HTMLElement, boolean>()\n\n private fillValueText(el: HTMLElement, text: string): void {\n let owned = this.ownsValueText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsValueText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n // 滑杆内的子部件:getParts 收的是整个元素范围,按滑杆子树过滤才归得对通道。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectColorPicker(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('swatch', api.getSwatchProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('area', api.getAreaProps() as Record<string, unknown>)\n put('area-thumb', api.getAreaThumbProps() as Record<string, unknown>)\n put('eye-dropper-trigger', api.getEyeDropperTriggerProps() as Record<string, unknown>)\n put('swatch-group', api.getSwatchGroupProps() as Record<string, unknown>)\n\n // 值串的显示由元素代填(作者只需给出空节点);作者写了内容就归作者,元素不再改写\n const valueText = this.getPart('value-text')\n if (valueText) {\n this.spreader.spread(valueText, api.getValueTextProps() as Record<string, unknown>)\n this.fillValueText(valueText, api.value)\n }\n\n // 通道滑杆是多实例 part,逐条打:身份取作者写的 channel 属性,漏写或写错都退回色相\n for (const el of this.getParts('channel-slider')) {\n const channel = colorPickerToChannel(el.getAttribute('channel') ?? undefined)\n this.spreader.spread(el, api.getChannelSliderProps({ channel }) as Record<string, unknown>)\n for (const track of this.partsIn(el, 'channel-slider-track'))\n this.spreader.spread(track, api.getChannelSliderTrackProps({ channel }) as Record<string, unknown>)\n for (const thumb of this.partsIn(el, 'channel-slider-thumb'))\n this.spreader.spread(thumb, api.getChannelSliderThumbProps({ channel }) as Record<string, unknown>)\n }\n\n // 数值框不必住在滑杆里(多半与滑杆各占一行),身份由它自己声明\n for (const el of this.getParts('channel-input')) {\n const channel = colorPickerToInputChannel(el.getAttribute('channel') ?? undefined)\n this.spreader.spread(el, api.getChannelInputProps({ channel }) as Record<string, unknown>)\n }\n\n for (const el of this.getParts('swatch-item'))\n this.spreader.spread(el, api.getSwatchItemProps({ value: el.getAttribute('value') ?? '' }) as Record<string, unknown>)\n\n // Light DOM 常驻,WC 自管可见性:作者层若给 content 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来。\n // 本包的样式自带 [hidden]{display:none} 压得住,但宿主不能指望作者装了这份样式\n this.setPartHidden(this.getPart('content'), !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type {\n ComboboxInputBehavior,\n ComboboxInputEl,\n ComboboxInputHost,\n ComboboxInputValueChangeDetails,\n ComboboxItemProps,\n ComboboxNode,\n ComboboxOpenChangeDetails,\n ComboboxSchema,\n ComboboxValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled } from '@xihan-ui/behavior'\nimport { comboboxAnatomy, comboboxMachine, comboboxMeta, connectCombobox } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-combobox>` —— Light-DOM 行为宿主:作者写 root/label/control/input/trigger/positioner/content/item/...\n * 角色节点,元素跑 combobox 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 control(浮层因此与整个输入行对齐),被定位的浮层取 positioner。\n *\n * 焦点自始至终在 input 上:候选不可聚焦、也不进 Tab 序列,高亮经 aria-activedescendant 报给读屏。\n *\n * 过滤不由本元素做:输入串变化时派发 input-value-change,作者据此增删 item 节点;\n * 元素每次接线完都会把当前候选条数与悬空高亮重新结算一遍,空态节点(empty)据此显形。\n *\n * @customElement xh-combobox\n * @attr {string} value - 受控选中值(单选简写);缺省该属性即非受控,多选请用 property 传数组\n * @attr {string} default-value - 非受控初始选中值\n * @attr {string} input-value - 受控输入串;缺省该属性即非受控\n * @attr {string} default-input-value - 非受控初始输入串\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} multiple - 多选:选中后列表不收起、输入串清空以便接着筛\n * @attr {boolean} disabled - 整个控件禁用:输入框与两个按钮都用原生 disabled\n * @attr {boolean} read-only - 只读:文字可选可复制,但展开、选中、清空一概不发生\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {string} placeholder - 输入框占位文字\n * @attr {boolean} allow-custom-value - 允许提交候选列表里没有的值\n * @attr {boolean} open-on-click - 点输入框即展开,默认 false\n * @attr {'none'|'autohighlight'|'autocomplete'} input-behavior - 输入行为,默认 none\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @fires input-value-change - 输入串变化;detail 为 `{ inputValue: string }`,作者据此过滤候选\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly/data-invalid)\n * @csspart label - 标题,须是原生 label(connect 给的 for 只在它身上生效)\n * @csspart control - 输入行容器,同时是浮层的定位锚点\n * @csspart input - 输入框,整个组合框唯一的 Tab 停靠点;写 input 时带 role=combobox,写 textarea 时保留它自带的 textbox 角色\n * @csspart trigger - 展开/收起按钮,须是原生 button;不占 Tab 位,可及名字由作者给\n * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=listbox 容器(消解层的根节点),收起时带 hidden\n * @csspart item - role=option 候选,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 候选文本(选中后回填输入框的取字处)\n * @csspart item-indicator - 候选选中标记(aria-hidden)\n * @csspart item-group - role=group 分组容器,须自带 value 属性标识身份\n * @csspart item-group-label - 分组标题(本组 aria-labelledby 的目标)\n * @csspart empty - 无匹配项提示;须放在 positioner 里当 content 的兄弟(列表内只允许 option 与 group)\n */\nexport class XhComboboxElement extends XhElement {\n static override partContract = { anatomy: comboboxAnatomy, meta: comboboxMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它候选的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n inputValue: { converter: STRING_CONVERTER, attribute: 'input-value' },\n defaultInputValue: { converter: STRING_CONVERTER, attribute: 'default-input-value' },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n multiple: { type: Boolean },\n disabled: { type: Boolean },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n allowCustomValue: { type: Boolean, attribute: 'allow-custom-value' },\n openOnClick: { type: Boolean, attribute: 'open-on-click' },\n inputBehavior: { converter: STRING_CONVERTER, attribute: 'input-behavior' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: ComboboxNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare inputValue?: string\n declare defaultInputValue?: string\n declare open?: boolean\n declare defaultOpen?: boolean\n declare multiple?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare loop?: boolean\n declare placeholder?: string\n declare allowCustomValue?: boolean\n declare openOnClick?: boolean\n declare inputBehavior?: ComboboxInputBehavior\n declare placement?: Placement\n declare offset?: number\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly comboboxScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: ComboboxValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyInputValue = (details: ComboboxInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('input-value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: ComboboxOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ComboboxSchema>(\n this,\n comboboxMachine,\n () => this.machineProps(),\n { scope: this.comboboxScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<ComboboxSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n inputValue: this.inputValue,\n defaultInputValue: this.defaultInputValue,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n multiple: this.multiple ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n loop: this.loop,\n placeholder: this.placeholder,\n allowCustomValue: this.allowCustomValue ?? false,\n openOnClick: this.openOnClick ?? false,\n inputBehavior: this.inputBehavior,\n placement: this.placement,\n offset: this.offset,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onInputValueChange: this.notifyInputValue,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.comboboxScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 整个输入行记为本层分支:点输入框或触发按钮算层内交互,开合交给它们自己切换。\n branches: () => [this.getPart('control')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 列表不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<ComboboxSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('control'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n svc.refs.set('getInputEl', () => this.getPart('input') as ComboboxInputEl | null)\n }\n\n /**\n * 提前发现一次角色节点:机器在 hostConnected 当场要按选中值去 content 里现查显示文本并回填输入框,\n * default-open 时还要同场挑出高亮。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n // 取 owner 子树内指定名字的角色节点。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectCombobox(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n // 宿主标签直接读作者写的标记:作者摆的是 input 还是 textarea,DOM 已经说明白了\n const inputHost: ComboboxInputHost = this.getPart('input')?.tagName === 'TEXTAREA' ? 'textarea' : 'input'\n put('input', api.getInputProps({ as: inputHost }) as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('empty', api.getEmptyProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item-group')) {\n const group = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getItemGroupProps(group) as Record<string, unknown>)\n for (const label of this.partsIn(el, 'item-group-label'))\n this.spreader.spread(label, api.getItemGroupLabelProps(group) as Record<string, unknown>)\n }\n\n // 候选逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled。\n // 这里回读 aria-disabled 是安全的(整控件禁用不向下传导到候选,写回的就是作者那份声明)。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供方向键现查。\n for (const el of this.getParts('item')) {\n const item: ComboboxItemProps = {\n value: el.getAttribute('value') ?? '',\n disabled: this.collection ? this.declaredDisabled(el) : isItemDisabled(el),\n }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n this.setPartHidden(this.getPart('empty'), !api.empty)\n\n // 每次接线完上报一次候选集合,让机器重算候选条数与悬空高亮\n if (this.ctrl.service.getStatus() === 'Started')\n this.ctrl.service.send({ type: 'ITEMS.SYNC' })\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type {\n ComposerRunStatus,\n ComposerSchema,\n ComposerSubmitDetails,\n ComposerTranslations,\n ComposerValueChangeDetails,\n} from '@xihan-ui/headless'\nimport { composerAnatomy, composerMachine, composerMeta, connectComposer } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席为 undefined、\"false\" 为 false、其余为 true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-composer>` —— Light-DOM 行为宿主:跑 composer 机器,把 connect 产出打到作者写的\n * root/input/submit-trigger 三类角色节点上。input 须是原生 `<textarea>`,值经 property 写、\n * 禁用走原生 disabled。流式期间发送按钮原位变停止,只换 `data-mode` 与 `aria-label`。\n *\n * @customElement xh-composer\n * @attr {string} value - 受控值,缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {boolean} disabled - 禁用,输入框带原生 disabled,发送与停止一并吃掉\n * @attr {'ready'|'streaming'} run-status - 宿主运行态,默认 ready;streaming 时发送按钮原位变停止\n * @attr {boolean} submit-on-enter - Enter 直接提交,默认 true;写 submit-on-enter=\"false\" 关掉\n * @fires value-change - 值变化;detail 为 `{ value: string }`\n * @fires submit - 提交;detail 为 `{ value: string }`,清空发生在派发之后。\n * 与原生表单提交同名,故不冒泡,请直接在 `<xh-composer>` 元素上监听\n * @fires stop - 流式期间按下停止;无 detail\n * @csspart root - 承载 data-disabled / data-status 的容器\n * @csspart input - 输入框,须是原生 `<textarea>`\n * @csspart submit-trigger - 发送 / 停止按钮,皮肤按 data-mode 换图标\n */\nexport class XhComposerElement extends XhElement {\n static override partContract = { anatomy: composerAnatomy, meta: composerMeta }\n\n // 描述符逐个写全,不用对象展开,CEM 分析器的 lit 插件读不了展开元素的名字\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n disabled: { converter: BOOLEAN_CONVERTER },\n runStatus: { converter: STRING_CONVERTER, attribute: 'run-status' },\n submitOnEnter: { converter: BOOLEAN_CONVERTER, attribute: 'submit-on-enter' },\n // 对象值走不了 HTML 属性,只作为 property 暴露\n translations: { attribute: false },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare disabled?: boolean\n declare runStatus?: ComposerRunStatus\n declare submitOnEnter?: boolean\n /** 输入框与发送/停止按钮的无障碍名,由 connect 写到节点上。 */\n declare translations?: Partial<ComposerTranslations>\n\n private readonly emit = (type: string, detail: unknown, bubbles = true): void => {\n this.dispatchEvent(new CustomEvent(type, { detail, bubbles, composed: bubbles }))\n }\n\n private readonly notifyValue = (details: ComposerValueChangeDetails): void => this.emit('value-change', details)\n // submit 与原生表单提交同名,故不冒泡,避免被祖先 <form> 当成自己的提交\n private readonly notifySubmit = (details: ComposerSubmitDetails): void => this.emit('submit', details, false)\n private readonly notifyStop = (): void => this.emit('stop', null)\n\n private readonly ctrl = new MachineController<ComposerSchema>(this, composerMachine, () => this.machineProps())\n\n private machineProps(): Partial<ComposerSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n disabled: this.disabled,\n runStatus: this.runStatus,\n submitOnEnter: this.submitOnEnter,\n translations: this.translations,\n onValueChange: this.notifyValue,\n onSubmit: this.notifySubmit,\n onStop: this.notifyStop,\n }\n }\n\n protected wire(): void {\n const api = connectComposer(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('submit-trigger', api.getSubmitTriggerProps() as Record<string, unknown>)\n // value 无需另行回写,spreader 已把它按 property 写入\n }\n}\n","import type { ContextMenuItemProps, ContextMenuNode, ContextMenuOpenChangeDetails, ContextMenuSchema, ContextMenuSelectDetails } from '@xihan-ui/headless'\nimport type { Cleanup, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectContextMenu, contextMenuAnatomy, contextMenuMachine, contextMenuMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕、连打检索)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-context-menu>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content 与若干\n * item / group / separator 角色节点,元素跑 context-menu 机器并把 connect 产出打上去。\n *\n * 与 `<xh-menu>` 的差别只在入口与锚点:这里由触发区上的右键(触摸端长按 700ms、\n * 键盘 ContextMenu / Shift+F10)打开,浮层钉在光标坐标上——锚点是虚拟的一点,\n * 不是某个元素,因此没有 getAnchorEl。展开着再右键只挪坐标,不先关再开。\n *\n * 条目身份取作者写在 item 上的 value 属性,禁用由部件自报(aria-disabled)。\n *\n * @customElement xh-context-menu\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 相对光标的首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与光标的间距(px),默认 0\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {boolean} typeahead - 连打检索,默认开;写 typeahead=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,默认 ltr\n * @attr {number} long-press-delay - 触摸端长按触发时长(ms),默认 700\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @fires select - 条目被选中(菜单随之关闭);detail 为 `{ value: string }`\n * @csspart root - 组件根容器(承载 data-state)\n * @csspart trigger - 右键触发区(aria-haspopup/aria-controls 所在,自带 Tab 位供键盘开启)\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=menu 容器(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden\n * @csspart item - role=menuitem 条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 条目文本(连打检索的取字处)\n * @csspart item-indicator - 条目标记位(勾选符号 / 图标 / 快捷键提示),aria-hidden\n * @csspart separator - 分隔线(role=separator,不入方向键导航)\n * @csspart group - role=group 分组容器,须自带 value 属性标识身份\n * @csspart group-label - 分组标题(本组 aria-labelledby 的目标)\n * @csspart arrow - 指向锚点的箭头(aria-hidden,data-placement 随实际放置位翻转)\n */\nexport class XhContextMenuElement extends XhElement {\n static override partContract = { anatomy: contextMenuAnatomy, meta: contextMenuMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的禁用即以数据为准\n collection: { attribute: false },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n typeahead: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n longPressDelay: { converter: NUMBER_CONVERTER, attribute: 'long-press-delay' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: ContextMenuNode[]\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare loop?: boolean\n declare typeahead?: boolean\n declare direction?: Direction\n declare longPressDelay?: number\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly menuScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyOpen = (details: ContextMenuOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelect = (details: ContextMenuSelectDetails): void => {\n this.dispatchEvent(new CustomEvent('select', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ContextMenuSchema>(\n this,\n contextMenuMachine,\n () => this.machineProps(),\n { scope: this.menuScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<ContextMenuSchema['props']> {\n return {\n collection: this.collection,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n loop: this.loop,\n typeahead: this.typeahead,\n dir: this.direction,\n longPressDelay: this.longPressDelay,\n tone: this.tone,\n size: this.size,\n onOpenChange: this.notifyOpen,\n onSelect: this.notifySelect,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.menuScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 触发区记为本层分支:展开着再右键要能就地换坐标,先被判成层外交互关一次就白闪了。\n // 代价是\"左键点在触发区内也该关\"落不到消解层头上,那条由 connect 在 pointerdown 上自己收口。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 右键菜单不带遮罩,没有\"点它就该关本层\"的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n private injectRefs(svc: Service<ContextMenuSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入展开态,\n * 进入那一刻的 entry 同步查 content 里的条目挑焦点锚点——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,锚点会留空,于是没有条目认领 tabindex=0,键盘进不去菜单。\n * 定位是 flush 推迟的(那时 partMap 已就位),这里只为锚点补上时机。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,锚点会停在一个已消失的值上:\n * 没有条目认领 tabindex=0、方向键也失去起点。这里替 DOM 把焦点离场如实上报,\n * 机器就地按当前活条目重挑锚点。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,分隔线与条目内的文本离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'ITEM.LOST' })\n }\n\n // 条目/分组内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectContextMenu(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可。\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n for (const el of this.getParts('group')) {\n const group = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getGroupProps(group) as Record<string, unknown>)\n for (const label of this.partsIn(el, 'group-label'))\n this.spreader.spread(label, api.getGroupLabelProps(group) as Record<string, unknown>)\n }\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled\n // (集合条目一律 aria-disabled,原生 disabled 不可聚焦、也不派 click)。\n // 打上去的 data-scope/data-part/data-value 正是方向键与连打检索在事件那一刻查 DOM 的依据,\n // 所以 wire 必须先于事件跑过——updated() 已保证。\n for (const el of this.getParts('item')) {\n const item: ContextMenuItemProps = {\n value: el.getAttribute('value') ?? '',\n disabled: this.collection ? this.declaredDisabled(el) : isItemDisabled(el),\n }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n // 条目内的文本与标记位跟着同一份声明走,样式层各处状态一致\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // 分隔线也是多实例 part,但不带身份、不入导航,属性对每个都一样\n for (const el of this.getParts('separator'))\n this.spreader.spread(el, api.getSeparatorProps() as Record<string, unknown>)\n\n // Light DOM content 常驻,WC 自管可见性:作者层给 content 设了 display(本仓样式是 flex)\n // 就会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住。\n // 展开时还回作者原本写的内联值,不把他自己的 style=\"display:grid\" 抹掉。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { CountdownFinishDetails, CountdownLive, CountdownSchema } from '@xihan-ui/headless'\nimport { connectCountdown, countdownAnatomy, countdownMachine, countdownMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席:`value=\"\"` 经 Number() 会变成 0,那是\"已经到点\",不是\"没写\"\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 缺省为真的开关(active)得能被 =\"false\" 关掉;三态:缺席 = undefined(用默认值),=\"false\" = false,其余 = true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-countdown>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,\n * 元素跑 countdown 机器,逐帧把剩余毫秒按模板铺成时分秒写进那个节点。\n *\n * 剩余量走的是与数值动画同一份补间:起点是这一轮开始时的剩余毫秒、终点是 0、\n * 时长恰好等于起点本身。改写 `value` 即把剩余量落到新值并从那里重新计时,\n * 停在 idle 时改 `value` 同样会重新走起来。\n *\n * `precision` 管的是取值粒度而不是排版:0 取到整秒、3 取到整毫秒;\n * 想显示毫秒得把 precision 提上去,只在 `format` 里写 `SSS` 会一直是 `000`。\n *\n * 根是 role=\"status\" 但 aria-live 缺省写死 off:status 的隐含 aria-live 就是 polite,\n * 一个每秒都在变的数字用 polite 会把读屏刷爆,要播报由作者把 live 开到 polite 或 assertive。\n *\n * @customElement xh-countdown\n * @attr {number} value - 剩余毫秒,缺省 0\n * @attr {string} format - 模板,缺省 `HH:mm:ss`;H 时、m 分、s 秒、S 毫秒,重复字母的个数即最少位数\n * @attr {boolean} active - 是否在走,缺省真;`active=\"false\"` 停在当前剩余量\n * @attr {number} precision - 取值粒度:0 到秒、1 到十分之一秒、2 到百分之一秒、3 到毫秒,缺省 0\n * @attr {'off'|'polite'|'assertive'} live - 读屏播报档位,缺省 off\n * @fires finish - 走到 0;detail 为 `{ value: number }`\n * @csspart root - 时间本身(承载 status 语义、data-state 与 data-finished);文字归元素写\n */\nexport class XhCountdownElement extends XhElement {\n static override partContract = { anatomy: countdownAnatomy, meta: countdownMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: NUMBER_CONVERTER },\n format: { converter: STRING_CONVERTER },\n active: { converter: BOOLEAN_CONVERTER },\n precision: { converter: NUMBER_CONVERTER },\n live: { converter: STRING_CONVERTER },\n }\n\n declare value?: number\n declare format?: string\n declare active?: boolean\n declare precision?: number\n declare live?: CountdownLive\n\n private readonly notify = (details: CountdownFinishDetails): void => {\n this.dispatchEvent(new CustomEvent('finish', { detail: details, bubbles: true, composed: true }))\n }\n\n // 机器的副作用只有一个逐帧循环(自身自足):不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<CountdownSchema>(this, countdownMachine, () => this.machineProps())\n\n private machineProps(): Partial<CountdownSchema['props']> {\n return {\n value: this.value,\n format: this.format,\n // 布尔属性经三态转换器进来:不在即 undefined,把缺省交回机器\n active: this.active,\n precision: this.precision,\n live: this.live,\n onFinish: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectCountdown(this.ctrl.service, wcNormalize)\n const root = this.getPart('root')\n if (!root)\n return\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n // 时间归元素写:spreader 只管属性与事件,写不了文本。\n // 比一次再写:值没动时的赋值会白白惊动一次变更记录,而这里每帧都会走一遍\n if (root.textContent !== api.text)\n root.textContent = api.text\n }\n}\n","import type { DateFieldSchema, DateFieldValueChangeDetails, DateGranularity, DateSegmentType } from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectDateField, dateFieldAnatomy, dateFieldMachine, dateFieldMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 默认的 Boolean 转换器判的是 v !== null,写 disabled=\"false\" 反而成了真\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\ntype SegmentTexts = { readonly [K in DateSegmentType]?: string }\n\n/** 作者写在段位上的下标。缺席或写坏了就退回文档序——手写 HTML 时把段位按顺序排下来本身就是声明。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-date-field>` —— Light-DOM 行为宿主:作者写 root/label/control/segment(多个)/hidden-input\n * 角色节点,元素跑 date-field 机器并把 connect 产出打上去。\n *\n * 每一段是一个 role=spinbutton 的可聚焦节点:上下键加减并在段区间里回绕、左右键与 Home/End 换段、\n * 数字键直填且敲满自动跳下一段、Backspace 清掉本段。是哪一段由 locale(zh-CN 年月日、\n * en-US 月日年)与 granularity 算出来,作者只声明下标,不声明段名——同一份标记换个 locale\n * 就换一副面孔。精度用不上的段带 hidden 留在文档里,不卸载作者节点。\n *\n * 段位没填齐时整份值是 null;填齐了才拼出 ISO 串,由 hidden-input 随表单提交。\n *\n * 占位串与读屏名字是逐段的对象,属性表达不了,只能走 property\n * (`el.placeholder = { year: '年' }`)。\n *\n * @customElement xh-date-field\n * @attr {string} value - 受控值,ISO 串;写成空串即\"受控且当前为空\";缺省该属性即非受控\n * @attr {string} default-value - 非受控初值,同样是 ISO 串\n * @attr {string} min - 下界 ISO 串,参与各段区间的收窄\n * @attr {string} max - 上界 ISO 串\n * @attr {string} locale - BCP 47 语言标记,决定年月日三段的先后,默认 en-US\n * @attr {string} time-zone - IANA 时区名,只用来取\"今天\"(空段按上下键时的起点)\n * @attr {'day'|'hour'|'minute'|'second'} granularity - 精度,决定一共几段,默认 day\n * @attr {boolean} disabled - 禁用:整组退出 Tab 序,隐藏输入不参与提交\n * @attr {boolean} read-only - 只读:可聚焦、可换段,但改不动\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} required - 必填标注,落到每段的 aria-required 上\n * @attr {string} name - 表单字段名;给了隐藏输入才带 name\n * @attr {'outline'|'subtle'|'ghost'} variant - 形态\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 值变化;detail 为 `{ value: string | null }`\n * @csspart root - 最外层,承载 data-disabled / data-invalid / data-complete / data-out-of-range\n * @csspart label - 标题;点它把焦点送进首段\n * @csspart control - role=group 的分段容器\n * @csspart segment - 一段一个的 spinbutton 节点,可自带 index 属性声明下标,缺省按文档序\n * @csspart hidden-input - type=hidden 的表单出口,值是 ISO 串\n */\nexport class XhDateFieldElement extends XhElement {\n static override partContract = { anatomy: dateFieldAnatomy, meta: dateFieldMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n min: { converter: STRING_CONVERTER },\n max: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n timeZone: { converter: STRING_CONVERTER, attribute: 'time-zone' },\n granularity: { converter: STRING_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n required: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n placeholder: { attribute: false },\n translations: { attribute: false },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare min?: string\n declare max?: string\n declare locale?: string\n declare timeZone?: string\n declare granularity?: DateGranularity\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare required?: boolean\n declare name?: string\n declare placeholder?: SegmentTexts\n declare translations?: SegmentTexts\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notifyChange = (details: DateFieldValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // date-field 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<DateFieldSchema>(this, dateFieldMachine, () => this.machineProps())\n\n private machineProps(): Partial<DateFieldSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n min: this.min,\n max: this.max,\n locale: this.locale,\n timeZone: this.timeZone,\n granularity: this.granularity,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n required: this.required ?? false,\n name: this.name,\n placeholder: this.placeholder,\n translations: this.translations,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyChange,\n }\n }\n\n protected wire(): void {\n const api = connectDateField(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n // 段位是多实例 part,逐个打。打上去的 data-scope/data-part 正是换段在事件那一刻\n // 现查 DOM 的依据,所以 wire 必须先于事件跑过——updated() 已保证。\n this.getParts('segment').forEach((el, position) => {\n const index = declaredIndex(el, position)\n this.spreader.spread(el, api.getSegmentProps({ index }) as Record<string, unknown>)\n const state = api.segments[index]\n // 段位的文字归元素写:spreader 只管属性与事件,写不了文本。\n // 比一次再写:无谓的赋值会清掉这个节点里的选区,还会白白惊动一次变更记录\n const text = state?.text ?? ''\n if (el.textContent !== text)\n el.textContent = text\n // connect 已置 hidden,但作者若给段位设了 display 就会盖过 UA 的 [hidden]{display:none};\n // 内联 style.display 优先级更高,压得住\n this.setPartHidden(el, state == null)\n })\n }\n}\n","import type {\n CalendarDay,\n CalendarSchema,\n CalendarSelectionMode,\n CalendarWeekDay,\n DateFieldSchema,\n DatePickerFieldApi,\n DatePickerFocusChangeDetails,\n DatePickerOpenChangeDetails,\n DatePickerSchema,\n DatePickerServices,\n DatePickerValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { calendarAnatomy, calendarMachine, connectDatePicker, dateFieldAnatomy, dateFieldMachine, datePickerAnatomy, datePickerCalendarProps, datePickerFieldEndProps, datePickerFieldProps, datePickerMachine, datePickerMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 取作者写在段位上的 index,缺席或写坏了退回组内文档序。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-date-picker>` —— Light-DOM 行为宿主:作者写 root/label/control/input/segment/trigger/\n * clear-trigger/positioner/content/calendar 角色节点,calendar 之内再照日历那套写\n * header/prev-trigger/next-trigger/heading/grid/grid-head/week-day/grid-body/week-row/cell/cell-trigger。\n *\n * 本元素是编排机,只持有开合与「分段输入 ↔ 日历」之间的值同步;选日期、翻月、网格键盘导航\n * 委派给内嵌日历,分段输入委派给内嵌分段输入,两部件之内的 DOM 各戴各自的 data-scope。\n *\n * 网格由作者渲染,元素不生成节点:读 `weeks` / `weekDays` / `headingLabel` 三个只读属性,\n * 听 `focused-value-change` 重画。日期身份取 cell 节点上的 `value`(ISO 串),\n * cell-trigger 跟随所在 cell;表头列取 week-day 上的 `value`(列序 0-6);\n * 段位可自带 `index` 属性声明下标,缺省按所在 input 之内的文档序。\n *\n * 区间模式(selection-mode=\"range\")下 input 写两个:文档序在前的是起点、在后的是终点,\n * 各自内部写一整套段位。段位与 hidden-input 按所在 input 归组,方向键不跨组;\n * hidden-input 写在 input 之外(如与 control 平级)时按文档序对应起止两端。\n * 其余模式只认第一个 input。\n *\n * @customElement xh-date-picker\n * @attr {string} value - 受控选中值(单选简写,ISO 串);缺省该属性即非受控,区间/多选请用 property 传数组\n * @attr {string} default-value - 非受控初始选中值\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} min - 可选范围下界(含当天),日历与分段输入共用\n * @attr {string} max - 可选范围上界(含当天)\n * @attr {string} locale - 决定周首日、月份文案与段位先后,默认 zh-CN(段序默认 en-US 由分段输入自定)\n * @attr {string} time-zone - 判定\"今天\"与格式化用的时区,默认宿主本地时区\n * @attr {'single'|'multiple'|'range'} selection-mode - 选择模式,默认 single\n * @attr {boolean} disabled - 整个控件禁用:trigger 转原生 disabled,段位退出 Tab 序\n * @attr {boolean} read-only - 只读:浮层照常展开、日历照常浏览,但选中值改不动\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} required - 必填标注,落到每段的 aria-required 上\n * @attr {string} name - 表单字段名;给了隐藏输入才带 name。区间模式下是起点那一份\n * @attr {string} end-name - 区间终点那份隐藏输入的表单字段名;不给即终点不参与提交\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} close-on-select - 选完即收起,默认 true;写 close-on-select=\"false\" 关掉\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @fires focused-value-change - 聚焦日变化(意味着展示月可能换了);detail 为 `{ focusedValue: string }`,作者据此重画网格\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly/data-invalid)\n * @csspart label - 标题;点它把焦点送进首段。刻意不是原生 label(段位是 div,标不了)\n * @csspart control - 输入行容器,同时是浮层的定位锚点\n * @csspart input - role=group 的分段容器,段位挂在它里面;区间模式下有起止两个,data-index 区分\n * @csspart segment - 一段一个的 spinbutton 节点(data-scope=\"date-field\"),可自带 index 属性;下标在所属 input 组内数\n * @csspart trigger - 展开日历的按钮,须是原生 button\n * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=dialog 浮层(消解层的根节点),收起时带 hidden\n * @csspart calendar - 内嵌日历的挂载点,同时充当日历的根节点\n * @csspart header - 日历标题栏外壳(data-scope=\"calendar\")\n * @csspart prev-trigger - 上一月;越过 min 时转原生 disabled\n * @csspart next-trigger - 下一月;越过 max 时转原生 disabled\n * @csspart heading - 展示月标题(grid 的 aria-labelledby 目标)\n * @csspart grid - role=grid 容器,网格键盘在此收口\n * @csspart grid-head - role=rowgroup 表头组,里面套一个 week-row\n * @csspart week-day - role=columnheader 列头,须自带 value 属性标明列序 0-6\n * @csspart grid-body - role=rowgroup 日期组\n * @csspart week-row - role=row 周行,表头与日期行共用\n * @csspart cell - role=gridcell 日期格,承载 aria-selected;须自带 value 属性(ISO 串)\n * @csspart cell-trigger - 真正可点可聚焦的那一层,承载 aria-disabled 与 roving tabindex\n * @csspart hidden-input - type=hidden 的表单出口,值是 ISO 串;区间模式下起止各一份\n */\nexport class XhDatePickerElement extends XhElement {\n // 分段输入与日历的 DOM 摊在本元素的 Light DOM 里由本元素接线,它们的角色节点归各自 scope 管\n static override partContract = {\n anatomy: datePickerAnatomy,\n meta: datePickerMeta,\n delegates: [dateFieldAnatomy, calendarAnatomy],\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n min: { converter: STRING_CONVERTER },\n max: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n timeZone: { converter: STRING_CONVERTER, attribute: 'time-zone' },\n selectionMode: { converter: STRING_CONVERTER, attribute: 'selection-mode' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n required: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n endName: { converter: STRING_CONVERTER, attribute: 'end-name' },\n // 文案是对象,只能走 property\n translations: { attribute: false },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n closeOnSelect: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-select' },\n // 判定函数只走 property\n isDateUnavailable: { attribute: false },\n }\n\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare open?: boolean\n declare defaultOpen?: boolean\n declare min?: string\n declare max?: string\n declare locale?: string\n declare timeZone?: string\n declare selectionMode?: CalendarSelectionMode\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare required?: boolean\n declare name?: string\n declare endName?: string\n declare translations?: DatePickerSchema['props']['translations']\n declare placement?: Placement\n declare offset?: number\n declare closeOnSelect?: boolean\n declare isDateUnavailable?: (value: string) => boolean\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n // 四台机器共用一份 scope,part id 里带组件名故不相撞\n private readonly pickerScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: DatePickerValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: DatePickerOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 网格由作者渲染,这条是「该重画了」的信号\n private readonly notifyFocus = (details: DatePickerFocusChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('focused-value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 声明顺序即 controller 挂载顺序:三台内嵌机器的 props 从编排机现读,编排机须先建\n private readonly rootCtrl = new MachineController<DatePickerSchema>(\n this,\n datePickerMachine,\n () => this.machineProps(),\n { scope: this.pickerScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private readonly calendarCtrl = new MachineController<CalendarSchema>(\n this,\n calendarMachine,\n () => datePickerCalendarProps(this.rootCtrl.service),\n {\n scope: this.pickerScope,\n // 机器跨月后靠它把焦点送进重画出来的格子\n onBuilt: (service) => {\n service.refs.set('getGridEl', () => this.getPart('grid'))\n },\n },\n )\n\n private readonly fieldCtrl = new MachineController<DateFieldSchema>(\n this,\n dateFieldMachine,\n () => datePickerFieldProps(this.rootCtrl.service),\n { scope: this.pickerScope },\n )\n\n // 终点那组段位;一律建起来不按模式条件建,机器实例数得是定数。\n // 非区间模式下它的值恒为空、写值入口自锁,connect 也不把它露出来\n private readonly fieldEndCtrl = new MachineController<DateFieldSchema>(\n this,\n dateFieldMachine,\n () => datePickerFieldEndProps(this.rootCtrl.service),\n { scope: this.pickerScope },\n )\n\n private services(): DatePickerServices {\n return {\n root: this.rootCtrl.service,\n calendar: this.calendarCtrl.service,\n field: this.fieldCtrl.service,\n fieldEnd: this.fieldEndCtrl.service,\n }\n }\n\n private machineProps(): Partial<DatePickerSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n min: this.min,\n max: this.max,\n locale: this.locale,\n timeZone: this.timeZone,\n selectionMode: this.selectionMode,\n isDateUnavailable: this.isDateUnavailable,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n required: this.required ?? false,\n name: this.name,\n endName: this.endName,\n translations: this.translations,\n placement: this.placement,\n offset: this.offset,\n closeOnSelect: this.closeOnSelect,\n onValueChange: this.notifyValue,\n onOpenChange: this.notifyOpen,\n onFocusedValueChange: this.notifyFocus,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.pickerScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 整个输入行记为本层分支:点 trigger 或段位算层内交互,开合交给它们自己切换。\n branches: () => [this.getPart('control')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<DatePickerSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('control'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /** 提前发现一次角色节点:default-open 时焦点域在 hostConnected 当场要去 content 里找聚焦日那一格。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /** 当前展示月的日期矩阵,作者照它重画网格。机器尚未建起时给空数组。 */\n get weeks(): CalendarDay[][] {\n return this.rootCtrl.service ? connectDatePicker(this.services(), wcNormalize).calendar.weeks : []\n }\n\n /** 七列表头(缩写 + 全称),列序与 weeks 的列序一致。 */\n get weekDays(): CalendarWeekDay[] {\n return this.rootCtrl.service ? connectDatePicker(this.services(), wcNormalize).calendar.weekDays : []\n }\n\n /** 展示月标题文案,作者写进 heading 节点。 */\n get headingLabel(): string {\n return this.rootCtrl.service ? connectDatePicker(this.services(), wcNormalize).calendar.headingLabel : ''\n }\n\n /** 取 owner 子树内指定名字的角色节点。 */\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n /**\n * 把隐藏输入分到起止两端:写在某个 input 之内的归那一组,\n * 写在全部 input 之外的按自己的文档序对号入座。多出来的一律不接线。\n */\n private hiddenInputGroups(inputs: readonly HTMLElement[]): HTMLElement[][] {\n const groups: HTMLElement[][] = [[], []]\n this.getParts('hidden-input').forEach((el, position) => {\n const owned = inputs.findIndex(input => input.contains(el))\n groups[owned >= 0 ? owned : position]?.push(el)\n })\n return groups\n }\n\n /** 打一组段位:下标在组内从 0 数起,段位文字与收起态一并落。 */\n private wireSegments(owner: HTMLElement, field: DatePickerFieldApi): void {\n // wire 跑在事件之前,换段时 data-scope/data-part 已在 DOM 上供现查\n this.partsIn(owner, 'segment').forEach((el, position) => {\n const index = declaredIndex(el, position)\n this.spreader.spread(el, field.getSegmentProps({ index }) as Record<string, unknown>)\n const state = field.segments[index]\n // 段位文字归元素写,比对后再赋值\n const text = state?.text ?? ''\n if (el.textContent !== text)\n el.textContent = text\n // 用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(el, state == null)\n })\n }\n\n protected wire(): void {\n const api = connectDatePicker(this.services(), wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('calendar', api.getCalendarProps() as Record<string, unknown>)\n\n // 起止两组各自成组:段位与隐藏输入按所属 input 归组,跨组不共用下标。\n // input 可缺省,作者没写就拿宿主自身当归组容器,段位全归起点那一组\n const inputs = this.getParts('input')\n const owners = [inputs[0] ?? (this as unknown as HTMLElement), inputs[1]]\n const hiddenInputs = this.hiddenInputGroups(inputs)\n for (const index of [0, 1] as const) {\n // 非区间模式没有终点那一组,作者多写的 input、段位与隐藏输入一概不接线\n const field = index === 0 ? api.field : api.fieldEnd\n if (!field)\n continue\n const input = inputs[index]\n if (input)\n this.spreader.spread(input, api.getInputProps({ index }) as Record<string, unknown>)\n const owner = owners[index]\n if (owner)\n this.wireSegments(owner, field)\n for (const el of hiddenInputs[index] ?? [])\n this.spreader.spread(el, field.getHiddenInputProps() as Record<string, unknown>)\n }\n\n // 内嵌日历的角色节点:行为取自本元素持有的那台日历机器\n put('header', api.calendar.getHeaderProps() as Record<string, unknown>)\n put('prev-trigger', api.calendar.getPrevTriggerProps() as Record<string, unknown>)\n put('next-trigger', api.calendar.getNextTriggerProps() as Record<string, unknown>)\n put('heading', api.calendar.getHeadingProps() as Record<string, unknown>)\n put('grid', api.calendar.getGridProps() as Record<string, unknown>)\n put('grid-head', api.calendar.getGridHeadProps() as Record<string, unknown>)\n put('grid-body', api.calendar.getGridBodyProps() as Record<string, unknown>)\n\n // 表头行与日期行共用 role=row,一并打\n for (const el of this.getParts('week-row'))\n this.spreader.spread(el, api.calendar.getWeekRowProps() as Record<string, unknown>)\n\n // 列头身份取作者写的 value(列序 0-6);漏写给 NaN,不写 aria-label\n for (const el of this.getParts('week-day')) {\n const raw = el.getAttribute('value')\n const index = raw == null || raw === '' ? Number.NaN : Number(raw)\n this.spreader.spread(el, api.calendar.getWeekDayProps({ value: index }) as Record<string, unknown>)\n }\n\n // 日期格逐个打,身份取 cell 上的 value,格内 trigger 跟着同一份声明走\n for (const el of this.getParts('cell')) {\n const cell = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.calendar.getCellProps(cell) as Record<string, unknown>)\n for (const trigger of this.partsIn(el, 'cell-trigger'))\n this.spreader.spread(trigger, api.calendar.getCellTriggerProps(cell) as Record<string, unknown>)\n }\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { DescriptionsColumns, DescriptionsPlacement, DescriptionsProps } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { connectDescriptions, descriptionsAnatomy, descriptionsMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-descriptions>` —— Light-DOM 行为宿主,无状态机,把 connectDescriptions 产出打到各角色节点。\n * 排版走 CSS Grid,columns 落成列数。\n *\n * 标签由作者定,root 写 `<dl>`、label 写 `<dt>`、value 写 `<dd>` 时标签与取值天然成对;\n * 组件不补 role,也不用 `<table>`——这是一份描述列表,不是数据表。\n *\n * @customElement xh-descriptions\n * @attr {1|2|3|4|5|6} columns - 每行摆几组,如实落成根上的 data-columns;不写即每行一组\n * @attr {boolean} bordered - 画外框,并在格与格之间画网格线\n * @attr {'top'|'left'} placement - 标签在上还是在左;不写即在上\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定每格的内边距、组与组的间距与整体字号\n * @csspart root - 网格容器,承载 data-columns / data-placement / data-size / data-bordered\n * @csspart item - 一组「标签 + 取值」,占网格里的一格\n * @csspart label - 标签\n * @csspart value - 取值\n */\nexport class XhDescriptionsElement extends XhElement {\n static override partContract = { anatomy: descriptionsAnatomy, meta: descriptionsMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n columns: { type: Number },\n bordered: { type: Boolean },\n placement: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare columns?: DescriptionsColumns\n declare bordered?: boolean\n declare placement?: DescriptionsPlacement\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectDescriptions({\n columns: this.columns,\n bordered: this.bordered ?? false,\n placement: this.placement,\n size: this.size,\n } satisfies DescriptionsProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 每一组都会出现多次,逐个打\n const putAll = (name: string, attrs: Record<string, unknown>): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, attrs)\n }\n\n putAll('item', api.getItemProps() as Record<string, unknown>)\n putAll('label', api.getLabelProps() as Record<string, unknown>)\n putAll('value', api.getValueProps() as Record<string, unknown>)\n }\n}\n","import type { DialogOpenChangeDetails, DialogSchema } from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, RuntimeConfig, Size } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectDialog, dialogAnatomy, dialogMachine, dialogMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 属性缺席翻成 undefined,缺省值由皮肤的缺省档决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-dialog>` —— Light-DOM 行为宿主,跑 dialog 机器并把 connect 产出打到角色节点上,\n * 关闭时用内联 style.display 隐藏浮层子树。\n *\n * @customElement xh-dialog\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为打开\n * @attr {boolean} modal - 模态(陷焦点、锁滚动、遮罩交互外关闭),默认 true\n * @attr {'dialog'|'alertdialog'} role - 语义角色,默认 dialog\n * @attr {boolean} close-on-escape - Esc 关闭,默认 true\n * @attr {boolean} restore-focus - 关闭后把焦点归还触发元素,默认 true\n * @attr {'sm'|'md'|'lg'} size - 尺寸:只换 content 的最大宽度,落在 content 上\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart trigger - 触发按钮\n * @csspart backdrop - 遮罩层\n * @csspart positioner - 浮层定位容器\n * @csspart content - 对话框内容(role/aria-modal/焦点陷阱所在)\n * @csspart title - 标题(aria-labelledby 目标)\n * @csspart description - 描述(aria-describedby 目标)\n * @csspart close-trigger - 关闭按钮\n */\nexport class XhDialogElement extends XhElement {\n static override partContract = { anatomy: dialogAnatomy, meta: dialogMeta }\n\n // role 不声明为响应式属性,复用 HTMLElement 原生反射,在 machineProps 里经 getAttribute 读取。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n modal: { converter: BOOLEAN_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n restoreFocus: { converter: BOOLEAN_CONVERTER, attribute: 'restore-focus' },\n size: { converter: STRING_CONVERTER },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare modal?: boolean\n declare closeOnEscape?: boolean\n declare restoreFocus?: boolean\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly dialogScope = createScope(null, this.idGen)\n private config: RuntimeConfig | null = null\n private contentNode: HTMLElement | null = null\n private backdropNode: HTMLElement | null = null\n\n private readonly notify = (details: DialogOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<DialogSchema>(\n this,\n dialogMachine,\n () => this.machineProps(),\n { scope: this.dialogScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<DialogSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n modal: this.modal,\n role: (this.getAttribute('role') as DialogSchema['props']['role']) ?? undefined,\n closeOnEscape: this.closeOnEscape,\n restoreFocus: this.restoreFocus,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.dialogScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数,层的入栈出栈由机器的 trackOverlay 效应跟着展开态做。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'modal',\n node: () => this.contentNode,\n branches: () => [],\n isModal: () => this.machineProps().modal ?? true,\n setModal: () => {},\n surfaces: () => [this.backdropNode].filter(Boolean) as Element[],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<DialogSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('presence', null)\n svc.refs.set('getContentEl', () => this.contentNode)\n svc.refs.set('getTriggerEl', () => this.getPart('trigger'))\n svc.refs.set('branches', () => [])\n }\n\n protected wire(): void {\n const svc = this.ctrl.service\n const api = connectDialog(svc, wcNormalize)\n const open = svc.state.get() === 'open'\n\n this.contentNode = this.getPart('content')\n this.backdropNode = this.getPart('backdrop')\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('backdrop', api.getBackdropProps() as Record<string, unknown>)\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n\n // 关闭时用内联 display 隐藏浮层子树,优先级高于样式表对 [hidden] 的覆盖\n const positioner = this.getPart('positioner')\n if (positioner)\n this.setPartHidden(positioner, !open)\n if (this.backdropNode)\n this.setPartHidden(this.backdropNode, !open)\n // positioner 不是必需部件,content 自己也要收起\n this.setPartHidden(this.contentNode, !open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { DrawerOpenChangeDetails, DrawerSchema } from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, RuntimeConfig, Size } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectDrawer, drawerAnatomy, drawerMachine, drawerMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-drawer>` —— Light-DOM 行为宿主,跑 drawer 机器并把 connect 产出打到角色节点上,\n * 关闭时用内联 style.display 隐藏浮层子树。\n *\n * 键盘与 ARIA 契约同 dialog;side 决定滑入方向,以 data-side 落在 root 与 content 上供样式取用。\n *\n * @customElement xh-drawer\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为打开\n * @attr {boolean} modal - 模态(陷焦点、锁滚动、遮罩交互外关闭),默认 true\n * @attr {'top'|'right'|'bottom'|'left'} side - 从哪条边滑出,默认 right\n * @attr {'dialog'|'alertdialog'} role - 语义角色,默认 dialog\n * @attr {boolean} close-on-escape - Esc 关闭,默认 true\n * @attr {boolean} close-on-interact-outside - 点击浮层外关闭;默认跟随 modal,alertdialog 恒不关\n * @attr {boolean} restore-focus - 关闭后把焦点归还触发元素,默认 true\n * @attr {'sm'|'md'|'lg'} size - 尺寸:横放时换面板宽度、竖放时换面板高度\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 留在页面原地的容器,承载 data-side / data-size / data-state\n * @csspart trigger - 触发按钮\n * @csspart backdrop - 遮罩层\n * @csspart positioner - 浮层定位容器(贴边布局写在它身上)\n * @csspart content - 抽屉面板(role/aria-modal/焦点陷阱所在,另带 data-side / data-size)\n * @csspart title - 标题(aria-labelledby 目标)\n * @csspart description - 描述(aria-describedby 目标)\n * @csspart close-trigger - 关闭按钮\n */\nexport class XhDrawerElement extends XhElement {\n static override partContract = { anatomy: drawerAnatomy, meta: drawerMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n // role 不声明为响应式属性,复用 HTMLElement 原生反射,在 machineProps 里经 getAttribute 读取。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n modal: { converter: BOOLEAN_CONVERTER },\n side: { converter: STRING_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n closeOnInteractOutside: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-interact-outside' },\n restoreFocus: { converter: BOOLEAN_CONVERTER, attribute: 'restore-focus' },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,只走 property\n translations: { attribute: false },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare modal?: boolean\n declare side?: DrawerSchema['props']['side']\n declare closeOnEscape?: boolean\n declare closeOnInteractOutside?: boolean\n declare restoreFocus?: boolean\n declare size?: Size\n declare translations?: DrawerSchema['props']['translations']\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly drawerScope = createScope(null, this.idGen)\n private config: RuntimeConfig | null = null\n private contentNode: HTMLElement | null = null\n private backdropNode: HTMLElement | null = null\n\n private readonly notify = (details: DrawerOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<DrawerSchema>(\n this,\n drawerMachine,\n () => this.machineProps(),\n { scope: this.drawerScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<DrawerSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n modal: this.modal,\n side: this.side,\n role: (this.getAttribute('role') as DrawerSchema['props']['role']) ?? undefined,\n closeOnEscape: this.closeOnEscape,\n closeOnInteractOutside: this.closeOnInteractOutside,\n restoreFocus: this.restoreFocus,\n size: this.size,\n translations: this.translations,\n onOpenChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.drawerScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数,层的入栈出栈由机器的 trackOverlay 效应跟着展开态做。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'modal',\n node: () => this.contentNode,\n branches: () => [],\n isModal: () => this.machineProps().modal ?? true,\n setModal: () => {},\n surfaces: () => [this.backdropNode].filter(Boolean) as Element[],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<DrawerSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('presence', null)\n svc.refs.set('getContentEl', () => this.contentNode)\n svc.refs.set('getTriggerEl', () => this.getPart('trigger'))\n svc.refs.set('branches', () => [])\n }\n\n protected wire(): void {\n const svc = this.ctrl.service\n const api = connectDrawer(svc, wcNormalize)\n const open = svc.state.get() === 'open'\n\n this.contentNode = this.getPart('content')\n this.backdropNode = this.getPart('backdrop')\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('backdrop', api.getBackdropProps() as Record<string, unknown>)\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n\n // 关闭时用内联 display 隐藏浮层子树,优先级高于样式表对 [hidden] 的覆盖\n const positioner = this.getPart('positioner')\n if (positioner)\n this.setPartHidden(positioner, !open)\n if (this.backdropNode)\n this.setPartHidden(this.backdropNode, !open)\n // positioner 不是必需部件,content 自己也要收起\n this.setPartHidden(this.contentNode, !open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { DynamicInputItemProps, DynamicInputSchema, DynamicInputTranslations, DynamicInputValueChangeDetails } from '@xihan-ui/headless'\nimport { connectDynamicInput, dynamicInputAnatomy, dynamicInputMachine, dynamicInputMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、=\"false\"=false、其余=true。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 作者写在行上的下标。缺席或写坏了就退回文档序——把行按顺序排下来本身就是声明。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-dynamic-input>` —— Light-DOM 行为宿主:作者写 root/item/item-content/item-action 与\n * add-trigger、remove-trigger、move-up-trigger、move-down-trigger 角色节点,\n * 元素跑 dynamic-input 机器并把 connect 产出打上去。\n *\n * 值是宿主自己的数据数组,元素只管增删与换序这套动作,行里放什么控件由作者写进 item-content。\n * 行节点由作者按当前值渲染(一行一个 item,身份取节点上的 index 属性,缺省按文档序),\n * 值变了要由作者那一侧增删行节点,改完 MutationObserver 会自动重新接线。\n *\n * 数据数组、造行工厂与读屏文案都表达不成属性,三者只作为 property 暴露。\n *\n * @customElement xh-dynamic-input\n * @attr {number} min - 最少几行;到了就按不动删除把手\n * @attr {number} max - 最多几行;到了就按不动新增把手\n * @attr {boolean} movable - 出不出换序把手;关时两个换序把手一律收起\n * @attr {boolean} disabled - 禁用:新增、删除、换序三路都按不动\n * @fires value-change - 数据数组变化;detail 为 `{ value: unknown[] }`\n * @csspart root - 整份列表的容器,承载 data-disabled / data-empty / data-at-min / data-at-max / data-movable\n * @csspart item - 一行一个,可自带 index 属性声明下标,缺省按文档序\n * @csspart item-content - 一行里放作者自己控件的位置\n * @csspart item-action - 一行里放把手的位置\n * @csspart add-trigger - 新增把手,须是原生 `<button>`;到上限转 aria-disabled 但仍可聚焦;名字取自身内容\n * @csspart remove-trigger - 删除把手,须是原生 `<button>`;到下限转 aria-disabled;自带 aria-label\n * @csspart move-up-trigger - 上移把手,须是原生 `<button>`;首行转 aria-disabled;自带 aria-label\n * @csspart move-down-trigger - 下移把手,须是原生 `<button>`;末行转 aria-disabled;自带 aria-label\n */\nexport class XhDynamicInputElement extends XhElement {\n static override partContract = { anatomy: dynamicInputAnatomy, meta: dynamicInputMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 宿主的行数据是任意值,属性表达不了,只走 property\n value: { attribute: false },\n defaultValue: { attribute: false },\n min: { converter: NUMBER_CONVERTER },\n max: { converter: NUMBER_CONVERTER },\n createItem: { attribute: false },\n movable: { converter: BOOLEAN_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n translations: { attribute: false },\n }\n\n declare value?: unknown[]\n declare defaultValue?: unknown[]\n declare min?: number\n declare max?: number\n declare createItem?: () => unknown\n declare movable?: boolean\n declare disabled?: boolean\n declare translations?: Partial<DynamicInputTranslations>\n\n private readonly notifyValue = (details: DynamicInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 机器只有一个还焦点的收尾动作(自己经 scope 取节点),不需要 config/layer/定位引擎,\n // 故 controller 只带 props。\n private readonly ctrl = new MachineController<DynamicInputSchema>(this, dynamicInputMachine, () => this.machineProps())\n\n private machineProps(): Partial<DynamicInputSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n min: this.min,\n max: this.max,\n createItem: this.createItem,\n movable: this.movable ?? false,\n disabled: this.disabled ?? false,\n translations: this.translations,\n onValueChange: this.notifyValue,\n }\n }\n\n // 行内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectDynamicInput(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('add-trigger', api.getAddTriggerProps() as Record<string, unknown>)\n\n // 行是多实例 part,逐个打:身份取作者写在节点上的 index,缺省按文档序\n this.getParts('item').forEach((el, position) => {\n const item: DynamicInputItemProps = { index: declaredIndex(el, position) }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const content of this.partsIn(el, 'item-content'))\n this.spreader.spread(content, api.getItemContentProps(item) as Record<string, unknown>)\n for (const action of this.partsIn(el, 'item-action'))\n this.spreader.spread(action, api.getItemActionProps(item) as Record<string, unknown>)\n for (const trigger of this.partsIn(el, 'remove-trigger'))\n this.spreader.spread(trigger, api.getRemoveTriggerProps(item) as Record<string, unknown>)\n // 不换序时把这对把手收起。只写 hidden 属性是不够的:作者层给这个 part 声明的任何一条\n // display 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n for (const trigger of this.partsIn(el, 'move-up-trigger')) {\n this.spreader.spread(trigger, api.getMoveUpTriggerProps(item) as Record<string, unknown>)\n this.setPartHidden(trigger, !api.movable)\n }\n for (const trigger of this.partsIn(el, 'move-down-trigger')) {\n this.spreader.spread(trigger, api.getMoveDownTriggerProps(item) as Record<string, unknown>)\n this.setPartHidden(trigger, !api.movable)\n }\n })\n }\n}\n","import type {\n EditableActivationMode,\n EditableEditChangeDetails,\n EditableSchema,\n EditableSubmitMode,\n EditableValueChangeDetails,\n EditableValueCommitDetails,\n EditableValueRevertDetails,\n} from '@xihan-ui/headless'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectEditable, editableAnatomy, editableMachine, editableMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关(select-on-focus)会因此永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-editable>` —— Light-DOM 行为宿主:作者写 root/label/area/preview/input/control\n * 与三颗按钮的角色节点,元素跑 editable 机器并把 connect 产出打上去。\n *\n * 预览态显示 preview、编辑态显示 input,另一个带 hidden 收起而不卸载:两边都是作者写的节点,\n * 替他删掉他就再也拿不回来,输入法状态与他挂在节点上的东西也一并没了。\n *\n * preview 的文字默认由元素填(值,或值为空时的 placeholder);作者自己写了内容就归作者,\n * 元素不再改写——首次见到该节点时定,之后不回读(读到的会是自己上一帧写的)。\n *\n * label 的 `for` 恒写向 input 的 id,所以 label 角色节点必须是原生 `<label>`、\n * input 角色节点必须是原生 `<input>`:任一边换成 `<div>`,读屏就念不出这个控件的名字。\n *\n * @customElement xh-editable\n * @attr {string} value - 受控值;缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {boolean} edit - 受控编辑态;缺省该属性即非受控\n * @attr {boolean} default-edit - 非受控初始即编辑态(挂载后焦点搬进输入框)\n * @attr {string} placeholder - 值为空时预览区显示它,输入框也拿它当占位\n * @attr {boolean} disabled - 禁用:进不了编辑态,输入框带原生 disabled\n * @attr {boolean} read-only - 只读:进不了编辑态,但已在编辑态时仍能退出\n * @attr {boolean} invalid - 校验失败标注\n * @attr {number} max-length - 字符数上限;同时落成原生 maxlength 与机器侧截断\n * @attr {string} name - 表单字段名;给了输入框才参与提交\n * @attr {'blur'|'enter'|'both'|'none'} submit-mode - 编辑态怎么收尾,默认 both\n * @attr {'click'|'dblclick'|'focus'|'none'} activation-mode - 预览区怎么进编辑态,默认 click\n * @attr {boolean} select-on-focus - 进编辑态时全选,默认开;写 select-on-focus=\"false\" 关掉\n * @attr {boolean} auto-resize - 输入框宽度跟着内容走(落成原生 size)\n * @fires value-change - 编辑途中的值变化;detail 为 `{ value: string }`\n * @fires value-commit - 提交;detail 为 `{ value: string, previousValue: string }`\n * @fires value-revert - 撤销;detail 为 `{ value: string, discardedValue: string }`\n * @fires edit-change - 编辑态变化;detail 为 `{ edit: boolean }`\n * @csspart root - role=group 容器,承载 data-state / data-disabled / data-readonly / data-invalid / data-empty\n * @csspart label - 标题;`for` 恒写向 input,故须是原生 `<label>`\n * @csspart area - 预览区与输入框的共同落点,两者轮流上场\n * @csspart preview - 预览态的文字;留空即由元素填入显示值,作者写了内容则归作者\n * @csspart input - 编辑态的输入框,须是原生 `<input>`;键盘交互全在它身上\n * @csspart control - 三颗按钮的容器\n * @csspart edit-trigger - 进编辑态的按钮;编辑态收起,不可编辑时置灰\n * @csspart submit-trigger - 提交按钮;预览态收起\n * @csspart cancel-trigger - 撤销按钮;预览态收起\n */\nexport class XhEditableElement extends XhElement {\n static override partContract = { anatomy: editableAnatomy, meta: editableMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n edit: { converter: BOOLEAN_CONVERTER },\n defaultEdit: { converter: BOOLEAN_CONVERTER, attribute: 'default-edit' },\n placeholder: { converter: STRING_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n maxLength: { converter: NUMBER_CONVERTER, attribute: 'max-length' },\n name: { converter: STRING_CONVERTER },\n submitMode: { converter: STRING_CONVERTER, attribute: 'submit-mode' },\n activationMode: { converter: STRING_CONVERTER, attribute: 'activation-mode' },\n selectOnFocus: { converter: BOOLEAN_CONVERTER, attribute: 'select-on-focus' },\n autoResize: { converter: BOOLEAN_CONVERTER, attribute: 'auto-resize' },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare edit?: boolean\n declare defaultEdit?: boolean\n declare placeholder?: string\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare maxLength?: number\n declare name?: string\n declare submitMode?: EditableSubmitMode\n declare activationMode?: EditableActivationMode\n declare selectOnFocus?: boolean\n declare autoResize?: boolean\n\n /** preview 的文字是否归元素填:首次见到该节点时定,之后不再回读。 */\n private readonly ownsPreviewText = new WeakMap<HTMLElement, boolean>()\n\n private readonly notifyValue = (details: EditableValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyCommit = (details: EditableValueCommitDetails): void => {\n this.dispatchEvent(new CustomEvent('value-commit', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyRevert = (details: EditableValueRevertDetails): void => {\n this.dispatchEvent(new CustomEvent('value-revert', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyEdit = (details: EditableEditChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('edit-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<EditableSchema>(\n this,\n editableMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<EditableSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n edit: this.edit,\n defaultEdit: this.defaultEdit ?? false,\n placeholder: this.placeholder,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n maxLength: this.maxLength,\n name: this.name,\n submitMode: this.submitMode,\n activationMode: this.activationMode,\n selectOnFocus: this.selectOnFocus,\n autoResize: this.autoResize ?? false,\n onValueChange: this.notifyValue,\n onValueCommit: this.notifyCommit,\n onValueRevert: this.notifyRevert,\n onEditChange: this.notifyEdit,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 交的是 getter 不是当下的节点:焦点搬运推迟一帧才跑,那时才现取真在 DOM 里的那个。\n private injectRefs(svc: Service<EditableSchema>): void {\n svc.refs.set('getInputEl', () => this.getPart('input'))\n svc.refs.set('getPreviewEl', () => this.getPart('preview'))\n }\n\n /**\n * 角色节点提前发现一次:default-edit 时机器在 hostConnected 当场进编辑态并排下焦点搬运,\n * 而常规发现要等首次 updated——那一刻 partMap 还空着,输入框取不到,焦点就再也搬不进去。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 预览区的文字由元素填(值,或值为空时的 placeholder)。\n * 作者若自己写了内容(自定义渲染),首次见到时就定为归作者,之后一概不碰——\n * 每帧回读分不清\"作者写的\"还是\"上一帧自己写的\",一旦写过就再也让不回去。\n */\n private fillPreviewText(el: HTMLElement, text: string): void {\n let owned = this.ownsPreviewText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsPreviewText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n const api = connectEditable(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('area', api.getAreaProps() as Record<string, unknown>)\n put('preview', api.getPreviewProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('edit-trigger', api.getEditTriggerProps() as Record<string, unknown>)\n put('submit-trigger', api.getSubmitTriggerProps() as Record<string, unknown>)\n put('cancel-trigger', api.getCancelTriggerProps() as Record<string, unknown>)\n // 输入框的 value 不必在这里另外回写:spreader 把 value 当 property 写\n // (dom/spread.ts 的 PROP_KEYS),属性写法只管初值、盖不住用户输入过的框\n\n const preview = this.getPart('preview')\n if (preview)\n this.fillPreviewText(preview, api.displayValue)\n\n // 收起只写 hidden 属性是不够的:作者层给这些 part 声明的任何一条 display\n // 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n this.setPartHidden(preview, api.editing)\n this.setPartHidden(this.getPart('input'), !api.editing)\n this.setPartHidden(this.getPart('edit-trigger'), api.editing)\n this.setPartHidden(this.getPart('submit-trigger'), !api.editing)\n this.setPartHidden(this.getPart('cancel-trigger'), !api.editing)\n }\n}\n","import type { EllipsisExpandedChangeDetails, EllipsisOverflowChangeDetails, EllipsisSchema } from '@xihan-ui/headless'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectEllipsis, ellipsisAnatomy, ellipsisMachine, ellipsisMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态:属性缺席 = 非受控,写了才是受控的那个布尔。\nconst TRISTATE_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-ellipsis>` —— 省略行为宿主:把一段文字夹在给定行数内,并如实报出它有没有被裁掉。\n *\n * 量测在机器的效应里跑:挂载后推迟一拍量一次,此后跟着盒子尺寸与盒内文字的变化重量。\n * 结论落成 root 上的 data-overflowing,浮层不在这里做——要不要套一层提示由作者按这个属性决定。\n * 开了 tooltip 则另给一条不用浮层的路:真被裁了才把整段文字写进 root 的 title,交给平台的原生提示。\n *\n * 行数写在 root 的内联 style 里(自定义属性只有这一条路能同时落到两个适配器上),\n * 于是 root 的内联 style 归本元素管,作者自己的内联样式写在外层元素上。\n *\n * @customElement xh-ellipsis\n * @attr {number} lines - 夹几行,1 为单行,默认 1\n * @attr {boolean} expandable - 点一下铺开全文\n * @attr {boolean} expanded - 受控展开;缺省该属性即非受控\n * @attr {boolean} default-expanded - 非受控初始为铺开\n * @attr {boolean} tooltip - 真被裁了才把整段文字交给平台的原生提示\n * @fires expanded-change - 展开状态变化;detail 为 `{ expanded: boolean }`\n * @fires overflow-change - 溢出结论翻面;detail 为 `{ overflowing: boolean }`\n * @csspart root - 夹字的盒子,承载 data-lines / data-multiline / data-expandable / data-expanded / data-overflowing\n */\nexport class XhEllipsisElement extends XhElement {\n static override partContract = { anatomy: ellipsisAnatomy, meta: ellipsisMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n lines: { converter: NUMBER_CONVERTER },\n expandable: { type: Boolean },\n expanded: { converter: TRISTATE_CONVERTER },\n defaultExpanded: { type: Boolean, attribute: 'default-expanded' },\n tooltip: { type: Boolean },\n }\n\n declare lines?: number\n declare expandable?: boolean\n declare expanded?: boolean\n declare defaultExpanded?: boolean\n declare tooltip?: boolean\n\n private readonly notifyExpanded = (details: EllipsisExpandedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('expanded-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOverflow = (details: EllipsisOverflowChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('overflow-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<EllipsisSchema>(\n this,\n ellipsisMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<EllipsisSchema['props']> {\n return {\n lines: this.lines,\n expandable: this.expandable ?? false,\n expanded: this.expanded,\n defaultExpanded: this.defaultExpanded ?? false,\n tooltip: this.tooltip ?? false,\n onExpandedChange: this.notifyExpanded,\n onOverflowChange: this.notifyOverflow,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n // 取值口惰性读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n private injectRefs(svc: Service<EllipsisSchema>): void {\n svc.refs.set('getRootEl', () => this.getPart('root'))\n }\n\n protected wire(): void {\n const api = connectEllipsis(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { EmptyStateLive, EmptyStateProps } from '@xihan-ui/headless'\nimport { connectEmptyState, emptyStateAnatomy, emptyStateMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-empty-state>` —— 空状态行为宿主,无状态机,把 connectEmptyState 产出的属性打到角色节点上。\n *\n * root 缺省是 role=status 的活区:节点应当常挂、用 hidden 收起,\n * 整块插进文档的活区读屏通常不播报。首屏静态占位写 live=\"off\"。\n *\n * @customElement xh-empty-state\n * @attr {'sm'|'md'|'lg'} size - 尺寸档位,写到 root 的 data-size 上\n * @attr {'polite'|'off'} live - 播报方式,off 时 root 不带 role\n * @csspart root - 承载 role 与 data-size 的容器\n * @csspart icon - 装饰图标,对读屏隐藏\n * @csspart title - 标题\n * @csspart description - 说明\n * @csspart action - 操作按钮槽\n */\nexport class XhEmptyStateElement extends XhElement {\n static override partContract = { anatomy: emptyStateAnatomy, meta: emptyStateMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n size: { converter: STRING_CONVERTER },\n live: { converter: STRING_CONVERTER },\n }\n\n declare size?: 'sm' | 'md' | 'lg'\n declare live?: EmptyStateLive\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const props: EmptyStateProps = { size: this.size, live: this.live }\n const api = connectEmptyState(props, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('icon', api.getIconProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('action', api.getActionProps() as Record<string, unknown>)\n }\n}\n","import type { FieldProps } from '@xihan-ui/headless'\nimport type { Scope } from '@xihan-ui/kernel'\nimport { connectField, fieldAnatomy, fieldMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,控件 id 的缺省由 connect 派生。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-field>` —— Light-DOM 行为宿主,无状态机,把 connectField 产出的 id 与 aria-* 打到\n * label/control/description/error-text 角色节点上,自动对齐 `for` 与描述链。控件本身由作者渲染。\n *\n * 每个实例自带一份 scope 派生 part id,同页多个 field 各出各的 id。\n *\n * @customElement xh-field\n * @attr {boolean} invalid - 校验失败态:控件 aria-invalid=true,错误文案接入描述链并显出\n * @attr {boolean} required - 必填:控件 aria-required=true\n * @attr {boolean} disabled - 禁用标注,只落 data-disabled,不代作者写原生 disabled\n * @attr {string} control-id - 接管控件 id;缺省该属性即由 scope 派生。刻意不叫 id:\n * 宿主的 id 是 `<xh-field>` 自己的 DOM id,挪去当控件 id 会让两个节点撞同一个 id\n * @csspart root - 承载 data-disabled/data-invalid/data-required 的容器\n * @csspart label - 标题;`for` 恒写向控件,故须是原生 `<label>` 才点得动控件\n * @csspart control - 真正的输入控件本身(id 与 aria-* 落在这里,别标在外层包裹节点上)\n * @csspart description - 常驻说明文案,恒在控件的描述链里\n * @csspart error-text - 错误文案(role=alert);非 invalid 时带 hidden 收起,节点不卸载\n */\nexport class XhFieldElement extends XhElement {\n // label 必须是原生 <label>:for 只在它身上有效,写成 div 则点标签不再聚焦控件\n // (名字关联仍由 control 上的 aria-labelledby 兜住,丢的是点击行为)。\n static override partContract = {\n anatomy: fieldAnatomy,\n meta: fieldMeta,\n tags: { label: ['label'] },\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n invalid: { type: Boolean },\n required: { type: Boolean },\n disabled: { type: Boolean },\n controlId: { converter: STRING_CONVERTER, attribute: 'control-id' },\n }\n\n declare invalid?: boolean\n declare required?: boolean\n declare disabled?: boolean\n declare controlId?: string\n\n // 实例级 scope 只建一次,避免派生出的 id 每帧变化\n private readonly fieldScope: Scope = createScope(null, createCounterIdGenerator())\n\n protected wire(): void {\n const props: FieldProps = {\n invalid: this.invalid,\n required: this.required,\n disabled: this.disabled,\n controlId: this.controlId,\n }\n const api = connectField(props, this.fieldScope, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n // 控件上只落 data-disabled,原生 disabled 归作者自己写\n put('control', api.getControlProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('error-text', api.getErrorTextProps() as Record<string, unknown>)\n\n // 错误文案常挂,非 invalid 时用内联 display 收起\n this.setPartHidden(this.getPart('error-text'), !api.invalid)\n }\n}\n","import type {\n FileUploadApi,\n FileUploadFileAcceptDetails,\n FileUploadFileRejectDetails,\n FileUploadFilesChangeDetails,\n FileUploadSchema,\n FileUploadTranslations,\n} from '@xihan-ui/headless'\nimport type { Scope } from '@xihan-ui/kernel'\nimport { connectFileUpload, fileUploadAnatomy, fileUploadMachine, fileUploadMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席,避免 Number('') 落成 0\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 取作者写在条目上的 index,缺席或写坏了退回文档序。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-file-upload>` —— Light-DOM 行为宿主:作者写 root/label/dropzone/trigger/hidden-input\n * 与列表若干角色节点,元素跑 file-upload 机器并把 connect 产出打上去。\n *\n * 投放区收 dragover/dragleave/drop,悬停期间带 data-dragging;点投放区、点 trigger、\n * 或在投放区上按 Enter/Space 都打开系统文件选择框(走隐藏输入的 click)。\n * 收进来的文件先过校验(类型/大小/数量),收下的进列表并派 file-accept,\n * 被拒的连同原因派 file-reject。\n *\n * 条目节点由作者按 `acceptedFiles` 渲染(听 files-change 重渲),元素不生成节点。\n * 条目按文档序对上列表里的文件,也可以自带 `index` 属性显式声明。\n * item-name 与 item-size-text 的文字由元素填(作者自己写了内容则不碰)。\n *\n * @customElement xh-file-upload\n * @attr {string} accept - 允许的类型,写法同原生 input:'image/*'、'.png'、精确 MIME,逗号分隔;数组形态请走 property\n * @attr {number} max-files - 最多留几个文件,默认 1\n * @attr {number} max-file-size - 单个文件的字节上限,默认不限\n * @attr {number} min-file-size - 单个文件的字节下限,默认 0\n * @attr {boolean} disabled - 禁用:投放区退出 Tab 序列,几个按钮带原生 disabled,增删改一律被守卫挡下\n * @attr {boolean} invalid - 校验失败标注\n * @attr {string} name - 表单字段名;给了隐藏输入才参与提交\n * @attr {boolean} allow-drop - 是否接受拖拽投放,默认 true;写 allow-drop=\"false\" 关掉\n * @attr {boolean} directory - 选目录而不是选文件(隐藏输入带 webkitdirectory)\n * @attr {'user'|'environment'} capture - 移动端直接调用摄像头/麦克风采集\n * @fires files-change - 列表变化;detail 为 `{ files: File[] }`\n * @fires file-accept - 本次收下了哪些;detail 为 `{ files: File[] }`\n * @fires file-reject - 本次拒了哪些、各自为什么;detail 为 `{ files: { file, reasons }[] }`\n * @csspart root - 组件根容器,承载 data-dragging / data-disabled / data-invalid / data-empty\n * @csspart label - 标题;`for` 恒写向隐藏输入,故须是原生 `<label>` 才点得动\n * @csspart dropzone - role=button 的投放区,键盘入口也在这里\n * @csspart trigger - 打开文件选择框的按钮,建议放在投放区之外(按钮里再套按钮读屏只念外面那个)\n * @csspart hidden-input - type=file 的表单出口,视觉上藏起来\n * @csspart item-group - role=list 的列表容器,承载 data-empty\n * @csspart item - role=listitem 的一行,可自带 index 属性声明对应第几个文件\n * @csspart item-preview - 缩略图占位(aria-hidden),带 data-file-type 供皮肤挑图标\n * @csspart item-name - 文件名(元素代填)\n * @csspart item-size-text - 人读的文件大小(元素代填)\n * @csspart item-delete-trigger - 删掉这一条\n * @csspart clear-trigger - 清空整份列表;列表为空时带原生 disabled\n */\nexport class XhFileUploadElement extends XhElement {\n static override partContract = { anatomy: fileUploadAnatomy, meta: fileUploadMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 文件与文案是对象,只走 property;files 给了即受控,内部写入只发 files-change\n files: { attribute: false },\n defaultFiles: { attribute: false },\n accept: { converter: STRING_CONVERTER },\n maxFiles: { converter: NUMBER_CONVERTER, attribute: 'max-files' },\n maxFileSize: { converter: NUMBER_CONVERTER, attribute: 'max-file-size' },\n minFileSize: { converter: NUMBER_CONVERTER, attribute: 'min-file-size' },\n disabled: { type: Boolean },\n invalid: { type: Boolean },\n name: { converter: STRING_CONVERTER },\n allowDrop: { converter: BOOLEAN_CONVERTER, attribute: 'allow-drop' },\n directory: { type: Boolean },\n capture: { converter: STRING_CONVERTER },\n translations: { attribute: false },\n }\n\n declare files?: File[]\n declare defaultFiles?: File[]\n declare accept?: string | string[]\n declare maxFiles?: number\n declare maxFileSize?: number\n declare minFileSize?: number\n declare disabled?: boolean\n declare invalid?: boolean\n declare name?: string\n declare allowDrop?: boolean\n declare directory?: boolean\n declare capture?: 'user' | 'environment'\n declare translations?: Partial<FileUploadTranslations>\n\n // scope 绑在本元素上:打开选择框要在 scope 的 root 里按 id 找回隐藏输入\n private readonly uploadScope: Scope = createScope(this, createCounterIdGenerator())\n\n private readonly notifyChange = (details: FileUploadFilesChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('files-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyAccept = (details: FileUploadFileAcceptDetails): void => {\n this.dispatchEvent(new CustomEvent('file-accept', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyReject = (details: FileUploadFileRejectDetails): void => {\n this.dispatchEvent(new CustomEvent('file-reject', { detail: details, bubbles: true, composed: true }))\n }\n\n // file-upload 机器无常驻副作用,controller 只带 props 与 scope。\n private readonly ctrl = new MachineController<FileUploadSchema>(\n this,\n fileUploadMachine,\n () => this.machineProps(),\n { scope: this.uploadScope },\n )\n\n private machineProps(): Partial<FileUploadSchema['props']> {\n return {\n files: this.files,\n defaultFiles: this.defaultFiles,\n accept: this.accept,\n maxFiles: this.maxFiles,\n maxFileSize: this.maxFileSize,\n minFileSize: this.minFileSize,\n disabled: this.disabled ?? false,\n invalid: this.invalid ?? false,\n name: this.name,\n allowDrop: this.allowDrop,\n directory: this.directory ?? false,\n capture: this.capture,\n translations: this.translations,\n onFilesChange: this.notifyChange,\n onFileAccept: this.notifyAccept,\n onFileReject: this.notifyReject,\n }\n }\n\n /** 命令式入口共用的取法;机器要到进文档(hostConnected)才建,未建则抛。 */\n private commands(): FileUploadApi {\n if (!this.ctrl.service)\n throw new Error('[xh] <xh-file-upload> 还没进文档,命令式接口此时不可用')\n return connectFileUpload(this.ctrl.service, wcNormalize)\n }\n\n /** 当前已收下的文件;作者据此渲染条目节点。 */\n get acceptedFiles(): File[] {\n return this.commands().acceptedFiles\n }\n\n /** 打开系统文件选择框(等价于点投放区或 trigger)。 */\n openFilePicker(): void {\n this.commands().openFilePicker()\n }\n\n /** 整份替换,照样过校验。 */\n setFiles(files: File[]): void {\n this.commands().setFiles(files)\n }\n\n /** 追加,照样过校验。 */\n addFiles(files: File[]): void {\n this.commands().addFiles(files)\n }\n\n /** 按引用剔除某一个。 */\n deleteFile(file: File): void {\n this.commands().deleteFile(file)\n }\n\n clearFiles(): void {\n this.commands().clearFiles()\n }\n\n /** 文本是否归元素填:节点非空即判为作者自定义渲染。首次见到时定死,之后不再回读——回读分不出内容是作者写的还是上一帧自己写的。 */\n private readonly ownsText = new WeakMap<HTMLElement, boolean>()\n\n private fillText(el: HTMLElement, text: string): void {\n let owned = this.ownsText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n /** 取 owner 子树内指定名字的角色节点。 */\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n /** 条目内的子部件名,交还与逐个打属性都按这一份走。 */\n private static readonly ITEM_PARTS = ['item-preview', 'item-name', 'item-size-text', 'item-delete-trigger'] as const\n\n /** 位子比文件多时整条交还:撤掉上一帧写的属性与处理器,代填的文字一并抹掉。 */\n private releaseItem(el: HTMLElement): void {\n this.spreader.release(el)\n for (const name of XhFileUploadElement.ITEM_PARTS) {\n for (const child of this.partsIn(el, name)) {\n this.spreader.release(child)\n if (this.ownsText.get(child))\n child.textContent = ''\n }\n }\n // 交还只摘属性与监听器,作者的 <button> 还在,仍占 Tab 位却已经按不动、\n // 连 aria-label 都撤回了(图标按钮就此没有可访问名)。空位整条收起来。\n this.setPartHidden(el, true)\n }\n\n protected wire(): void {\n const api = connectFileUpload(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('dropzone', api.getDropzoneProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n put('item-group', api.getItemGroupProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n\n // 条目逐个打,身份取列表里对应位置的那个文件\n const files = api.acceptedFiles\n this.getParts('item').forEach((el, position) => {\n const file = files[declaredIndex(el, position)]\n if (!file) {\n this.releaseItem(el)\n return\n }\n const item = { file }\n this.setPartHidden(el, false)\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const preview of this.partsIn(el, 'item-preview'))\n this.spreader.spread(preview, api.getItemPreviewProps(item) as Record<string, unknown>)\n for (const name of this.partsIn(el, 'item-name')) {\n this.spreader.spread(name, api.getItemNameProps(item) as Record<string, unknown>)\n this.fillText(name, file.name)\n }\n for (const size of this.partsIn(el, 'item-size-text')) {\n this.spreader.spread(size, api.getItemSizeTextProps(item) as Record<string, unknown>)\n this.fillText(size, api.getFileSizeText(file))\n }\n for (const del of this.partsIn(el, 'item-delete-trigger'))\n this.spreader.spread(del, api.getItemDeleteTriggerProps(item) as Record<string, unknown>)\n })\n }\n}\n","import type { FlexProps } from '@xihan-ui/headless'\nimport { connectFlex, flexAnatomy, flexMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-flex>` —— Light-DOM 行为宿主,无状态机,把 connectFlex 产出打到 root 角色节点。\n * 六个排版参数原样落成 data-*,排布规则写在皮肤里。\n *\n * 根上不写 role:容器只做排布,里面装的是列表还是一组按钮由作者自己声明。\n *\n * @customElement xh-flex\n * @attr {'row'|'column'} direction - 主轴方向,缺省 row\n * @attr {'start'|'center'|'end'|'stretch'|'baseline'} align - 交叉轴对齐\n * @attr {'start'|'center'|'end'|'between'|'around'|'evenly'} justify - 主轴分布\n * @attr {'xs'|'sm'|'md'|'lg'|'xl'} gap - 子项间距档位,逐档对应一个间距令牌\n * @attr {boolean} wrap - 一行放不下时折行\n * @attr {boolean} inline - 容器按行内盒排版,宽度收到内容\n * @csspart root - 排布容器,承载 data-direction / data-align / data-justify / data-gap / data-wrap / data-inline\n */\nexport class XhFlexElement extends XhElement {\n static override partContract = { anatomy: flexAnatomy, meta: flexMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n direction: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n align: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n justify: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n gap: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n wrap: { type: Boolean },\n inline: { type: Boolean },\n }\n\n declare direction?: string\n declare align?: string\n declare justify?: string\n declare gap?: string\n declare wrap?: boolean\n declare inline?: boolean\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectFlex({\n direction: this.direction as FlexProps['direction'],\n align: this.align as FlexProps['align'],\n justify: this.justify as FlexProps['justify'],\n gap: this.gap as FlexProps['gap'],\n wrap: this.wrap ?? false,\n inline: this.inline ?? false,\n } satisfies FlexProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type {\n CollapsibleOpenChangeDetails,\n CollapsibleSchema,\n FloatButtonAppearance,\n FloatButtonExpandTrigger,\n FloatButtonPlacement,\n FloatButtonShape,\n FloatButtonTranslations,\n} from '@xihan-ui/headless'\nimport { collapsibleMachine, connectFloatButton, floatButtonAnatomy, floatButtonMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态:属性缺席 = 非受控,写了才是受控的那个布尔。\nconst TRISTATE_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-float-button>` —— 悬浮按钮行为宿主:一颗钉在视口一角的触发器,展开一组动作。\n *\n * 开合跑的是 collapsible 机器——一颗触发器管着一组内容的开合,正是那台机器的活儿;\n * 落位、外形与展开方式不入机器,只决定接哪几个监听、往根上写哪几个 data-*。\n *\n * 作者须把 trigger 写成 `<button>`:激活与 Tab 停靠由平台提供,元素不接管这两件。\n * 收起时 list 带 hidden,里面的按钮一并退出 Tab 序列与无障碍树。\n * 贴边距离写在 root 的内联 style 里(自定义属性只有这一条路能同时落到两个适配器上),\n * 于是 root 的内联 style 归本元素管,作者自己的内联样式写在外层元素上。\n *\n * @customElement xh-float-button\n * @attr {boolean} open - 受控展开;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} disabled - 禁用触发器\n * @attr {'top-start'|'top-end'|'bottom-start'|'bottom-end'} placement - 钉在哪一角,默认 bottom-end\n * @attr {number} offset - 距那两条边的距离(px),默认 24\n * @attr {'circle'|'square'} shape - 触发器外形,默认 circle\n * @attr {'hover'|'click'} expand-trigger - 展开方式,默认 click\n * @fires open-change - 展开状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 定位壳,承载 data-state / data-placement / data-shape / data-disabled\n * @csspart trigger - 触发按钮,须写成 `<button>`;可及名字由 translations.trigger 给\n * @csspart list - 展开的那一组动作;收起时带 hidden\n */\nexport class XhFloatButtonElement extends XhElement {\n static override partContract = { anatomy: floatButtonAnatomy, meta: floatButtonMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: TRISTATE_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n disabled: { type: Boolean },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n shape: { converter: STRING_CONVERTER },\n expandTrigger: { converter: STRING_CONVERTER, attribute: 'expand-trigger' },\n // 文案是对象,只走 property\n translations: { attribute: false },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare disabled?: boolean\n declare placement?: FloatButtonPlacement\n declare offset?: number\n declare shape?: FloatButtonShape\n declare expandTrigger?: FloatButtonExpandTrigger\n declare translations?: Partial<FloatButtonTranslations>\n\n private readonly notify = (details: CollapsibleOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<CollapsibleSchema>(\n this,\n collapsibleMachine,\n () => this.machineProps(),\n )\n\n private machineProps(): Partial<CollapsibleSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n disabled: this.disabled ?? false,\n onOpenChange: this.notify,\n }\n }\n\n private appearance(): FloatButtonAppearance {\n return {\n placement: this.placement,\n offset: this.offset,\n shape: this.shape,\n expandTrigger: this.expandTrigger,\n translations: this.translations,\n }\n }\n\n protected wire(): void {\n const api = connectFloatButton(this.ctrl.service, this.appearance(), wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n\n const list = this.getPart('list')\n if (list) {\n const props = api.getListProps() as Record<string, unknown>\n this.spreader.spread(list, props)\n // Light DOM 常驻,WC 自管可见性:作者层若给这个 part 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来\n this.setPartHidden(list, props.hidden === true)\n }\n }\n}\n","import type {\n FormApi,\n FormErrorPatch,\n FormErrorsChangeDetails,\n FormInvalidDetails,\n FormSchema,\n FormSubmitDetails,\n FormValidateOn,\n FormValues,\n FormValuesChangeDetails,\n} from '@xihan-ui/headless'\nimport { connectForm, formAnatomy, formMachine, formMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 自带的 Boolean 转换器判的是 v !== null,写 disabled=\"false\" 反而成了真\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * 字段容器与摘要条目自报的字段名,取作者写的 `value` 属性。\n *\n * 刻意不叫 `name`:那是原生表单控件的属性,落在 div / a 上没有含义,\n * 而且 Vue 侧它会被声明成 prop 而不落进 DOM,两个适配器的快照会当场分叉。\n * 也不自创一个 `field`:宿主基类只观察 value / disabled / aria-disabled 这几个\n * 「作者声明」属性,用别的名字的话,列表复用节点时的原地改名在 WC 侧不会重新接线——\n * 节点上会留着上一个字段的 id 与 data-name,摘要里的链接就此指错人。\n */\nfunction fieldNameOf(el: HTMLElement): string {\n return el.getAttribute('value') ?? ''\n}\n\n/**\n * `<xh-form>` —— Light-DOM 行为宿主:作者写 root(必须是原生 `<form>`)与\n * field-group / error-summary / error-summary-item / submit-trigger / reset-trigger 角色节点,\n * 元素跑 form 机器并把 connect 产出打上去。\n *\n * 提交只有一条路:`<form>` 自己的 submit 事件。回车的隐式提交、`type=submit` 按钮、\n * 以及命令式的 `submit()` 全部汇到那里,连接层一律 preventDefault——页面永不刷新,\n * 校验与回调都由组件收口。\n *\n * 值与错误都是「表」:元素不去收割原生控件里的值(那要替作者猜 checkbox / 多选 / 数字的类型),\n * 而是由作者经 `values` 属性或 `setFieldValue()` 写进来。校验函数同样由作者给。\n *\n * 每个字段用一个 field-group 包住并用 `value` 属性自报字段名:错误摘要的链接指向它,\n * 提交失败后的焦点也落进它——落点按**文档序**取第一个出错的字段,而不是错误表的键序。\n *\n * @customElement xh-form\n * @attr {string} validate-on - 校验时机:submit(默认)/ blur / change\n * @attr {boolean} disabled - 整个表单禁用:提交、重置、写值一概不发生,两颗按钮带原生 disabled\n * @attr {boolean} read-only - 只读:写值与重置不发生,但仍可提交\n * @fires values-change - 值表变化;detail 为 `{ values }`\n * @fires errors-change - 错误表变化;detail 为 `{ errors }`\n * @fires submit - 校验通过才派发;detail 为 `{ values }`\n * @fires invalid - 校验不通过时派发;detail 为 `{ errors, values }`\n * @csspart root - 表单根容器,必须是原生 `<form>`(承载 data-state/data-disabled/data-readonly/data-invalid)\n * @csspart field-group - 单个字段的容器,须自带 value 属性标识字段名;带 id 供摘要链接指向\n * @csspart error-summary - role=alert 的错误汇总,提交失败且仍有错误时才显形\n * @csspart error-summary-item - 摘要里的一条,须是原生 `<a>` 且自带 value 属性标识字段名;无对应错误时带 hidden\n * @csspart submit-trigger - 提交键,须是原生 button(连接层写成 type=submit)\n * @csspart reset-trigger - 重置键,须是原生 button(连接层写成 type=reset)\n */\nexport class XhFormElement extends XhElement {\n static override partContract = { anatomy: formAnatomy, meta: formMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 四张表与校验函数都是对象/函数,走不了属性;只作为 property 暴露,与 Vue 侧的同名 prop 对齐。\n // values / errors 给了即受控:元素内部的写入只发事件,等宿主自己写回\n values: { attribute: false },\n defaultValues: { attribute: false },\n errors: { attribute: false },\n defaultErrors: { attribute: false },\n validate: { attribute: false },\n validateOn: { converter: STRING_CONVERTER, attribute: 'validate-on' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n }\n\n declare values?: FormValues\n declare defaultValues?: FormValues\n declare errors?: FormErrorPatch\n declare defaultErrors?: FormErrorPatch\n declare validate?: FormSchema['props']['validate']\n declare validateOn?: FormValidateOn\n declare disabled?: boolean\n declare readOnly?: boolean\n\n private readonly notifyValues = (details: FormValuesChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('values-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyErrors = (details: FormErrorsChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('errors-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 与原生 submit 撞不上:连接层已经把那条原生事件的冒泡掐断在 <form> 上,\n // 从本元素冒出去的 submit 只可能是这一条(且只在校验通过时才有)\n private readonly notifySubmit = (details: FormSubmitDetails): void => {\n this.dispatchEvent(new CustomEvent('submit', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyInvalid = (details: FormInvalidDetails): void => {\n this.dispatchEvent(new CustomEvent('invalid', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<FormSchema>(\n this,\n formMachine,\n () => this.machineProps(),\n // 落焦与\"哪个字段排在前面\"都要现查这棵子树,机器因此得拿到那个 <form>。\n // getter 而不是当下的节点:角色节点是作者渲染的,随时可能换一批\n { onBuilt: svc => svc.refs.set('getRootEl', () => this.getPart('root')) },\n )\n\n private machineProps(): Partial<FormSchema['props']> {\n return {\n values: this.values,\n defaultValues: this.defaultValues,\n errors: this.errors,\n defaultErrors: this.defaultErrors,\n validate: this.validate,\n validateOn: this.validateOn,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n onValuesChange: this.notifyValues,\n onErrorsChange: this.notifyErrors,\n onSubmit: this.notifySubmit,\n onInvalid: this.notifyInvalid,\n }\n }\n\n /**\n * 命令式入口共用的取法。机器要到进文档(hostConnected)才建:\n * 还没进文档就下命令是调用方的时序问题,明说好过把这条命令静默丢掉。\n */\n private commands(): FormApi {\n if (!this.ctrl.service)\n throw new Error('[xh] <xh-form> 还没进文档,命令式接口此时不可用')\n return connectForm(this.ctrl.service, wcNormalize)\n }\n\n /** 写一个字段的值;禁用或只读时不动。 */\n setFieldValue(name: string, value: unknown): void {\n this.commands().setFieldValue(name, value)\n }\n\n /** 写一个字段的错误;不给文案(或给空串)即清掉这一条。 */\n setFieldError(name: string, message?: string): void {\n this.commands().setFieldError(name, message)\n }\n\n clearErrors(): void {\n this.commands().clearErrors()\n }\n\n /** 走完整的校验与提交流程,与用户按提交键完全同一条路。 */\n submit(): void {\n this.commands().submit()\n }\n\n /** 值与错误都回到初始;禁用或只读时不动。 */\n reset(): void {\n this.commands().reset()\n }\n\n /** 字段容器的 DOM id:作者要把它落到自己的控件上时取这里,别自己拼。 */\n getFieldId(name: string): string {\n return this.commands().getFieldId(name)\n }\n\n getFieldValue(name: string): unknown {\n return this.commands().getFieldValue(name)\n }\n\n /** 该字段此刻的错误文案;没错时为 undefined。 */\n getFieldError(name: string): string | undefined {\n return this.commands().getFieldError(name)\n }\n\n /** 出错的字段名,插入顺序。 */\n get errorNames(): string[] {\n return this.commands().errorNames\n }\n\n get errorCount(): number {\n return this.commands().errorCount\n }\n\n /** 错误表非空。与\"提交失败过\"无关。 */\n get invalid(): boolean {\n return this.commands().invalid\n }\n\n /** 上一次提交被拦下了:错误摘要据此显形。 */\n get submitFailed(): boolean {\n return this.commands().submitFailed\n }\n\n protected wire(): void {\n const api = connectForm(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('error-summary', api.getErrorSummaryProps() as Record<string, unknown>)\n put('submit-trigger', api.getSubmitTriggerProps() as Record<string, unknown>)\n put('reset-trigger', api.getResetTriggerProps() as Record<string, unknown>)\n\n // 字段容器与摘要条目都是多实例 part,逐个打:身份取作者写的 value 属性\n for (const el of this.getParts('field-group'))\n this.spreader.spread(el, api.getFieldGroupProps({ name: fieldNameOf(el) }) as Record<string, unknown>)\n\n for (const el of this.getParts('error-summary-item')) {\n this.spreader.spread(el, api.getErrorSummaryItemProps({ name: fieldNameOf(el) }) as Record<string, unknown>)\n // Light DOM 常驻,WC 自管可见性:作者层若给条目声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来\n this.setPartHidden(el, api.getFieldError(fieldNameOf(el)) === undefined)\n }\n\n this.setPartHidden(this.getPart('error-summary'), !(api.submitFailed && api.invalid))\n }\n}\n","import type { GradientTextDirection, GradientTextProps } from '@xihan-ui/headless'\nimport { connectGradientText, gradientTextAnatomy, gradientTextMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-gradient-text>` —— Light-DOM 行为宿主,无状态机,把 connectGradientText 产出打到 root 角色节点。\n *\n * 两端颜色写成 root 上的内联 CSS 变量,渐变怎么画、缺省用哪族颜色都在皮肤里;\n * 走向按档位落成 data-direction,皮肤逐档换算成 `to <边或角>`。\n *\n * 给了 from 或 to 时 root 的内联 style 归本元素管,作者自己的内联样式请写在宿主元素上。\n *\n * @customElement xh-gradient-text\n * @attr {string} from - 起点颜色,写成 root 上的 --xh-gradient-text-from\n * @attr {string} to - 终点颜色,写成 root 上的 --xh-gradient-text-to\n * @attr {'to-right'|'to-left'|'to-bottom'|'to-top'|'to-bottom-right'|'to-bottom-left'|'to-top-right'|'to-top-left'} direction - 渐变走向档位,缺省 to-right\n * @csspart root - 被上色的文字容器,承载 data-direction 与两端颜色变量\n */\nexport class XhGradientTextElement extends XhElement {\n static override partContract = { anatomy: gradientTextAnatomy, meta: gradientTextMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n from: { converter: STRING_CONVERTER },\n to: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER },\n }\n\n declare from?: string\n declare to?: string\n declare direction?: GradientTextDirection\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const props: GradientTextProps = { from: this.from, to: this.to, direction: this.direction }\n const api = connectGradientText(props, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { GridProps } from '@xihan-ui/headless'\nimport { connectGrid, gridAnatomy, gridMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/** 断点对象形态的列数,从 GridProps 上取,不在这里另抄一份档位清单。 */\ntype ColsByBreakpoint = Exclude<GridProps['cols'], number | undefined>\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n/**\n * 列数写整数就是各档同一个列数(`cols=\"3\"`),写 JSON 对象就是逐档的列数\n * (`cols='{\"base\":1,\"md\":3}'`)。解析不出对象时当没写:落一个半截对象进去,\n * 缺的那几档会安静地退回一列,而作者看不出是哪里写坏了。\n */\nconst COLS_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v === null)\n return undefined\n if (!v.trimStart().startsWith('{'))\n return Number(v)\n try {\n const parsed: unknown = JSON.parse(v)\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as ColsByBreakpoint)\n : undefined\n }\n catch {\n return undefined\n }\n },\n}\n\n/** 读作者写在角色节点上的数值声明:属性缺席、为空或不是数字时当作没写。 */\nfunction authorNumber(el: HTMLElement, name: string): number | undefined {\n const raw = el.getAttribute(name)\n if (raw == null || raw.trim() === '')\n return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\n/**\n * `<xh-grid>` —— Light-DOM 行为宿主,无状态机,把 connectGrid 产出打到 root 与各 item 角色节点。\n * 列数、间距档位与两条对齐轴原样落成 data-*,排布规则写在皮肤里。\n * 列数可以逐档写:`cols='{\"base\":1,\"md\":3}'` 落成 data-cols 与 data-cols-md,\n * 窄视口分一列、宽到 md 断点后分三列。\n *\n * 每一格的跨列与错列写在 item 角色节点自己的 `span` / `offset` 属性上。\n * 运行期改写这两个属性不触发重新接线,需作者自行 requestUpdate。\n *\n * 根上不写 role:容器只做排布,里面装的是列表还是一组卡片由作者自己声明。\n *\n * @customElement xh-grid\n * @attr {number|string} cols - 列数(1–12),不写按一列排;写 JSON 对象则逐档给列数(base / sm / md / lg / xl)\n * @attr {'xs'|'sm'|'md'|'lg'|'xl'} gap - 行列间距档位,逐档对应一个间距令牌\n * @attr {'start'|'center'|'end'|'stretch'|'baseline'} align - 每一项在自己那格里的块向对齐\n * @attr {'start'|'center'|'end'|'stretch'} justify - 每一项在自己那格里的行内对齐\n * @csspart root - 排布容器,承载 data-cols(及逐档的 data-cols-sm/-md/-lg/-xl)/ data-gap / data-align / data-justify\n * @csspart item - 一格,承载自报的 data-span / data-offset\n */\nexport class XhGridElement extends XhElement {\n static override partContract = { anatomy: gridAnatomy, meta: gridMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n cols: { converter: COLS_CONVERTER },\n gap: { converter: STRING_CONVERTER },\n align: { converter: STRING_CONVERTER },\n justify: { converter: STRING_CONVERTER },\n }\n\n declare cols?: number | ColsByBreakpoint\n declare gap?: string\n declare align?: string\n declare justify?: string\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectGrid({\n cols: this.cols,\n gap: this.gap as GridProps['gap'],\n align: this.align as GridProps['align'],\n justify: this.justify as GridProps['justify'],\n } satisfies GridProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 多实例 part 逐个打,每一格的占位取作者写的 span 与 offset\n for (const el of this.getParts('item')) {\n const attrs = api.getItemProps({\n span: authorNumber(el, 'span'),\n offset: authorNumber(el, 'offset'),\n })\n this.spreader.spread(el, attrs as Record<string, unknown>)\n }\n }\n}\n","import type { HighlightApi, HighlightProps } from '@xihan-ui/headless'\nimport { connectHighlight, highlightAnatomy, highlightMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-highlight>` —— Light-DOM 行为宿主,无状态机,把 text 按 keyword 切段铺进 root。\n *\n * 作者写一个空的行内容器当 root:命中位置是按 text 这个串逐字符算的,\n * 切出来的片段作者自己写不出,故 root 的内容整份由本元素接管,写在里面的东西会被替换掉。\n *\n * 一处有多个关键词都命中时取最长的那个,重叠的命中只切出一段。\n * 关键词全程逐字符比对,不拼进正则:搜索框里敲进来的 `.` `*` `(` 都是普通字符。\n *\n * 多个关键词只能走 property(`el.keyword = ['a', 'b']`):属性里的一个串就是一个关键词,\n * 按空格拆的话带空格的关键词就没法写了。\n *\n * @customElement xh-highlight\n * @attr {string} text - 要显示的整段文本\n * @attr {string} keyword - 一个关键词;一组关键词走 property\n * @attr {boolean} case-sensitive - 区分大小写,缺省不区分\n * @csspart root - 包住整段文本的容器,承载 data-case-sensitive\n * @csspart mark - 命中关键词的那一小段,渲染成 `<mark>`\n */\nexport class XhHighlightElement extends XhElement {\n static override partContract = { anatomy: highlightAnatomy, meta: highlightMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n text: { converter: STRING_CONVERTER },\n keyword: { converter: STRING_CONVERTER },\n caseSensitive: { type: Boolean, attribute: 'case-sensitive' },\n }\n\n declare text?: string\n declare keyword?: string | readonly string[]\n declare caseSensitive?: boolean\n\n /** 上一次往哪个 root 铺过哪一串片段。 */\n #painted?: { host: Element, key: string }\n\n protected wire(): void {\n const root = this.getPart('root')\n if (!root)\n return\n\n // 读响应式 property,不回读 DOM 特性\n const api = connectHighlight({\n text: this.text,\n keyword: this.keyword,\n caseSensitive: this.caseSensitive,\n } satisfies HighlightProps, wcNormalize)\n\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n this.#paint(root, api)\n }\n\n /**\n * 把切好的片段铺进 root:命中的建一个 `<mark>`,其余建文本节点。\n * 片段没变就不重铺——每帧重建节点会把用户正在拖的选区弄没。\n */\n #paint(root: HTMLElement, api: HighlightApi): void {\n const key = JSON.stringify(api.segments)\n if (this.#painted?.host === root && this.#painted.key === key)\n return\n this.#painted = { host: root, key }\n\n const doc = root.ownerDocument\n const frame = doc.createDocumentFragment()\n const markProps = api.getMarkProps() as Record<string, unknown>\n for (const segment of api.segments) {\n if (!segment.matched) {\n frame.appendChild(doc.createTextNode(segment.text))\n continue\n }\n const mark = doc.createElement('mark')\n this.spreader.spread(mark, markProps)\n mark.textContent = segment.text\n frame.appendChild(mark)\n }\n root.replaceChildren(frame)\n }\n}\n","import type { HoverCardOpenChangeDetails, HoverCardSchema } from '@xihan-ui/headless'\nimport type { Cleanup, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectHoverCard, hoverCardAnatomy, hoverCardMachine, hoverCardMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 写不成数的值(文字、单位后缀)当作没写,缺省仍由机器给\nconst NUMBER_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v === null)\n return undefined\n const n = Number(v)\n return Number.isFinite(n) ? n : undefined\n },\n}\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-hover-card>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/arrow 角色节点,\n * 元素跑 hover-card 机器并把 connect 产出打上去。\n *\n * 它是 popover 的悬停变体:指针停在 trigger 上够久才展开,离开 trigger 或 content 够久才收起——\n * 那段收起等待同时是指针从 trigger 走到 content 的通行时间,两者之间隔着 offset 也走得过去。\n * 与 tooltip 相反,卡片内容是可交互、可聚焦的一块面板:Tab 走得进去,Escape 收得掉,\n * 但从不陷焦点、不锁滚动,展开时也不抢焦点。\n *\n * @customElement xh-hover-card\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 请求的浮层朝向(top/right/bottom/left,可带 -start/-end 后缀),默认 bottom;空间不足时由引擎避让\n * @attr {number} offset - 浮层与锚点的间距(px),默认 8\n * @attr {number} open-delay - 悬停进入到展开的等待毫秒,默认 700\n * @attr {number} close-delay - 指针移出到收起的等待毫秒,默认 300\n * @attr {'ltr'|'rtl'} dir - 文字方向,只在显式给了才写到 root 上\n * @attr {boolean} disabled - 只关掉卡片,trigger 本身仍可点、可聚焦\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 承载 data-state / data-disabled / dir 的容器\n * @csspart trigger - 悬停/聚焦的锚点(aria-expanded/aria-controls 所在),同时是定位锚点\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=dialog 的卡片内容(消解层的根节点),收起时带 hidden\n * @csspart arrow - 指向锚点的箭头(aria-hidden,data-placement 随实际放置位翻转)\n */\nexport class XhHoverCardElement extends XhElement {\n static override partContract = { anatomy: hoverCardAnatomy, meta: hoverCardMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n openDelay: { converter: NUMBER_CONVERTER, attribute: 'open-delay' },\n closeDelay: { converter: NUMBER_CONVERTER, attribute: 'close-delay' },\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n disabled: { type: Boolean },\n size: { converter: STRING_CONVERTER },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare openDelay?: number\n declare closeDelay?: number\n declare direction?: Direction\n declare disabled?: boolean\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly hoverCardScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notify = (details: HoverCardOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<HoverCardSchema>(\n this,\n hoverCardMachine,\n () => this.machineProps(),\n { scope: this.hoverCardScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<HoverCardSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n openDelay: this.openDelay,\n closeDelay: this.closeDelay,\n dir: this.direction,\n disabled: this.disabled ?? false,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.hoverCardScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着可见态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:指针按在它上面算层内交互,不该把刚悬停出来的卡片关掉\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n // 悬停卡片从不模态:不陷焦点、不锁滚动、没有自带遮罩\n isModal: () => false,\n setModal: () => {},\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 每次(重)建机器后都要重注:refs 属于机器实例,重连时的新机器不会继承旧的。\n private injectRefs(svc: Service<HoverCardSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入可见态,\n * 定位副作用同步取一次 trigger/positioner——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,引擎挂不上,浮层会停在容器左上角。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n protected wire(): void {\n const api = connectHoverCard(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是坐标对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n // Light DOM content 常驻,WC 自管可见性:本仓的 hover-card.css 给 content 设了 display:flex,\n // 任何 display 都会盖过 UA 的 [hidden]{display:none}。那份样式自带\n // [data-part=content][hidden]{display:none} 压得住,但宿主不能指望作者装了它——\n // 换别家样式给 content 来一句 display,收起态的卡片就会永久悬在页面上,只有内联 style 压得住。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由可见态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { IconApi, IconProps, IconWeight } from '@xihan-ui/headless'\nimport type { IconNode, IconRecord, Size, Tone } from '@xihan-ui/kernel'\nimport { connectIcon, iconAnatomy, iconMeta } from '@xihan-ui/headless'\nimport { DIAGNOSTIC_CODES, reportDiagnostic } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** 自带可及名字的控件;图标落在它们里面时名字该写在控件上。 */\nconst NAMED_CONTROLS = 'button, a[href], [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [role=\"option\"]'\n\n/**\n * 按记录建一棵 SVG 子树。\n * 走 createElementNS + setAttribute,全程不碰 HTML 解析器;SVG 命名空间下属性名大小写原样保留。\n */\nfunction buildNode(doc: Document, node: IconNode): SVGElement {\n const el = doc.createElementNS(SVG_NS, node.tag)\n for (const [key, value] of Object.entries(node.attrs ?? {}))\n el.setAttribute(key, value)\n for (const child of node.children ?? [])\n el.appendChild(buildNode(doc, child))\n return el\n}\n\n/**\n * `<xh-icon>` —— 图标宿主,无状态机,把命名与档位打到 root 上,把图元铺进 glyph 空壳。\n *\n * 作者在 `<svg data-xh-part=\"root\">` 里留一个空的 `<g data-xh-part=\"glyph\"></g>` 即授权本元素\n * 在其内部铺图元;不写 glyph 时元素一个节点都不动,几何归作者(手写内联 SVG 或 `<use>`),\n * 命名与档位照常打在 root 上。\n *\n * 图标记录是对象,只走 property:`el.icon = checkIcon`。\n *\n * @customElement xh-icon\n * @attr {string} label - 可及名字;非空白时输出 role=img + aria-label,否则输出 aria-hidden=true\n * @attr {'sm'|'md'|'lg'} size - 直径档位,缺省 md\n * @attr {'light'|'regular'|'bold'} weight - 描边粗细档位,缺省 regular\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @csspart root - 根 `<svg>`,承载 viewBox/data-icon/命名属性/data-size/data-weight/data-tone\n * @csspart glyph - 作者留出的空 `<g>`,图元铺在它内部\n */\nexport class XhIconElement extends XhElement {\n static override partContract = {\n anatomy: iconAnatomy,\n meta: iconMeta,\n // root 不是 <svg> 时 viewBox 会被小写化而静默失效;glyph 不是 <g> 时铺进去的图元挂在 HTML 元素下,什么都不显示\n tags: { root: ['svg'], glyph: ['g'] },\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n label: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n weight: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n // 记录是对象,只走 property\n icon: { attribute: false },\n }\n\n declare label?: string\n declare size?: Size\n declare weight?: IconWeight\n declare tone?: Tone\n declare icon?: IconRecord\n\n /** 一个 glyph 节点归谁,首次见到时定死。 */\n readonly #glyphOwned = new WeakMap<Element, boolean>()\n\n /** 上一次铺进哪个 glyph 节点、铺的是哪条记录。 */\n #painted?: { host: Element, record: IconRecord }\n\n protected wire(): void {\n const props: IconProps = {\n icon: this.icon,\n label: this.label,\n size: this.size,\n weight: this.weight,\n tone: this.tone,\n }\n const api = connectIcon(props, wcNormalize)\n\n const root = this.getPart('root')\n const glyph = this.getPart('glyph')\n // 所有权在写 root 之前定:本次 wire 刚写上的 data-icon 会把首次客户端渲染也算成服务端画过\n const owned = glyph ? this.#ownsGlyph(glyph, root) : false\n\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n if (glyph)\n this.spreader.spread(glyph, api.getGlyphProps() as Record<string, unknown>)\n\n this.#paint(glyph, owned, api.content)\n this.#report(root, glyph, owned, api)\n }\n\n /**\n * 一个 glyph 节点归谁,首次见到时定死:\n * 空壳 = 授权;非空但 root 上已有 data-icon = 服务端渲染出来的、也是本元素的产出。\n * data-icon 只由 connect 写出。\n */\n #ownsGlyph(host: Element, root: Element | null): boolean {\n let owned = this.#glyphOwned.get(host)\n if (owned === undefined) {\n owned = host.childElementCount === 0 || root?.hasAttribute('data-icon') === true\n this.#glyphOwned.set(host, owned)\n }\n return owned\n }\n\n /**\n * 把记录的图元铺进 glyph。\n * 本元素其余各处都不替作者生成节点,这里是唯一的例外:图元是算出来的派生数据,作者没法自己写,\n * 且铺设范围被限死在作者显式留出的那个空壳里。\n * 内容判据是记录的引用相等——记录是模块级常量,同一个图标永远是同一个对象。\n * childElementCount 那一条兜住外部代码清空过 glyph 的情形。\n */\n #paint(host: Element | null, owned: boolean, record: IconRecord | undefined): void {\n if (!host || !record) {\n this.#painted = undefined\n return\n }\n if (!owned)\n return\n if (this.#painted?.host === host && this.#painted.record === record && host.childElementCount > 0)\n return\n this.#painted = { host, record }\n\n const doc = host.ownerDocument\n const frame = doc.createDocumentFragment()\n for (const node of record.nodes)\n frame.appendChild(buildNode(doc, node))\n host.replaceChildren(frame)\n }\n\n /** 传了图标却铺不上、以及在自带名字的控件里又给图标命名,两类都会静默走偏,报出来。 */\n #report(root: Element | null, glyph: Element | null, owned: boolean, api: IconApi): void {\n const scope = iconAnatomy.name\n if (api.content && !glyph) {\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.warn,\n level: 'warn',\n message: '传了 icon 却没有 data-xh-part=\"glyph\" 空壳,图元无处可铺;要么补上空的 <g data-xh-part=\"glyph\">,要么自己把几何写进 root',\n scope,\n part: 'glyph',\n node: this,\n })\n }\n else if (api.content && glyph && !owned) {\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.warn,\n level: 'warn',\n message: 'glyph 里已有作者写的内容,这些节点不会被改写,传入的 icon 不生效',\n scope,\n part: 'glyph',\n node: glyph,\n })\n }\n if (api.label !== undefined && root?.closest(NAMED_CONTROLS)) {\n reportDiagnostic({\n code: DIAGNOSTIC_CODES.warn,\n level: 'warn',\n message: '可聚焦控件内部的图标应当是装饰态,名字写在控件上,否则读屏会念两遍',\n scope,\n part: 'root',\n node: root,\n })\n }\n }\n}\n","import type { IconWrapperProps } from '@xihan-ui/headless'\nimport type { ActionVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectIconWrapper, iconWrapperAnatomy, iconWrapperMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-icon-wrapper>` —— Light-DOM 行为宿主,无状态机,把 connectIconWrapper 产出打到 root 角色节点。\n *\n * 根上不写 role、也不写 aria-hidden:里面那个图元是装饰还是信息,由作者按用途声明。\n *\n * @customElement xh-icon-wrapper\n * @attr {'solid'|'subtle'|'outline'|'ghost'} variant - 形态,决定底色、描边与前景怎么用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定用哪族颜色\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定底座直径与里面图元的直径\n * @csspart root - 底座容器,承载 data-variant / data-tone / data-size\n */\nexport class XhIconWrapperElement extends XhElement {\n static override partContract = { anatomy: iconWrapperAnatomy, meta: iconWrapperMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n variant: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n tone: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n size: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n }\n\n declare variant?: ActionVariant\n declare tone?: Tone\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectIconWrapper({\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n } satisfies IconWrapperProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { ImageSchema, ImageStatus, ImageStatusChangeDetails } from '@xihan-ui/headless'\nimport { connectImage, imageAnatomy, imageMachine, imageMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-image>` —— Light-DOM 行为宿主:作者写 root/image/fallback 角色节点,\n * 元素跑 image 机器并把 connect 产出打上去。图片来源由宿主的 src/alt 写进 image 节点,\n * 加载成败经 image 自己的 load/error 回送给机器;两个节点都常挂,靠 hidden 互斥显隐。\n *\n * 与头像不同的是回退内容有个延迟门槛:`fallback-delay` 之内不显示回退内容,\n * 走缓存的快图直接从空位切到图片,不会闪一下占位。\n *\n * @customElement xh-image\n * @attr {string} src - 图片地址;缺省该属性即没有来源,直接落回退态\n * @attr {string} alt - 图片替代文本,原样写到 image 节点上\n * @attr {number} fallback-delay - 加载超过这么多毫秒才让回退内容露面,默认 0(立刻露面)\n * @fires status-change - 加载状态变化;detail 为 `{ status: 'loading' | 'loaded' | 'error' }`\n * @csspart root - 图片根容器(承载 data-status)\n * @csspart image - 图片节点,必须是原生 img;src/alt 由宿主写入(作者别自己写,会被覆盖或清掉),未就绪时带 hidden\n * @csspart fallback - 回退内容(占位图、骨架屏、图标);加载失败恒显,加载途中要看延迟门槛\n */\nexport class XhImageElement extends XhElement {\n static override partContract = { anatomy: imageAnatomy, meta: imageMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n src: { converter: STRING_CONVERTER },\n alt: { converter: STRING_CONVERTER },\n fallbackDelay: { converter: NUMBER_CONVERTER, attribute: 'fallback-delay' },\n }\n\n declare src?: string\n declare alt?: string\n declare fallbackDelay?: number\n\n private readonly notify = (details: ImageStatusChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('status-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // image 机器不碰 DOM、不用定位与消解层:不需要 config/layer/refs/scope,controller 只带 props。\n private readonly ctrl = new MachineController<ImageSchema>(this, imageMachine, () => this.machineProps())\n\n private machineProps(): Partial<ImageSchema['props']> {\n return {\n src: this.src,\n alt: this.alt,\n fallbackDelay: this.fallbackDelay,\n onStatusChange: this.notify,\n }\n }\n\n /**\n * 图片早在监听器挂上之前就已就绪时补一次上报:load 已经派发完,机器再也等不到,\n * 状态会永远停在 loading——图片明明在手边,台前却一直是回退内容。两处会撞上:\n * 作者把同一个 src 也写进了 img 标记(升级前浏览器就加载完了),\n * 以及元素在 DOM 中被移动导致机器重建(状态从头走一遍,而 src 没变的 img 不会重新加载)。\n *\n * 三个条件缺一不可:complete 排除还在路上的请求;naturalWidth 排除加载失败——失败与\n * \"压根没发起请求\"在这里分不开,不去猜,留在 loading 上照样只显示回退内容;\n * currentSrc 与 src 相等排除换图那一瞬,此刻旧图仍是 complete 的,误报会把旧图当新图显出来。\n *\n * 只在 loading 补报:idle 期间补会被随后落地的来源决议一脚踢回 loading。\n * 报完即进 loaded,下一帧不再命中,不会闭成回路。\n */\n private syncSettledImage(status: ImageStatus): void {\n if (status !== 'loading')\n return\n const { getStatus, send } = this.ctrl.service\n // 宿主断开后仍可能跑完一次挂起的更新,此刻机器已停机(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n // 角色节点不是原生 img 时 complete / naturalWidth 都取不到,条件自然不成立\n const image = this.getPart('image') as HTMLImageElement | null\n if (image?.complete && image.naturalWidth > 0 && image.currentSrc === image.src)\n send({ type: 'IMAGE.LOAD' })\n }\n\n protected wire(): void {\n const api = connectImage(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n // src 写在 onLoad/onError 之前也不漏事件:图片的 load/error 一律异步派发,\n // 而这两个监听器在同一段同步代码里就挂上了。\n put('image', api.getImageProps() as Record<string, unknown>)\n put('fallback', api.getFallbackProps() as Record<string, unknown>)\n\n // 两个节点都常挂、互斥显隐,WC 自管可见性。connect 已置 hidden,但宿主不能指望作者装了\n // styled 那份样式:任何一句 `img { display: block }`、`[data-part=fallback] { display: flex }`\n // 都是 author 层,优先级高于 UA 的 [hidden]{display:none},hidden 压不住;内联样式才压得住。\n this.setPartHidden(this.getPart('image'), !api.loaded)\n this.setPartHidden(this.getPart('fallback'), !api.showFallback)\n\n // 属性与监听器都已落到 image 上,此刻才问得出\"它是不是早就加载完了\"\n this.syncSettledImage(api.status)\n }\n}\n","import type { InfiniteScrollSchema } from '@xihan-ui/headless'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectInfiniteScroll, infiniteScrollAnatomy, infiniteScrollMachine, infiniteScrollMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined、在场=true、显式写 \"false\"=false\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-infinite-scroll>` —— 无限滚动行为宿主:摆在列表末尾的哨兵一进可视区就报「该取下一页了」。\n *\n * 滚动本身一概不接管,走浏览器原生通路;触发的判据是哨兵与可视区的交叠。\n * 列表滚在某个 overflow 容器里时把容器交给 target:distance 的提前量扩的正是那块可视区,\n * 不给就只对窗口视口生效,落到列表上等于没写。\n * 观察器只在 idle 挂着:loading 与 disabled 两段都不观察,哨兵留在可视区里也不会连着触发第二次。\n *\n * @customElement xh-infinite-scroll\n * @attr {number} distance - 提前量(px):哨兵离可视区还有这么远就算进入,默认 0\n * @attr {boolean} disabled - 关掉,不再观察也不再触发\n * @attr {boolean} loading - 正在取数,其间不观察、不重复触发;取完由宿主写回 false\n * @fires load - 该取下一页了\n * @csspart root - 列表外壳,承载 data-state / data-loading / data-disabled 与 aria-busy\n * @csspart sentinel - 哨兵,摆在列表末尾;对读屏隐藏\n */\nexport class XhInfiniteScrollElement extends XhElement {\n static override partContract = { anatomy: infiniteScrollAnatomy, meta: infiniteScrollMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n distance: { converter: NUMBER_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n loading: { converter: BOOLEAN_CONVERTER },\n // 滚动容器是 DOM 句柄,只走 property;不给即以窗口视口为准\n target: { attribute: false },\n }\n\n declare distance?: number\n declare disabled?: boolean\n declare loading?: boolean\n declare target?: HTMLElement | null\n\n private readonly notify = (): void => {\n this.dispatchEvent(new CustomEvent('load', { bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<InfiniteScrollSchema>(\n this,\n infiniteScrollMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<InfiniteScrollSchema['props']> {\n return {\n distance: this.distance,\n disabled: this.disabled,\n loading: this.loading,\n onLoad: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n // 哨兵惰性读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n private injectRefs(svc: Service<InfiniteScrollSchema>): void {\n svc.refs.set('getSentinelEl', () => this.getPart('sentinel'))\n svc.refs.set('getTargetEl', () => this.target ?? null)\n }\n\n protected wire(): void {\n const api = connectInfiniteScroll(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('sentinel', api.getSentinelProps() as Record<string, unknown>)\n }\n}\n","import type { LayoutSchema, LayoutSiderCollapsedChangeDetails, LayoutSiderPlacement } from '@xihan-ui/headless'\nimport { connectLayout, layoutAnatomy, layoutMachine, layoutMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-layout>` —— 页面骨架的 Light-DOM 行为宿主,跑 layout 机器并把 connect 产出打到\n * root/header/sider/content/footer/sider-trigger 角色节点。\n *\n * 除 root 外的部件全部可缺省。各段一律不带 role:地标该不该标、标在哪一段,\n * 取决于这套骨架在页面里的位置,由作者自己声明。\n *\n * 侧栏宽度只写成 sider 上的内联 inline-size,宽度过渡由皮肤声明。\n *\n * 固定定位只落 data-fixed 标记:钉住的实现(含滚动容器的分工)归皮肤。\n *\n * @customElement xh-layout\n * @attr {boolean} sider-collapsed - 受控折叠态;缺省该属性即非受控\n * @attr {boolean} default-sider-collapsed - 非受控初始为折叠\n * @attr {string} sider-width - 展开时侧栏的宽度,任意 CSS 长度\n * @attr {string} sider-collapsed-width - 折叠时侧栏的宽度,任意 CSS 长度\n * @attr {'start'|'end'} sider-placement - 侧栏挂在行首还是行尾,缺省 start\n * @attr {boolean} header-fixed - 头吸顶:滚动时头钉在滚动容器的上沿\n * @attr {boolean} sider-fixed - 侧栏吸附:滚动时侧栏钉在滚动容器的上沿,头也吸顶时让开头那一条\n * @attr {boolean} bordered - 在头、侧栏、脚与内容之间画分隔线\n * @fires sider-collapsed-change - 折叠态变化;detail 为 `{ collapsed: boolean }`\n * @csspart root - 骨架根容器,承载 data-sider-placement / data-sider-collapsed / data-header-fixed / data-sider-fixed / data-bordered\n * @csspart header - 顶部横幅区,横贯整行;吸顶时带 data-fixed\n * @csspart sider - 侧栏,宽度随折叠态在两档之间切换;吸附时带 data-fixed\n * @csspart content - 主内容区\n * @csspart footer - 底部区,横贯整行\n * @csspart sider-trigger - 折叠把手(aria-expanded / aria-controls 所在)\n */\nexport class XhLayoutElement extends XhElement {\n // 把手写成非 button 时 Enter/Space 的激活会静默失效,登记进契约\n static override partContract = {\n anatomy: layoutAnatomy,\n meta: layoutMeta,\n tags: { 'sider-trigger': ['button'] },\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n siderCollapsed: {\n attribute: 'sider-collapsed',\n converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') },\n },\n defaultSiderCollapsed: { type: Boolean, attribute: 'default-sider-collapsed' },\n siderWidth: { attribute: 'sider-width', converter: STRING_CONVERTER },\n siderCollapsedWidth: { attribute: 'sider-collapsed-width', converter: STRING_CONVERTER },\n siderPlacement: { attribute: 'sider-placement', converter: STRING_CONVERTER },\n headerFixed: { type: Boolean, attribute: 'header-fixed' },\n siderFixed: { type: Boolean, attribute: 'sider-fixed' },\n bordered: { type: Boolean },\n }\n\n declare siderCollapsed?: boolean\n declare defaultSiderCollapsed?: boolean\n declare siderWidth?: string\n declare siderCollapsedWidth?: string\n declare siderPlacement?: LayoutSiderPlacement\n declare headerFixed?: boolean\n declare siderFixed?: boolean\n declare bordered?: boolean\n\n private readonly notify = (details: LayoutSiderCollapsedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('sider-collapsed-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<LayoutSchema>(this, layoutMachine, () => this.machineProps())\n\n private machineProps(): Partial<LayoutSchema['props']> {\n return {\n siderCollapsed: this.siderCollapsed,\n defaultSiderCollapsed: this.defaultSiderCollapsed ?? false,\n siderWidth: this.siderWidth,\n siderCollapsedWidth: this.siderCollapsedWidth,\n siderPlacement: this.siderPlacement,\n headerFixed: this.headerFixed ?? false,\n siderFixed: this.siderFixed ?? false,\n bordered: this.bordered ?? false,\n onSiderCollapsedChange: this.notify,\n }\n }\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectLayout(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('header', api.getHeaderProps() as Record<string, unknown>)\n put('sider', api.getSiderProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('footer', api.getFooterProps() as Record<string, unknown>)\n put('sider-trigger', api.getSiderTriggerProps() as Record<string, unknown>)\n }\n}\n","import type { ListProps } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { connectList, listAnatomy, listMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-list>` —— Light-DOM 行为宿主,无状态机,把 connectList 产出打到各角色节点。\n * 除 root 外的部件全部可缺省:空列表、只有一行标题的条目都是合法形态。\n *\n * 标签由作者定:root 写 `<ul>`/`<ol>` 就进读屏的列表语义,写 `<div>` 就只是一摞盒子;\n * item 同理。组件不补 role。\n *\n * @customElement xh-list\n * @attr {boolean} bordered - 给整份列表画一圈描边与圆角\n * @attr {boolean} hoverable - 指针悬停时条目换底色\n * @attr {boolean} split - 条目之间画分隔线\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定条目的内边距、图文间距与两行文字的字号\n * @csspart root - 列表根容器,承载 data-size / data-bordered / data-hoverable / data-split\n * @csspart item - 一条条目\n * @csspart item-media - 条目最前的媒体位,放头像、图标或缩略图\n * @csspart item-content - 条目的文字区,装标题与说明\n * @csspart item-title - 条目标题\n * @csspart item-description - 条目标题下的说明\n * @csspart item-action - 条目末尾的操作位\n */\nexport class XhListElement extends XhElement {\n static override partContract = { anatomy: listAnatomy, meta: listMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n bordered: { type: Boolean },\n hoverable: { type: Boolean },\n split: { type: Boolean },\n size: { converter: STRING_CONVERTER },\n }\n\n declare bordered?: boolean\n declare hoverable?: boolean\n declare split?: boolean\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectList({\n bordered: this.bordered ?? false,\n hoverable: this.hoverable ?? false,\n split: this.split ?? false,\n size: this.size,\n } satisfies ListProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 条目与条目内的四个位都可以出现多次,逐个打\n const putAll = (name: string, attrs: Record<string, unknown>): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, attrs)\n }\n\n putAll('item', api.getItemProps() as Record<string, unknown>)\n putAll('item-media', api.getItemMediaProps() as Record<string, unknown>)\n putAll('item-content', api.getItemContentProps() as Record<string, unknown>)\n putAll('item-title', api.getItemTitleProps() as Record<string, unknown>)\n putAll('item-description', api.getItemDescriptionProps() as Record<string, unknown>)\n putAll('item-action', api.getItemActionProps() as Record<string, unknown>)\n }\n}\n","import type { ListboxItemProps, ListboxNode, ListboxSchema, ListboxSelectionMode, ListboxValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectListbox, listboxAnatomy, listboxMachine, listboxMeta } from '@xihan-ui/headless'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\n// (value 尤其:落成 null 就分不出\"非受控\"与\"受控且当前无选中\")。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕、连打检索)只有三态才关得掉——\n// Lit 默认的 Boolean 转换器是 v !== null,写 loop=\"false\" 照样是真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-listbox>` —— Light-DOM 行为宿主:作者写 root/label/content 与若干 item 角色节点,\n * 元素跑 listbox 机器并把 connect 产出打上去。条目身份取自条目节点上的 value 属性,\n * 禁用由条目自报 aria-disabled(集合条目一律如此,原生 disabled 不可聚焦、也不派 click)。\n * 分组同样用 value 属性声明身份,分组标题的 id 由它派生。\n *\n * 导航与选中在事件那一刻按 data-scope+data-part 查活 DOM,依赖 connect 回写的 data-value,\n * 因此 wire 必须先于交互跑过(基类 updated 已保证)。\n *\n * 选中值是集合:单选可以直接写 value=\"apple\" 属性,多选只能走 property(`el.value = ['a','b']`),\n * 属性表达不了数组。\n *\n * 条目的禁用也可以交给数据:`el.collection = [{ value, label, disabled }]`,此时条目部件只需自报 value。\n *\n * @customElement xh-listbox\n * @attr {string} value - 受控选中值(单选简写);缺省该属性即非受控,多选请用 property\n * @attr {string} default-value - 非受控初始选中值\n * @attr {boolean} multiple - selection-mode=\"multiple\" 的简写\n * @attr {'single'|'multiple'|'extended'} selection-mode - 选择模式,默认 single\n * @attr {boolean} disabled - 整列禁用:条目全转 aria-disabled,键盘与点击都改不了选中值\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键语义,默认 ltr\n * @attr {'horizontal'|'vertical'} orientation - 方向键轴向,默认 vertical\n * @attr {boolean} typeahead - 连打检索,默认开;写 typeahead=\"false\" 关掉\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @csspart root - 组件根容器(承载 data-orientation/data-disabled)\n * @csspart label - 列表标题(aria-labelledby 目标)\n * @csspart content - role=listbox 容器,键盘在此收口,也是 roving tabindex 的兜底位\n * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 条目文本(连打检索的取字处)\n * @csspart item-indicator - 条目选中标记(aria-hidden)\n * @csspart item-group - role=group 分组容器,须自带 value 属性标识身份\n * @csspart item-group-label - 分组标题(本组 aria-labelledby 的目标)\n */\nexport class XhListboxElement extends XhElement {\n static override partContract = { anatomy: listboxAnatomy, meta: listboxMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。别名保留原生行为,\n // 同时让 dir 进 observedAttributes——运行期改 dir 才会重跑 wire 换掉按键处理器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n multiple: { type: Boolean },\n selectionMode: { converter: STRING_CONVERTER, attribute: 'selection-mode' },\n disabled: { type: Boolean },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n orientation: { converter: STRING_CONVERTER },\n typeahead: { converter: BOOLEAN_CONVERTER },\n }\n\n declare collection?: ListboxNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare multiple?: boolean\n declare selectionMode?: ListboxSelectionMode\n declare disabled?: boolean\n declare loop?: boolean\n declare direction?: Direction\n declare orientation?: Orientation\n declare typeahead?: boolean\n\n // 整列禁用期间的条目自身声明快照。connect 每帧都把 aria-disabled 写回条目,整列禁用更是写满每一个,\n // 此时回读分不清「作者声明的」还是「自己上一帧写的」,解禁后条目就永远解不开。\n private readonly declaredDisabled = new WeakMap<HTMLElement, boolean>()\n /** 上一帧是否整列禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */\n private wasListDisabled = false\n\n private readonly notify = (details: ListboxValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // listbox 机器无副作用(连打缓冲住在 refs 里、由机器自己建),\n // 不需要 config/layer/定位引擎,故 controller 只带 props。\n private readonly ctrl = new MachineController<ListboxSchema>(this, listboxMachine, () => this.machineProps())\n\n private machineProps(): Partial<ListboxSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n multiple: this.multiple ?? false,\n selectionMode: this.selectionMode,\n disabled: this.disabled ?? false,\n loop: this.loop,\n dir: this.direction,\n orientation: this.orientation,\n typeahead: this.typeahead,\n onValueChange: this.notify,\n }\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * 容器判自己\"焦点在列表内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整组零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,条目内的文本与标记离场不会误判;\n // 只有走的正是持有锚点的那个条目才报,否则删任一无关条目都会清掉方向键起点\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'LIST.BLUR' })\n }\n\n /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */\n private readonly declaredItemDisabled = createDeclaredDisabled()\n\n private itemProps(el: HTMLElement): ListboxItemProps {\n const value = el.getAttribute('value') ?? ''\n // 给了 collection 就以数据为事实源:现读会读到 connect 上一帧写回的 aria-disabled,\n // 「作者没写」表达不出 undefined,数据里的禁用就永远轮不到生效。\n if (this.collection)\n return { value, disabled: this.declaredItemDisabled(el) }\n const listDisabled = !!this.disabled\n // 只有「本帧与上一帧都没整列禁用」时,节点上的 aria-disabled 才等于作者声明:\n // 整列禁用那几帧 connect 把每个条目都写成了 true,解禁当帧 DOM 上还留着这些写回值,\n // 此刻现读会把机器自己的产物误当声明、条目再也解不开。\n // 头一回见到这个条目时,DOM 上还只有作者写的东西(本帧的写回尚未发生),\n // 此刻无论整列禁没禁用都记得下真声明。少了这一条,「挂载那刻就整列禁用」\n // 会一路没有快照,解禁时退回现读、读到机器自己写的 true,整列就此永久锁死。\n if (!this.declaredDisabled.has(el)) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n if (!listDisabled && !this.wasListDisabled) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n return { value, disabled: this.declaredDisabled.get(el)! }\n }\n\n // 条目/分组内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectListbox(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item-group')) {\n const group = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getItemGroupProps(group) as Record<string, unknown>)\n for (const label of this.partsIn(el, 'item-group-label'))\n this.spreader.spread(label, api.getItemGroupLabelProps(group) as Record<string, unknown>)\n }\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled\n for (const el of this.getParts('item')) {\n const item = this.itemProps(el)\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n // 条目内的文本与选中标记跟着同一份声明走,样式层各处状态一致\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // 本帧的写回已落地,下一帧才知道 DOM 上的 aria-disabled 可不可信\n this.wasListDisabled = !!this.disabled\n }\n}\n","import type { LoadingBarSchema, LoadingBarTranslations, LoadingBarValueChangeDetails } from '@xihan-ui/headless'\nimport type { Tone } from '@xihan-ui/kernel'\nimport { connectLoadingBar, loadingBarAnatomy, loadingBarMachine, loadingBarMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席:`value=\"\"` 经 Number() 会变成 0,那是一个货真价实的进度值,不是\"没写\"\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 缺省为真的开关(trickle)得能被 =\"false\" 关掉;三态:缺席 = undefined(用默认值),=\"false\" = false,其余 = true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 厚度两用:`height=\"3\"` 按像素,`height=\"0.25rem\"` 按 CSS 长度原样交给 connect\nconst HEIGHT_CONVERTER = {\n fromAttribute: (v: string | null): string | number | undefined => {\n if (v == null || v === '')\n return undefined\n const px = Number(v)\n return Number.isFinite(px) ? px : v\n },\n}\n\n/**\n * `<xh-loading-bar>` —— Light-DOM 行为宿主:作者写 root/track/range 角色节点,\n * 元素跑 loading-bar 机器并把 connect 产出打上去。\n *\n * 两种模式泾渭分明:给了 `value` 就是确定进度,宽度照它显示、读屏拿得到 aria-valuenow;\n * 不给就走假进度——`loading` 置真时先跳到 `minimum`,随后按 `trickle-speed` 一拍一拍地爬,\n * 步长按剩余量取,因此越接近满格越慢且永远到不了 100;此时按规范**不报** aria-valuenow,\n * 属性缺席本身就是\"进度未知\"的表达。`loading` 转假时先冲到 100,走完淡出窗口才归零收起。\n *\n * 收起态只给 root 加 hidden 并压一条内联 display,作者写的结构一个都不卸载。\n *\n * @customElement xh-loading-bar\n * @attr {number} value - 受控进度值(0-100);给了即确定进度,内部爬升整个让位\n * @attr {number} default-value - 非受控初值,默认 0\n * @attr {boolean} loading - 加载开关:属性在即开始,`loading=\"false\"` 或摘掉即结束\n * @attr {string|number} height - 条子厚度:纯数字按像素,其余按 CSS 长度;默认 2px\n * @attr {string} color - 进度段颜色(任意 CSS 颜色);不给就用皮肤的品牌色\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定进度段用哪族颜色;给了 color 就以 color 为准\n * @attr {boolean} trickle - 不确定进度时自行往前爬,默认开;`trickle=\"false\"` 关掉\n * @attr {number} trickle-speed - 爬升节拍毫秒,默认 200;<=0 等同于关掉爬升\n * @attr {number} minimum - 起步值,默认 8\n * @attr {number} fade-duration - 冲到 100 之后的淡出窗口毫秒,默认 200\n * @fires value-change - 进度值变化;detail 为 `{ value: number }`\n * @csspart root - progressbar 本身(承载名字、值域、data-state 与收起态)\n * @csspart track - 背景槽\n * @csspart range - 进度段;宽度由元素写进内联样式,样式层别碰那条轴\n */\nexport class XhLoadingBarElement extends XhElement {\n static override partContract = { anatomy: loadingBarAnatomy, meta: loadingBarMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: NUMBER_CONVERTER },\n defaultValue: { converter: NUMBER_CONVERTER, attribute: 'default-value' },\n loading: { converter: BOOLEAN_CONVERTER },\n height: { converter: HEIGHT_CONVERTER },\n color: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n trickle: { converter: BOOLEAN_CONVERTER },\n trickleSpeed: { converter: NUMBER_CONVERTER, attribute: 'trickle-speed' },\n minimum: { converter: NUMBER_CONVERTER },\n fadeDuration: { converter: NUMBER_CONVERTER, attribute: 'fade-duration' },\n // 文案是对象,走不了属性;只作为 property 暴露,与 Vue 侧的 translations prop 对齐\n translations: { attribute: false },\n }\n\n declare value?: number\n declare defaultValue?: number\n declare loading?: boolean\n declare height?: string | number\n declare color?: string\n declare tone?: Tone\n declare trickle?: boolean\n declare trickleSpeed?: number\n declare minimum?: number\n declare fadeDuration?: number\n declare translations?: Partial<LoadingBarTranslations>\n\n private readonly notify = (details: LoadingBarValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // loading-bar 机器的副作用只有两个计时器(自身自足):不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<LoadingBarSchema>(this, loadingBarMachine, () => this.machineProps())\n\n private machineProps(): Partial<LoadingBarSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n // 布尔属性经三态转换器进来:不在即 undefined,把缺省交回机器\n loading: this.loading,\n height: this.height,\n color: this.color,\n tone: this.tone,\n trickle: this.trickle,\n trickleSpeed: this.trickleSpeed,\n minimum: this.minimum,\n fadeDuration: this.fadeDuration,\n translations: this.translations,\n onValueChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectLoadingBar(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('track', api.getTrackProps() as Record<string, unknown>)\n put('range', api.getRangeProps() as Record<string, unknown>)\n\n // 收起只写 hidden 属性是不够的:作者层给 root 声明的任何一条 display\n // 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n this.setPartHidden(this.getPart('root'), !api.visible)\n }\n}\n","import type { LogProps, LogTranslations, ThreadSchema, ThreadStickChangeDetails } from '@xihan-ui/headless'\nimport type { IdGenerator, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectLog, logAnatomy, logMeta, threadMachine } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 空串按缺席处理,避免 Number('') 落成 0\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-log>` —— Light-DOM 行为宿主:作者写 root/viewport/content/line 角色节点,\n * 元素把 connectLog 的产出打上去。行长出来时跟随滚动到底部,用户上滚后解除粘附,\n * 滚回底部阈值内或调 scrollToBottom() 时恢复。\n *\n * 粘底整套复用 thread 的机器:它只认滚动容器与内容容器两个节点,不认解剖。\n *\n * 行的内容不替作者生成:文本、级别、时间戳、标注都写在 line 角色节点里,元素只发身份与等宽排版。\n *\n * @customElement xh-log\n * @attr {number} rows - 视口按多少行定高;缺省时高度由皮肤给\n * @attr {boolean} loading - 行还在路上:日志区报 aria-busy,根落 data-loading\n * @fires stick-change - 粘底状态变化;detail 为 `{ atBottom: boolean, sticking: boolean }`\n * @csspart root - 组件根容器,承载 data-loading / data-at-bottom / data-sticking\n * @csspart viewport - 滚动容器;role=log + tabindex=0,按行数定高写进内联样式\n * @csspart content - 所有行的包裹层,尺寸变化的观察目标\n * @csspart line - 一行日志,只拿身份与等宽排版\n */\nexport class XhLogElement extends XhElement {\n static override partContract = { anatomy: logAnatomy, meta: logMeta }\n\n // 描述符逐个写全,不用对象展开,CEM 分析器的 lit 插件读不了展开元素的名字\n static override properties = {\n rows: { converter: NUMBER_CONVERTER },\n loading: { type: Boolean },\n // 对象值走不了 HTML 属性,只作为 property 暴露\n translations: { attribute: false },\n }\n\n declare rows?: number\n declare loading?: boolean\n /** 日志区的无障碍名,由 connect 写到视口上。 */\n declare translations?: Partial<LogTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly logScope = createScope(null, this.idGen)\n private config: RuntimeConfig | null = null\n\n private readonly notify = (details: ThreadStickChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('stick-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ThreadSchema>(\n this,\n threadMachine,\n () => ({ onStickChange: this.notify }),\n { scope: this.logScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.logScope, idGenerator: this.idGen })\n }\n\n /** 装填 config 与两个节点 getter;onBuilt 在 ctrl 构造期就跑,故 service 由参数传入。 */\n private injectRefs(svc: Service<ThreadSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('getViewportEl', () => this.getPart('viewport'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n private viewProps(): LogProps {\n return {\n rows: this.rows,\n loading: this.loading ?? false,\n translations: this.translations,\n }\n }\n\n /**\n * 滚回底部并恢复粘附。机器要等 hostConnected 才建,还没进 DOM 时如实什么都不做、别炸。\n * 元素不带内置的\"回到底部\"按钮,作者自己的按钮调它。\n */\n scrollToBottom(): void {\n const service = this.ctrl.service as Service<ThreadSchema> | undefined\n service?.send({ type: 'SCROLL_TO_BOTTOM' })\n }\n\n protected wire(): void {\n const api = connectLog(this.ctrl.service, this.viewProps(), wcNormalize)\n\n // 角色节点可能晚一拍才填进来,每次接线都让句柄按当前节点重绑\n this.ctrl.service.refs.get('stick')?.retarget()\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('viewport', api.getViewportProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 多实例 part 逐个打,行有几条打几条\n for (const el of this.getParts('line'))\n this.spreader.spread(el, api.getLineProps() as Record<string, unknown>)\n }\n}\n","import type { MarqueeDirection, MarqueeProps } from '@xihan-ui/headless'\nimport { connectMarquee, marqueeAnatomy, marqueeMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-marquee>` —— Light-DOM 行为宿主,无状态机,把 connectMarquee 产出打到 root 与 content 上。\n *\n * 作者写一个 root 窗口,里面写一条 content 轨道,内容放进轨道里。\n * 滚动整段在皮肤里:横竖各一条 @keyframes,四个方向与两种铺法只换起止点,元素这边一行动画都不跑。\n *\n * 开了 auto-fill 就要在轨道里写两份内容,每份包一层 `data-xh-copy` 的壳,第二份同时标 aria-hidden 与 inert:\n * 皮肤此时按\"走完一份的长度\"排动画,只写一份会在走到一半时露出空白;\n * 副本若只标 aria-hidden 而仍可聚焦,焦点会落进一个读屏看不见的地方。\n *\n * 给了 speed 时 root 的内联 style 归本元素管,作者自己的内联样式请写在宿主元素上。\n *\n * @customElement xh-marquee\n * @attr {'left'|'right'|'up'|'down'} direction - 滚动方向,缺省 left\n * @attr {number} speed - 每秒滚过的像素数,写成 root 上的 --xh-marquee-speed\n * @attr {boolean} pause-on-hover - 指针停在窗口上时暂停,键盘焦点落进窗口时同样暂停\n * @attr {boolean} auto-fill - 轨道里铺两份内容,走完一份正好接上第二份\n * @csspart root - 只露出一段的窗口,承载 data-direction / data-orientation / data-pause-on-hover / data-auto-fill\n * @csspart content - 在窗口里走的轨道,动画挂在它身上\n */\nexport class XhMarqueeElement extends XhElement {\n static override partContract = { anatomy: marqueeAnatomy, meta: marqueeMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n direction: { converter: STRING_CONVERTER },\n speed: { converter: NUMBER_CONVERTER },\n pauseOnHover: { type: Boolean, attribute: 'pause-on-hover' },\n autoFill: { type: Boolean, attribute: 'auto-fill' },\n }\n\n declare direction?: MarqueeDirection\n declare speed?: number\n declare pauseOnHover?: boolean\n declare autoFill?: boolean\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectMarquee({\n direction: this.direction,\n speed: this.speed,\n pauseOnHover: this.pauseOnHover ?? false,\n autoFill: this.autoFill ?? false,\n } satisfies MarqueeProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n }\n}\n","import type {\n MentionInputEl,\n MentionInputHost,\n MentionItemProps,\n MentionNode,\n MentionOpenChangeDetails,\n MentionQueryChangeDetails,\n MentionSchema,\n MentionSelectDetails,\n MentionTranslations,\n MentionValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectMention, mentionAnatomy, mentionMachine, mentionMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-mention>` —— Light-DOM 行为宿主:作者写 root/input/positioner/content/item 角色节点,\n * 元素跑 mention 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点就是输入框本身(浮层贴着整个输入框,不跟着光标走)。\n *\n * 与组合框的分水岭有两条。其一,浮层由「光标处的前缀字符」开合:前缀必须紧跟在行首或空白之后,\n * 邮箱地址里的 @ 因此不会误触发;前缀到光标之间那段就是查询串。其二,选中候选不是替换整个值,\n * 而是把那段查询串换成候选文本、前后文一字不动,光标随后落在插入内容之后。\n *\n * input 部件写成 textarea(缺省)时保留它自带的 textbox 角色:ARIA in HTML 只允许 textarea\n * 取 textbox,而 aria-expanded 不在 textbox 的支持属性里,两者一并让位;\n * 「有候选浮层」改由 aria-haspopup、aria-controls、aria-autocomplete 与 aria-activedescendant 表达。\n * 写成 input 时才补上 role=combobox 与 aria-expanded。\n *\n * 过滤不由本元素做:查询串变化时派发 query-change,作者据此增删 item 节点。\n *\n * @customElement xh-mention\n * @attr {string} prefix - 开候选的前缀字符,默认 '@';多种前缀并存请用 property 传数组\n * @attr {string} value - 受控正文;缺省该属性即非受控\n * @attr {string} default-value - 非受控初始正文\n * @attr {boolean} disabled - 整个控件禁用:输入框用原生 disabled,候选一概不开\n * @attr {string} placeholder - 输入框占位文字;不写就保留作者标在 input 部件上的那份\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与输入框的间距(px)\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 正文变化;detail 为 `{ value: string }`\n * @fires query-change - 查询串变化;detail 为 `{ query, prefix }`,作者据此过滤候选;收起时报 null\n * @fires select - 候选被插进正文;detail 为 `{ value, label, prefix }`\n * @fires open-change - 浮层开合;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled 与三个视觉轴)\n * @csspart input - 输入框,写 textarea(推荐)或 input;可及名字由作者自己给\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=listbox 容器(消解层的根节点),收起时带 hidden\n * @csspart item - role=option 候选,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 候选文本,也是插回正文的取字处\n */\nexport class XhMentionElement extends XhElement {\n static override partContract = { anatomy: mentionAnatomy, meta: mentionMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了 collection 候选的文本与禁用即以数据为准\n collection: { attribute: false },\n translations: { attribute: false },\n // prefix 撞 Element 的原生只读属性(命名空间前缀),字段改名,属性名不变\n triggerPrefix: { converter: STRING_CONVERTER, attribute: 'prefix' },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n disabled: { type: Boolean },\n placeholder: { converter: STRING_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: MentionNode[]\n declare translations?: MentionTranslations\n declare triggerPrefix?: string | string[]\n declare value?: string\n declare defaultValue?: string\n declare disabled?: boolean\n declare placeholder?: string\n declare loop?: boolean\n declare placement?: Placement\n declare offset?: number\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly mentionScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: MentionValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyQuery = (details: MentionQueryChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('query-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelect = (details: MentionSelectDetails): void => {\n this.dispatchEvent(new CustomEvent('select', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: MentionOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<MentionSchema>(\n this,\n mentionMachine,\n () => this.machineProps(),\n { scope: this.mentionScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<MentionSchema['props']> {\n return {\n prefix: this.triggerPrefix,\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n disabled: this.disabled ?? false,\n placeholder: this.placeholder,\n loop: this.loop,\n placement: this.placement,\n offset: this.offset,\n translations: this.translations,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onQueryChange: this.notifyQuery,\n onSelect: this.notifySelect,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.mentionScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 输入框记为本层分支:在正文里打字、点击都算层内交互,不该把浮层点没\n branches: () => [this.getPart('input')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<MentionSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n svc.refs.set('getInputEl', () => this.getPart('input') as MentionInputEl | null)\n }\n\n /** 提前发现一次角色节点:机器挂载当场就要读得到输入框与候选容器。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n // 取 owner 子树内指定名字的角色节点。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectMention(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n\n // 宿主标签直接读作者写的标记:作者摆的是 textarea 还是 input,DOM 已经说明白了\n const inputEl = this.getPart('input') as MentionInputEl | null\n const inputHost: MentionInputHost = inputEl?.tagName === 'INPUT' ? 'input' : 'textarea'\n const inputProps = api.getInputProps({ as: inputHost }) as Record<string, unknown>\n // 值一样就别重写:给 value 重新赋值会把光标弹到末尾,正文中间的提及就插不进去了\n if (inputEl && inputEl.value === inputProps.value)\n delete inputProps.value\n put('input', inputProps)\n\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 候选逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供方向键现查。\n for (const el of this.getParts('item')) {\n const item: MentionItemProps = {\n value: el.getAttribute('value') ?? '',\n disabled: this.declaredDisabled(el),\n }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n }\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n\n // 每次接线完上报一次候选集合,让机器重算候选条数与悬空高亮\n if (this.ctrl.service.getStatus() === 'Started')\n this.ctrl.service.send({ type: 'ITEMS.SYNC' })\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { MenuNode, MenuOpenChangeDetails, MenuSchema, MenuSelectDetails } from '@xihan-ui/headless'\nimport type { Cleanup, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectMenu, menuAnatomy, menuMachine, menuMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-menu>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/item/... 角色节点,\n * 元素跑 menu 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 trigger、被定位的浮层取 positioner;机器只认端口,不认识具体引擎。\n * 条目身份取用户写在 item 上的 value 属性,禁用由部件自报(aria-disabled)。\n *\n * @customElement xh-menu\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,默认 ltr\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @fires select - 条目被选中(菜单随之关闭);detail 为 `{ value: string }`\n * @csspart trigger - 触发按钮(aria-haspopup/aria-expanded/aria-controls 所在),同时是定位锚点\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=menu 容器(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden\n * @csspart item - role=menuitem 条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart separator - 分隔线(role=separator,不入方向键导航)\n * @csspart arrow - 指向锚点的箭头(aria-hidden,data-placement 随实际放置位翻转)\n */\nexport class XhMenuElement extends XhElement {\n static override partContract = { anatomy: menuAnatomy, meta: menuMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: MenuNode[]\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare loop?: boolean\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly menuScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyOpen = (details: MenuOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelect = (details: MenuSelectDetails): void => {\n this.dispatchEvent(new CustomEvent('select', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<MenuSchema>(\n this,\n menuMachine,\n () => this.machineProps(),\n { scope: this.menuScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<MenuSchema['props']> {\n return {\n collection: this.collection,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n loop: this.loop,\n dir: this.direction,\n tone: this.tone,\n size: this.size,\n onOpenChange: this.notifyOpen,\n onSelect: this.notifySelect,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.menuScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n // 否则同一次点击先被判为层外交互关一次、再被 click 打开一次,菜单等于关不掉。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 菜单不带遮罩,没有\"点它就该关本层\"的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n private injectRefs(svc: Service<MenuSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入展开态,\n * 进入那一刻的 entry 同步查 content 里的条目挑焦点锚点——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,锚点会留空,于是没有条目认领 tabindex=0,键盘进不去菜单。\n * 定位是 flush 推迟的(那时 partMap 已就位),这里只为锚点补上时机。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,锚点会停在一个已消失的值上:\n * 没有条目认领 tabindex=0、方向键也失去起点。这里替 DOM 把焦点离场如实上报,\n * 机器就地按当前活条目重挑锚点。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,separator 与 arrow 离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'ITEM.LOST' })\n }\n\n protected wire(): void {\n const api = connectMenu(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可。\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled\n // (集合条目一律 aria-disabled,原生 disabled 不可聚焦、也不派 click)。\n // 打上去的 data-scope/data-part/data-value 正是方向键在事件那一刻查 DOM 的依据,\n // 所以 wire 必须先于事件跑过——updated() 已保证。\n for (const el of this.getParts('item')) {\n const props = api.getItemProps({\n value: el.getAttribute('value') ?? '',\n disabled: this.collection ? this.declaredDisabled(el) : isItemDisabled(el),\n })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n // 分隔线也是多实例 part,但不带身份、不入导航,属性对每个都一样\n for (const el of this.getParts('separator'))\n this.spreader.spread(el, api.getSeparatorProps() as Record<string, unknown>)\n\n // Light DOM content 常驻,WC 自管可见性。读 styled/styles/menu.css 的结论:\n // content 是 display:flex,positioner 只声明 position/z-index/pointer-events、没有 display,\n // connect 也不给 positioner 发 hidden——所以只兜 content 这一处。\n // 该文件自己带了 [data-part=content][hidden]{display:none} 压住那条 flex,\n // 但宿主不能指望作者装了这份样式:换别家样式给 content 设 display 就又盖过 UA 的\n // [hidden]{display:none},只有内联 style.display 压得住。展开时置空串即撤掉内联声明。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { MenubarItemProps, MenubarNode, MenubarSchema, MenubarSelectDetails, MenubarValueChangeDetails } from '@xihan-ui/headless'\nimport type { Cleanup, Direction, IdGenerator, Layer, Orientation, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectMenubar, menubarAnatomy, menubarMachine, menubarMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 读角色节点的禁用声明,并摘掉作者写的原生 disabled,禁用态归一到 aria-disabled。 */\nfunction authorDisabled(el: HTMLElement): boolean {\n const disabled = isItemDisabled(el)\n if (el.hasAttribute('disabled'))\n el.removeAttribute('disabled')\n return disabled\n}\n\n/**\n * `<xh-menubar>` —— Light-DOM 行为宿主:作者写\n * root/trigger/positioner/content/item/item-text/item-indicator/separator/group/group-label 角色节点,\n * 元素跑 menubar 机器并把 connect 产出打上去。\n *\n * 一排菜单同时只展开一张:已展开时指针掠过别的 trigger 直接切过去,未展开时掠过不响应。\n * 整条菜单栏只有一个 Tab 位(roving tabindex),进来之后靠方向键在 trigger 之间走。\n *\n * 标签由作者写:trigger 必须是 `<button>`。\n * trigger / positioner / content 三者靠各自的 value 属性配对,同一项写同一个值。\n *\n * @customElement xh-menubar\n * @attr {string} value - 受控展开项;缺省该属性即非受控\n * @attr {string} default-value - 非受控的初始展开项\n * @attr {'horizontal'|'vertical'} orientation - 菜单栏排布轴,默认 horizontal;决定方向键在 trigger 之间走哪一对键\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,只影响水平轴上 ArrowLeft/ArrowRight 的前后语义\n * @attr {boolean} disabled - 整条菜单栏禁用\n * @attr {boolean} typeahead - 菜单内的连打检索,默认开;写 typeahead=\"false\" 关掉\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 展开项变化;detail 为 `{ value: string | null }`\n * @fires select - 条目被选中(菜单随之收起);detail 为 `{ menu: string, value: string }`\n * @csspart root - role=menubar 容器,承载 roving tabindex 的兜底 Tab 位与焦点离场\n * @csspart trigger - role=menuitem 的展开按钮,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart positioner - 浮层定位容器,须自带 value 与同项 trigger 配对;坐标由引擎写成内联样式\n * @csspart content - role=menu 容器,须自带 value 与同项 trigger 配对;收起时带 hidden\n * @csspart item - role=menuitem 条目,须自带 value 属性;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 条目文本(连打检索取的就是它),对读屏透明\n * @csspart item-indicator - 条目标记位(勾选符号/图标/快捷键提示),aria-hidden\n * @csspart separator - 分隔线(role=separator,不入方向键导航)\n * @csspart group - 一组条目(role=group),须自带 value 属性\n * @csspart group-label - 分组标题,靠 id 被同组 group 的 aria-labelledby 指着\n */\nexport class XhMenubarElement extends XhElement {\n static override partContract = { anatomy: menubarAnatomy, meta: menubarMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它入口与条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n orientation: { converter: STRING_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n disabled: { converter: BOOLEAN_CONVERTER },\n typeahead: { converter: BOOLEAN_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: MenubarNode[]\n declare value?: string\n declare defaultValue?: string\n declare orientation?: Orientation\n declare loop?: boolean\n declare direction?: Direction\n declare disabled?: boolean\n declare typeahead?: boolean\n declare placement?: Placement\n declare offset?: number\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n // trigger 与 content 按 value 逐对互指的 id 由 scope 派生\n private readonly barScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: MenubarValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelect = (details: MenubarSelectDetails): void => {\n this.dispatchEvent(new CustomEvent('select', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<MenubarSchema>(\n this,\n menubarMachine,\n () => this.machineProps(),\n { scope: this.barScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<MenubarSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n orientation: this.orientation,\n // 布尔缺席即 undefined,缺省交回 connect\n loop: this.loop,\n dir: this.direction,\n disabled: this.disabled,\n typeahead: this.typeahead,\n placement: this.placement,\n offset: this.offset,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onSelect: this.notifySelect,\n }\n }\n\n /** 按作者写的 value 取某一项的角色节点。 */\n private partFor(name: string, value: string | null): HTMLElement | null {\n if (value == null)\n return null\n return this.getParts(name).find(el => el.getAttribute('value') === value) ?? null\n }\n\n private openValue(): string | null {\n return this.ctrl.service.context.get('value') ?? null\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.barScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.partFor('content', this.openValue()),\n // 整条菜单栏记为本层分支:点 trigger、在 trigger 之间走、掠过换菜单都算层内交互,\n // 开合归菜单栏自己切换。\n branches: () => [this.getPart('root')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 菜单不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<MenubarSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.partFor('trigger', this.openValue()))\n svc.refs.set('getFloatingEl', () => this.partFor('positioner', this.openValue()))\n svc.refs.set('getContentEl', () => this.partFor('content', this.openValue()))\n svc.refs.set('getRootEl', () => this.getPart('root'))\n }\n\n /** 提前发现一次角色节点:default-value 时机器在 hostConnected 当场要去 content 里挑焦点锚点。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /** 承载焦点的条目被移出 DOM 时上报 ITEM.LOST,让机器按当前数据重挑焦点锚点。 */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n const focusedItem = context.get('focusedItem')\n if (focusedItem == null)\n return\n // 只认 item,trigger 与 content 也带 data-value\n if (nodes.some(el => el.dataset.xhPart === 'item' && el.getAttribute(ITEM_VALUE_ATTR) === focusedItem))\n send({ type: 'ITEM.LOST' })\n }\n\n // 取 owner 子树内指定名字的角色节点。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectMenubar(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // trigger 逐个打:身份取作者写的 value,禁用经 authorDisabled 归一到 aria-disabled。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供方向键现查。\n for (const el of this.getParts('trigger')) {\n const props = api.getTriggerProps({\n value: el.getAttribute('value') ?? '',\n disabled: authorDisabled(el),\n })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n for (const el of this.getParts('positioner'))\n this.spreader.spread(el, api.getPositionerProps({ value: el.getAttribute('value') ?? '' }) as Record<string, unknown>)\n\n // 菜单常挂,按本帧产出的 hidden 用内联 display 收起\n for (const el of this.getParts('content')) {\n const props = api.getContentProps({ value: el.getAttribute('value') ?? '' }) as Record<string, unknown>\n this.spreader.spread(el, props)\n this.setPartHidden(el, props.hidden === true)\n }\n\n for (const el of this.getParts('group')) {\n const group = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getGroupProps(group) as Record<string, unknown>)\n for (const label of this.partsIn(el, 'group-label'))\n this.spreader.spread(label, api.getGroupLabelProps(group) as Record<string, unknown>)\n }\n\n for (const el of this.getParts('item')) {\n const item: MenubarItemProps = {\n value: el.getAttribute('value') ?? '',\n disabled: authorDisabled(el),\n }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n // 条目内的文本与标记位跟着同一份声明走\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // 分隔线不带身份,属性对每个都一样\n for (const el of this.getParts('separator'))\n this.spreader.spread(el, api.getSeparatorProps() as Record<string, unknown>)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { NavigationMenuNode, NavigationMenuSchema, NavigationMenuTranslations, NavigationMenuValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, IdGenerator, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled } from '@xihan-ui/behavior'\nimport { connectNavigationMenu, navigationMenuAnatomy, navigationMenuMachine, navigationMenuMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * 作者写在角色节点上的布尔声明,三态读法:属性缺席 = false,=\"false\" = false,其余 = true。\n */\nfunction authorFlag(el: HTMLElement, name: string): boolean {\n const raw = el.getAttribute(name)\n return raw != null && raw !== 'false'\n}\n\n/**\n * 读条目的禁用声明,顺手把作者写的原生 disabled 摘掉。\n *\n * 集合条目的禁用一律由 aria-disabled 表达:原生禁用的按钮不可聚焦、也收不到 click,\n * 「禁用项仍是方向键起点、仍挡得住点击」这两条在原生 disabled 下根本无从成立\n * (连点击都到不了处理器,挡住的是浏览器不是组件)。\n * 摘掉之后禁用态由 connect 产出的 aria-disabled 承接,下一轮接线照样读得到。\n */\nfunction authorDisabled(el: HTMLElement): boolean {\n const disabled = isItemDisabled(el)\n if (el.hasAttribute('disabled'))\n el.removeAttribute('disabled')\n return disabled\n}\n\n/**\n * `<xh-navigation-menu>` —— Light-DOM 行为宿主:作者写\n * root/list/item/trigger/content/link/indicator/viewport 角色节点,\n * 元素跑 navigation-menu 机器并把 connect 产出打上去。\n *\n * 与 `<xh-menu>` 的分野:这里的条目是链接不是命令,因此不做 roving tabindex——\n * 每个 trigger 都留在 Tab 序列里,面板紧跟在 trigger 之后,Tab 才走得进去。\n *\n * 标签由作者写,且必须写对:root 是 `<nav>`(地标语义只有标签给得了),list 是 `<ul>`,\n * item 与 indicator 都是 `<li>`(`<ul>` 里只放得下 `<li>`),trigger 是 `<button>`,\n * link 是 `<a>`。面板(content)写在同一个 item 里、紧跟 trigger 之后。\n *\n * @customElement xh-navigation-menu\n * @attr {string} value - 受控展开项;缺省该属性即非受控\n * @attr {string} default-value - 非受控的初始展开项\n * @attr {'horizontal'|'vertical'} orientation - 方向键轴向,默认 horizontal\n * @attr {number} delay-duration - 悬停/聚焦到展开的等待毫秒,默认 200\n * @attr {number} skip-delay-duration - 收起之后的静默毫秒,默认 300;窗口内再碰 trigger 直接展开\n * @attr {'ltr'|'rtl'} dir - 文字方向,只影响水平轴上 ArrowLeft/ArrowRight 的前后语义\n * @attr {boolean} loop - 方向键走到尽头回绕,默认开启;写 loop=\"false\" 关掉\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 展开项变化;detail 为 `{ value: string | null }`\n * @csspart root - nav 地标,承载 aria-label;指针离开/焦点离场/Escape 三条收起出口都在这儿\n * @csspart list - ul 容器,同时是指示条定位的参照系\n * @csspart item - li 条目,一项一个\n * @csspart trigger - 展开面板的按钮,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart content - 面板,须自带 value 属性与 trigger 配对;收起时 hidden\n * @csspart link - 面板里的链接;指向当前页面的那条写 current 属性,得到 aria-current=\"page\"\n * @csspart indicator - 指示条,须写成 `<li>` 并住在 list 里;对读屏隐藏,位置由机器量好写成内联样式\n * @csspart viewport - 可选的共享面板外壳,放在 root 里;都收起时 hidden\n */\nexport class XhNavigationMenuElement extends XhElement {\n static override partContract = { anatomy: navigationMenuAnatomy, meta: navigationMenuMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它入口的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n orientation: { converter: STRING_CONVERTER },\n delayDuration: { converter: NUMBER_CONVERTER, attribute: 'delay-duration' },\n skipDelayDuration: { converter: NUMBER_CONVERTER, attribute: 'skip-delay-duration' },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n loop: { converter: BOOLEAN_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,走不了属性;只作为 property 暴露,与 Vue 侧的 translations prop 对齐\n translations: { attribute: false },\n }\n\n declare collection?: NavigationMenuNode[]\n declare value?: string\n declare defaultValue?: string\n declare orientation?: Orientation\n declare delayDuration?: number\n declare skipDelayDuration?: number\n declare direction?: Direction\n declare loop?: boolean\n declare tone?: Tone\n declare size?: Size\n declare translations?: Partial<NavigationMenuTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n // trigger 与 content 要按 value 逐对互指(aria-controls / aria-labelledby),\n // 那些 id 由 scope 派生,因此这里必须自己建一个\n private readonly menuScope = createScope(null, this.idGen)\n\n private readonly notify = (details: NavigationMenuValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<NavigationMenuSchema>(\n this,\n navigationMenuMachine,\n () => this.machineProps(),\n { scope: this.menuScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<NavigationMenuSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n orientation: this.orientation,\n delayDuration: this.delayDuration,\n skipDelayDuration: this.skipDelayDuration,\n dir: this.direction,\n // 布尔属性缺席即 undefined,把缺省交回 connect(回绕默认开)\n loop: this.loop,\n tone: this.tone,\n size: this.size,\n translations: this.translations,\n onValueChange: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 惰性 getter:量测推迟到 DOM 就位之后才调它。\n private injectRefs(svc: Service<NavigationMenuSchema>): void {\n svc.refs.set('getListEl', () => this.getPart('list'))\n }\n\n protected wire(): void {\n const api = connectNavigationMenu(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('list', api.getListProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用经 authorDisabled 归一到 aria-disabled。\n // 打上去的 data-scope/data-part/data-value 正是方向键在事件那一刻查 DOM 的依据,\n // 所以 wire 必须先于事件跑过——updated() 已保证。\n for (const el of this.getParts('trigger')) {\n const props = api.getTriggerProps({\n value: el.getAttribute('value') ?? '',\n disabled: authorDisabled(el),\n })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n // 面板常挂,未展开的由 connect 输出 hidden;styled 给 content 设了 display,\n // 那条声明会盖过 UA 的 [hidden]{display:none},得用内联 style.display 压住。\n // 判据直接取 connect 这一帧的产出,不另起一套:两边各判一次迟早会说岔。\n for (const el of this.getParts('content')) {\n const props = api.getContentProps({ value: el.getAttribute('value') ?? '' }) as Record<string, unknown>\n this.spreader.spread(el, props)\n this.setPartHidden(el, props.hidden === true)\n }\n\n for (const el of this.getParts('link'))\n this.spreader.spread(el, api.getLinkProps({ current: authorFlag(el, 'current') }) as Record<string, unknown>)\n\n const indicator = this.getPart('indicator')\n if (indicator) {\n const props = api.getIndicatorProps() as Record<string, unknown>\n this.spreader.spread(indicator, props)\n this.setPartHidden(indicator, props.hidden === true)\n }\n\n const viewport = this.getPart('viewport')\n if (viewport) {\n const props = api.getViewportProps() as Record<string, unknown>\n this.spreader.spread(viewport, props)\n this.setPartHidden(viewport, props.hidden === true)\n }\n }\n}\n","import type { NumberAnimationEasing, NumberAnimationFinishDetails, NumberAnimationLive, NumberAnimationSchema } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectNumberAnimation, numberAnimationAnatomy, numberAnimationMachine, numberAnimationMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席:`to=\"\"` 经 Number() 会变成 0,那是一个货真价实的终点,不是\"没写\"\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 缺省为真的开关(active)得能被 =\"false\" 关掉;三态:缺席 = undefined(用默认值),=\"false\" = false,其余 = true\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-number-animation>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,\n * 元素跑 number-animation 机器,逐帧把补间算出的数字格式化后写进那个节点。\n *\n * 参数改写分两路:改 `from` 是\"换起点\",数字当场落到新起点再重跑;\n * 改 `to` / `duration` / `easing` 是\"换目标\",从当前数字接着走,不跳回起点。\n * 已经跑完停在 idle 时改 `to` 同样会重新跑起来,所以\"数字跟着数据走\"不必额外拨 `active`。\n *\n * 根是 role=\"status\" 但 aria-live 缺省写死 off:status 的隐含 aria-live 就是 polite,\n * 一个每帧都在变的数字用 polite 会把读屏刷爆,要播报由作者把 live 开到 polite 或 assertive。\n *\n * @customElement xh-number-animation\n * @attr {number} from - 起点,缺省 0\n * @attr {number} to - 终点,缺省 0\n * @attr {number} duration - 时长毫秒,缺省 1000;<=0 即一步到位\n * @attr {'linear'|'ease-in'|'ease-out'|'ease-in-out'} easing - 缓动,缺省 linear\n * @attr {number} precision - 小数位,缺省 0\n * @attr {string} separator - 千位分隔符,缺省不分隔\n * @attr {boolean} active - 是否在跑,缺省真;`active=\"false\"` 停在当前值\n * @attr {'sm'|'md'|'lg'} size - 尺寸,只改字号\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定数字用哪族颜色\n * @attr {'off'|'polite'|'assertive'} live - 读屏播报档位,缺省 off\n * @fires finish - 走到终点;detail 为 `{ value: number }`\n * @csspart root - 数字本身(承载 status 语义、data-state 与两个视觉轴);文字归元素写\n */\nexport class XhNumberAnimationElement extends XhElement {\n static override partContract = { anatomy: numberAnimationAnatomy, meta: numberAnimationMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n from: { converter: NUMBER_CONVERTER },\n to: { converter: NUMBER_CONVERTER },\n duration: { converter: NUMBER_CONVERTER },\n easing: { converter: STRING_CONVERTER },\n precision: { converter: NUMBER_CONVERTER },\n separator: { converter: STRING_CONVERTER },\n active: { converter: BOOLEAN_CONVERTER },\n size: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n live: { converter: STRING_CONVERTER },\n }\n\n declare from?: number\n declare to?: number\n declare duration?: number\n declare easing?: NumberAnimationEasing\n declare precision?: number\n declare separator?: string\n declare active?: boolean\n declare size?: Size\n declare tone?: Tone\n declare live?: NumberAnimationLive\n\n private readonly notify = (details: NumberAnimationFinishDetails): void => {\n this.dispatchEvent(new CustomEvent('finish', { detail: details, bubbles: true, composed: true }))\n }\n\n // 机器的副作用只有一个逐帧循环(自身自足):不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<NumberAnimationSchema>(this, numberAnimationMachine, () => this.machineProps())\n\n private machineProps(): Partial<NumberAnimationSchema['props']> {\n return {\n from: this.from,\n to: this.to,\n duration: this.duration,\n easing: this.easing,\n precision: this.precision,\n separator: this.separator,\n // 布尔属性经三态转换器进来:不在即 undefined,把缺省交回机器\n active: this.active,\n size: this.size,\n tone: this.tone,\n live: this.live,\n onFinish: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectNumberAnimation(this.ctrl.service, wcNormalize)\n const root = this.getPart('root')\n if (!root)\n return\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n // 数字归元素写:spreader 只管属性与事件,写不了文本。\n // 比一次再写:值没动时的赋值会白白惊动一次变更记录,而这里每帧都会走一遍\n if (root.textContent !== api.text)\n root.textContent = api.text\n }\n}\n","import type { NumberFieldSchema, NumberFieldValueChangeDetails } from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectNumberField, numberFieldAnatomy, numberFieldMachine, numberFieldMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-number-field>` —— Light-DOM 行为宿主:作者写 root/label/input/加减按钮四类角色节点,\n * 元素跑 number-field 机器并把 connect 产出打上去。\n *\n * 键盘全在 input 上(ArrowUp/Down 步进、PageUp/Down 大步进、Home/End 取端点),\n * 两个按钮对读屏隐藏——它们只是指针用户的快捷方式,暴露出来等于把同一个控件报两遍。\n *\n * @customElement xh-number-field\n * @attr {string} value - 受控值(原始输入串);缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {number} min - 下界;给了 Home 才接管\n * @attr {number} max - 上界;给了 End 才接管\n * @attr {number} step - 方向键与按钮的步长,默认 1\n * @attr {number} large-step - PageUp/PageDown 的步长,默认 10 倍 step\n * @attr {boolean} disabled - 禁用:不可聚焦、推不动\n * @attr {boolean} read-only - 只读:仍可聚焦与复制,推不动\n * @attr {boolean} required - 必填标注\n * @attr {boolean} invalid - 校验失败标注\n * @attr {string} name - 表单字段名;给了才参与提交\n * @attr {number} change-delay - 按住加减按钮多久开始连发,默认 300ms\n * @attr {number} change-interval - 连发间隔,默认 50ms\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 值变化;detail 为 `{ value: string, valueAsNumber: number }`\n * @csspart root - 承载 data-disabled / data-readonly / data-invalid / data-empty 的容器\n * @csspart label - 标题;`for` 恒写向 input,故须是原生 `<label>` 才点得动\n * @csspart input - role=spinbutton 的输入框,键盘交互全在它身上\n * @csspart increment-trigger - 加一步;贴住 max 时转 disabled\n * @csspart decrement-trigger - 减一步;贴住 min 时转 disabled\n */\nexport class XhNumberFieldElement extends XhElement {\n static override partContract = { anatomy: numberFieldAnatomy, meta: numberFieldMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n min: { converter: NUMBER_CONVERTER },\n max: { converter: NUMBER_CONVERTER },\n step: { converter: NUMBER_CONVERTER },\n largeStep: { converter: NUMBER_CONVERTER, attribute: 'large-step' },\n disabled: { type: Boolean },\n readOnly: { type: Boolean, attribute: 'read-only' },\n required: { type: Boolean },\n invalid: { type: Boolean },\n name: { converter: STRING_CONVERTER },\n changeDelay: { converter: NUMBER_CONVERTER, attribute: 'change-delay' },\n changeInterval: { converter: NUMBER_CONVERTER, attribute: 'change-interval' },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare min?: number\n declare max?: number\n declare step?: number\n declare largeStep?: number\n declare disabled?: boolean\n declare readOnly?: boolean\n declare required?: boolean\n declare invalid?: boolean\n declare name?: string\n declare changeDelay?: number\n declare changeInterval?: number\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: NumberFieldValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<NumberFieldSchema>(this, numberFieldMachine, () => this.machineProps())\n\n private machineProps(): Partial<NumberFieldSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n min: this.min,\n max: this.max,\n step: this.step,\n largeStep: this.largeStep,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n required: this.required ?? false,\n invalid: this.invalid ?? false,\n name: this.name,\n changeDelay: this.changeDelay,\n changeInterval: this.changeInterval,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectNumberField(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('increment-trigger', api.getIncrementTriggerProps() as Record<string, unknown>)\n put('decrement-trigger', api.getDecrementTriggerProps() as Record<string, unknown>)\n // 输入框的 value 不需要在这里另外回写:spreader 把 value/checked/selected 三个键\n // 当 property 写(dom/spread.ts 的 PROP_KEYS),属性写法只管初值、盖不住用户输入过的框\n }\n}\n","import type { PageHeaderProps } from '@xihan-ui/headless'\nimport type { Size } from '@xihan-ui/kernel'\nimport { connectPageHeader, pageHeaderAnatomy, pageHeaderMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-page-header>` —— Light-DOM 行为宿主,无状态机,把 connectPageHeader 产出打到各角色节点。\n * 除 root 外的部件全部可缺省:返回位、标题、副标题、操作、页脚按需摆。\n *\n * 返回位只拿身份与位置:标签、type、可及名字、点了往哪走,全归作者自己的按钮。\n * root 上不写 role:这一块算不算 banner 地标取决于它摆在页面的哪一层,由作者自己声明。\n *\n * @customElement xh-page-header\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定标题字号与整块的上下留白\n * @attr {boolean} bordered - 底部画一条分隔线\n * @csspart root - 页头根容器,承载 data-size / data-bordered\n * @csspart back-trigger - 返回位,作者自己的按钮,组件只摆位置\n * @csspart title - 页面标题\n * @csspart subtitle - 与标题同行的补充信息\n * @csspart extra - 行尾的操作区\n * @csspart footer - 整行另起的附加区,装描述、标签页或一组摘要\n */\nexport class XhPageHeaderElement extends XhElement {\n static override partContract = { anatomy: pageHeaderAnatomy, meta: pageHeaderMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n size: { converter: STRING_CONVERTER },\n bordered: { type: Boolean },\n }\n\n declare size?: Size\n declare bordered?: boolean\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectPageHeader({\n size: this.size,\n bordered: this.bordered ?? false,\n } satisfies PageHeaderProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('back-trigger', api.getBackTriggerProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('subtitle', api.getSubtitleProps() as Record<string, unknown>)\n put('extra', api.getExtraProps() as Record<string, unknown>)\n put('footer', api.getFooterProps() as Record<string, unknown>)\n }\n}\n","import type { PaginationPageChangeDetails, PaginationSchema, PaginationTranslations } from '@xihan-ui/headless'\nimport type { Direction, Size, Tone } from '@xihan-ui/kernel'\nimport { connectPagination, paginationAnatomy, paginationMachine, paginationMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 数值属性统一走这个转换器:属性缺席即 undefined,缺省值的唯一事实源留在 connect。\n// 空串也当缺席:`page=\"\"` 经 Number() 会变成 0,那是个不存在的页。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/** 页码按钮自报的页数;缺失或空串一律给 NaN(见 wire 里的说明)。 */\nfunction itemPage(el: HTMLElement): number {\n const raw = el.getAttribute('value')\n return raw == null || raw === '' ? Number.NaN : Number(raw)\n}\n\n/**\n * `<xh-pagination>` —— Light-DOM 行为宿主:作者写 root/prev-trigger/item/ellipsis/next-trigger\n * 角色节点,元素跑 pagination 机器并把 connect 产出打上去。\n *\n * root 必须是 `<nav>`:分页器是\"跳到某一页\"的导航地标,元素只往上打 aria-label,\n * 地标语义得由标签自己给。页码按钮须自带 `value` 属性标明是第几页。\n *\n * 页码序列(几号页、哪里该出省略号)由作者按 headless 的 `pages` 渲染,元素不替作者生成节点:\n * 生成节点就等于收走模板控制权,外层 `<li>` 壳、图标、i18n 文案都再塞不进来。\n *\n * @customElement xh-pagination\n * @attr {number} count - 总条数(不是总页数)\n * @attr {number} page-size - 每页条数,默认 10\n * @attr {number} page - 受控页码;缺省该属性即非受控\n * @attr {number} default-page - 非受控初始页,默认 1\n * @attr {number} sibling-count - 当前页两侧各显示几页,默认 1\n * @attr {'ltr'|'rtl'} dir - 文字方向,只影响排版;上一页/下一页的语义不随之翻转\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires page-change - 页码变化;detail 为 `{ page: number, pageSize: number }`\n * @csspart root - nav 地标,承载 aria-label 与 data-empty\n * @csspart prev-trigger - 上一页;首页时转原生 disabled\n * @csspart next-trigger - 下一页;末页时转原生 disabled\n * @csspart item - 页码按钮,须自带 value 属性;当前页带 aria-current=\"page\" 与 data-selected\n * @csspart ellipsis - 折叠掉的那几页的占位,对读屏隐藏\n */\nexport class XhPaginationElement extends XhElement {\n static override partContract = { anatomy: paginationAnatomy, meta: paginationMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n count: { converter: NUMBER_CONVERTER },\n pageSize: { converter: NUMBER_CONVERTER, attribute: 'page-size' },\n page: { converter: NUMBER_CONVERTER },\n defaultPage: { converter: NUMBER_CONVERTER, attribute: 'default-page' },\n siblingCount: { converter: NUMBER_CONVERTER, attribute: 'sibling-count' },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,走不了属性;只作为 property 暴露,与 Vue 侧的 translations prop 对齐\n translations: { attribute: false },\n }\n\n declare count?: number\n declare pageSize?: number\n declare page?: number\n declare defaultPage?: number\n declare siblingCount?: number\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n declare translations?: Partial<PaginationTranslations>\n\n private readonly notify = (details: PaginationPageChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('page-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // pagination 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<PaginationSchema>(this, paginationMachine, () => this.machineProps())\n\n private machineProps(): Partial<PaginationSchema['props']> {\n return {\n count: this.count,\n pageSize: this.pageSize,\n page: this.page,\n defaultPage: this.defaultPage,\n siblingCount: this.siblingCount,\n dir: this.direction,\n tone: this.tone,\n size: this.size,\n translations: this.translations,\n onPageChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectPagination(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('prev-trigger', api.getPrevTriggerProps() as Record<string, unknown>)\n put('next-trigger', api.getNextTriggerProps() as Record<string, unknown>)\n\n // 页码是多实例 part,逐个打:身份取作者写的 value。\n // 漏写时给 NaN 而不是 Number(null) 的 0:NaN 与任何页都不相等,按钮点了会被机器\n // 夹回第 1 页,但绝不会冒充当前页;Vue 侧漏写 value 拿到的同样是 NaN,两侧一致。\n for (const el of this.getParts('item')) {\n const props = api.getItemProps({ page: itemPage(el) })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n for (const el of this.getParts('ellipsis'))\n this.spreader.spread(el, api.getEllipsisProps() as Record<string, unknown>)\n }\n}\n","import type { PinInputSchema, PinInputTranslations, PinInputType, PinInputValueChangeDetails } from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectPinInput, pinInputAnatomy, pinInputMachine, pinInputMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 值在属性里是一整串(value=\"1234\"),逐字符摊成数组;长度归一交给机器。\n// 直接给 property 赋数组时不过转换器,两种写法都通\nconst ARRAY_CONVERTER = { fromAttribute: (v: string | null) => (v == null ? undefined : [...v]) }\n\n/** 作者写在格子上的下标。缺席或写坏了就退回文档序——手写 HTML 时把格子按顺序排下来本身就是声明。 */\nfunction declaredIndex(el: HTMLElement, position: number): number {\n const raw = el.getAttribute('index')\n if (raw == null || raw.trim() === '')\n return position\n const parsed = Number(raw)\n return Number.isFinite(parsed) ? Math.trunc(parsed) : position\n}\n\n/**\n * `<xh-pin-input>` —— Light-DOM 行为宿主:作者写 root/label/input(多个)/hidden-input 角色节点,\n * 元素跑 pin-input 机器并把 connect 产出打上去。\n *\n * 每格是一个原生输入框:敲一个字符自动跳下一格,退格在空格上回退并清掉上一格,\n * 左右键与 Home/End 在格间移动,粘贴整串按格分发。不接受的字符直接丢弃,\n * 既不进值也不留在框里。整份值另由 hidden-input 随表单提交。\n *\n * @customElement xh-pin-input\n * @attr {string} value - 受控值,逐字符摊进各格;缺省该属性即非受控\n * @attr {string} default-value - 非受控初值,同样逐字符摊开\n * @attr {number} length - 格数,默认 6\n * @attr {'numeric'|'alphanumeric'|'alphabetic'} type - 接受的字符类别,默认 numeric\n * @attr {boolean} mask - 遮蔽显示:每格转 type=password\n * @attr {boolean} otp - 一次性验证码:补 autocomplete=one-time-code\n * @attr {string} placeholder - 空格子的占位字符\n * @attr {boolean} disabled - 禁用:每格带原生 disabled,隐藏输入不参与提交\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} blur-on-complete - 填满即把焦点撤走\n * @attr {string} name - 表单字段名;给了隐藏输入才带 name\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 值变化;detail 为 `{ value: string[], valueAsString: string }`\n * @fires value-complete - 每格都填满;detail 同上\n * @csspart root - role=group 的容器,承载 data-disabled / data-invalid / data-complete\n * @csspart label - 标题;`for` 恒写向首格,故须是原生 `<label>` 才点得动\n * @csspart input - 一格一个的输入框,可自带 index 属性声明下标,缺省按文档序;aria-label 由内置文案给出\n * @csspart hidden-input - type=hidden 的表单出口,值是拼好的整串\n */\nexport class XhPinInputElement extends XhElement {\n static override partContract = { anatomy: pinInputAnatomy, meta: pinInputMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: ARRAY_CONVERTER },\n defaultValue: { converter: ARRAY_CONVERTER, attribute: 'default-value' },\n length: { converter: NUMBER_CONVERTER },\n type: { converter: STRING_CONVERTER },\n mask: { type: Boolean },\n otp: { type: Boolean },\n placeholder: { converter: STRING_CONVERTER },\n disabled: { type: Boolean },\n invalid: { type: Boolean },\n blurOnComplete: { type: Boolean, attribute: 'blur-on-complete' },\n name: { converter: STRING_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n // 文案是对象,走不了属性;只作为 property 暴露,与 Vue 侧的 translations prop 对齐\n translations: { attribute: false },\n }\n\n declare value?: string[]\n declare defaultValue?: string[]\n declare length?: number\n declare type?: PinInputType\n declare mask?: boolean\n declare otp?: boolean\n declare placeholder?: string\n declare disabled?: boolean\n declare invalid?: boolean\n declare blurOnComplete?: boolean\n declare name?: string\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n declare translations?: Partial<PinInputTranslations>\n\n private readonly notifyChange = (details: PinInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyComplete = (details: PinInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-complete', { detail: details, bubbles: true, composed: true }))\n }\n\n // pin-input 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<PinInputSchema>(this, pinInputMachine, () => this.machineProps())\n\n private machineProps(): Partial<PinInputSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n length: this.length,\n type: this.type,\n mask: this.mask ?? false,\n otp: this.otp ?? false,\n placeholder: this.placeholder,\n disabled: this.disabled ?? false,\n invalid: this.invalid ?? false,\n blurOnComplete: this.blurOnComplete ?? false,\n name: this.name,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n translations: this.translations,\n onValueChange: this.notifyChange,\n onValueComplete: this.notifyComplete,\n }\n }\n\n protected wire(): void {\n const api = connectPinInput(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n // 格子是多实例 part,逐个打。打上去的 data-scope/data-part 正是移格与粘贴在事件那一刻\n // 现查 DOM 的依据,所以 wire 必须先于事件跑过——updated() 已保证。\n this.getParts('input').forEach((el, position) => {\n const props = api.getInputProps({ index: declaredIndex(el, position) })\n this.spreader.spread(el, props as Record<string, unknown>)\n })\n // 各格的 value 不需要在这里另外回写:spreader 把 value/checked/selected 三个键\n // 当 property 写(dom/spread.ts 的 PROP_KEYS),属性写法只管初值、盖不住用户输入过的框\n }\n}\n","import type { PopconfirmIntents, PopoverOpenChangeDetails, PopoverSchema } from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectPopconfirm, popconfirmAnatomy, popconfirmMeta, popoverMachine } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(Esc 关闭、外部交互关闭)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-popconfirm>` —— Light-DOM 行为宿主:用户写 root/trigger/positioner/content/... 角色节点,\n * 元素跑 popover 机器(开合、定位、消解层、焦点域都在那里)并把 connectPopconfirm 产出打上去。\n * 确认与取消不入机器,点下去先派出对应事件再请求收起。\n *\n * 浮层不陷焦点,也没有关闭按钮:答复由 confirm-trigger / cancel-trigger 两颗按钮给出,\n * Escape 与层外交互只收起浮层、只派 open-change。\n *\n * @customElement xh-popconfirm\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 首选放置位,默认 bottom;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px),默认 8\n * @attr {boolean} close-on-escape - Esc 关闭,默认 true;写 close-on-escape=\"false\" 关掉\n * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 true;写 \"false\" 关掉\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @fires confirm - 点了确认按钮;随后浮层收起\n * @fires cancel - 点了取消按钮;随后浮层收起\n * @csspart root - 框住触发器的根容器,承载 data-state\n * @csspart trigger - 触发按钮(aria-haspopup/aria-expanded/aria-controls 所在),同时是定位锚点\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - 浮层内容(role=alertdialog;焦点域与消解层的根节点),收起时带 hidden\n * @csspart title - 标题(aria-labelledby 目标)\n * @csspart description - 问题正文(aria-describedby 目标)\n * @csspart confirm-trigger - 确认按钮\n * @csspart cancel-trigger - 取消按钮\n */\nexport class XhPopconfirmElement extends XhElement {\n static override partContract = { anatomy: popconfirmAnatomy, meta: popconfirmMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n closeOnInteractOutside: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-interact-outside' },\n size: { converter: STRING_CONVERTER },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare closeOnEscape?: boolean\n declare closeOnInteractOutside?: boolean\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly popconfirmScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notify = (details: PopoverOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly intents: PopconfirmIntents = {\n onConfirm: () => {\n this.dispatchEvent(new CustomEvent('confirm', { bubbles: true, composed: true }))\n },\n onCancel: () => {\n this.dispatchEvent(new CustomEvent('cancel', { bubbles: true, composed: true }))\n },\n }\n\n private readonly ctrl = new MachineController<PopoverSchema>(\n this,\n popoverMachine,\n () => this.machineProps(),\n { scope: this.popconfirmScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<PopoverSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n closeOnEscape: this.closeOnEscape,\n closeOnInteractOutside: this.closeOnInteractOutside,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.popconfirmScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n // 否则同一次点击先被判为层外交互关一次、再被 click 打开一次,浮层等于关不掉。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 气泡确认不自带遮罩,没有\"点它就该关本层\"的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n private injectRefs(svc: Service<PopoverSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入 open,\n * 定位副作用同步取一次 trigger/positioner——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,引擎挂不上,浮层会停在容器左上角。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n protected wire(): void {\n const api = connectPopconfirm(this.ctrl.service, this.intents, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可。\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('confirm-trigger', api.getConfirmTriggerProps() as Record<string, unknown>)\n put('cancel-trigger', api.getCancelTriggerProps() as Record<string, unknown>)\n\n // content 常驻 Light DOM,收起态由宿主用内联 display 兜住:皮肤给 content 设了 display,\n // 会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { PopoverOpenChangeDetails, PopoverSchema, PopoverTranslations } from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectPopover, popoverAnatomy, popoverMachine, popoverMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(Esc 关闭、外部交互关闭)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-popover>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/... 角色节点,\n * 元素跑 popover 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 trigger、被定位的浮层取 positioner;机器只认端口,不认识具体引擎。\n *\n * @customElement xh-popover\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 首选放置位,默认 bottom;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px),默认 8\n * @attr {boolean} modal - 模态浮层陷住焦点并回绕 Tab,默认 false\n * @attr {boolean} close-on-escape - Esc 关闭,默认 true;写 close-on-escape=\"false\" 关掉\n * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 true;写 \"false\" 关掉\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart trigger - 触发按钮(aria-haspopup/aria-expanded/aria-controls 所在),同时是定位锚点\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - 浮层内容(role=dialog;焦点域与消解层的根节点),收起时带 hidden\n * @csspart title - 标题(aria-labelledby 目标)\n * @csspart description - 描述(aria-describedby 目标)\n * @csspart close-trigger - 关闭按钮\n * @csspart arrow - 指向锚点的箭头(aria-hidden,data-placement 随实际放置位翻转)\n */\nexport class XhPopoverElement extends XhElement {\n static override partContract = { anatomy: popoverAnatomy, meta: popoverMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n modal: { converter: BOOLEAN_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n closeOnInteractOutside: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-interact-outside' },\n size: { converter: STRING_CONVERTER },\n // 对象值进不了属性,只作为 property 暴露\n translations: { attribute: false },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare modal?: boolean\n declare closeOnEscape?: boolean\n declare closeOnInteractOutside?: boolean\n declare size?: Size\n /** 关闭按钮的无障碍名;connect 每帧重写 aria-label,作者自己写在节点上会被盖掉,只能从这里给。 */\n declare translations?: Partial<PopoverTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly popoverScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notify = (details: PopoverOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<PopoverSchema>(\n this,\n popoverMachine,\n () => this.machineProps(),\n { scope: this.popoverScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<PopoverSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n modal: this.modal,\n closeOnEscape: this.closeOnEscape,\n closeOnInteractOutside: this.closeOnInteractOutside,\n translations: this.translations,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.popoverScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n // 否则同一次点击先被判为层外交互关一次、再被 click 打开一次,浮层等于关不掉。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => this.modal ?? false,\n setModal: () => {},\n // 非模态浮层不自带遮罩,没有\"点它就该关本层\"的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n private injectRefs(svc: Service<PopoverSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入 open,\n * 定位副作用同步取一次 trigger/positioner——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,引擎挂不上,浮层会停在容器左上角。\n * 消解层与焦点域的 ref 是懒读的,不受影响,这里只为定位补上时机。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n protected wire(): void {\n const api = connectPopover(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可。\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n // Light DOM content 常驻,WC 自管可见性。读 styled/styles/popover.css 的结论:\n // content 是 display:flex,positioner 只声明 position/z-index/pointer-events、没有 display,\n // connect 也不给 positioner 发 hidden——所以只兜 content 这一处。\n // 该文件自己带了 [data-part=content][hidden]{display:none} 压住那条 flex,\n // 但宿主不能指望作者装了这份样式:换别家样式给 content 设 display 就又盖过 UA 的\n // [hidden]{display:none},只有内联 style.display 压得住。open 时置空串即撤掉内联声明。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type {\n ListboxSchema,\n ListboxValueChangeDetails,\n PopoverOpenChangeDetails,\n PopoverSchema,\n PopselectItemProps,\n PopselectNode,\n} from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectPopselect, listboxMachine, popoverMachine, popselectAnatomy, popselectMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定\n// (value 尤其:落成 null 就分不出「非受控」与「受控且当前无选中」)。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕、连打检索、Esc 关闭)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-popselect>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/item 角色节点,\n * 元素同时跑两台机器——浮层开合、定位、消解层与焦点域归 popover,选中集合与焦点锚点归 listbox——\n * 再把 connectPopselect 的产出打到各角色节点上。定位引擎在本元素里建好、经 refs 注入 popover 机器,\n * 锚点取 trigger、被定位的浮层取 positioner。\n *\n * 条目身份取作者写在 item 上的 value 属性,禁用由条目自报 aria-disabled 或写进 collection。\n * 单选落值即收起浮层、焦点归还 trigger;多选保持展开继续挑。\n *\n * 选中值是集合:单选可以直接写 value=\"apple\" 属性,多选只能走 property(`el.value = ['a','b']`),\n * 属性表达不了数组。\n *\n * @customElement xh-popselect\n * @attr {string} value - 受控选中值(单选简写);缺省该属性即非受控,多选请用 property\n * @attr {string} default-value - 非受控初始选中值\n * @attr {boolean} multiple - 多选:落值即在集合里增删该项,浮层不收起\n * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,键盘与点击都改不了选中值\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {boolean} typeahead - 连打检索,默认开;写 typeahead=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键语义,默认 ltr\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 首选放置位,默认 bottom;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} close-on-escape - Esc 关闭,默认 true;写 close-on-escape=\"false\" 关掉\n * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 true;写 \"false\" 关掉\n * @attr {'outline'|'subtle'|'ghost'} variant - 形态,决定触发器的描边与底色怎么用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定聚焦与选中强调用哪族颜色\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定触发器高度、内边距与字号档位\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器,承载 data-state 与三个视觉轴,浮层从这里继承私有槽\n * @csspart trigger - 触发按钮(aria-haspopup=listbox/aria-expanded/aria-controls 所在),同时是定位锚点,须是原生 button\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=listbox 容器(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden\n * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 条目文本(连打检索的取字处)\n * @csspart item-indicator - 条目选中标记(aria-hidden)\n */\nexport class XhPopselectElement extends XhElement {\n static override partContract = { anatomy: popselectAnatomy, meta: popselectMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n multiple: { type: Boolean },\n disabled: { type: Boolean },\n loop: { converter: BOOLEAN_CONVERTER },\n typeahead: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n closeOnInteractOutside: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-interact-outside' },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: PopselectNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare multiple?: boolean\n declare disabled?: boolean\n declare loop?: boolean\n declare typeahead?: boolean\n declare direction?: Direction\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare closeOnEscape?: boolean\n declare closeOnInteractOutside?: boolean\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n // 两台机器共用一个 scope:trigger 与 content 的 id 由它派生,aria-controls 才指得准\n private readonly popselectScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyOpen = (details: PopoverOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyValue = (details: ListboxValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly popoverCtrl = new MachineController<PopoverSchema>(\n this,\n popoverMachine,\n () => this.popoverProps(),\n { scope: this.popselectScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n // listbox 机器无副作用(连打缓冲住在它自己的 refs 里),不需要 config/layer/定位引擎\n private readonly listboxCtrl = new MachineController<ListboxSchema>(\n this,\n listboxMachine,\n () => this.listboxProps(),\n { scope: this.popselectScope },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private popoverProps(): Partial<PopoverSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n closeOnEscape: this.closeOnEscape,\n closeOnInteractOutside: this.closeOnInteractOutside,\n // 弹出选择不陷焦点:Tab 走得出去,走出去即由消解层判定收起\n modal: false,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private listboxProps(): Partial<ListboxSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n multiple: this.multiple ?? false,\n disabled: this.disabled ?? false,\n loop: this.loop,\n typeahead: this.typeahead,\n dir: this.direction,\n onValueChange: this.notifyValue,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.popselectScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(popover 机器的 trackLayer 效应负责)。\n // 连接期就注册会让层与开合无关地常驻栈里,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n // 否则同一次点击先被判为层外交互关一次、再被 click 打开一次,浮层等于关不掉。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 列表不带遮罩,没有「点它就该关本层」的表面\n surfaces: () => [],\n })\n }\n\n // service 由参数传入,不回头去读 this.popoverCtrl:机器重建时这个回调先于赋值跑。\n private injectRefs(svc: Service<PopoverSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 角色节点提前发现一次:default-open 时 popover 机器在 hostConnected 当场进入 open,\n * 定位副作用同步取一次 trigger/positioner——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,引擎挂不上,浮层会停在容器左上角。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * content 判自己「焦点在列表内」退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整组零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.listboxCtrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,条目内的文本与标记离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'LIST.BLUR' })\n }\n\n /** 条目身份取作者写的 value,禁用取首见那一份声明(没写即交给 collection 定夺)。 */\n private itemProps(el: HTMLElement): PopselectItemProps {\n return { value: el.getAttribute('value') ?? '', disabled: this.declaredDisabled(el) }\n }\n\n // 条目内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectPopselect({\n popover: this.popoverCtrl.service,\n listbox: this.listboxCtrl.service,\n props: { variant: this.variant, tone: this.tone, size: this.size },\n }, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象(position/insetInlineStart/insetBlockStart),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打;条目内的文本与选中标记跟着同一份声明走,样式层各处状态一致\n for (const el of this.getParts('item')) {\n const item = this.itemProps(el)\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // Light DOM content 常驻,WC 自管可见性:皮肤给 content 设了 display:flex,\n // 那条声明会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectProgress, progressAnatomy, progressMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-progress>` —— Light-DOM 行为宿主,无状态机,把 connectProgress 产出打到 root/track/range 角色节点。\n *\n * @customElement xh-progress\n * @attr {number} value - 当前进度值,越界会被夹到 [0, max],默认 0\n * @attr {number} max - 满值上限,默认 100\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @csspart root - role=progressbar 的容器(承载 aria-valuenow/aria-valuemax/data-state)\n * @csspart track - 进度轨道(满长背景)\n * @csspart range - 已完成区段,长度按百分比写成内联 inline-size\n */\nexport class XhProgressElement extends XhElement {\n static override partContract = { anatomy: progressAnatomy, meta: progressMeta }\n\n static override properties = {\n value: { type: Number },\n max: { type: Number },\n tone: {},\n size: {},\n }\n\n declare value?: number\n declare max?: number\n declare tone?: Tone\n declare size?: Size\n\n protected wire(): void {\n const api = connectProgress({ value: this.value, max: this.max, tone: this.tone, size: this.size }, wcNormalize)\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n const track = this.getPart('track')\n if (track)\n this.spreader.spread(track, api.getTrackProps() as Record<string, unknown>)\n const range = this.getPart('range')\n if (!range)\n return\n // style 是对象,摘出来单独写成内联样式,其余键照常 spread。\n const { style, ...attrs } = api.getRangeProps() as Record<string, unknown> & { style?: { inlineSize?: string } }\n this.spreader.spread(range, attrs)\n range.style.inlineSize = style?.inlineSize ?? ''\n }\n}\n","import type { QrCodeApi, QrCodeProps, QrLevel } from '@xihan-ui/headless'\nimport { connectQrCode, qrCodeAnatomy, qrCodeMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** 本元素生成的几何节点的标记:作者写的节点不带它,重画时只清掉自己生成的那几个。 */\nconst GEOM_ATTR = 'data-xh-geom'\n\ntype ModuleShape = NonNullable<QrCodeProps['moduleShape']>\ntype EyeShape = NonNullable<QrCodeProps['eyeShape']>\n\nfunction makeGeom(doc: Document, tag: string, name: string): Element {\n const node = doc.createElementNS(SVG_NS, tag)\n node.setAttribute(GEOM_ATTR, name)\n return node\n}\n\n/**\n * `<xh-qr-code>` —— 二维码宿主,无状态机,把命名与档位打到 root 上,把几何铺进 root。\n *\n * 作者写一个空的 `<svg data-xh-part=\"root\"></svg>`,几何由本元素生成:模块是算出来的派生数据,\n * 作者没法自己写。矩阵在 connectQrCode 里算一遍,这里只取现成的 path。\n *\n * 几何恒是两条 `<path>`:除码眼外的模块一条、三个码眼一条,码眼那条另有 `--xh-qr-code-eye-fg` 可单独上色。\n *\n * 要放中心 logo 就在 root 里写一个 `<svg data-xh-part=\"logo\">` 并把图形放进去,落位与尺寸由本元素写上;\n * 那块底下会先铺一个底色矩形把模块挖空,作者的图形画在它上面。放了 logo 就把 level 提到 Q 或 H:\n * 挖掉的码字超出所选级别的纠错余量时,诊断通道会收到一条 `qr-code.logo-damage` 警告,码照画。\n *\n * 内容超出 40 版容量时不画任何模块,root 上落 `data-state=\"error\"`:\n * 截断能画出一张扫得开的码,但扫出来的是半截内容。\n *\n * @customElement xh-qr-code\n * @attr {string} value - 要编码的内容,按 UTF-8 取字节走字节模式\n * @attr {'L'|'M'|'Q'|'H'} level - 纠错级别,缺省 M\n * @attr {number} size - 像素边长,缺省 160\n * @attr {number} margin - 静区宽度(模块数),缺省 4\n * @attr {string} label - 可及名字,缺省用 value\n * @attr {'square'|'dot'|'rounded'} module-shape - 码点形状,缺省 square\n * @attr {'square'|'rounded'} eye-shape - 码眼形状,缺省 square\n * @csspart root - 根 `<svg>`,承载 viewBox / role=img / aria-label / data-level / data-version / data-modules / data-state / data-logo\n * @csspart logo - 码面正中放 logo 的嵌套 `<svg>`,承载 x / y / width / height\n */\nexport class XhQrCodeElement extends XhElement {\n static override partContract = {\n anatomy: qrCodeAnatomy,\n meta: qrCodeMeta,\n // root 不是 <svg> 时 viewBox 会被小写成 viewbox 而静默失效,铺进去的 <path> 也不显示;\n // logo 不是嵌套 <svg> 时 x / y / width / height 无处生效,那块图形会摊在整张码上\n tags: { root: ['svg'], logo: ['svg'] },\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n level: { converter: STRING_CONVERTER },\n label: { converter: STRING_CONVERTER },\n size: { type: Number },\n margin: { type: Number },\n moduleShape: { converter: STRING_CONVERTER, attribute: 'module-shape' },\n eyeShape: { converter: STRING_CONVERTER, attribute: 'eye-shape' },\n }\n\n declare value?: string\n declare level?: QrLevel\n declare label?: string\n declare size?: number\n declare margin?: number\n declare moduleShape?: ModuleShape\n declare eyeShape?: EyeShape\n\n /** 上一次往哪个 root 铺过哪一版几何。 */\n #painted?: { host: Element, key: string }\n\n protected wire(): void {\n const root = this.getPart('root')\n if (!root)\n return\n // 作者写没写 logo 部件决定要不要在码面上留位,故先取部件再算矩阵\n const logo = this.getPart('logo')\n\n // 读响应式 property,不回读 DOM 特性\n const api = connectQrCode({\n value: this.value,\n level: this.level,\n size: this.size,\n margin: this.margin,\n label: this.label,\n moduleShape: this.moduleShape,\n eyeShape: this.eyeShape,\n logo: logo != null,\n } satisfies QrCodeProps, wcNormalize)\n\n // style 是对象,摘出来单独写成内联样式,其余键照常 spread\n const { style, ...attrs } = api.getRootProps() as Record<string, unknown> & {\n style?: { inlineSize?: string, blockSize?: string }\n }\n this.spreader.spread(root, attrs)\n root.style.inlineSize = style?.inlineSize ?? ''\n root.style.blockSize = style?.blockSize ?? ''\n this.#paint(root, api)\n if (logo)\n this.spreader.spread(logo, api.getLogoProps() as Record<string, unknown>)\n }\n\n /**\n * 把数据模块、码眼、logo 挖空铺进 root,三样都排在作者写的节点之前——\n * 挖空必须压在模块之上、又在 logo 之下。\n *\n * 走 createElementNS 建节点:SVG 图元挂在非 SVG 命名空间下什么都不显示。\n * 只清 root 直属的、本元素自己标记过的几何节点:整个清空会连作者写的 logo 一起端掉。\n */\n #paint(host: Element, api: QrCodeApi): void {\n const area = api.logoArea\n const key = `${api.path}|${api.eyePath}|${area ? `${area.x} ${area.y} ${area.size}` : ''}`\n const existing = Array.from(host.children).filter(node => node.hasAttribute(GEOM_ATTR))\n const want = (api.path === '' ? 0 : 1) + (api.eyePath === '' ? 0 : 1) + (area ? 1 : 0)\n if (this.#painted?.host === host && this.#painted.key === key && existing.length === want)\n return\n this.#painted = { host, key }\n\n for (const node of existing) node.remove()\n const doc = host.ownerDocument\n const made: Element[] = []\n if (api.path !== '') {\n const node = makeGeom(doc, 'path', 'modules')\n node.setAttribute('d', api.path)\n made.push(node)\n }\n if (api.eyePath !== '') {\n const node = makeGeom(doc, 'path', 'eyes')\n node.setAttribute('d', api.eyePath)\n made.push(node)\n }\n if (area) {\n const node = makeGeom(doc, 'rect', 'logo-clear')\n node.setAttribute('x', String(area.x))\n node.setAttribute('y', String(area.y))\n node.setAttribute('width', String(area.size))\n node.setAttribute('height', String(area.size))\n made.push(node)\n }\n if (made.length)\n host.prepend(...made)\n }\n}\n","import type { RadioGroupItemProps, RadioGroupNode, RadioGroupSchema, RadioGroupValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectRadioGroup, radioGroupAnatomy, radioGroupMachine, radioGroupMeta } from '@xihan-ui/headless'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-radio-group>` —— Light-DOM 行为宿主:用户写 root/label 与若干 item 角色节点,\n * 每个 item 内自带 hidden-input/indicator/item-text,元素跑 radio-group 机器并把 connect 产出打上去。\n * 条目身份取自条目节点上的 value 属性;导航与选中在事件那一刻按 data-scope+data-part 查活 DOM,\n * 依赖 connect 回写的 data-value,因此 wire 必须先于交互跑过(基类 updated 已保证)。\n *\n * @customElement xh-radio-group\n * @attr {string} value - 受控选中值;缺省该属性即非受控\n * @attr {string} default-value - 非受控初始选中值\n * @attr {boolean} disabled - 整组禁用\n * @attr {'horizontal'|'vertical'} orientation - 视觉排布,默认 vertical\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键语义,默认 ltr\n * @attr {string} name - 表单字段名;给定后隐藏输入才带 name 并参与提交\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 选中值变化;detail 为 `{ value: string | null }`\n * @csspart root - role=radiogroup 容器(承载 roving tabindex 的兜底位)\n * @csspart label - 组标题(aria-labelledby 目标)\n * @csspart item - role=radio 条目,作者用 value 属性声明身份\n * @csspart item-text - 条目文本\n * @csspart indicator - 条目选中标记\n * @csspart hidden-input - 条目的表单影子输入(必须是原生 input)\n */\nexport class XhRadioGroupElement extends XhElement {\n static override partContract = { anatomy: radioGroupAnatomy, meta: radioGroupMeta }\n\n // dir 是 HTMLElement 原生访问器,同名声明会与基类冲突并盖掉原生反射,故字段叫 direction、属性名仍用 dir\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n defaultValue: { attribute: 'default-value' },\n disabled: { type: Boolean },\n orientation: {},\n direction: { attribute: 'dir' },\n name: {},\n tone: {},\n size: {},\n }\n\n declare collection?: RadioGroupNode[]\n declare value?: string\n declare defaultValue?: string\n declare disabled?: boolean\n declare orientation?: Orientation\n declare direction?: Direction\n declare name?: string\n declare tone?: Tone\n declare size?: Size\n\n // 整组禁用期间的条目自身声明快照:connect 每帧把 aria-disabled 写回条目,回读分不清作者声明与自己的写回\n private readonly declaredDisabled = new WeakMap<HTMLElement, boolean>()\n /** 上一帧是否整组禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */\n private wasGroupDisabled = false\n\n private readonly notify = (details: RadioGroupValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<RadioGroupSchema>(this, radioGroupMachine, () => this.machineProps())\n\n private machineProps(): Partial<RadioGroupSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue ?? null,\n disabled: this.disabled ?? false,\n orientation: this.orientation,\n dir: this.direction,\n name: this.name,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n /** 承载焦点的条目被移出 DOM 时浏览器不派 focusout,这里替 DOM 上报焦点离场,免得焦点锚点停在已消失的值上。 */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上:只有持有焦点的那个条目离场才上报\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'GROUP.BLUR' })\n }\n\n /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */\n private readonly declaredItemDisabled = createDeclaredDisabled()\n\n private itemProps(el: HTMLElement): RadioGroupItemProps {\n const value = el.getAttribute('value') ?? ''\n // 给了 collection 就以数据为事实源:现读会读到 connect 上一帧写回的 aria-disabled,\n // 「作者没写」表达不出 undefined,数据里的禁用就永远轮不到生效。\n if (this.collection)\n return { value, disabled: this.declaredItemDisabled(el) }\n const groupDisabled = !!this.disabled\n // 头一回见到这个条目:本帧的写回尚未发生,DOM 上还只有作者声明,此刻无论禁没禁用都要记下快照\n if (!this.declaredDisabled.has(el)) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 只有本帧与上一帧都没整组禁用时,节点上的 aria-disabled 才等于作者声明\n if (!groupDisabled && !this.wasGroupDisabled) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 整组禁用那几帧(以及解禁当帧)DOM 上留着机器的写回值,只认快照\n return { value, disabled: this.declaredDisabled.get(el)! }\n }\n\n // 条目内的子部件:getParts 收的是整个元素范围,按 item 子树过滤才归得对条目。\n private partsIn(item: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => item.contains(el))\n }\n\n // hidden-input 的 style 是对象、checked 只认 DOM property,走 spread 都会写坏,两者绕开 spread 单独落\n private spreadHiddenInput(input: HTMLInputElement, props: Record<string, unknown>): void {\n const { style, checked, ...attrs } = props\n this.spreader.spread(input, attrs)\n input.checked = checked === true\n Object.assign(input.style, style as Record<string, string> | undefined)\n }\n\n protected wire(): void {\n const api = connectRadioGroup(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item')) {\n const item = this.itemProps(el)\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n for (const input of this.partsIn(el, 'hidden-input'))\n this.spreadHiddenInput(input as HTMLInputElement, api.getHiddenInputProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'indicator'))\n this.spreader.spread(indicator, api.getIndicatorProps(item) as Record<string, unknown>)\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n }\n\n // 本帧的写回已落地,下一帧才知道 DOM 上的 aria-disabled 可不可信\n this.wasGroupDisabled = !!this.disabled\n }\n}\n","import type { RatingHoverChangeDetails, RatingItemProps, RatingSchema, RatingValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Size, Tone } from '@xihan-ui/kernel'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectRating, ratingAnatomy, ratingMachine, ratingMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:属性缺席 = undefined(用默认值)、=\"false\" = false、其余 = true。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-rating>` —— Light-DOM 行为宿主:作者写 root/label/control 与若干 item 角色节点\n * (可选再写一个 hidden-input 参与表单提交),元素跑 rating 机器并把 connect 产出打上去。\n *\n * 每颗星用 value 属性自报自己是第几颗(1 起),导航与选中都以它认人;\n * 键盘挂在 control 上(它才是那条 role=radiogroup 的星星带),指针预览挂在每颗星上。\n *\n * @customElement xh-rating\n * @attr {number} value - 受控评分;缺省该属性即非受控\n * @attr {number} default-value - 非受控初值,缺省 0(还没评)\n * @attr {number} count - 星星颗数,默认 5\n * @attr {boolean} allow-half - 允许半颗星:档位从 1 变成 0.5\n * @attr {boolean} disabled - 整个不可交互:整条带子退出 Tab 序列,指针与键盘都不认\n * @attr {boolean} read-only - 只读:仍可聚焦与朗读,但改不动,也没有悬停预览\n * @attr {boolean} required - 必填标注;表单影子据此参与原生校验\n * @attr {string} name - 表单字段名;给了表单影子才带 name 并参与提交\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键与\"指针落在哪半边\"的语义,默认 ltr\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 评分变化;detail 为 `{ value: number }`\n * @fires hover-change - 悬停预览变化;detail 为 `{ value: number | null }`,指针离开时带 null\n * @csspart root - 承载 data-disabled / data-readonly / data-empty 的外壳\n * @csspart label - 评分带标题(aria-labelledby 目标)\n * @csspart control - role=radiogroup 的星星带,键盘交互全在它身上\n * @csspart item - role=radio 的一颗星,作者用 value 属性声明它是第几颗;\n * 点亮看 data-highlighted,半亮看 data-half\n * @csspart hidden-input - 表单影子输入(必须是原生 input)\n */\nexport class XhRatingElement extends XhElement {\n static override partContract = { anatomy: ratingAnatomy, meta: ratingMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n // dir 占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。别名保留原生行为,\n // 同时让 dir 进 observedAttributes——运行期改 dir 才会重跑 wire 换掉按键处理器。\n static override properties = {\n value: { converter: NUMBER_CONVERTER },\n defaultValue: { converter: NUMBER_CONVERTER, attribute: 'default-value' },\n count: { converter: NUMBER_CONVERTER },\n allowHalf: { converter: BOOLEAN_CONVERTER, attribute: 'allow-half' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n required: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: number\n declare defaultValue?: number\n declare count?: number\n declare allowHalf?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare required?: boolean\n declare name?: string\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n\n private readonly notifyValue = (details: RatingValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyHover = (details: RatingHoverChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('hover-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<RatingSchema>(this, ratingMachine, () => this.machineProps())\n\n private machineProps(): Partial<RatingSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n count: this.count,\n allowHalf: this.allowHalf ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n required: this.required ?? false,\n name: this.name,\n dir: this.direction,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onHoverChange: this.notifyHover,\n }\n }\n\n /**\n * 承载焦点的星被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一颗已消失的星上:\n * 容器判自己\"焦点在带内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整条评分带零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,标题与表单影子离场不会误判;\n // 只有走的正是持有焦点的那颗星才报,否则删任一无关条目都会清掉方向键起点\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === String(focusedValue)))\n send({ type: 'CONTROL.BLUR' })\n }\n\n /** 条目身份取自作者写的 value 属性;没写就不是一颗合法的星,交给 connect 按非法值处理。 */\n private itemProps(el: HTMLElement): RatingItemProps {\n return { value: Number(el.getAttribute('value')) }\n }\n\n protected wire(): void {\n const api = connectRating(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps(this.itemProps(el)) as Record<string, unknown>)\n }\n}\n","import type { ResultProps, ResultStatus } from '@xihan-ui/headless'\nimport { connectResult, resultAnatomy, resultMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-result>` —— 结果页行为宿主,无状态机,把 connectResult 产出的属性打到角色节点上。\n *\n * 除 root 外的部件全部可缺省。图标画什么由作者塞进图标槽,库不带插画资产;\n * status 只落成 root 的 data-status,皮肤据它给图标区上语气色。\n *\n * root 上不写 role:整页结果随页面一起呈现,就地换出来的结果用 `<xh-empty-state>` 或 `<xh-alert>`。\n *\n * @customElement xh-result\n * @attr {'404'|'403'|'500'|'success'|'warning'|'error'|'info'} status - 结果类型,写到 root 的 data-status 上\n * @attr {'sm'|'md'|'lg'} size - 尺寸档位,写到 root 的 data-size 上\n * @csspart root - 承载 data-status 与 data-size 的容器\n * @csspart icon - 装饰图标位,对读屏隐藏,颜色随 status 走\n * @csspart title - 结果标题\n * @csspart description - 标题下的说明\n * @csspart action - 操作按钮槽\n */\nexport class XhResultElement extends XhElement {\n static override partContract = { anatomy: resultAnatomy, meta: resultMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n status: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare status?: ResultStatus\n declare size?: 'sm' | 'md' | 'lg'\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const props: ResultProps = { status: this.status, size: this.size }\n const api = connectResult(props, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('icon', api.getIconProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('action', api.getActionProps() as Record<string, unknown>)\n }\n}\n","import type { ScrollAreaOrientation, ScrollAreaSchema, ScrollAreaScrollbarProps, ScrollAreaType } from '@xihan-ui/headless'\nimport type { Direction, IdGenerator, Orientation } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectScrollArea, scrollAreaAnatomy, scrollAreaMachine, scrollAreaMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-scroll-area>` —— Light-DOM 行为宿主:作者写 root/viewport/content/scrollbar/thumb/corner\n * 角色节点,元素跑 scroll-area 机器并把 connect 产出打上去。\n *\n * 滚动本身一概不接管:viewport 是真正 overflow:auto 的那层,键盘(PageUp/PageDown、方向键、\n * Home/End)与滚轮全部走浏览器原生通路,元素只是把原生滚动条藏起来另画一套。\n * 自绘的 scrollbar/thumb 对读屏隐藏——同一件事没必要报两遍。\n *\n * 滑块的位置与长度按视口/内容/滚动量算出来后写进内联样式:竖向是 inset-block-start + block-size,\n * 横向是 inset-inline-start + inline-size(逻辑属性,RTL 下自动换向)。\n * 尺寸在机器的效应里量:挂载后推迟一拍量一次,此后跟着 scroll 事件与 ResizeObserver 走。\n *\n * 每条滚动条用 orientation 属性写明自己管哪条轴(不写即 vertical),\n * 滑块按所在滚动条的轴向取几何,不必另写。\n *\n * @customElement xh-scroll-area\n * @attr {'auto'|'always'|'scroll'|'hover'} type - 滚动条露面的时机,默认 hover\n * @attr {number} scroll-hide-delay - 收起前的等待毫秒(type 为 scroll / hover 时生效),默认 600\n * @attr {'horizontal'|'vertical'|'both'} orientation - 哪几条轴归本组件管,默认 both\n * @attr {'ltr'|'rtl'} dir - 排版方向,只改写横轴的滚动量正负与指针位移方向\n * @csspart root - 组件根容器(承载 data-orientation / data-type / data-dragging),指针进出的判据挂在它身上\n * @csspart viewport - 真正 overflow:auto 的那层,带 tabindex=0 让键盘用户落得进来\n * @csspart content - 内容包裹层,横向溢出靠它撑出宽度,尺寸变化也观察它\n * @csspart scrollbar - 自绘滚动条轨道,须用 orientation 属性写明轴向;收起时带 hidden\n * @csspart thumb - 滑块,位置与长度由内联逻辑属性给出;按住可拖\n * @csspart corner - 两条滚动条同时在场时右下角那块补丁;只有一条时带 hidden\n */\nexport class XhScrollAreaElement extends XhElement {\n static override partContract = { anatomy: scrollAreaAnatomy, meta: scrollAreaMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n type: { converter: STRING_CONVERTER },\n scrollHideDelay: { converter: NUMBER_CONVERTER, attribute: 'scroll-hide-delay' },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n }\n\n declare type?: ScrollAreaType\n declare scrollHideDelay?: number\n declare orientation?: ScrollAreaOrientation\n declare direction?: Direction\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly scrollAreaScope = createScope(null, this.idGen)\n\n private readonly ctrl = new MachineController<ScrollAreaSchema>(\n this,\n scrollAreaMachine,\n () => this.machineProps(),\n { scope: this.scrollAreaScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<ScrollAreaSchema['props']> {\n return {\n type: this.type,\n scrollHideDelay: this.scrollHideDelay,\n orientation: this.orientation,\n dir: this.direction,\n }\n }\n\n /**\n * 这条滚动条管哪条轴。作者在节点上写 orientation=\"horizontal\",与 Vue 侧的同名 prop\n * 是同一份声明;没写或写不出来即竖向(两个适配器同一个缺省)。\n */\n private barOrientation(el: HTMLElement): Orientation {\n return el.getAttribute('orientation') === 'horizontal' ? 'horizontal' : 'vertical'\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 三个 getter 都懒读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n // 滚动条按轴现查而不是缓存:作者随时可能增删一条轴的滚动条\n private injectRefs(svc: Service<ScrollAreaSchema>): void {\n svc.refs.set('getViewportEl', () => this.getPart('viewport'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n svc.refs.set('getScrollbarEl', (axis: Orientation) =>\n this.getParts('scrollbar').find(el => this.barOrientation(el) === axis) ?? null)\n }\n\n // 滑块住在滚动条里:getParts 收的是整个元素范围,按子树过滤才归得对轴。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectScrollArea(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('viewport', api.getViewportProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('corner', api.getCornerProps() as Record<string, unknown>)\n\n // 滚动条是多实例 part,逐个打:轴向取作者写的 orientation,几何按轴取\n for (const el of this.getParts('scrollbar')) {\n const bar: ScrollAreaScrollbarProps = { orientation: this.barOrientation(el) }\n this.spreader.spread(el, api.getScrollbarProps(bar) as Record<string, unknown>)\n // 滑块的 style 是对象(两条轴的键每帧写全),spreader 见对象 style 会逐条写内联样式\n for (const thumb of this.partsIn(el, 'thumb'))\n this.spreader.spread(thumb, api.getThumbProps(bar) as Record<string, unknown>)\n // Light DOM 常驻,WC 自管可见性:作者层若给这个 part 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来。\n // 本包的样式自带 [hidden]{display:none} 压得住,但宿主不能指望作者装了这份样式\n this.setPartHidden(el, !(bar.orientation === 'vertical' ? api.vertical : api.horizontal).visible)\n }\n\n this.setPartHidden(this.getPart('corner'), !api.cornerVisible)\n }\n}\n","import type { SelectItemProps, SelectNode, SelectOpenChangeDetails, SelectSchema, SelectValueChangeDetails } from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectSelect, selectAnatomy, selectMachine, selectMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-select>` —— Light-DOM 行为宿主:用户写 root/trigger/value-text/positioner/content/item/...\n * 角色节点,元素跑 select 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 trigger、被定位的浮层取 positioner。\n * 条目身份取用户写在 item 上的 value 属性,禁用由部件自报(aria-disabled)。\n *\n * value-text 的显示文字与表单影子 hidden-select 的选项由元素代填,作者只需给出空节点;\n * value-text 里作者写了内容就归作者,元素不再改写。\n *\n * @customElement xh-select\n * @attr {string} value - 受控选中值;缺省该属性即非受控。多选集合请写 property,属性只递得进单值\n * @attr {string} default-value - 非受控初始选中值。多选集合请写 property,属性只递得进单值\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,表单影子不参与提交\n * @attr {boolean} required - 原生表单校验:无选中值时提交被拦下;多选下的门槛是至少选中一项\n * @attr {string} name - 表单字段名;给定后表单影子才带 name 并参与提交\n * @attr {string} placeholder - 无选中时 value-text 显示的占位文字\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} loop - 方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {boolean} multiple - 多选:点中即在集合里增删该项,列表不收起;存在即开,关掉要摘属性(不同于 loop,写 multiple=\"false\" 仍是开)\n * @attr {'ltr'|'rtl'} dir - 文字方向,默认 ltr\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 选中值变化;detail 为 `{ value: string[] }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled,也是表单影子的定位基准)\n * @csspart label - 组标题(aria-labelledby 目标)\n * @csspart trigger - 触发按钮(aria-haspopup=listbox/aria-expanded/aria-controls 所在),同时是定位锚点,须是原生 button\n * @csspart value-text - 选中项文本的显示位;留空即由元素填入 displayText,作者写了内容则归作者\n * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - role=listbox 容器(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden\n * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart item-text - 条目文本(连打检索与 value-text 的取字处)\n * @csspart item-indicator - 条目选中标记(aria-hidden)\n * @csspart hidden-select - 表单影子,须是原生 select 空壳;选项由元素按当前值补齐(多选时开原生 multiple),省略该节点即不参与表单\n */\nexport class XhSelectElement extends XhElement {\n static override partContract = { anatomy: selectAnatomy, meta: selectMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n disabled: { type: Boolean },\n required: { type: Boolean },\n name: { converter: STRING_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n multiple: { type: Boolean },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n // 属性只递得进单值,多选集合走 property\n declare collection?: SelectNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare open?: boolean\n declare defaultOpen?: boolean\n declare disabled?: boolean\n declare required?: boolean\n declare name?: string\n declare placeholder?: string\n declare placement?: Placement\n declare offset?: number\n declare loop?: boolean\n declare multiple?: boolean\n declare direction?: Direction\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly selectScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n /** value-text 是否归元素填:首次见到该节点时定,之后不再回读(回读到的会是自己写的字)。 */\n private readonly ownsValueText = new WeakMap<HTMLElement, boolean>()\n /** 表单影子当前这批选项对应的值与文字,同一份不重建。 */\n private readonly hiddenOptionKey = new WeakMap<HTMLElement, string>()\n\n private readonly notifyValue = (details: SelectValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: SelectOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<SelectSchema>(\n this,\n selectMachine,\n () => this.machineProps(),\n { scope: this.selectScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<SelectSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue ?? null,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n disabled: this.disabled ?? false,\n required: this.required ?? false,\n name: this.name,\n placeholder: this.placeholder,\n placement: this.placement,\n offset: this.offset,\n loop: this.loop,\n multiple: this.multiple ?? false,\n dir: this.direction,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.selectScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 列表不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<SelectSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 提前发现一次角色节点:机器在 hostConnected 当场要按当前值去 content 里现查显示文本,\n * default-open 时还要同场挑出高亮锚点。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时上报 ITEM.LOST,让机器按当前数据重挑高亮锚点。\n * 判据是「焦点已不在列表内」且离场的正是持有锚点的那个条目。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, scope, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n // 收起态无高亮锚点\n const highlighted = context.get('highlightedValue')\n if (highlighted == null)\n return\n const content = this.getPart('content')\n const active = scope.getActiveElement()\n if (content && active && content.contains(active))\n return\n // data-value 只写在 item 上,item-text / item-indicator 离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === highlighted))\n send({ type: 'ITEM.LOST' })\n }\n\n // 取 item 子树内指定名字的角色节点。\n private partsIn(item: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => item.contains(el))\n }\n\n /** 填入选中项显示文字;首次见到该节点时若已有内容则归作者,之后不再改写。 */\n private fillValueText(el: HTMLElement, text: string): void {\n let owned = this.ownsValueText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsValueText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n /**\n * 给表单影子补齐选项:空串选项是无选中时的落点,每个选中值一个 selected 选项。\n * 必须晚于属性写入:multiple 还没落到元素上时,单选 select 每收下一个 selected 选项\n * 就会跑一次原生「ask for a reset」,把前面的选中全撤掉。\n */\n private syncHiddenOptions(el: HTMLElement, values: string[], texts: string[], multiple: boolean): void {\n // 键要能无歧义还原这一批选项:值里带分隔符时拼接式键会碰撞,选项就不会重建。\n // multiple 也算进键里,否则运行期翻转多选而值不变时选项不重建,选中态会停在旧模式上。\n const key = JSON.stringify([values, texts, multiple])\n if (this.hiddenOptionKey.get(el) === key)\n return\n this.hiddenOptionKey.set(el, key)\n el.textContent = ''\n const blank = this.ownerDocument.createElement('option')\n blank.value = ''\n el.appendChild(blank)\n // 选中态一律靠选项的 selected 表达,多选下 select.value 表达不了集合\n for (const [i, v] of values.entries()) {\n const option = this.ownerDocument.createElement('option')\n option.value = v\n option.textContent = texts[i] ?? v\n option.selected = true\n el.appendChild(option)\n }\n }\n\n protected wire(): void {\n const api = connectSelect(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('indicator', api.getIndicatorProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 属性先落,再填显示文字\n const valueText = this.getPart('value-text')\n if (valueText) {\n this.spreader.spread(valueText, api.getValueTextProps() as Record<string, unknown>)\n this.fillValueText(valueText, api.displayText)\n }\n\n // 表单影子可缺省\n const hiddenSelect = this.getPart('hidden-select')\n if (hiddenSelect) {\n this.spreader.spread(hiddenSelect, api.getHiddenSelectProps() as Record<string, unknown>)\n this.syncHiddenOptions(hiddenSelect, api.value, api.valueText, api.multiple)\n }\n\n // 条目逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供方向键与连打检索现查。\n for (const el of this.getParts('item')) {\n const item: SelectItemProps = {\n value: el.getAttribute('value') ?? '',\n disabled: this.collection ? this.declaredDisabled(el) : isItemDisabled(el),\n }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n // 条目内的文本与选中标记跟着同一份声明走\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const indicator of this.partsIn(el, 'item-indicator'))\n this.spreader.spread(indicator, api.getItemIndicatorProps(item) as Record<string, unknown>)\n }\n\n // content 常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { SeparatorProps } from '@xihan-ui/headless'\nimport { connectSeparator, separatorAnatomy, separatorMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n/**\n * `<xh-separator>` —— Light-DOM 行为宿主,无状态机,把 connectSeparator 产出打到 root 角色节点。\n *\n * @customElement xh-separator\n * @attr {'horizontal'|'vertical'} orientation - 朝向,默认 horizontal\n * @attr {boolean} decorative - 装饰性分隔,仅视觉分组(role=none,退出无障碍树)\n * @csspart root - 承载 role/aria-orientation/data-orientation 的分隔节点\n */\nexport class XhSeparatorElement extends XhElement {\n static override partContract = { anatomy: separatorAnatomy, meta: separatorMeta }\n\n // 属性缺席翻成 undefined,缺省值由 connect 决定\n static override properties = {\n orientation: { converter: { fromAttribute: (v: string | null) => v ?? undefined } },\n decorative: { type: Boolean },\n }\n\n declare orientation?: string\n declare decorative?: boolean\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectSeparator({\n orientation: this.orientation as SeparatorProps['orientation'],\n decorative: this.decorative ?? false,\n }, wcNormalize)\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { SkeletonProps, SkeletonVariant } from '@xihan-ui/headless'\nimport { connectSkeleton, skeletonAnatomy, skeletonMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 允许的形状名,作者写错时落回容器的默认值。 */\nconst VARIANTS: readonly string[] = ['text', 'circle', 'rect']\n\n/** 读单根骨架条自报的形状。 */\nfunction boneVariant(el: HTMLElement): SkeletonVariant | undefined {\n const raw = el.getAttribute('variant')\n return raw != null && VARIANTS.includes(raw) ? raw as SkeletonVariant : undefined\n}\n\n/**\n * `<xh-skeleton>` —— 骨架屏宿主,无状态机,把 connectSkeleton 产出的属性打到角色节点上。\n *\n * 骨架条自报形状:在 bone 节点上写 `variant`。运行期改写这个属性不触发重新接线,\n * 需作者自行 requestUpdate。\n *\n * @customElement xh-skeleton\n * @attr {boolean} loading - 是否还在加载,写 \"false\" 结束加载态\n * @attr {'text'|'circle'|'rect'} variant - 容器内骨架条的默认形状\n * @csspart root - 骨架容器,加载期间带 aria-busy,结束后带 hidden\n * @csspart bone - 单根骨架条,加载期间带 aria-hidden,不进无障碍树\n */\nexport class XhSkeletonElement extends XhElement {\n static override partContract = { anatomy: skeletonAnatomy, meta: skeletonMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n loading: { converter: BOOLEAN_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n }\n\n declare loading?: boolean\n declare variant?: SkeletonVariant\n\n protected wire(): void {\n const props: SkeletonProps = { loading: this.loading, variant: this.variant }\n const api = connectSkeleton(props, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 多实例 part 逐个打,形状取该节点自报的 variant\n for (const el of this.getParts('bone'))\n this.spreader.spread(el, api.getBoneProps({ variant: boneVariant(el) }) as Record<string, unknown>)\n }\n}\n","import type { SliderSchema, SliderValueChangeDetails, SliderValueChangeEndDetails, SliderValueTextDetails } from '@xihan-ui/headless'\nimport type { Direction, IdGenerator, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectSlider, sliderAnatomy, sliderMachine, sliderMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定;Lit 自带转换器会落成 null / false,\n// 那样就表达不了\"未指定\"(value 尤其:落成 null 分不出\"非受控\"与\"受控且当前为空\")。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n/**\n * 值恒是数组,属性写成逗号分隔(单滑块 value=\"30\",双滑块 value=\"20,80\")。\n * 解析不出任何有限数就当没写:留下 NaN 会一路写进 aria-valuenow 与定位百分比。\n */\nconst NUMBER_LIST_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v == null || v.trim() === '')\n return undefined\n const out = v.split(',').map(Number).filter(Number.isFinite)\n return out.length ? out : undefined\n },\n}\n\n/**\n * `<xh-slider>` —— Light-DOM 行为宿主:作者写 root/label/control/track/range/thumb\n * 与拇指内的 hidden-input 角色节点,元素跑 slider 机器并把 connect 产出打上去。\n *\n * 键盘全在拇指上(方向键步进、PageUp/PageDown 大步进、Home/End 取端点),\n * 指针拖动挂在 control 上(拇指常浮出轨道,只挂 track 会抓不住拇指本身),\n * 值与坐标的换算取 track 的矩形——矩形在事件发生的那一刻才量,连接期一律不碰 DOM。\n *\n * 多滑块时每个拇指要用 index 属性写明自己是第几个(`index=\"1\"`),\n * 拇指内的 hidden-input 按所在拇指的下标取值,不必另写。\n *\n * @customElement xh-slider\n * @attr {string} value - 受控值,逗号分隔(如 \"20,80\");缺省该属性即非受控\n * @attr {string} default-value - 非受控初值,同样逗号分隔;缺省时是单滑块停在 min\n * @attr {number} min - 下界,默认 0\n * @attr {number} max - 上界,默认 100\n * @attr {number} step - 方向键与吸附网格的步长,默认 1\n * @attr {number} large-step - PageUp/PageDown 的步长,默认 10 倍 step\n * @attr {number} min-steps-between-thumbs - 相邻滑块至少隔几格,默认 0\n * @attr {'horizontal'|'vertical'} orientation - 轨道朝向,默认 horizontal\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写水平轨道上左右两键与指针的语义,默认 ltr\n * @attr {boolean} disabled - 禁用:拇指退出 Tab 序列、推不动、不参与表单提交\n * @attr {boolean} read-only - 只读:仍可聚焦与被读屏念出,推不动\n * @attr {boolean} invalid - 校验失败标注\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @attr {string} name - 表单字段名;给了才参与提交,多滑块逐个同名 append\n * @fires value-change - 值变化(拖动途中会连发);detail 为 `{ value: number[] }`\n * @fires value-change-end - 一次操作收尾发一次;detail 为 `{ value: number[], index: number }`\n * @csspart root - 承载 data-orientation / data-disabled / data-readonly / data-invalid / data-dragging 的容器\n * @csspart label - 组标题(拇指的 aria-labelledby 目标)\n * @csspart control - 指针命中区,按下即跳到落点并接管拖动\n * @csspart track - 轨道本体,值与坐标的换算以它的矩形为准\n * @csspart range - 已选区间,起止由内联逻辑属性给出\n * @csspart thumb - role=slider 的拇指,键盘交互全在它身上;多滑块须写 index 属性\n * @csspart hidden-input - 拇指内的表单影子(须是原生 input)\n */\nexport class XhSliderElement extends XhElement {\n static override partContract = { anatomy: sliderAnatomy, meta: sliderMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: NUMBER_LIST_CONVERTER },\n defaultValue: { converter: NUMBER_LIST_CONVERTER, attribute: 'default-value' },\n min: { converter: NUMBER_CONVERTER },\n max: { converter: NUMBER_CONVERTER },\n step: { converter: NUMBER_CONVERTER },\n largeStep: { converter: NUMBER_CONVERTER, attribute: 'large-step' },\n minStepsBetweenThumbs: { converter: NUMBER_CONVERTER, attribute: 'min-steps-between-thumbs' },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n name: { converter: STRING_CONVERTER },\n // 格式化函数只能按 property 给(属性表达不了函数),与 Vue 的同名 prop 是同一件事\n getValueText: { attribute: false },\n }\n\n declare value?: number[]\n declare defaultValue?: number[]\n declare min?: number\n declare max?: number\n declare step?: number\n declare largeStep?: number\n declare minStepsBetweenThumbs?: number\n declare orientation?: Orientation\n declare direction?: Direction\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare tone?: Tone\n declare size?: Size\n declare name?: string\n declare getValueText?: (details: SliderValueTextDetails) => string\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly sliderScope = createScope(null, this.idGen)\n\n private readonly notifyValue = (details: SliderValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyValueEnd = (details: SliderValueChangeEndDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change-end', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<SliderSchema>(\n this,\n sliderMachine,\n () => this.machineProps(),\n { scope: this.sliderScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<SliderSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n min: this.min,\n max: this.max,\n step: this.step,\n largeStep: this.largeStep,\n minStepsBetweenThumbs: this.minStepsBetweenThumbs,\n orientation: this.orientation,\n dir: this.direction,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n tone: this.tone,\n size: this.size,\n name: this.name,\n getValueText: this.getValueText,\n onValueChange: this.notifyValue,\n onValueChangeEnd: this.notifyValueEnd,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 轨道懒读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n private injectRefs(svc: Service<SliderSchema>): void {\n svc.refs.set('getTrackEl', () => this.getPart('track'))\n }\n\n /**\n * 拇指自报的下标。多滑块时作者在节点上写 index=\"1\",与 Vue 侧的 `:index` 是同一份声明;\n * 写不出数字(没写、写错)时退回 0,单滑块因此不必写。\n */\n private thumbIndex(el: HTMLElement): number {\n const raw = Number(el.getAttribute('index'))\n return Number.isFinite(raw) ? raw : 0\n }\n\n // 拇指内的子部件:getParts 收的是整个元素范围,按拇指子树过滤才归得对下标。\n private partsIn(thumb: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => thumb.contains(el))\n }\n\n protected wire(): void {\n const api = connectSlider(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('track', api.getTrackProps() as Record<string, unknown>)\n put('range', api.getRangeProps() as Record<string, unknown>)\n\n for (const el of this.getParts('thumb')) {\n const index = this.thumbIndex(el)\n this.spreader.spread(el, api.getThumbProps(index) as Record<string, unknown>)\n for (const input of this.partsIn(el, 'hidden-input'))\n this.spreader.spread(input, api.getHiddenInputProps(index) as Record<string, unknown>)\n }\n }\n}\n","import type { SpinnerProps, SpinnerTranslations } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectSpinner, spinnerAnatomy, spinnerMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-spinner>` —— 加载指示器宿主,无状态机,把活区语义与可及名字打到角色节点上。\n * 转圈图形由皮肤画在 root 的伪元素上,元素不生成任何结构。\n *\n * @customElement xh-spinner\n * @attr {string} label - 可及名字;label 角色节点显示的应当是同一段文案\n * @attr {'sm'|'md'|'lg'} size - 直径档位,缺省 md\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @csspart root - role=status 的活区容器,承载 aria-live/aria-label/data-size/data-tone\n * @csspart label - 可见文案节点,可省\n */\nexport class XhSpinnerElement extends XhElement {\n static override partContract = { anatomy: spinnerAnatomy, meta: spinnerMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n label: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n // 文案是对象,只走 property\n translations: { attribute: false },\n }\n\n declare label?: string\n declare size?: Size\n declare tone?: Tone\n declare translations?: Partial<SpinnerTranslations>\n\n protected wire(): void {\n const props: SpinnerProps = {\n label: this.label,\n size: this.size,\n tone: this.tone,\n translations: this.translations,\n }\n const api = connectSpinner(props, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n }\n}\n","import type { SplitterPanelProps, SplitterSchema, SplitterSizeChangeDetails, SplitterSizeChangeEndDetails } from '@xihan-ui/headless'\nimport type { Direction, IdGenerator, Orientation } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectSplitter, splitterAnatomy, splitterMachine, splitterMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\n// (size 尤其:落成 null 就分不出\"非受控\"与\"受控且当前为空\")。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n/**\n * 布局是百分比数组,属性写成逗号分隔(两栏 size=\"30,70\")。\n * 解析不出任何有限数就当没写:留下 NaN 会一路写进 aria-valuenow 与定位百分比。\n */\nconst NUMBER_LIST_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v == null || v.trim() === '')\n return undefined\n const out = v.split(',').map(Number).filter(Number.isFinite)\n return out.length ? out : undefined\n },\n}\n/**\n * 面板约束写成 JSON 数组(`panels='[{\"id\":\"main\",\"min\":20}]'`)。\n * 解析不出数组就当没写——落一个半截对象进去会让面板块数与作者写的节点数对不上,\n * 那时错的是布局而不只是某一条约束,回到\"全都不设限\"反而更接近作者本意。\n */\nconst PANELS_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v == null || v.trim() === '')\n return undefined\n try {\n const parsed: unknown = JSON.parse(v)\n return Array.isArray(parsed) ? (parsed as SplitterPanelProps[]) : undefined\n }\n catch {\n return undefined\n }\n },\n}\n\n/**\n * `<xh-splitter>` —— Light-DOM 行为宿主:作者写 root/panel/resize-trigger 角色节点,\n * 元素跑 splitter 机器并把 connect 产出打上去。\n *\n * 面板尺寸是百分比,总和恒为 100;每块的尺寸由元素每帧写进内联样式(flex-basis),\n * 作者的样式表不要再碰这条轴。\n *\n * 拖拽挂在分隔条上(按下—跟手—松手),像素与百分比的换算取 root 的矩形——\n * 矩形在拖拽开始那一刻才量,连接期一律不碰 DOM。\n * 键盘全在分隔条上:方向键按 step 推、Shift+方向键按 largeStep 推、\n * Home/End 取该面板眼下能到的两端、Enter 折叠或展开可折叠的面板。\n *\n * 面板与分隔条都要用 index 属性写明自己是第几个(`index=\"1\"`);\n * 第 index 条分隔条坐在第 index 与第 index+1 块面板之间,调整的是前一块。\n *\n * @customElement xh-splitter\n * @attr {string} size - 受控布局,逗号分隔的百分比(如 \"30,70\");缺省该属性即非受控\n * @attr {string} default-size - 非受控初值,同样逗号分隔;缺省时按面板数等分\n * @attr {string} panels - 逐块约束的 JSON 数组:id / min / max / collapsible / collapsedSize\n * @attr {'horizontal'|'vertical'} orientation - 面板排布轴,默认 horizontal(并排)\n * @attr {'ltr'|'rtl'} dir - 文字方向,只对调水平排布下左右两键与指针位移的正负,默认 ltr\n * @attr {boolean} disabled - 禁用:分隔条退出 Tab 序列、拖不动也推不动\n * @attr {number} step - 方向键的步长(百分比),默认 1\n * @attr {number} large-step - Shift + 方向键的步长(百分比),默认 10\n * @fires size-change - 布局变化(拖动途中会连发);detail 为 `{ size: number[] }`\n * @fires size-change-end - 一次拖拽收尾发一次;detail 为 `{ size: number[], index: number }`\n * @csspart root - 承载 data-orientation / data-disabled / data-dragging 的容器,矩形以它为准\n * @csspart panel - 一块面板;尺寸由内联 flex-basis 给出,折叠时带 data-collapsed\n * @csspart resize-trigger - role=separator 的分隔条,指针与键盘交互全在它身上\n */\nexport class XhSplitterElement extends XhElement {\n static override partContract = { anatomy: splitterAnatomy, meta: splitterMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n size: { converter: NUMBER_LIST_CONVERTER },\n defaultSize: { converter: NUMBER_LIST_CONVERTER, attribute: 'default-size' },\n panels: { converter: PANELS_CONVERTER },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n disabled: { converter: BOOLEAN_CONVERTER },\n step: { converter: NUMBER_CONVERTER },\n largeStep: { converter: NUMBER_CONVERTER, attribute: 'large-step' },\n }\n\n declare size?: number[]\n declare defaultSize?: number[]\n declare panels?: SplitterPanelProps[]\n declare orientation?: Orientation\n declare direction?: Direction\n declare disabled?: boolean\n declare step?: number\n declare largeStep?: number\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly splitterScope = createScope(null, this.idGen)\n\n private readonly notifySize = (details: SplitterSizeChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('size-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySizeEnd = (details: SplitterSizeChangeEndDetails): void => {\n this.dispatchEvent(new CustomEvent('size-change-end', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<SplitterSchema>(\n this,\n splitterMachine,\n () => this.machineProps(),\n { scope: this.splitterScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<SplitterSchema['props']> {\n return {\n size: this.size,\n defaultSize: this.defaultSize,\n panels: this.panels,\n orientation: this.orientation,\n dir: this.direction,\n disabled: this.disabled ?? false,\n step: this.step,\n largeStep: this.largeStep,\n onSizeChange: this.notifySize,\n onSizeChangeEnd: this.notifySizeEnd,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 容器懒读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着。\n private injectRefs(svc: Service<SplitterSchema>): void {\n svc.refs.set('getRootEl', () => this.getPart('root'))\n }\n\n /**\n * 部件自报的下标。作者在节点上写 index=\"1\",与 Vue 侧的 `:index` 是同一份声明;\n * 写不出数字(没写、写错)时退回 0。\n */\n private partIndex(el: HTMLElement): number {\n const raw = Number(el.getAttribute('index'))\n return Number.isFinite(raw) ? raw : 0\n }\n\n protected wire(): void {\n const api = connectSplitter(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n for (const el of this.getParts('panel'))\n this.spreader.spread(el, api.getPanelProps(this.partIndex(el)) as Record<string, unknown>)\n\n for (const el of this.getParts('resize-trigger'))\n this.spreader.spread(el, api.getResizeTriggerProps(this.partIndex(el)) as Record<string, unknown>)\n }\n}\n","import type { StatisticProps } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectStatistic, statisticAnatomy, statisticMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-statistic>` —— Light-DOM 行为宿主,无状态机,把 connectStatistic 产出打到各角色节点。\n *\n * 除 root 外的部件全部可缺省:只摆一个数值也是一块合法的统计。\n * 数值由作者格式化好再塞进 value 槽,组件不做千分位、不做单位换算、不做动画。\n *\n * root 上不写 role:一块统计数是不是列表项、要不要可及名字,由它被摆在哪里决定。\n *\n * @customElement xh-statistic\n * @attr {'sm'|'md'|'lg'} size - 尺寸档位,写到 root 的 data-size 上\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,写到 root 的 data-tone 上\n * @csspart root - 承载 data-size 与 data-tone 的容器\n * @csspart label - 数值上方的标签\n * @csspart value - 数值本体,用等宽数字排版\n * @csspart prefix - 数值前的货币符号或升降箭头\n * @csspart suffix - 数值后的单位或百分号\n */\nexport class XhStatisticElement extends XhElement {\n static override partContract = { anatomy: statisticAnatomy, meta: statisticMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n size: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n }\n\n declare size?: Size\n declare tone?: Tone\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const props: StatisticProps = { size: this.size, tone: this.tone }\n const api = connectStatistic(props, wcNormalize)\n\n const put = (name: string, attrs: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, attrs)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('value', api.getValueProps() as Record<string, unknown>)\n put('prefix', api.getPrefixProps() as Record<string, unknown>)\n put('suffix', api.getSuffixProps() as Record<string, unknown>)\n }\n}\n","import type { StepsItemProps, StepsSchema, StepsStepChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectSteps, stepsAnatomy, stepsMachine, stepsMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 数值属性统一走这个转换器:属性缺席即 undefined,缺省值的唯一事实源留在 connect。\n// 空串也当缺席:`step=\"\"` 经 Number() 会变成 0,那是一个真实存在的步序,不该由笔误产生。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:属性缺席 = undefined(用默认值),=\"false\" = false,其余 = true。\n// Lit 自带的 Boolean 转换器判的是 v !== null,写 =\"false\" 反而成了真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n\n/** 角色节点自报的步序;缺失或空串一律给 NaN(与任何一步都不相等,绝不冒充当前步)。 */\nfunction stepIndexOf(el: HTMLElement): number {\n const raw = el.getAttribute('value')\n return raw == null || raw === '' ? Number.NaN : Number(raw)\n}\n\n/**\n * `<xh-steps>` —— Light-DOM 行为宿主:作者写\n * root/list/item/trigger/indicator/title/description/separator/content 角色节点,\n * 元素跑 steps 机器并把 connect 产出打上去。\n *\n * 身份写在 item 节点的 `value` 属性上(第几步,0 起),\n * trigger / indicator / title / description / separator 向上找自己的 item,不必各写一遍。\n * content 挂在 list 之外、够不到 item,因此自带 `value` 与 trigger 配对(与 `<xh-tabs>` 同一套写法)。\n *\n * 步序序列由作者渲染,元素不替作者生成节点:生成节点就等于收走模板控制权,\n * 图标、自定义序号、i18n 文案都再塞不进来。\n *\n * @customElement xh-steps\n * @attr {number} step - 受控步序(0 起);缺省该属性即非受控\n * @attr {number} default-step - 非受控初始步序,默认 0\n * @attr {number} count - 总步数;步序上界取它(等于它即\"全部完成\")\n * @attr {'horizontal'|'vertical'} orientation - 方向键轴向,默认 horizontal\n * @attr {boolean} linear - 线性模式:跳不到还没走到的步(那些 trigger 一律禁用)\n * @attr {boolean} disabled - 整组不可交互,连 Tab 停靠点都不留\n * @attr {'ltr'|'rtl'} dir - 文字方向,只影响水平轴上 ArrowLeft/ArrowRight 的前后语义,默认 ltr\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires step-change - 步序变化;detail 为 `{ step: number }`\n * @csspart root - 组件根容器(承载 data-orientation / data-complete / data-empty)\n * @csspart list - role=tablist 容器(方向键与 Tab 序列在此收口)\n * @csspart item - 单个步骤容器;作者在此写 value(身份)与可选 disabled\n * @csspart trigger - role=tab 的步骤按钮(roving tabindex 落在它身上)\n * @csspart indicator - 序号/对勾圆点,对读屏隐藏\n * @csspart title - 步骤标题\n * @csspart description - 步骤说明\n * @csspart separator - 指向下一步的连接线,对读屏隐藏\n * @csspart content - role=tabpanel 的面板,须自带 value 与 trigger 配对;非当前步带 hidden\n */\nexport class XhStepsElement extends XhElement {\n static override partContract = { anatomy: stepsAnatomy, meta: stepsMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名响应式字段会与基类类型打架。属性仍进 observedAttributes,改 dir 照样触发重算。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n step: { converter: NUMBER_CONVERTER },\n defaultStep: { converter: NUMBER_CONVERTER, attribute: 'default-step' },\n count: { converter: NUMBER_CONVERTER },\n orientation: { converter: STRING_CONVERTER },\n linear: { converter: BOOLEAN_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare step?: number\n declare defaultStep?: number\n declare count?: number\n declare orientation?: Orientation\n declare linear?: boolean\n declare disabled?: boolean\n declare direction?: Direction\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: StepsStepChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('step-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // steps 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<StepsSchema>(this, stepsMachine, () => this.machineProps())\n\n private machineProps(): Partial<StepsSchema['props']> {\n return {\n step: this.step,\n defaultStep: this.defaultStep,\n count: this.count,\n orientation: this.orientation,\n // 布尔属性缺席即 undefined,把缺省交回 connect\n linear: this.linear,\n disabled: this.disabled,\n dir: this.direction,\n tone: this.tone,\n size: this.size,\n onStepChange: this.notify,\n }\n }\n\n /**\n * 取角色节点所属步骤的身份:value 与 disabled 都写在 item 节点上,\n * trigger/indicator/title/description/separator 向上找自己的 item(item 自身 closest 命中的就是它自己)。\n * 没有 item 包裹层时退回读节点自身,扁平结构也能用。\n * 越出本宿主的 item 不算数——嵌套步骤条的内层节点不会认外层条目。\n */\n private itemProps(el: HTMLElement): StepsItemProps {\n const owner = el.closest<HTMLElement>(ITEM_SELECTOR)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n return { index: stepIndexOf(source), disabled: isItemDisabled(source) }\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的下标上:\n * 容器判自己\"焦点在组内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整组零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedStep = context.get('focusedStep')\n if (focusedStep == null)\n return\n // data-value 由连接层写在 trigger 与 item 上,面板离场不会误判;\n // 只有持有焦点的那一步走了才报\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === String(focusedStep)))\n send({ type: 'LIST.BLUR' })\n }\n\n protected wire(): void {\n const api = connectSteps(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('list', api.getListProps() as Record<string, unknown>)\n\n // 集合类 part 逐个 spread:身份由节点自报,不依赖下标,条目增删无需记账。\n // wire 跑在事件之前(element-base 的 updated),因此按键那一刻 data-scope/data-part/data-value\n // 已经在 DOM 上,导航原语查得到本台步骤条的 trigger 集合。\n const putAll = (name: string, get: (item: StepsItemProps) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(this.itemProps(el)) as Record<string, unknown>)\n }\n putAll('item', item => api.getItemProps(item))\n putAll('trigger', item => api.getTriggerProps(item))\n putAll('indicator', item => api.getIndicatorProps(item))\n putAll('title', item => api.getTitleProps(item))\n putAll('description', item => api.getDescriptionProps(item))\n putAll('separator', item => api.getSeparatorProps(item))\n\n // 面板身份取自己写的 value,不向上找 item:它本来就挂在 list 之外。\n // 收起靠连接层给的 hidden,再用内联 display 兜一道——作者层任何一条 display\n // 都会盖过 UA 的 [hidden]{display:none},而宿主不能指望作者装的正是随包那份样式。\n for (const el of this.getParts('content')) {\n const index = stepIndexOf(el)\n this.spreader.spread(el, api.getContentProps({ index }) as Record<string, unknown>)\n this.setPartHidden(el, index !== api.step)\n }\n }\n}\n","import type { SwitchCheckedChangeDetails, SwitchSchema } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectSwitch, switchAnatomy, switchMachine, switchMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-switch>` —— Light-DOM 行为宿主,跑 switch 机器并把 connect 产出打到 root/thumb 角色节点。\n *\n * @customElement xh-switch\n * @attr {boolean} checked - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-checked - 非受控初始为选中\n * @attr {boolean} disabled - 禁用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires checked-change - checked 状态变化;detail 为 `{ checked: boolean }`\n * @csspart root - role=switch 的按钮(承载 aria-checked / data-state)\n * @csspart thumb - 滑块\n */\nexport class XhSwitchElement extends XhElement {\n static override partContract = { anatomy: switchAnatomy, meta: switchMeta }\n\n static override properties = {\n checked: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n defaultChecked: { type: Boolean, attribute: 'default-checked' },\n disabled: { type: Boolean },\n tone: {},\n size: {},\n }\n\n declare checked?: boolean\n declare defaultChecked?: boolean\n declare disabled?: boolean\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: SwitchCheckedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('checked-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<SwitchSchema>(this, switchMachine, () => this.machineProps())\n\n private machineProps(): Partial<SwitchSchema['props']> {\n return {\n checked: this.checked,\n defaultChecked: this.defaultChecked ?? false,\n disabled: this.disabled ?? false,\n tone: this.tone,\n size: this.size,\n onCheckedChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectSwitch(this.ctrl.service, wcNormalize)\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n const thumb = this.getPart('thumb')\n if (thumb)\n this.spreader.spread(thumb, api.getThumbProps() as Record<string, unknown>)\n }\n}\n","import type {\n TableColumnDef,\n TableColumnProps,\n TableExpandedChangeDetails,\n TableRowDef,\n TableRowProps,\n TableSchema,\n TableSelection,\n TableSelectionChangeDetails,\n TableSelectionMode,\n TableSortChangeDetails,\n TableSortDescriptor,\n} from '@xihan-ui/headless'\nimport type { Direction, Size } from '@xihan-ui/kernel'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTable, tableAnatomy, tableMachine, tableMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 行系部件的归属容器:行内的把手与单元格向上找最近的那一行。 */\nconst ROW_SELECTOR = '[data-xh-part=\"row\"]'\n/** 列系部件的归属容器:排序把手向上找最近的那个列标题。 */\nconst COLUMN_HEADER_SELECTOR = '[data-xh-part=\"column-header\"]'\nconst HEADER_SELECTOR = '[data-xh-part=\"header\"]'\nconst FOOTER_SELECTOR = '[data-xh-part=\"footer\"]'\n\n/**\n * `<xh-table>` —— Light-DOM 行为宿主:作者写 root/caption/header/body/footer 与若干\n * row / column-header / cell 角色节点,元素跑 table 机器并把 connect 产出打上去。\n * 身份取自节点上的 value 属性:行系部件上是行 id,列系部件上是列 id。\n *\n * 行号(aria-rowindex / aria-rowcount)与列号(aria-colindex / aria-colcount)查 `rows` 与\n * `columns` 两份定义,不从 DOM 反推,故两份定义必须与标记同源。\n *\n * 同一个 row 部件写在 header / body / footer 里语义不同(表头行、数据行、脚注行),\n * 元素按祖先链现查区段,作者无需换用别的部件名。\n *\n * 两份定义与三个集合都是数组/对象,只走 property(`el.rows = [...]`)。\n *\n * @customElement xh-table\n * @attr {'none'|'single'|'multiple'} selection-mode - 选择模式,默认 none(不声明就没有选择这回事)\n * @attr {boolean} loading - 数据在路上:root 报 aria-busy,表体为空时加载态节点显形\n * @attr {boolean} empty - 显式声明表体为空;缺省按 rows 是否为空推导,写 empty=\"false\" 强制不空\n * @attr {boolean} sticky-header - 表头吸顶,只落 data-sticky,钉住的实现归皮肤\n * @attr {boolean} footer - 表格带脚注行:行号空间的最后一行留给它,aria-rowcount 也算上\n * @attr {boolean} loop - 上下键走到首尾回绕,默认关;写 loop=\"true\" 打开\n * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的展开/收起语义,默认 ltr\n * @attr {'sm'|'md'|'lg'} size - 密度:只换单元格的纵向内边距与字号,列宽不受影响\n * @fires sort-change - 排序链变化;detail 为 `{ value: { id, direction }[] }`\n * @fires selection-change - 选中集合变化;detail 为 `{ value: string[] | 'all' }`\n * @fires expanded-change - 展开集合变化;detail 为 `{ value: string[] }`\n * @csspart root - role=grid 容器(rows 里有可展开的行时为 treegrid),报行列总数与多选声明\n * @csspart caption - 表格标题(aria-labelledby 目标)\n * @csspart header - role=rowgroup 表头区\n * @csspart body - role=rowgroup 表体区,键盘在此收口,也是行级 roving 的兜底 Tab 位\n * @csspart footer - role=rowgroup 脚注区\n * @csspart row - role=row;写在 body 里的须自带 value 属性标识行身份\n * @csspart column-header - role=columnheader,须自带 value 属性标识列身份;承载 aria-sort\n * @csspart cell - role=gridcell,须自带 value 属性标识列身份;可写 colspan 属性声明跨列数\n * @csspart select-all-trigger - 全选把手,三态(aria-checked 半选为 mixed),自占一个 Tab 位\n * @csspart row-select-trigger - 行选择把手(aria-hidden 且不占 Tab 位,键盘那一路由 Space 承担)\n * @csspart sort-trigger - 排序把手,自占一个 Tab 位;按住 Shift 点是追加到排序链\n * @csspart expand-trigger - 展开把手(aria-hidden 且不占 Tab 位,键盘那一路由左右方向键承担)\n * @csspart expanded-row - role=row 详情行,须自带 value 属性与它所属的数据行配对,内部须放一个 cell 承载详情;收起时 hidden\n * @csspart empty-state - 空态节点,表体为空且不在加载时显形\n * @csspart loading-state - 加载态节点,表体为空且正在加载时显形\n */\nexport class XhTableElement extends XhElement {\n static override partContract = { anatomy: tableAnatomy, meta: tableMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n columns: { attribute: false },\n rows: { attribute: false },\n sort: { attribute: false },\n defaultSort: { attribute: false },\n selection: { attribute: false },\n defaultSelection: { attribute: false },\n expanded: { attribute: false },\n defaultExpanded: { attribute: false },\n selectionMode: { converter: STRING_CONVERTER, attribute: 'selection-mode' },\n loading: { type: Boolean },\n empty: { converter: BOOLEAN_CONVERTER },\n stickyHeader: { type: Boolean, attribute: 'sticky-header' },\n footer: { type: Boolean },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n size: { converter: STRING_CONVERTER },\n }\n\n declare columns?: TableColumnDef[]\n declare rows?: TableRowDef[]\n declare sort?: TableSortDescriptor[]\n declare defaultSort?: TableSortDescriptor[]\n declare selection?: TableSelection\n declare defaultSelection?: TableSelection\n declare expanded?: string[]\n declare defaultExpanded?: string[]\n declare selectionMode?: TableSelectionMode\n declare loading?: boolean\n declare empty?: boolean\n declare stickyHeader?: boolean\n declare footer?: boolean\n declare loop?: boolean\n declare direction?: Direction\n declare size?: Size\n\n private readonly notifySort = (details: TableSortChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('sort-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelection = (details: TableSelectionChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('selection-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyExpanded = (details: TableExpandedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('expanded-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // table 机器无副作用,controller 只带 props。\n private readonly ctrl = new MachineController<TableSchema>(this, tableMachine, () => this.machineProps())\n\n private machineProps(): Partial<TableSchema['props']> {\n return {\n columns: this.columns,\n rows: this.rows,\n sort: this.sort,\n // 不补 [],缺省由机器兜\n defaultSort: this.defaultSort,\n selection: this.selection,\n defaultSelection: this.defaultSelection,\n expanded: this.expanded,\n defaultExpanded: this.defaultExpanded,\n selectionMode: this.selectionMode,\n loading: this.loading ?? false,\n empty: this.empty,\n stickyHeader: this.stickyHeader ?? false,\n footer: this.footer ?? false,\n loop: this.loop,\n dir: this.direction,\n size: this.size,\n onSortChange: this.notifySort,\n onSelectionChange: this.notifySelection,\n onExpandedChange: this.notifyExpanded,\n }\n }\n\n /** 承载焦点的行被移出 DOM 时上报 TABLE.BLUR,让机器重挑焦点锚点。 */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n const focusedRow = context.get('focusedRow')\n if (focusedRow == null)\n return\n // data-value 只写在数据行与列头上,且只有持有锚点的那一行离场才报\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedRow))\n send({ type: 'TABLE.BLUR' })\n }\n\n /**\n * 取角色节点自报的身份:行系部件上是行 id,列系部件上是列 id。\n * 行内的把手与装饰节点向上找本宿主内最近的容器,没有则读节点自身。\n */\n private identityOf(el: HTMLElement, selector: string): string {\n const owner = el.closest<HTMLElement>(selector)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n return source.getAttribute('value') ?? ''\n }\n\n private rowOf(el: HTMLElement): TableRowProps {\n return { value: this.identityOf(el, ROW_SELECTOR) }\n }\n\n private columnOf(el: HTMLElement): TableColumnProps {\n return { value: this.identityOf(el, COLUMN_HEADER_SELECTOR) }\n }\n\n /** 按祖先链现查行所在的区段。 */\n private sectionOf(el: HTMLElement): 'header' | 'body' | 'footer' {\n const header = el.closest<HTMLElement>(HEADER_SELECTOR)\n if (header && this.contains(header))\n return 'header'\n const footer = el.closest<HTMLElement>(FOOTER_SELECTOR)\n if (footer && this.contains(footer))\n return 'footer'\n return 'body'\n }\n\n protected wire(): void {\n const api = connectTable(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('caption', api.getCaptionProps() as Record<string, unknown>)\n put('header', api.getHeaderProps() as Record<string, unknown>)\n put('body', api.getBodyProps() as Record<string, unknown>)\n put('footer', api.getFooterProps() as Record<string, unknown>)\n // 两个状态节点的显隐直接读连接层给的 hidden\n const emptyProps = api.getEmptyStateProps() as Record<string, unknown>\n const loadingProps = api.getLoadingStateProps() as Record<string, unknown>\n put('empty-state', emptyProps)\n put('loading-state', loadingProps)\n\n // 集合类 part 逐个 spread,身份由节点自报,不依赖下标。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供连接层现查。\n const putAll = (name: string, get: (el: HTMLElement) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(el) as Record<string, unknown>)\n }\n putAll('row', (el) => {\n const section = this.sectionOf(el)\n if (section === 'header')\n return api.getHeaderRowProps()\n if (section === 'footer')\n return api.getFooterRowProps()\n return api.getRowProps(this.rowOf(el))\n })\n putAll('column-header', el => api.getColumnHeaderProps(this.columnOf(el)))\n // 单元格自报列身份,行身份跟着所在行走;表头与脚注的格子没有行可跟\n putAll('cell', (el) => {\n const row = el.closest<HTMLElement>(ROW_SELECTOR)\n const inBody = !!row && this.contains(row) && this.sectionOf(el) === 'body'\n const colspan = el.getAttribute('colspan')\n return api.getCellProps({\n value: el.getAttribute('value') ?? '',\n row: inBody ? (row.getAttribute('value') ?? '') : undefined,\n colSpan: colspan == null ? undefined : Number(colspan),\n })\n })\n putAll('select-all-trigger', () => api.getSelectAllTriggerProps())\n putAll('row-select-trigger', el => api.getRowSelectTriggerProps(this.rowOf(el)))\n putAll('sort-trigger', el => api.getSortTriggerProps(this.columnOf(el)))\n putAll('expand-trigger', el => api.getExpandTriggerProps(this.rowOf(el)))\n putAll('expanded-row', el => api.getExpandedRowProps({ value: el.getAttribute('value') ?? '' }))\n\n // 行的禁用只认 rows 里的声明并归一到 aria-disabled,摘掉作者写在行上的原生 disabled\n for (const el of this.getParts('row')) {\n if (el.hasAttribute('disabled'))\n el.removeAttribute('disabled')\n }\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n for (const el of this.getParts('expanded-row'))\n this.setPartHidden(el, !api.isExpanded(el.getAttribute('value') ?? ''))\n this.setPartHidden(this.getPart('empty-state'), !!emptyProps.hidden)\n this.setPartHidden(this.getPart('loading-state'), !!loadingProps.hidden)\n }\n}\n","import type { TabsActivationMode, TabsNode, TabsSchema, TabsValueChangeDetails, TabsVariant } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTabs, tabsAnatomy, tabsMachine, tabsMeta } from '@xihan-ui/headless'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-tabs>` —— Light-DOM 行为宿主,跑 tabs 机器并把 connect 产出打到 root/list/trigger/content\n * 角色节点上。条目身份取作者写在 trigger/content 上的 value 属性,trigger 的禁用由部件自报。\n *\n * @customElement xh-tabs\n * @attr {string} value - 受控选中值;缺省该属性即非受控\n * @attr {string} default-value - 非受控的初始选中值\n * @attr {'horizontal'|'vertical'} orientation - 方向键轴向,默认 horizontal\n * @attr {'ltr'|'rtl'} dir - 文字方向,只影响水平轴上 ArrowLeft/ArrowRight 的前后语义,默认 ltr\n * @attr {'automatic'|'manual'} activation-mode - 方向键移动焦点是否顺带切换选中,默认 automatic\n * @attr {boolean} loop - 方向键走到尽头回绕,默认开启\n * @attr {'line'|'card'|'segment'} variant - 形态,默认 line\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 选中值变化;detail 为 `{ value: string | null }`\n * @csspart root - 组件根容器(承载 data-orientation)\n * @csspart list - role=tablist 容器(方向键与 Tab 序列在此收口)\n * @csspart trigger - role=tab 的标签按钮,须自带 value 属性标识身份\n * @csspart content - role=tabpanel 的面板,须自带 value 属性与 trigger 配对;未选中时 hidden\n */\nexport class XhTabsElement extends XhElement {\n static override partContract = { anatomy: tabsAnatomy, meta: tabsMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n activationMode: { converter: STRING_CONVERTER, attribute: 'activation-mode' },\n loop: { converter: BOOLEAN_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare collection?: TabsNode[]\n declare value?: string\n declare defaultValue?: string\n declare orientation?: Orientation\n declare direction?: Direction\n declare activationMode?: TabsActivationMode\n declare loop?: boolean\n declare variant?: TabsVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: TabsValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<TabsSchema>(this, tabsMachine, () => this.machineProps())\n\n /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */\n private readonly declaredDisabled = createDeclaredDisabled()\n\n private machineProps(): Partial<TabsSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n orientation: this.orientation,\n dir: this.direction,\n activationMode: this.activationMode,\n loop: this.loop,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n /** 承载焦点的条目被移出 DOM 时浏览器不派 focusout,这里替 DOM 上报焦点离场。 */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // 只在持有焦点的那个条目离场时上报\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'LIST.BLUR' })\n }\n\n protected wire(): void {\n const api = connectTabs(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('list', api.getListProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled\n for (const el of this.getParts('trigger')) {\n const props = api.getTriggerProps({\n value: el.getAttribute('value') ?? '',\n disabled: this.collection ? this.declaredDisabled(el) : isItemDisabled(el),\n })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n\n // 面板常挂,未选中的由 connect 输出的 hidden 收起\n for (const el of this.getParts('content')) {\n const props = api.getContentProps({ value: el.getAttribute('value') ?? '' })\n this.spreader.spread(el, props as Record<string, unknown>)\n }\n }\n}\n","import type {\n TagsInputBlurBehavior,\n TagsInputInputValueChangeDetails,\n TagsInputItemProps,\n TagsInputSchema,\n TagsInputValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTagsInput, tagsInputAnatomy, tagsInputMachine, tagsInputMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、=\"false\"=false、其余=true。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 标签集合写进属性时一律按逗号拆(属性表达不了数组)。\n// 用别的 delimiter 时请走 property(`el.value = ['a;b']`):转换器看不见同一元素上的另一个属性\nconst ARRAY_CONVERTER = {\n fromAttribute: (v: string | null) => (v == null ? undefined : v.split(',').map(s => s.trim()).filter(s => s !== '')),\n}\n\n/**\n * `<xh-tags-input>` —— Light-DOM 行为宿主:作者写 root/label/control/input/item 一族与\n * clear-trigger/hidden-input 角色节点,元素跑 tags-input 机器并把 connect 产出打上去。\n *\n * 标签节点由作者按当前值渲染(每个标签一个 item,身份取节点上的 value 属性);\n * 元素自己不生成结构,值变了要由作者那一侧增删节点,改完 MutationObserver 会自动重新接线。\n *\n * label 的 `for` 恒写向 input 的 id,所以 label 必须是原生 `<label>`、input 必须是原生 `<input>`。\n * 就地编辑框(item-input)与预览(item-preview)互斥收起而不是卸载,作者写的节点不会被替他删掉。\n *\n * @customElement xh-tags-input\n * @attr {string} value - 受控标签集合,按逗号拆;缺省该属性即非受控,别的分隔符请用 property\n * @attr {string} default-value - 非受控初始标签集合,同样按逗号拆\n * @attr {string} input-value - 受控输入文本\n * @attr {string} default-input-value - 非受控初始输入文本\n * @attr {number} max - 最多几个标签;写 0 即一个也不许加\n * @attr {boolean} allow-overflow - 允许越过 max,越过后打出 data-overflow\n * @attr {boolean} disabled - 禁用:输入框与各按钮都不可用\n * @attr {boolean} read-only - 只读:仍可聚焦与复制,加删改都走不通\n * @attr {boolean} invalid - 校验失败标注\n * @attr {string} name - 表单字段名;给了 hidden-input 才参与提交(按 delimiter 拼成一串)\n * @attr {string} placeholder - 输入框占位文案\n * @attr {string} delimiter - 断词符,默认逗号;显式写空串即关掉断词\n * @attr {boolean} add-on-paste - 粘贴时按 delimiter 拆成多个标签\n * @attr {boolean} editable - 允许双击标签就地改\n * @attr {'add'|'clear'} blur-behavior - 焦点离开整个组件时怎么处置残留文本\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 标签集合变化;detail 为 `{ value: string[] }`\n * @fires input-value-change - 输入文本变化;detail 为 `{ inputValue: string }`\n * @csspart root - 承载 data-disabled / data-readonly / data-invalid / data-empty / data-at-max / data-overflow\n * @csspart label - 标题;`for` 恒写向 input,故须是原生 `<label>` 才点得动\n * @csspart control - role=group 的框,点它的空白处即聚焦输入框\n * @csspart input - 真正的输入框,须是原生 `<input>`;键盘交互全在它身上\n * @csspart item - 一个标签一个,须自带 value 属性标识身份\n * @csspart item-preview - 标签平常那一套(文本 + 删除按钮);就地编辑时收起\n * @csspart item-text - 标签文本\n * @csspart item-delete-trigger - 删除按钮,须是原生 `<button>`;不占 Tab 位,自带 aria-label\n * @csspart item-input - 就地编辑框,须是原生 `<input>`;不编辑时收起\n * @csspart clear-trigger - 清空按钮;没东西可清时置灰\n * @csspart hidden-input - type=hidden 的表单出口,值是按 delimiter 拼好的整串\n */\nexport class XhTagsInputElement extends XhElement {\n static override partContract = { anatomy: tagsInputAnatomy, meta: tagsInputMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: ARRAY_CONVERTER },\n defaultValue: { converter: ARRAY_CONVERTER, attribute: 'default-value' },\n inputValue: { converter: STRING_CONVERTER, attribute: 'input-value' },\n defaultInputValue: { converter: STRING_CONVERTER, attribute: 'default-input-value' },\n max: { converter: NUMBER_CONVERTER },\n allowOverflow: { converter: BOOLEAN_CONVERTER, attribute: 'allow-overflow' },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n delimiter: { converter: STRING_CONVERTER },\n addOnPaste: { converter: BOOLEAN_CONVERTER, attribute: 'add-on-paste' },\n editable: { converter: BOOLEAN_CONVERTER },\n blurBehavior: { converter: STRING_CONVERTER, attribute: 'blur-behavior' },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: string[]\n declare defaultValue?: string[]\n declare inputValue?: string\n declare defaultInputValue?: string\n declare max?: number\n declare allowOverflow?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare name?: string\n declare placeholder?: string\n declare delimiter?: string\n declare addOnPaste?: boolean\n declare editable?: boolean\n declare blurBehavior?: TagsInputBlurBehavior | null\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notifyValue = (details: TagsInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyInputValue = (details: TagsInputInputValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('input-value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // 机器只有一个聚焦副作用(自己经 scope 取节点),不需要 config/layer/定位引擎,\n // 故 controller 只带 props。\n private readonly ctrl = new MachineController<TagsInputSchema>(this, tagsInputMachine, () => this.machineProps())\n\n private machineProps(): Partial<TagsInputSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n inputValue: this.inputValue,\n defaultInputValue: this.defaultInputValue,\n max: this.max,\n allowOverflow: this.allowOverflow ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n name: this.name,\n placeholder: this.placeholder,\n delimiter: this.delimiter,\n addOnPaste: this.addOnPaste ?? false,\n editable: this.editable ?? false,\n blurBehavior: this.blurBehavior,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyValue,\n onInputValueChange: this.notifyInputValue,\n }\n }\n\n /**\n * 承载焦点的标签被移出 DOM 时浏览器不派 focusout(Chrome 如此),机器读不到这件事:\n * 就地编辑框会连同标签一起消失,机器却还停在 editing,光标锚点指着一个已经不存在的标签,\n * 从此既进不了编辑框、也回不到输入框。这里替 DOM 把焦点离场如实上报。\n *\n * 判据在这一侧只能按锚点值判,不能按\"当下正持有焦点\":回调是在节点已经离开文档之后调的,\n * 那时 activeElement 早退回 body 了。Vue 那一侧有 onBeforeUnmount(节点还在),故按焦点判。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,标签内的文本、按钮与编辑框离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'ITEM.FOCUS_LOST' })\n }\n\n // 标签内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectTagsInput(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n // 输入框的 value 不必另外回写:spreader 把 value/checked/selected 三个键当 property 写\n // (dom/spread.ts 的 PROP_KEYS),属性写法只管初值、盖不住用户输入过的框\n\n // 标签是多实例 part,逐个打:身份取作者写在节点上的 value\n for (const el of this.getParts('item')) {\n const item: TagsInputItemProps = { value: el.getAttribute('value') ?? '' }\n this.spreader.spread(el, api.getItemProps(item) as Record<string, unknown>)\n const editing = api.editedValue === item.value\n for (const preview of this.partsIn(el, 'item-preview')) {\n this.spreader.spread(preview, api.getItemPreviewProps(item) as Record<string, unknown>)\n // 只写 hidden 属性是不够的:作者层给这个 part 声明的任何一条 display\n // 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n this.setPartHidden(preview, editing)\n }\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const trigger of this.partsIn(el, 'item-delete-trigger'))\n this.spreader.spread(trigger, api.getItemDeleteTriggerProps(item) as Record<string, unknown>)\n for (const input of this.partsIn(el, 'item-input')) {\n this.spreader.spread(input, api.getItemInputProps(item) as Record<string, unknown>)\n this.setPartHidden(input, !editing)\n }\n }\n }\n}\n","import type { TextFieldSchema, TextFieldValueChangeDetails } from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectTextField, textFieldAnatomy, textFieldMachine, textFieldMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-text-field>` —— Light-DOM 行为宿主:作者写 root/label/input/clear-trigger 四类角色节点,\n * 元素跑 text-field 机器并把 connect 产出打上去。\n *\n * label 的 `for` 恒写向 input 的 id,所以 label 角色节点必须是原生 `<label>`、\n * input 角色节点必须是原生 `<input>`:任一边换成 `<div>`,点标题不聚焦、读屏也念不出名字。\n *\n * 键盘只额外接一个 Escape(clearable 且有值时清空),其余光标与选区行为全归浏览器。\n * 清空按钮对读屏隐藏、不占 Tab 位——它只是指针用户的快捷方式,键盘那一路走 Escape。\n *\n * @customElement xh-text-field\n * @attr {string} value - 受控值;缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {string} placeholder - 占位文案\n * @attr {boolean} disabled - 禁用:不可聚焦、写不进\n * @attr {boolean} read-only - 只读:仍可聚焦与复制,写不进\n * @attr {boolean} required - 必填标注\n * @attr {boolean} invalid - 校验失败标注\n * @attr {string} name - 表单字段名;给了才参与提交\n * @attr {number} max-length - 字符数上限;同时落成原生 maxlength 与机器侧截断\n * @attr {boolean} clearable - 开启清空:清空按钮显出并在有值时可用,Escape 接管\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 值变化;detail 为 `{ value: string }`\n * @csspart root - 承载 data-disabled / data-readonly / data-invalid / data-empty / data-at-limit 的容器\n * @csspart label - 标题;`for` 恒写向 input,故须是原生 `<label>` 才点得动\n * @csspart input - 真正的输入框,须是原生 `<input>`;键盘交互全在它身上\n * @csspart clear-trigger - 清空按钮;未开 clearable 时收起,无值或不可编辑时置灰\n */\nexport class XhTextFieldElement extends XhElement {\n static override partContract = { anatomy: textFieldAnatomy, meta: textFieldMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n placeholder: { converter: STRING_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n required: { converter: BOOLEAN_CONVERTER },\n invalid: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n maxLength: { converter: NUMBER_CONVERTER, attribute: 'max-length' },\n clearable: { converter: BOOLEAN_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare placeholder?: string\n declare disabled?: boolean\n declare readOnly?: boolean\n declare required?: boolean\n declare invalid?: boolean\n declare name?: string\n declare maxLength?: number\n declare clearable?: boolean\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: TextFieldValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<TextFieldSchema>(this, textFieldMachine, () => this.machineProps())\n\n private machineProps(): Partial<TextFieldSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n placeholder: this.placeholder,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n required: this.required ?? false,\n invalid: this.invalid ?? false,\n name: this.name,\n maxLength: this.maxLength,\n clearable: this.clearable ?? false,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectTextField(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('input', api.getInputProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n // 输入框的 value 不必在这里另外回写:spreader 把 value/checked/selected 三个键\n // 当 property 写(dom/spread.ts 的 PROP_KEYS),属性写法只管初值、盖不住用户输入过的框\n\n // 收起清空按钮只写 hidden 属性是不够的:作者层给这个 part 声明的任何一条 display\n // 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n this.setPartHidden(this.getPart('clear-trigger'), !api.clearable)\n }\n}\n","import type { ThreadSchema, ThreadStatus, ThreadStickChangeDetails, ThreadTranslations } from '@xihan-ui/headless'\nimport type { IdGenerator, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectThread, threadAnatomy, threadMachine, threadMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 给出\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串按缺席处理,避免 Number('') 落成 0\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-thread>` —— Light-DOM 行为宿主:跑 thread 机器,把 connect 产出打到作者写的角色节点上。\n * 内容长高时跟随滚动到底部,用户上滚后解除粘附,滚回底部阈值内或按回到底部按钮时恢复。\n *\n * @customElement xh-thread\n * @attr {'idle'|'submitted'|'streaming'|'error'} status - 这一轮的运行态,只透出成 data-status\n * @attr {number} threshold - 距底多少 px 视为在底,默认 64\n * @fires stick-change - 粘底状态变化;detail 为 `{ atBottom: boolean, sticking: boolean }`\n * @csspart root - 组件根容器,承载 data-status\n * @csspart viewport - 滚动容器;role=log + aria-live=off + tabindex=0\n * @csspart content - 内容包裹层,尺寸变化的观察目标\n * @csspart scroll-button - 回到底部按钮,在底时收起(hidden + 内联 display)\n * @csspart live-region - 视觉隐藏的播报区(role=status + aria-live=polite + aria-atomic)\n */\nexport class XhThreadElement extends XhElement {\n static override partContract = { anatomy: threadAnatomy, meta: threadMeta }\n\n // 描述符逐个写全,不用对象展开,CEM 分析器的 lit 插件读不了展开元素的名字\n static override properties = {\n status: { converter: STRING_CONVERTER },\n threshold: { converter: NUMBER_CONVERTER },\n // 对象值走不了 HTML 属性,只作为 property 暴露\n translations: { attribute: false },\n }\n\n declare status?: ThreadStatus\n declare threshold?: number\n /** 消息区与回到底部按钮的无障碍名,由 connect 写到节点上。 */\n declare translations?: Partial<ThreadTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly threadScope = createScope(null, this.idGen)\n private config: RuntimeConfig | null = null\n\n private readonly notify = (details: ThreadStickChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('stick-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ThreadSchema>(\n this,\n threadMachine,\n () => this.machineProps(),\n { scope: this.threadScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<ThreadSchema['props']> {\n return {\n status: this.status,\n threshold: this.threshold,\n translations: this.translations,\n onStickChange: this.notify,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.threadScope, idGenerator: this.idGen })\n }\n\n /** 装填 config 与两个节点 getter;onBuilt 在 ctrl 构造期就跑,故 service 由参数传入。 */\n private injectRefs(svc: Service<ThreadSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('getViewportEl', () => this.getPart('viewport'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n protected wire(): void {\n const api = connectThread(this.ctrl.service, wcNormalize)\n\n // 角色节点可能晚一拍才填进来,每次接线都让句柄按当前节点重绑\n this.ctrl.service.refs.get('stick')?.retarget()\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('viewport', api.getViewportProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('scroll-button', api.getScrollButtonProps() as Record<string, unknown>)\n put('live-region', api.getLiveRegionProps() as Record<string, unknown>)\n\n // 除 hidden 属性外还写内联 display,压住作者层给该 part 声明的 display\n this.setPartHidden(this.getPart('scroll-button'), !api.showScrollButton)\n }\n}\n","import type { TimeLocale, TimeProps, TimeType, TimeValue } from '@xihan-ui/headless'\nimport { connectTime, timeAnatomy, timeMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * `<xh-time>` —— Light-DOM 行为宿主,无状态机,把 connectTime 产出打到 root 角色节点。\n *\n * 作者写一个空的 `<time data-xh-part=\"root\"></time>`:datetime 与显示文本都是算出来的,\n * 两者取自同一个墙钟,元素不做时区换算。作者若自己在这个节点里写了文本,那份文本原样留着,\n * 元素只覆盖自己上一次铺进去的那一份。\n *\n * 认不出的时刻落 `data-state=\"invalid\"`,此时不写 datetime——\n * 与其给机器一个瞎编的时间戳,不如什么都不给。\n *\n * 数字时间戳只能走 property(`el.value = 1786000000000`):属性里的一串数字与年份写法分不开。\n *\n * @customElement xh-time\n * @attr {string} value - 要显示的时刻;只写年月日的串按本地零点解读\n * @attr {'date'|'datetime'|'relative'} type - 呈现方式,缺省 datetime\n * @attr {string} format - 自定义格式串,记号是 YYYY / YY / MM / M / DD / D / HH / H / mm / m / ss / s\n * @attr {'zh-CN'|'en'} locale - 用词,缺省 zh-CN;只换给人看的文本\n * @attr {string} now - 算相对说法时的参照时刻,缺省取当前时刻\n * @csspart root - 那个 `<time>`,承载 datetime / data-type / data-state / data-relative\n */\nexport class XhTimeElement extends XhElement {\n static override partContract = {\n anatomy: timeAnatomy,\n meta: timeMeta,\n // root 不是 <time> 时 datetime 只是个自定义属性,机器读不到任何时刻\n tags: { root: ['time'] },\n }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n value: { converter: STRING_CONVERTER },\n type: { converter: STRING_CONVERTER },\n format: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n now: { converter: STRING_CONVERTER },\n }\n\n declare value?: TimeValue\n declare type?: TimeType\n declare format?: string\n declare locale?: TimeLocale\n declare now?: TimeValue\n\n /** 上一次铺进 root 的那份文本。 */\n #painted?: string\n\n protected wire(): void {\n const root = this.getPart('root')\n if (!root)\n return\n\n // 读响应式 property,不回读 DOM 特性\n const api = connectTime({\n value: this.value,\n type: this.type,\n format: this.format,\n locale: this.locale,\n now: this.now,\n } satisfies TimeProps, wcNormalize)\n\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n this.#paintText(root, api.text)\n }\n\n /**\n * 把格式化好的文本铺进 root。\n * 节点里已有的文本不是本元素铺的(作者自己写的兜底文案)就不动它。\n */\n #paintText(root: HTMLElement, text: string): void {\n const current = root.textContent ?? ''\n if (current.trim() !== '' && current !== this.#painted)\n return\n this.#painted = text\n if (current !== text)\n root.textContent = text\n }\n}\n","import type { TimeFieldSchema, TimeFieldValueChangeDetails, TimeGranularity, TimeHourCycle, TimeSegmentType } from '@xihan-ui/headless'\nimport type { ControlVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectTimeField, timeFieldAnatomy, timeFieldMachine, timeFieldMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\n// Lit 默认的 Boolean 转换器是 v !== null,缺省为真的开关会因此永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 小时制只有 12 与 24 两个取值,写别的一律当作没写(回落到 locale 推断)\nconst HOUR_CYCLE_CONVERTER = {\n fromAttribute: (v: string | null): TimeHourCycle | undefined => (v === '12' ? 12 : v === '24' ? 24 : undefined),\n}\n\nconst SEGMENT_TYPES: readonly TimeSegmentType[] = ['hour', 'minute', 'second', 'dayPeriod']\n\n/** 作者写在段上的身份声明。写坏了或没写就按文档序补,手写 HTML 时按顺序排下来本身就是声明。 */\nfunction declaredSegment(el: HTMLElement, position: number): TimeSegmentType {\n const raw = el.getAttribute('segment')?.trim()\n if (raw && (SEGMENT_TYPES as readonly string[]).includes(raw))\n return raw as TimeSegmentType\n return SEGMENT_TYPES[Math.min(position, SEGMENT_TYPES.length - 1)]!\n}\n\n/**\n * `<xh-time-field>` —— Light-DOM 行为宿主:作者写 root/label/control/segment(多个)/hidden-input\n * 角色节点,元素跑 time-field 机器并把 connect 产出打上去。\n *\n * 每一段是一个 role=spinbutton 的展示节点:上下键加减、左右键换段、数字直输并自动跳段、\n * Backspace 清段;12 小时制下多出一个上午/下午段,可用上下键翻面或直接按 a/p。\n * 整组只占一个 Tab 位(roving tabindex)。完整的 ISO 串另由 hidden-input 随表单提交。\n *\n * 段上的文字由元素填(作者写不出\"此刻该显示几点\");作者自己写了内容的段一概不碰。\n *\n * @customElement xh-time-field\n * @attr {string} value - 受控值,ISO 时间串('13:45' / '13:45:30');缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {string} min - 下界(含),只用来标注越界,不改写值\n * @attr {string} max - 上界(含),同上\n * @attr {string} locale - BCP 47 语言标记,决定上午/下午文字与默认小时制\n * @attr {'12'|'24'} hour-cycle - 小时制;不写则按 locale 推断,再没有就用 24\n * @attr {'hour'|'minute'|'second'} granularity - 值精确到哪一段,默认 minute\n * @attr {boolean} disabled - 禁用:整组退出 Tab 序列,隐藏输入不参与提交\n * @attr {boolean} read-only - 只读:仍可聚焦与换段,改不动值\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} required - 必填标注,落到每段的 aria-required 上\n * @attr {string} name - 表单字段名;给了隐藏输入才带 name\n * @attr {string} placeholder - 空段的占位字符(单字符),默认 '-'\n * @attr {'outline'|'subtle'|'ghost'} variant - 形态\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires value-change - 值变化;detail 为 `{ value: string }`\n * @csspart root - 承载 data-disabled / data-readonly / data-invalid / data-empty / data-out-of-range 的容器\n * @csspart label - 标题;点它会把焦点送到第一段\n * @csspart control - role=group 的段容器,由 label 命名\n * @csspart segment - 一段一个的 spinbutton,可自带 segment 属性声明身份,缺省按文档序\n * @csspart hidden-input - type=hidden 的表单出口,值是完整 ISO 串\n */\nexport class XhTimeFieldElement extends XhElement {\n static override partContract = { anatomy: timeFieldAnatomy, meta: timeFieldMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n min: { converter: STRING_CONVERTER },\n max: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n hourCycle: { converter: HOUR_CYCLE_CONVERTER, attribute: 'hour-cycle' },\n granularity: { converter: STRING_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n required: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare min?: string\n declare max?: string\n declare locale?: string\n declare hourCycle?: TimeHourCycle\n declare granularity?: TimeGranularity\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare required?: boolean\n declare name?: string\n declare placeholder?: string\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notifyChange = (details: TimeFieldValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // time-field 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<TimeFieldSchema>(this, timeFieldMachine, () => this.machineProps())\n\n private machineProps(): Partial<TimeFieldSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n min: this.min,\n max: this.max,\n locale: this.locale,\n hourCycle: this.hourCycle,\n granularity: this.granularity,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n required: this.required ?? false,\n name: this.name,\n placeholder: this.placeholder,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onValueChange: this.notifyChange,\n }\n }\n\n /** 段上的文字归谁写:作者首次被看到时就写了内容,之后一概不碰。 */\n private readonly ownsSegmentText = new WeakMap<HTMLElement, boolean>()\n\n /**\n * 填段上的文字。每帧回读分不清\"作者写的\"还是\"上一帧自己写的\",\n * 所以归属只在第一次见到这个节点时定一次,一旦写过就再也让不回去。\n */\n private fillSegmentText(el: HTMLElement, text: string): void {\n let owned = this.ownsSegmentText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsSegmentText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n const api = connectTimeField(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n // 段是多实例 part,逐个打。打上去的 data-scope/data-part/data-value 正是换段与\n // 自动跳段在事件那一刻现查 DOM 的依据,所以 wire 必须先于事件跑过——updated() 已保证。\n this.getParts('segment').forEach((el, position) => {\n const segment = declaredSegment(el, position)\n this.spreader.spread(el, api.getSegmentProps({ segment }) as Record<string, unknown>)\n this.fillSegmentText(el, api.getSegmentText({ segment }))\n // 收起不参与显示的段只写 hidden 属性是不够的:作者层给这个 part 声明的任何一条\n // display 都会盖过 UA 的 [hidden]{display:none},只有内联 style.display 压得住\n this.setPartHidden(el, !api.segments.includes(segment))\n })\n }\n}\n","import type {\n TimeGranularity,\n TimeHourCycle,\n TimePickerColumnUnit,\n TimePickerOpenChangeDetails,\n TimePickerSchema,\n TimePickerValueChangeDetails,\n TimeSegmentType,\n} from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectTimePicker, timePickerAnatomy, timePickerMachine, timePickerMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,以此区分受控与非受控。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(用默认值)、=\"false\"=false、其余=true。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n// 小时制只认 12 与 24,写别的当作没写\nconst HOUR_CYCLE_CONVERTER = {\n fromAttribute: (v: string | null): TimeHourCycle | undefined => (v === '12' ? 12 : v === '24' ? 24 : undefined),\n}\n\nconst SEGMENT_TYPES: readonly TimeSegmentType[] = ['hour', 'minute', 'second', 'dayPeriod']\nconst COLUMN_UNITS: readonly TimePickerColumnUnit[] = ['hour', 'minute', 'second']\n\n/** 取作者写在段上的 segment,缺席或写坏了按文档序补。 */\nfunction declaredSegment(el: HTMLElement, position: number): TimeSegmentType {\n const raw = el.getAttribute('segment')?.trim()\n if (raw && (SEGMENT_TYPES as readonly string[]).includes(raw))\n return raw as TimeSegmentType\n return SEGMENT_TYPES[Math.min(position, SEGMENT_TYPES.length - 1)]!\n}\n\n/** 作者写在列上的单位声明,规则同上。 */\nfunction declaredUnit(el: HTMLElement, position: number): TimePickerColumnUnit {\n const raw = el.getAttribute('unit')?.trim()\n if (raw && (COLUMN_UNITS as readonly string[]).includes(raw))\n return raw as TimePickerColumnUnit\n return COLUMN_UNITS[Math.min(position, COLUMN_UNITS.length - 1)]!\n}\n\n/**\n * `<xh-time-picker>` —— Light-DOM 行为宿主:作者写 root/label/control/input(多个)/trigger/\n * clear-trigger/positioner/content/column(多个)/option(多个)/hidden-input 角色节点,\n * 元素跑 time-picker 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点取 control(浮层因此与整个输入行对齐),被定位的浮层取 positioner。\n *\n * 两条改值的路写同一份值:输入行里逐段敲(每段是 role=spinbutton,上下键加减、数字直输自动跳段),\n * 浮层里按列挑(每列是一个 listbox,上下键在列内走、左右键换列、Enter 选中)。\n *\n * 段与格子上的文字由元素填;作者自己写了内容的不碰。\n *\n * @customElement xh-time-picker\n * @attr {string} value - 受控值,ISO 时间串('13:45' / '13:45:30');缺省该属性即非受控\n * @attr {string} default-value - 非受控初值\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} min - 下界(含):裁掉浮层里落在界外的可选值,并把已填的越界值标注出来\n * @attr {string} max - 上界(含),同上\n * @attr {string} locale - BCP 47 语言标记,决定上午/下午文字与默认小时制\n * @attr {'12'|'24'} hour-cycle - 小时制;不写则按 locale 推断,再没有就用 24\n * @attr {'hour'|'minute'|'second'} granularity - 值精确到哪一段,默认 minute\n * @attr {number} step - 分列的步进(分钟),默认 1\n * @attr {boolean} disabled - 禁用:段整组退出 Tab 序列,触发器用原生 disabled,隐藏输入不参与提交\n * @attr {boolean} read-only - 只读:浮层照常展开与浏览,但值改不动也清不掉\n * @attr {boolean} invalid - 校验失败标注\n * @attr {boolean} required - 必填标注,落到每段的 aria-required 上\n * @attr {string} name - 表单字段名;给了隐藏输入才带 name\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @fires value-change - 值变化;detail 为 `{ value: string }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly/data-invalid/data-empty)\n * @csspart label - 标题;点它会把焦点送到第一段\n * @csspart control - role=group 的输入行,同时是浮层的定位锚点\n * @csspart input - 一段一个的 spinbutton,可自带 segment 属性声明身份,缺省按文档序\n * @csspart trigger - 展开/收起按钮,须是原生 button\n * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - 浮层容器(消解层与焦点域的根节点),收起时带 hidden\n * @csspart column - role=listbox 的一列,可自带 unit 属性声明单位,缺省按文档序\n * @csspart option - role=option 的一格,须自带 value 属性(两位补零的显示串)\n * @csspart hidden-input - type=hidden 的表单出口,值是完整 ISO 串\n */\nexport class XhTimePickerElement extends XhElement {\n static override partContract = { anatomy: timePickerAnatomy, meta: timePickerMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n min: { converter: STRING_CONVERTER },\n max: { converter: STRING_CONVERTER },\n locale: { converter: STRING_CONVERTER },\n hourCycle: { converter: HOUR_CYCLE_CONVERTER, attribute: 'hour-cycle' },\n granularity: { converter: STRING_CONVERTER },\n step: { converter: NUMBER_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n required: { converter: BOOLEAN_CONVERTER },\n name: { converter: STRING_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n }\n\n declare value?: string\n declare defaultValue?: string\n declare open?: boolean\n declare defaultOpen?: boolean\n declare min?: string\n declare max?: string\n declare locale?: string\n declare hourCycle?: TimeHourCycle\n declare granularity?: TimeGranularity\n declare step?: number\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare required?: boolean\n declare name?: string\n declare placement?: Placement\n declare offset?: number\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly pickerScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n private readonly notifyValue = (details: TimePickerValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: TimePickerOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<TimePickerSchema>(\n this,\n timePickerMachine,\n () => this.machineProps(),\n { scope: this.pickerScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<TimePickerSchema['props']> {\n return {\n value: this.value,\n defaultValue: this.defaultValue,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n min: this.min,\n max: this.max,\n locale: this.locale,\n hourCycle: this.hourCycle,\n granularity: this.granularity,\n step: this.step,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n required: this.required ?? false,\n name: this.name,\n placement: this.placement,\n offset: this.offset,\n onValueChange: this.notifyValue,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.pickerScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // 整个输入行记为本层分支:点触发器算层内交互,开合交给它自己切换。\n branches: () => [this.getPart('control')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<TimePickerSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('control'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /** 提前发现一次角色节点:default-open 时焦点域在 hostConnected 当场要去 content 里找那一格。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /** 段与格子上的文字是否归元素填,首次见到该节点时定。 */\n private readonly ownsText = new WeakMap<HTMLElement, boolean>()\n\n /** 填节点上的文字,归属只在第一次见到这个节点时定一次。 */\n private fillText(el: HTMLElement, text: string): void {\n let owned = this.ownsText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n const api = connectTimePicker(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('control', api.getControlProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n // 段逐个打;wire 跑在事件之前,换段与自动跳段时 data-scope/data-part/data-value 已在 DOM 上\n this.getParts('input').forEach((el, position) => {\n const segment = declaredSegment(el, position)\n this.spreader.spread(el, api.getInputProps({ segment }) as Record<string, unknown>)\n this.fillText(el, api.getSegmentText({ segment }))\n // 用内联 display 收起不参与显示的段(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(el, !api.segments.includes(segment))\n })\n\n // 列同理,格子归属按子树切分\n this.getParts('column').forEach((columnEl, position) => {\n const unit = declaredUnit(columnEl, position)\n this.spreader.spread(columnEl, api.getColumnProps({ unit }) as Record<string, unknown>)\n this.setPartHidden(columnEl, !api.columns.some(column => column.unit === unit))\n for (const optionEl of this.getParts('option').filter(el => columnEl.contains(el))) {\n const value = optionEl.getAttribute('value') ?? ''\n this.spreader.spread(optionEl, api.getOptionProps({ unit, value }) as Record<string, unknown>)\n this.fillText(optionEl, value)\n }\n })\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { TimelineItemProps, TimelinePlacement, TimelineProps } from '@xihan-ui/headless'\nimport type { Orientation, Size, Tone } from '@xihan-ui/kernel'\nimport { connectTimeline, timelineAnatomy, timelineMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n\n/**\n * `<xh-timeline>` —— 事件流行为宿主,无状态机,把 connectTimeline 产出打到角色节点上。\n *\n * 作者写 root / item / indicator / connector / content / title / description / time 角色节点,\n * 元素只往上打属性,不替作者生成任何节点。\n * 标签上的建议:root 写 `<ol>`、item 写 `<li>`、time 写 `<time datetime=\"…\">`,\n * 机读时间归作者,元素不代填。\n *\n * 这不是步骤条:`<xh-steps>` 表达「流程走到第几步」,有当前项与完成态;\n * 这里表达「按时间排的事件流」,条目已经发生、彼此平等,没有当前项,也就没有任何状态属性。\n * 一条与另一条的差别只有语气色,写在 item 节点的 `tone` 属性上,圆点向上找自己的 item 取用。\n * 运行期改写 item 上的 `tone` 不触发重新接线,需作者自行 requestUpdate。\n *\n * @customElement xh-timeline\n * @attr {'vertical'|'horizontal'} orientation - 事件排列方向,默认 vertical\n * @attr {'start'|'end'|'alternate'} placement - 内容在线的哪一侧;alternate 逐条交替\n * @attr {'sm'|'md'|'lg'} size - 尺寸,决定圆点直径、条目间距与字号\n * @csspart root - role=list 的容器,承载 data-orientation / data-placement / data-size\n * @csspart item - role=listitem 的单条事件;作者在此写 tone(这一条的语气色)\n * @csspart indicator - 事件那一刻的圆点,对读屏隐藏,颜色随所属条目的 tone 走\n * @csspart connector - 圆点之间的连线,对读屏隐藏;长度与首尾裁切归皮肤\n * @csspart content - 这一条的文字容器\n * @csspart title - 事件标题\n * @csspart description - 标题下的说明\n * @csspart time - 时刻文本\n */\nexport class XhTimelineElement extends XhElement {\n static override partContract = { anatomy: timelineAnatomy, meta: timelineMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n orientation: { converter: STRING_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare orientation?: Orientation\n declare placement?: TimelinePlacement\n declare size?: Size\n\n /**\n * 取角色节点所属条目的语气:tone 写在 item 节点上,圆点向上找自己的 item。\n * 没有 item 包裹层时退回读节点自身,扁平结构也能用;\n * 越出本宿主的 item 不算数——时间线套时间线时内层圆点不会认外层条目。\n */\n private itemProps(el: HTMLElement): TimelineItemProps {\n const owner = el.closest<HTMLElement>(ITEM_SELECTOR)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n // tone 来自作者写在 HTML 上的属性,类型系统够不着;写错值只是不匹配任何皮肤选择器\n return { tone: (source.getAttribute('tone') as Tone | null) ?? undefined }\n }\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectTimeline({\n orientation: this.orientation,\n placement: this.placement,\n size: this.size,\n } satisfies TimelineProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n\n // 集合类 part 逐个 spread:条目数由作者的 DOM 决定,不依赖下标,增删无需记账\n const putAll = (name: string, get: (el: HTMLElement) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(el) as Record<string, unknown>)\n }\n putAll('item', () => api.getItemProps())\n putAll('indicator', el => api.getIndicatorProps(this.itemProps(el)))\n putAll('connector', () => api.getConnectorProps())\n putAll('content', () => api.getContentProps())\n putAll('title', () => api.getTitleProps())\n putAll('description', () => api.getDescriptionProps())\n putAll('time', () => api.getTimeProps())\n }\n}\n","import type { ToastActionDetails, ToastSchema, ToastStatusChangeDetails, ToastTranslations, ToastType } from '@xihan-ui/headless'\nimport { connectToast, toastAnatomy, toastMachine, toastMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席:duration=\"\" 经 Number() 会变成 0,而 0 在这里是\"关掉自动消失\"的意思\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(用缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(closable)只有三态才关得掉——Lit 默认的 Boolean 转换器是 v !== null,\n// 写 closable=\"false\" 照样是真,\"这条不许关\"在 HTML 里就说不出口\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-toast>` —— Light-DOM 行为宿主:作者写 root/title/description/action-trigger/close-trigger\n * 角色节点,元素跑 toast 机器并把 connect 产出打上去。\n *\n * root 承载 role 与 aria-live:默认 status + polite(排队等读屏的空隙),\n * type=\"error\" 换成 alert + assertive(打断当前朗读)。指针停在通知上、\n * 或焦点落进通知内部都会把倒计时按住,离开才接着走剩下的那一段。\n *\n * 退场窗口走完只把 root 收起、不删节点:作者写在里面的内容归作者,\n * 什么时候把这条从队列里删掉是 `<xh-toaster>` 的事(它收本元素冒泡上去的 status-change)。\n *\n * @customElement xh-toast\n * @attr {string} id - 队列身份,`<xh-toaster>` 按它寻址;不给就用实例自己的 scope id\n * @attr {string} title - 标题文案;作者没在 title 部件里写内容时由元素填入\n * @attr {string} description - 补充说明;作者没在 description 部件里写内容时由元素填入\n * @attr {'info'|'success'|'warning'|'error'|'loading'} type - 语气,默认 info;loading 不自动消失\n * @attr {number} duration - 停留毫秒,默认 5000;<=0 即关掉自动消失\n * @attr {number} remove-delay - 退场窗口毫秒,默认 200,留给退场动画\n * @attr {boolean} closable - 是否给可用的关闭按钮,默认 true;写 closable=\"false\" 关掉\n * @attr {boolean} pause-on-page-idle - 页面切到后台时按住计时,默认关\n * @fires status-change - 生命周期落位;detail 为 `{ id: string, status: 'dismissing'|'unmounted' }`\n * @fires action - 操作按钮被按下;detail 为 `{ id: string }`\n * @csspart root - role=status(error 时 alert)的容器,承载 data-type / data-tone / data-state / data-paused\n * @csspart title - 标题,aria-labelledby 的目标\n * @csspart description - 补充说明,aria-describedby 的目标\n * @csspart action-trigger - 操作按钮:先发 action 再进入退场\n * @csspart close-trigger - 关闭按钮;closable=false 时转原生 disabled 并收起\n */\nexport class XhToastElement extends XhElement {\n static override partContract = { anatomy: toastAnatomy, meta: toastMeta }\n\n // 字段名与属性名分家的两处都是躲原生访问器:HTMLElement 的 id 与 title 都是原生反射属性,\n // 同名声明会盖掉它们(`el.id` 从此不再是 DOM id)。属性名保持与 Vue 侧的 prop 同名。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n toastId: { converter: STRING_CONVERTER, attribute: 'id' },\n titleText: { converter: STRING_CONVERTER, attribute: 'title' },\n description: { converter: STRING_CONVERTER },\n type: { converter: STRING_CONVERTER },\n duration: { converter: NUMBER_CONVERTER },\n removeDelay: { converter: NUMBER_CONVERTER, attribute: 'remove-delay' },\n closable: { converter: BOOLEAN_CONVERTER },\n pauseOnPageIdle: { converter: BOOLEAN_CONVERTER, attribute: 'pause-on-page-idle' },\n // 文案是对象,走不了属性;只作为 property 暴露,与 Vue 侧的 translations prop 对齐\n translations: { attribute: false },\n }\n\n declare toastId?: string\n declare titleText?: string\n declare description?: string\n declare type?: ToastType\n declare duration?: number\n declare removeDelay?: number\n declare closable?: boolean\n declare pauseOnPageIdle?: boolean\n declare translations?: Partial<ToastTranslations>\n\n private readonly notifyStatus = (details: ToastStatusChangeDetails): void => {\n // 必须冒泡:外层 `<xh-toaster>` 就靠这条事件知道该把记录删掉了\n this.dispatchEvent(new CustomEvent('status-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyAction = (details: ToastActionDetails): void => {\n this.dispatchEvent(new CustomEvent('action', { detail: details, bubbles: true, composed: true }))\n }\n\n // toast 机器的副作用只有计时器与 visibilitychange,都由机器自己经 scope 拿,\n // 不需要 config/layer/定位引擎,故 controller 只带 props。\n private readonly ctrl = new MachineController<ToastSchema>(this, toastMachine, () => this.machineProps())\n\n private machineProps(): Partial<ToastSchema['props']> {\n return {\n id: this.toastId,\n title: this.titleText,\n description: this.description,\n type: this.type,\n duration: this.duration,\n removeDelay: this.removeDelay,\n closable: this.closable,\n pauseOnPageIdle: this.pauseOnPageIdle,\n translations: this.translations,\n onStatusChange: this.notifyStatus,\n onAction: this.notifyAction,\n }\n }\n\n /** 这个部件的文字归不归作者:头一回见到它时定案,之后不再改口。 */\n private readonly authorOwnsText = new WeakMap<HTMLElement, boolean>()\n\n /**\n * 作者没往部件里写内容时,用 props 上的文案填进去。\n *\n * 归属只判一次:判完本轮就会把文字写进去,再回读分不清是作者写的还是自己写的,\n * 从那以后 title 属性改了也再刷不动(Vue 侧是响应式渲染,会跟着改,两侧就此分叉)。\n */\n private fillText(el: HTMLElement | null, text: string | undefined): void {\n if (!el)\n return\n let authored = this.authorOwnsText.get(el)\n if (authored === undefined) {\n // 头一回见到这个节点:此刻里面的东西只可能是作者写的(本轮写入尚未发生)。\n // 元素子节点也算数——只放了个图标、文字留给 props 的标题同样是作者写过的,\n // 只看文字会把那个图标当空白冲掉\n authored = el.childElementCount > 0 || (el.textContent ?? '').trim() !== ''\n this.authorOwnsText.set(el, authored)\n }\n if (authored)\n return\n const next = text ?? ''\n // 比一次再写:写文本节点会命中宿主的变动观察器,值没变就别去惊动它\n if (el.textContent !== next)\n el.textContent = next\n }\n\n protected wire(): void {\n const api = connectToast(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('action-trigger', api.getActionTriggerProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n\n this.fillText(this.getPart('title'), api.title)\n this.fillText(this.getPart('description'), api.description)\n\n // connect 已经置了 hidden,但作者层给 [data-part=root] 写的任何一条 display\n // 都盖得过 UA 的 [hidden]{display:none};内联 style.display 优先级更高,压得住。\n // 关闭按钮同理:不可关闭时留一个按不动的叉,比压根没有叉更让人困惑\n this.setPartHidden(this.getPart('root'), api.status === 'unmounted')\n this.setPartHidden(this.getPart('close-trigger'), !api.closable)\n }\n}\n","import type {\n ResolvedToast,\n ToasterApi,\n ToasterSchema,\n ToasterToastsChangeDetails,\n ToasterTranslations,\n ToastOptions,\n ToastPlacement,\n ToastRecord,\n ToastStatusChangeDetails,\n} from '@xihan-ui/headless'\nimport { connectToaster, toasterAnatomy, toasterMachine, toasterMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 空串也当缺席:max=\"\" 经 Number() 会变成 0,那等于\"一条都不显示\"\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(用缺省)、在场=true、显式写 \"false\"=false。\n// 与 `<xh-toast>` 上的同名开关同一套写法,两处的 HTML 说法才对得上\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * 这一摞对应哪个位置。属性缺席就交 undefined,由 connect 回落到 toaster 的 placement。\n * 写坏了照原样交出去:它与九个位没有一个对得上,这摞就一直是空的——\n * 空得明显好过悄悄冒充另一个位置,把通知摆到作者没想到的角落。\n */\nfunction groupPlacement(el: HTMLElement): ToastPlacement | undefined {\n const raw = el.getAttribute('placement')\n return raw == null || raw === '' ? undefined : (raw as ToastPlacement)\n}\n\n/**\n * `<xh-toaster>` —— Light-DOM 行为宿主:作者写 root 与若干 group 角色节点,\n * 元素跑 toaster 机器并把 connect 产出打上去。每个 group 用 `placement` 属性声明自己是哪个位置,\n * 不写就落在 toaster 的 placement 上。\n *\n * 单条通知的节点由作者按队列渲染(读 `visibleToasts` 或听 `toasts-change`),元素不替作者生成:\n * 生成节点就等于收走模板控制权,图标、进度条、i18n 文案都再塞不进来。\n * 每条渲染成一个 `<xh-toast>`,它走完退场会冒泡一条 status-change,本元素据此把记录删掉。\n *\n * @customElement xh-toaster\n * @attr {'top-start'|'top'|'top-end'|'middle-start'|'middle'|'middle-end'|'bottom-start'|'bottom'|'bottom-end'} placement - 默认落位,默认 bottom-end\n * @attr {number} max - 每个位置最多同时留几条,超出挤掉最旧的;不给即不限\n * @attr {number} gap - 同一摞内的间距(px),默认 16\n * @attr {number} duration - 单条没写 duration 时的默认停留毫秒\n * @attr {number} remove-delay - 单条没写 remove-delay 时的默认退场窗口毫秒\n * @attr {boolean} pause-on-page-idle - 页面切到后台时按住计时,逐条下发\n * @fires toasts-change - 队列变化;detail 为 `{ toasts: ToastRecord[] }`\n * @csspart root - role=region 的地标容器,承载 data-count / data-empty\n * @csspart group - 某一个位置上的那一摞,可自带 placement 属性;承载 data-placement / data-count / data-empty 与间距\n */\nexport class XhToasterElement extends XhElement {\n static override partContract = { anatomy: toasterAnatomy, meta: toasterMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 队列与文案都是对象,走不了属性;只作为 property 暴露,与 Vue 侧的同名 prop 对齐。\n // toasts 给了即受控:元素内部的写入只发 toasts-change,等宿主自己写回\n toasts: { attribute: false },\n defaultToasts: { attribute: false },\n placement: { converter: STRING_CONVERTER },\n max: { converter: NUMBER_CONVERTER },\n gap: { converter: NUMBER_CONVERTER },\n duration: { converter: NUMBER_CONVERTER },\n removeDelay: { converter: NUMBER_CONVERTER, attribute: 'remove-delay' },\n pauseOnPageIdle: { converter: BOOLEAN_CONVERTER, attribute: 'pause-on-page-idle' },\n translations: { attribute: false },\n }\n\n declare toasts?: ToastRecord[]\n declare defaultToasts?: ToastRecord[]\n declare placement?: ToastPlacement\n declare max?: number\n declare gap?: number\n declare duration?: number\n declare removeDelay?: number\n declare pauseOnPageIdle?: boolean\n declare translations?: Partial<ToasterTranslations>\n\n private readonly notify = (details: ToasterToastsChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('toasts-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // toaster 机器只有队列这一份状态,无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<ToasterSchema>(this, toasterMachine, () => this.machineProps())\n\n private machineProps(): Partial<ToasterSchema['props']> {\n return {\n toasts: this.toasts,\n defaultToasts: this.defaultToasts,\n placement: this.placement,\n max: this.max,\n gap: this.gap,\n duration: this.duration,\n removeDelay: this.removeDelay,\n pauseOnPageIdle: this.pauseOnPageIdle,\n translations: this.translations,\n onToastsChange: this.notify,\n }\n }\n\n /**\n * 命令式入口共用的取法。机器要到进文档(hostConnected)才建:\n * 还没进文档就发通知是调用方的时序问题,明说好过把这条通知静默丢掉。\n */\n private commands(): ToasterApi {\n if (!this.ctrl.service)\n throw new Error('[xh] <xh-toaster> 还没进文档,命令式接口此时不可用')\n return connectToaster(this.ctrl.service, wcNormalize)\n }\n\n /** 入队并返回 id;同 id 已存在则就地改写,位置不动(loading 转 success 走的就是这条)。 */\n create(options: ToastOptions = {}): string {\n return this.commands().create(options)\n }\n\n /**\n * 刻意不叫 `update`:那是 Lit 自己的渲染生命周期钩子,占用它会让宿主每次重渲\n * 都拐进这里来(还带着一个 changedProperties 当 id),组件当场不工作。\n * Vue 侧没有这层基类,composable 上仍叫 `update`。\n */\n updateToast(id: string, options: Partial<ToastOptions>): void {\n this.commands().update(id, options)\n }\n\n dismiss(id: string): void {\n this.commands().dismiss(id)\n }\n\n dismissAll(): void {\n this.commands().dismissAll()\n }\n\n /** max 之内、按加入先后排列的可见条目,已补齐默认值,可直接摊给 `<xh-toast>`。 */\n get visibleToasts(): ResolvedToast[] {\n return this.commands().visibleToasts\n }\n\n /** 当前有条目的位置,按九宫格固定顺序。 */\n get placements(): ToastPlacement[] {\n return this.commands().placements\n }\n\n get count(): number {\n return this.commands().count\n }\n\n getToastsByPlacement(placement: ToastPlacement): ResolvedToast[] {\n return this.commands().getToastsByPlacement(placement)\n }\n\n /**\n * 单条通知走完退场会冒泡上来:记录该从队列里删掉了。\n * 认元素名而不是只认事件名——avatar 之类的部件也派 status-change,且完全可能就摆在通知内部。\n */\n private readonly onToastStatus = (event: Event): void => {\n const target = event.target as Element | null\n if (target?.tagName.toLowerCase() !== 'xh-toast')\n return\n const detail = (event as CustomEvent<ToastStatusChangeDetails>).detail\n if (detail?.status !== 'unmounted')\n return\n // 整页拆除时可能先停机再收到最后一条:停机后送事件在 dev 下会抛\n if (this.ctrl.service?.getStatus() !== 'Started')\n return\n this.dismiss(detail.id)\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n // 挂在自己身上而不是逐条通知上:条目是作者渲染的,元素看不见它们的出生与死亡\n this.addEventListener('status-change', this.onToastStatus)\n }\n\n override disconnectedCallback(): void {\n this.removeEventListener('status-change', this.onToastStatus)\n super.disconnectedCallback()\n }\n\n protected wire(): void {\n const api = connectToaster(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 摞是多实例 part,逐个打:位置取作者写的 placement 属性\n for (const el of this.getParts('group'))\n this.spreader.spread(el, api.getGroupProps({ placement: groupPlacement(el) }) as Record<string, unknown>)\n }\n}\n","import type { TogglePressedChangeDetails, ToggleSchema } from '@xihan-ui/headless'\nimport type { ActionVariant, Size, Tone } from '@xihan-ui/kernel'\nimport { connectToggle, toggleAnatomy, toggleMachine, toggleMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n/**\n * `<xh-toggle>` —— Light-DOM 行为宿主,跑 toggle 机器并把 connect 产出打到 root 角色节点。\n *\n * @customElement xh-toggle\n * @attr {boolean} pressed - 受控按下态;缺省该属性即非受控\n * @attr {boolean} default-pressed - 非受控初始为按下\n * @attr {boolean} disabled - 禁用\n * @attr {'solid'|'subtle'|'outline'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires pressed-change - pressed 状态变化;detail 为 `{ pressed: boolean }`\n * @csspart root - role=button 的按钮(承载 aria-pressed / data-state)\n */\nexport class XhToggleElement extends XhElement {\n static override partContract = { anatomy: toggleAnatomy, meta: toggleMeta }\n\n static override properties = {\n pressed: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n defaultPressed: { type: Boolean, attribute: 'default-pressed' },\n disabled: { type: Boolean },\n variant: {},\n tone: {},\n size: {},\n }\n\n declare pressed?: boolean\n declare defaultPressed?: boolean\n declare disabled?: boolean\n declare variant?: ActionVariant\n declare tone?: Tone\n declare size?: Size\n\n private readonly notify = (details: TogglePressedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('pressed-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<ToggleSchema>(this, toggleMachine, () => this.machineProps())\n\n private machineProps(): Partial<ToggleSchema['props']> {\n return {\n pressed: this.pressed,\n defaultPressed: this.defaultPressed ?? false,\n disabled: this.disabled ?? false,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n onPressedChange: this.notify,\n }\n }\n\n protected wire(): void {\n const api = connectToggle(this.ctrl.service, wcNormalize)\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n }\n}\n","import type { ToggleGroupItemProps, ToggleGroupNode, ToggleGroupSchema, ToggleGroupValueChangeDetails } from '@xihan-ui/headless'\nimport type { Direction, Orientation } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectToggleGroup, toggleGroupAnatomy, toggleGroupMachine, toggleGroupMeta } from '@xihan-ui/headless'\nimport { createDeclaredDisabled } from '../dom/declared-disabled'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 字符串属性统一走这个转换器:属性缺席即 undefined,缺省值的唯一事实源留在 connect。\n// Lit 默认转换器会在属性被移除时把值落成 null,那样 value 就再也表达不了\"非受控\"。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n// 布尔三态:缺席 = undefined(用 connect 的默认值),=\"false\" = false,其余 = true。\n// Lit 自带的 Boolean 转换器是 v !== null,缺省为真的 loop / roving-focus 会因此永远关不掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-toggle-group>` —— Light-DOM 行为宿主:作者写 root 与若干 item 角色节点,\n * 元素跑 toggle-group 机器并把 connect 产出打上去。条目须是原生 `<button>`\n * (Enter/Space 的激活由平台负责),身份取写在条目上的 value 属性,禁用由条目自报 aria-disabled。\n *\n * 单选(默认)与多选是两套 ARIA:单选 root=radiogroup、条目 role=radio + aria-checked;\n * 多选 root=group、条目保持原生按钮 + aria-pressed。\n *\n * 受控值的多选形态只能走 property(`el.value = ['a','b']`):HTML 属性只装得下一个字符串。\n *\n * @customElement xh-toggle-group\n * @attr {string} value - 受控选中值(属性形式只表达单值);缺省该属性即非受控\n * @attr {string} default-value - 非受控的初始选中值\n * @attr {boolean} multiple - 允许多项同时选中,默认关闭\n * @attr {boolean} disabled - 整组禁用\n * @attr {boolean} disallow-empty - 不许把值点空(最后一个选中项摘不掉)\n * @attr {'horizontal'|'vertical'} orientation - 视觉排布,默认 horizontal;方向键四个恒响应,与它无关\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键语义,默认 ltr\n * @attr {boolean} loop - 方向键走到尽头回绕,默认开启\n * @attr {boolean} roving-focus - roving tabindex,默认开启;关掉后每个条目各占一个 Tab 位\n * @fires value-change - 选中值变化;detail 为 `{ value: string | string[] | null }`(形态跟着 multiple 走)\n * @csspart root - role=radiogroup / group 的容器(承载键盘收口与 Tab 兜底位)\n * @csspart item - 开关按钮,须是原生 `<button>` 并自带 value 属性标识身份\n */\nexport class XhToggleGroupElement extends XhElement {\n static override partContract = { anatomy: toggleGroupAnatomy, meta: toggleGroupMeta }\n\n // dir 占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。别名保留原生行为,\n // 同时让 dir 进 observedAttributes——运行期改 dir 才会重跑 wire 换掉按键处理器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n // 数组只走 property,属性表达不了;给了它条目的文本与禁用即以数据为准\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n multiple: { converter: BOOLEAN_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n disallowEmpty: { converter: BOOLEAN_CONVERTER, attribute: 'disallow-empty' },\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n loop: { converter: BOOLEAN_CONVERTER },\n rovingFocus: { converter: BOOLEAN_CONVERTER, attribute: 'roving-focus' },\n }\n\n // 属性只喂得进字符串,property 还能直接喂数组(多选受控走这一路)\n declare collection?: ToggleGroupNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare multiple?: boolean\n declare disabled?: boolean\n declare disallowEmpty?: boolean\n declare orientation?: Orientation\n declare direction?: Direction\n declare loop?: boolean\n declare rovingFocus?: boolean\n\n // 整组禁用期间的条目自身声明快照。connect 每帧都把 aria-disabled 写回条目,整组禁用更是写满每一个,\n // 此时回读分不清「作者声明的」还是「自己上一帧写的」,组解禁后条目就永远解不开。\n private readonly declaredDisabled = new WeakMap<HTMLElement, boolean>()\n /** 上一帧是否整组禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */\n private wasGroupDisabled = false\n\n private readonly notify = (details: ToggleGroupValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // toggle-group 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<ToggleGroupSchema>(this, toggleGroupMachine, () => this.machineProps())\n\n private machineProps(): Partial<ToggleGroupSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n // 布尔一律原样透传:属性不在即 undefined,把缺省交回 connect\n // (multiple / disabled / disallowEmpty 默认关,loop / rovingFocus 默认开)\n multiple: this.multiple,\n disabled: this.disabled,\n disallowEmpty: this.disallowEmpty,\n orientation: this.orientation,\n dir: this.direction,\n loop: this.loop,\n rovingFocus: this.rovingFocus,\n onValueChange: this.notify,\n }\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * 容器判自己\"焦点在组内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整组零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // 只有走的正是持有焦点的那个条目才报,否则删任一无关条目都会清掉方向键起点\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'GROUP.BLUR' })\n }\n\n /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */\n private readonly declaredItemDisabled = createDeclaredDisabled()\n\n private itemProps(el: HTMLElement): ToggleGroupItemProps {\n const value = el.getAttribute('value') ?? ''\n // 给了 collection 就以数据为事实源:现读会读到 connect 上一帧写回的 aria-disabled,\n // 「作者没写」表达不出 undefined,数据里的禁用就永远轮不到生效。\n if (this.collection)\n return { value, disabled: this.declaredItemDisabled(el) }\n // 只有「本帧与上一帧都没整组禁用」时,节点上的 aria-disabled 才等于作者声明:\n // 整组禁用那几帧 connect 把每个条目都写成了 true,解禁当帧 DOM 上还留着这些写回值,\n // 此刻现读会把机器自己的产物误当声明、条目再也解不开。\n // 头一回见到这个条目时,DOM 上还只有作者写的东西(本帧的写回尚未发生),\n // 此刻无论整组禁没禁用都记得下真声明。少了这一条,「挂载那刻就整组禁用」\n // 会一路没有快照,解禁时退回现读、读到机器自己写的 true,整组就此永久锁死。\n if (!this.declaredDisabled.has(el)) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n if (!this.disabled && !this.wasGroupDisabled) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 整组禁用那几帧(以及解禁当帧)DOM 上留着机器的写回值,只认快照\n return { value, disabled: this.declaredDisabled.get(el)! }\n }\n\n protected wire(): void {\n const api = connectToggleGroup(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled。\n // 打上去的 data-scope/data-part/data-value 正是键盘导航在事件那一刻查 DOM 的依据,\n // 所以 wire 必须先于事件跑过——updated() 已保证。\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps(this.itemProps(el)) as Record<string, unknown>)\n\n // 本帧的写回已落地,下一帧才知道 DOM 上的 aria-disabled 可不可信\n this.wasGroupDisabled = !!this.disabled\n }\n}\n","import type { ToolbarItemProps, ToolbarSchema } from '@xihan-ui/headless'\nimport type { Direction, Orientation, Size } from '@xihan-ui/kernel'\nimport { isItemDisabled, ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectToolbar, toolbarAnatomy, toolbarMachine, toolbarMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 字符串属性统一走这个转换器:属性缺席即 undefined,缺省值的唯一事实源留在 connect。\n// Lit 默认转换器会在属性被移除时把值落成 null,那样就再也表达不了\"未指定\"。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n// 布尔三态:缺席 = undefined(用 connect 的默认值),=\"false\" = false,其余 = true。\n// Lit 自带的 Boolean 转换器是 v !== null,缺省为真的 loop 会因此永远关不掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-toolbar>` —— Light-DOM 行为宿主:作者写 root、若干 item,可选的 group 与 separator,\n * 元素跑 toolbar 机器并把 connect 产出打上去。\n *\n * 工具条只管两件事:整条一个 Tab 位的方向键导航,以及 role=toolbar / role=group /\n * role=separator 这套 ARIA。条目自己是按钮、切换钮还是下拉触发器,各自的角色、按下态与\n * 点击行为一律归它自己——元素不覆盖条目的 role,也不接管条目的 click。\n * 条目身份取写在条目上的 value 属性;禁用由条目自报 aria-disabled\n * (集合条目一律如此,原生 disabled 不可聚焦、就当不成方向键的起点)。\n * 落在 form 里的按钮式条目记得自己写 type=\"button\",否则回车会直接提交表单。\n *\n * 导航在事件那一刻按 data-scope+data-part 查活 DOM,依赖 connect 回写的 data-value,\n * 因此 wire 必须先于交互跑过(基类 updated 已保证)。\n *\n * @customElement xh-toolbar\n * @attr {'horizontal'|'vertical'} orientation - 主轴,默认 horizontal;横排收左右键、竖排收上下键,另一轴放行给页面\n * @attr {'ltr'|'rtl'} dir - 文字方向,只改写水平主轴上左右方向键的语义,默认 ltr\n * @attr {boolean} loop - 方向键走到尽头回绕,默认开启;写 loop=\"false\" 关掉\n * @attr {boolean} disabled - 整条禁用:条目全转 aria-disabled,方向键不再接管\n * @attr {'sm'|'md'|'lg'} size - 尺寸:只换条目间距与整条内边距,条目自身的大小归条目\n * @csspart root - role=toolbar 的容器(键盘在此收口,也是 roving tabindex 的兜底位)\n * @csspart group - role=group 的小分组,装一串相关控件\n * @csspart item - 工具条条目,须自带 value 属性标识身份;禁用写 aria-disabled=\"true\"\n * @csspart separator - role=separator 分隔线,朝向恒与主轴垂直\n */\nexport class XhToolbarElement extends XhElement {\n static override partContract = { anatomy: toolbarAnatomy, meta: toolbarMeta }\n\n // dir 占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。别名保留原生行为,\n // 同时让 dir 进 observedAttributes——运行期改 dir 才会重跑 wire 换掉按键处理器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n orientation: { converter: STRING_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n loop: { converter: BOOLEAN_CONVERTER },\n disabled: { converter: BOOLEAN_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare orientation?: Orientation\n declare direction?: Direction\n declare loop?: boolean\n declare disabled?: boolean\n declare size?: Size\n\n // 整条禁用期间的条目自身声明快照。connect 每帧都把 aria-disabled 写回条目,整条禁用更是写满每一个,\n // 此时回读分不清「作者声明的」还是「自己上一帧写的」,解禁后条目就永远解不开。\n private readonly declaredDisabled = new WeakMap<HTMLElement, boolean>()\n /** 上一帧是否整条禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */\n private wasToolbarDisabled = false\n\n // toolbar 机器无副作用:不需要 config/layer/refs,controller 只带 props。\n private readonly ctrl = new MachineController<ToolbarSchema>(this, toolbarMachine, () => this.machineProps())\n\n private machineProps(): Partial<ToolbarSchema['props']> {\n return {\n orientation: this.orientation,\n dir: this.direction,\n // 布尔一律原样透传:属性不在即 undefined,把缺省交回 connect(loop 默认开、disabled 默认关)\n loop: this.loop,\n disabled: this.disabled,\n size: this.size,\n }\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * 容器判自己\"焦点在条内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 整条零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 上,分组与分隔线离场不会误判;\n // 只有走的正是持有锚点的那个条目才报,否则删任一无关条目都会清掉方向键起点\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'TOOLBAR.BLUR' })\n }\n\n private itemProps(el: HTMLElement): ToolbarItemProps {\n const value = el.getAttribute('value') ?? ''\n // 只有「本帧与上一帧都没整条禁用」时,节点上的 aria-disabled 才等于作者声明:\n // 整条禁用那几帧 connect 把每个条目都写成了 true,解禁当帧 DOM 上还留着这些写回值,\n // 此刻现读会把机器自己的产物误当声明、条目再也解不开。\n // 头一回见到这个条目时,DOM 上还只有作者写的东西(本帧的写回尚未发生),\n // 此刻无论整条禁没禁用都记得下真声明。少了这一条,「挂载那刻就整条禁用」\n // 会一路没有快照,解禁时退回现读、读到机器自己写的 true,整条就此永久锁死。\n if (!this.declaredDisabled.has(el)) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n if (!this.disabled && !this.wasToolbarDisabled) {\n const own = isItemDisabled(el)\n this.declaredDisabled.set(el, own)\n return { value, disabled: own }\n }\n // 整条禁用那几帧(以及解禁当帧)DOM 上留着机器的写回值,只认快照\n return { value, disabled: this.declaredDisabled.get(el)! }\n }\n\n protected wire(): void {\n const api = connectToolbar(this.ctrl.service, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 分组与分隔线都是多实例 part,且属性与身份无关,逐个打同一份产出即可\n for (const el of this.getParts('group'))\n this.spreader.spread(el, api.getGroupProps() as Record<string, unknown>)\n for (const el of this.getParts('separator'))\n this.spreader.spread(el, api.getSeparatorProps() as Record<string, unknown>)\n\n // 条目逐个打:身份取作者写的 value,禁用取部件自报的 aria-disabled。\n // 打上去的 data-scope/data-part/data-value 正是方向键在事件那一刻查 DOM 的依据,\n // 所以 wire 必须先于事件跑过——updated() 已保证。\n for (const el of this.getParts('item'))\n this.spreader.spread(el, api.getItemProps(this.itemProps(el)) as Record<string, unknown>)\n\n // 本帧的写回已落地,下一帧才知道 DOM 上的 aria-disabled 可不可信\n this.wasToolbarDisabled = !!this.disabled\n }\n}\n","import type { TooltipOpenChangeDetails, TooltipSchema } from '@xihan-ui/headless'\nimport type { Placement, PositionEnginePort, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectTooltip, tooltipAnatomy, tooltipMachine, tooltipMeta } from '@xihan-ui/headless'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 字符串属性统一走这个转换器:属性缺席即 undefined,缺省值的唯一事实源留在机器。\n// Lit 默认转换器会在属性被移除时把值落成 null,那样就再也表达不了\"没写过\"。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n// 数值属性同理;写不成数的值(文字、单位后缀)当作没写,缺省仍由机器给。\nconst NUMBER_CONVERTER = {\n fromAttribute: (v: string | null) => {\n if (v === null)\n return undefined\n const n = Number(v)\n return Number.isFinite(n) ? n : undefined\n },\n}\n\n/**\n * `<xh-tooltip>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/arrow 角色节点,\n * 元素跑 tooltip 机器并把 connect 产出打上去。浮层坐标由本元素建的定位引擎算出,\n * 经 refs 交给机器的定位效应;引擎或角色节点缺席时机器照常转移,只是不产出坐标。\n *\n * @customElement xh-tooltip\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {string} placement - 请求的浮层朝向(top/right/bottom/left,可带 -start/-end 后缀),默认 bottom;空间不足时由引擎避让\n * @attr {number} offset - 浮层与锚点的间距(px),默认 8\n * @attr {number} open-delay - 悬停进入到展开的等待毫秒,默认 700\n * @attr {number} close-delay - 悬停移出到收起的等待毫秒,默认 300\n * @attr {boolean} disabled - 只关掉提示,被包裹的控件仍可用\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart trigger - 悬停/聚焦的锚点按钮(aria-describedby 指向 content)\n * @csspart positioner - 浮层定位容器(坐标写成内联样式,落定朝向在 data-placement)\n * @csspart content - role=tooltip 的提示内容(收起时 hidden)\n * @csspart arrow - 指向锚点的箭头,装饰性\n */\nexport class XhTooltipElement extends XhElement {\n static override partContract = { anatomy: tooltipAnatomy, meta: tooltipMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') } },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n openDelay: { converter: NUMBER_CONVERTER, attribute: 'open-delay' },\n closeDelay: { converter: NUMBER_CONVERTER, attribute: 'close-delay' },\n disabled: { type: Boolean },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare placement?: Placement\n declare offset?: number\n declare openDelay?: number\n declare closeDelay?: number\n declare disabled?: boolean\n declare tone?: Tone\n declare size?: Size\n\n private engine: PositionEnginePort | null = null\n\n private readonly notify = (details: TooltipOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<TooltipSchema>(\n this,\n tooltipMachine,\n () => this.machineProps(),\n { onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<TooltipSchema['props']> {\n return {\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n openDelay: this.openDelay,\n closeDelay: this.closeDelay,\n disabled: this.disabled ?? false,\n tone: this.tone,\n size: this.size,\n onOpenChange: this.notify,\n }\n }\n\n // 每次(重)建机器后都要重注:refs 属于机器实例,重连时的新机器不会继承旧的。\n // service 取参数不取 this.ctrl,重建时不依赖字段已回填。\n private injectRefs(svc: Service<TooltipSchema>): void {\n // 无 DOM(SSR / 纯逻辑测试)时不建引擎,机器读到 null 会跳过定位\n if (!this.engine && typeof document !== 'undefined')\n this.engine = createPositionEngine()\n svc.refs.set('position', this.engine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n }\n\n /**\n * 机器在 hostConnected 就挂载,初始即展开(open / default-open)时定位效应当场执行;\n * 而基类要到首次 updated 才发现角色节点,refs 的 getter 此刻取到 null,引擎静默跳过,\n * 之后状态不变就没有第二次机会——浮层会停在 0,0。故连接时先自行发现一次。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n protected wire(): void {\n const api = connectTooltip(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是坐标对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n // 提示内容常挂,收起时由 connect 输出 hidden。这里不做内联 display 兜底:\n // styled 的 [data-part=content] 只设 pointer-events/尺寸/配色,\n // [data-part=positioner] 只设 position/inset/z-index/pointer-events,两处都没有 display 声明,\n // UA 的 [hidden]{display:none} 压得住(collapsible/dialog 那两处 author 层给了 display,\n // 才必须用内联样式盖过)。\n put('content', api.getContentProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n // 本仓自带的 tooltip.css 确实没给 content 设 display,但宿主不该指望作者装了这份样式:\n // 作者层只要给 content 来一句 display(Tailwind 的 flex/block 也算),\n // 就会盖过 UA 的 [hidden]{display:none},收起态的提示框会永久悬在页面上。\n // 与 dialog/collapsible/popover 一致,用内联样式兜底。\n const content = this.getPart('content')\n if (content)\n this.setPartHidden(content, !api.open)\n }\n}\n","import type {\n TourCompleteDetails,\n TourOpenChangeDetails,\n TourSchema,\n TourSkipDetails,\n TourStep,\n TourStepChangeDetails,\n TourTranslations,\n} from '@xihan-ui/headless'\nimport type { Cleanup, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectTour, tourAnatomy, tourMachine, tourMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(Esc 退出、画遮罩)只有三态才关得掉。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/**\n * `<xh-tour>` —— Light-DOM 行为宿主:用户写 root/backdrop/spotlight/positioner/content/... 角色节点,\n * 元素跑 tour 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,\n * 锚点是每一步 target 选择器查出来的页面节点(由机器解析),被定位的浮层取 positioner。\n *\n * @customElement xh-tour\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {number} step - 受控步序(0 起);缺省该属性即非受控\n * @attr {number} default-step - 非受控初始步序,默认 0\n * @attr {string} placement - 整份引导的首选放置位,默认 bottom;单步可用自己的 placement 覆盖\n * @attr {number} offset - 气泡与目标的间距(px)\n * @attr {boolean} close-on-escape - Esc 放弃引导,默认 true;写 close-on-escape=\"false\" 关掉\n * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 false;写 \"true\" 打开\n * @attr {boolean} show-backdrop - 画遮罩,默认 true;写 show-backdrop=\"false\" 关掉\n * @attr {number} spotlight-padding - 高亮框在目标四周留出的空白(px),默认 8\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @fires step-change - 步序变化;detail 为 `{ step: number }`\n * @fires complete - 末步再按下一步;detail 为 `{ step: number }`\n * @fires skip - 用户放弃(跳过按钮或 Escape);detail 为 `{ step: number }`\n * @csspart root - 引导根节点(data-state/data-step 所在)\n * @csspart backdrop - 遮罩层(aria-hidden;showBackdrop 为假时带 hidden)\n * @csspart spotlight - 挖洞的高亮框,位置尺寸由内联 style 给出;居中步带 hidden\n * @csspart positioner - 浮层定位容器;锚定步坐标由引擎写成内联样式,居中步交给样式表摆\n * @csspart content - 引导浮层(role=dialog + aria-modal;焦点域与消解层的根节点),收起时带 hidden\n * @csspart title - 标题(aria-labelledby 目标);作者没写内容时由元素填当前步的 title\n * @csspart description - 描述(aria-describedby 目标);作者没写内容时填当前步的 description\n * @csspart progress-text - \"第 m 步,共 n 步\"(aria-live=polite);作者没写内容时由元素填\n * @csspart prev-trigger - 上一步(首步时原生 disabled)\n * @csspart next-trigger - 下一步(末步带 data-last,语义是\"完成\")\n * @csspart skip-trigger - 跳过(发 skip 事件后关闭)\n * @csspart close-trigger - 关闭(只关,不算放弃)\n * @csspart arrow - 指向目标的箭头(aria-hidden;居中步带 hidden)\n */\nexport class XhTourElement extends XhElement {\n static override partContract = { anatomy: tourAnatomy, meta: tourMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n step: { converter: NUMBER_CONVERTER },\n defaultStep: { converter: NUMBER_CONVERTER, attribute: 'default-step' },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n closeOnEscape: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-escape' },\n closeOnInteractOutside: { converter: BOOLEAN_CONVERTER, attribute: 'close-on-interact-outside' },\n showBackdrop: { converter: BOOLEAN_CONVERTER, attribute: 'show-backdrop' },\n spotlightPadding: { converter: NUMBER_CONVERTER, attribute: 'spotlight-padding' },\n // 对象值进不了属性,只作为 property 暴露\n steps: { attribute: false },\n translations: { attribute: false },\n }\n\n declare open?: boolean\n declare defaultOpen?: boolean\n declare step?: number\n declare defaultStep?: number\n declare placement?: Placement\n declare offset?: number\n declare closeOnEscape?: boolean\n declare closeOnInteractOutside?: boolean\n declare showBackdrop?: boolean\n declare spotlightPadding?: number\n /** 步骤清单。它是步序的上界,也是读屏\"第 m 步,共 n 步\"的分母。 */\n declare steps?: TourStep[]\n /** 关闭按钮的无障碍名与进度文案;connect 每帧重写,作者写在节点上会被盖掉,只能从这里给。 */\n declare translations?: Partial<TourTranslations>\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly tourScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n private contentNode: HTMLElement | null = null\n private backdropNode: HTMLElement | null = null\n /** 哪些文本节点归元素填:作者自己写了内容的一概不碰。 */\n private readonly ownsText = new WeakMap<HTMLElement, boolean>()\n\n private readonly emit = (type: string, detail: unknown): void => {\n this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: TourOpenChangeDetails): void => this.emit('open-change', details)\n private readonly notifyStep = (details: TourStepChangeDetails): void => this.emit('step-change', details)\n private readonly notifyComplete = (details: TourCompleteDetails): void => this.emit('complete', details)\n private readonly notifySkip = (details: TourSkipDetails): void => this.emit('skip', details)\n\n private readonly ctrl = new MachineController<TourSchema>(\n this,\n tourMachine,\n () => this.machineProps(),\n { scope: this.tourScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<TourSchema['props']> {\n return {\n steps: this.steps,\n step: this.step,\n defaultStep: this.defaultStep,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n placement: this.placement,\n offset: this.offset,\n closeOnEscape: this.closeOnEscape,\n closeOnInteractOutside: this.closeOnInteractOutside,\n showBackdrop: this.showBackdrop,\n spotlightPadding: this.spotlightPadding,\n translations: this.translations,\n onOpenChange: this.notifyOpen,\n onStepChange: this.notifyStep,\n onComplete: this.notifyComplete,\n onSkip: this.notifySkip,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.tourScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n // 连接期就注册会让层常驻栈里占着栈顶,把同页其它层的 Escape 堵死。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'modal',\n node: () => this.contentNode,\n branches: () => [],\n isModal: () => true,\n setModal: () => {},\n // 遮罩是\"点它就该关本层\"的表面;关不关仍由 closeOnInteractOutside 说了算(缺省不关)\n surfaces: () => [this.backdropNode].filter(Boolean) as Element[],\n })\n }\n\n // onBuilt 在机器建好、启动之前跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n private injectRefs(svc: Service<TourSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n // 机器启动前先接一次线。default-open 时机器在紧接着的 mount 里当场进入 open,\n // 焦点域会在同一拍里挑落点——那一刻 content 若还没被写上 tabindex 就不可聚焦,\n // 焦点只能推到下一帧才落下,而 Vue 侧首帧就已经接好线、焦点当场落定:两侧首帧分叉。\n // 角色节点由 connectedCallback 里的 refreshParts 提前发现,这里已经够得着。\n this.wireWith(svc)\n }\n\n /**\n * 角色节点提前发现一次:default-open 时机器在 hostConnected 当场进入 open,\n * 定位副作用同步取一次 positioner——而常规发现要等首次 updated,\n * 那一刻 partMap 还空着,引擎挂不上,浮层会停在容器左上角。\n * 消解层与焦点域的 ref 是懒读的,不受影响,这里只为定位补上时机。\n */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 标题、描述与进度文案的文字只有步骤清单里才有,作者在标记里写不出来(每步都不一样),\n * 由元素填。作者若自己写了内容(自定义渲染),首次见到时就定为归作者,之后一概不碰——\n * 每帧回读分不清\"作者写的\"还是\"上一帧自己写的\",一旦写过就再也让不回去。\n */\n private fillText(el: HTMLElement | null, text: string | undefined): void {\n if (!el || text === undefined)\n return\n let owned = this.ownsText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n this.wireWith(this.ctrl.service)\n }\n\n // service 由参数传入:机器启动前的那次接线发生在 this.ctrl 赋值之前,取不到 this.ctrl.service\n private wireWith(svc: Service<TourSchema>): void {\n const api = connectTour(svc, wcNormalize)\n\n this.contentNode = this.getPart('content')\n this.backdropNode = this.getPart('backdrop')\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('backdrop', api.getBackdropProps() as Record<string, unknown>)\n // spotlight 与 positioner 的 style 是对象(position/inset/尺寸),\n // spreader 见对象 style 会逐条写内联样式,直接 spread 即可\n put('spotlight', api.getSpotlightProps() as Record<string, unknown>)\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('title', api.getTitleProps() as Record<string, unknown>)\n put('description', api.getDescriptionProps() as Record<string, unknown>)\n put('progress-text', api.getProgressTextProps() as Record<string, unknown>)\n put('prev-trigger', api.getPrevTriggerProps() as Record<string, unknown>)\n put('next-trigger', api.getNextTriggerProps() as Record<string, unknown>)\n put('skip-trigger', api.getSkipTriggerProps() as Record<string, unknown>)\n put('close-trigger', api.getCloseTriggerProps() as Record<string, unknown>)\n put('arrow', api.getArrowProps() as Record<string, unknown>)\n\n this.fillText(this.getPart('title'), api.currentStep?.title)\n this.fillText(this.getPart('description'), api.currentStep?.description)\n this.fillText(this.getPart('progress-text'), api.progressText)\n\n // Light DOM 常驻,WC 自管可见性:connect 已经给这几个角色发了 hidden,但样式表里\n // 只要给它们声明过 display(本仓的 tour.css 给 positioner/content/spotlight 都声明了),\n // author 层就会盖掉 UA 的 [hidden]{display:none}。宿主不能指望作者装的是哪一份样式,\n // 只有内联 style.display 压得住;展开时还回作者原本写的内联值。\n for (const name of ['backdrop', 'spotlight', 'positioner', 'content', 'arrow']) {\n const el = this.getPart(name)\n if (el)\n this.setPartHidden(el, el.hasAttribute('hidden'))\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层由展开态的效应自己入栈出栈,断开时机器停机会一并撤掉,这里无需再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type {\n TransferFilter,\n TransferItem,\n TransferSchema,\n TransferSelectedChangeDetails,\n TransferSide,\n TransferValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Direction } from '@xihan-ui/kernel'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTransfer, transferAnatomy, transferFocusKey, transferMachine, transferMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(方向键回绕)只有三态才关得掉——\n// Lit 默认的 Boolean 转换器是 v !== null,写 loop=\"false\" 照样是真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\nconst SIDES: readonly TransferSide[] = ['source', 'target']\n\n/**\n * 读条目节点上作者写的原生 disabled,顺手摘掉。\n *\n * 集合条目的禁用一律由 aria-disabled 表达(禁用声明的事实源是 items,不是标记):\n * 原生禁用的节点不可聚焦、也收不到 click,「禁用项仍是方向键起点、仍挡得住点击」\n * 这两条在原生 disabled 下根本无从成立。摘掉之后禁用态由 connect 写回的 aria-disabled 承接。\n */\nfunction stripNativeDisabled(el: HTMLElement): void {\n if (el.hasAttribute('disabled'))\n el.removeAttribute('disabled')\n}\n\n/**\n * `<xh-transfer>` —— Light-DOM 行为宿主:作者写\n * root/source-panel/target-panel/panel-header/panel-title/panel-count/search/list/item/...\n * 角色节点,元素跑 transfer 机器并把 connect 产出打上去。\n *\n * 条目全集由 `items` 属性(property)给出,它是标签与禁用的唯一事实源;\n * **两侧面板各挂一份全集**,不属于本侧、或被搜索筛掉的那一份由元素打上 hidden,\n * 节点不卸载。条目身份取节点上的 `value` 属性,归哪一侧则取它落在哪个面板里。\n *\n * 过滤由本元素做,不是作者做:搜索串住在机器里,作者最多给一个 `filter` 谓词。\n *\n * 导航与勾选在事件那一刻按 data-scope+data-part 查活 DOM,依赖 connect 回写的 data-value,\n * 因此 wire 必须先于交互跑过(基类 updated 已保证)。\n *\n * 集合类输入(items / value / selected / filter)都表达不成属性,只能走 property:\n * `el.items = [...]`、`el.value = ['a']`。\n *\n * @customElement xh-transfer\n * @attr {boolean} searchable - 每侧带一个搜索框;关掉时搜索框仍在 DOM 里但带 hidden\n * @attr {boolean} disabled - 整个控件禁用:条目转 aria-disabled,按钮与搜索框用原生 disabled\n * @attr {boolean} one-way - 只能往右不能往回:往回搬那条路封死,右侧也不再接受勾选\n * @attr {boolean} loop - 列表内方向键走到尽头回绕,默认 true;写 loop=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,决定列表内哪个横向方向键是\"搬向对面\",默认 ltr\n * @fires value-change - 落在右侧的值变化;detail 为 `{ value: string[] }`\n * @fires selected-change - 勾选集合变化;detail 为 `{ selected: string[] }`\n * @csspart root - 组件根容器(承载 data-disabled/data-one-way)\n * @csspart source-panel - 左侧面板容器,其内的角色节点一律归左侧\n * @csspart target-panel - 右侧面板容器,其内的角色节点一律归右侧\n * @csspart panel-header - 面板头部容器(标题、计数、全选格的落脚处)\n * @csspart panel-title - 面板标题(本侧 list 与搜索框 aria-labelledby 的目标)\n * @csspart panel-count - 计数节点,只带 data-count / data-checked-count,文案由作者写\n * @csspart search - 本侧搜索框,须是原生 input;searchable 关掉时带 hidden\n * @csspart list - role=listbox 容器,键盘在此收口,也是 roving tabindex 的兜底位\n * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写在 items 里,不写在节点上\n * @csspart item-text - 条目文本\n * @csspart item-checkbox - 条目勾选标记(aria-hidden);oneWay 下右侧的那一份带 hidden\n * @csspart select-all-trigger - 本侧全选格,须是原生 button;三态经 aria-checked 上报\n * @csspart to-target-trigger - 往右搬的按钮,须是原生 button\n * @csspart to-source-trigger - 往左搬的按钮,须是原生 button;oneWay 下恒为禁用\n */\nexport class XhTransferElement extends XhElement {\n static override partContract = { anatomy: transferAnatomy, meta: transferMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n items: { attribute: false },\n value: { attribute: false },\n defaultValue: { attribute: false },\n selected: { attribute: false },\n defaultSelected: { attribute: false },\n filter: { attribute: false },\n searchable: { type: Boolean },\n disabled: { type: Boolean },\n oneWay: { type: Boolean, attribute: 'one-way' },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n }\n\n declare items?: TransferItem[]\n declare value?: string[]\n declare defaultValue?: string[]\n declare selected?: string[]\n declare defaultSelected?: string[]\n declare filter?: TransferFilter\n declare searchable?: boolean\n declare disabled?: boolean\n declare oneWay?: boolean\n declare loop?: boolean\n declare direction?: Direction\n\n private readonly notifyValue = (details: TransferValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelected = (details: TransferSelectedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('selected-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // transfer 机器无副作用、无 refs(两侧集合全部从 items + value + 搜索串推导),\n // 不需要 config / 定位引擎,故 controller 只带 props。\n private readonly ctrl = new MachineController<TransferSchema>(this, transferMachine, () => this.machineProps())\n\n private machineProps(): Partial<TransferSchema['props']> {\n return {\n items: this.items,\n value: this.value,\n defaultValue: this.defaultValue,\n selected: this.selected,\n defaultSelected: this.defaultSelected,\n filter: this.filter,\n searchable: this.searchable ?? false,\n disabled: this.disabled ?? false,\n oneWay: this.oneWay ?? false,\n loop: this.loop,\n dir: this.direction,\n onValueChange: this.notifyValue,\n onSelectedChange: this.notifySelected,\n }\n }\n\n /**\n * 承载焦点的条目被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * 列表容器判自己\"焦点在组内\"退出 Tab 序列,又没有条目认领得了这个锚点,\n * 这一侧零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n for (const side of SIDES) {\n const focused = context.get(transferFocusKey(side))\n if (focused == null)\n continue\n // data-value 只写在 item 上,条目内的文本与勾选标记离场不会误判;\n // 再比一次 data-side,另一侧那份同值节点离场才不会把本侧的锚点清掉\n const gone = nodes.some(el =>\n el.getAttribute(ITEM_VALUE_ATTR) === focused && el.getAttribute('data-side') === side)\n if (gone)\n send({ type: 'LIST.BLUR', side })\n }\n }\n\n // 面板内的子部件:getParts 收的是整个元素范围,按子树过滤才归得对\n // (两侧共用同一套 part 名,不过滤就会把对面那份也算进来)。\n private partsIn(owner: HTMLElement, name: string): HTMLElement[] {\n return this.getParts(name).filter(el => owner.contains(el))\n }\n\n protected wire(): void {\n const api = connectTransfer(this.ctrl.service, wcNormalize)\n\n const put = (el: HTMLElement | null, props: Record<string, unknown>): void => {\n if (el)\n this.spreader.spread(el, props)\n }\n put(this.getPart('root'), api.getRootProps() as Record<string, unknown>)\n put(this.getPart('to-target-trigger'), api.getToTargetTriggerProps() as Record<string, unknown>)\n put(this.getPart('to-source-trigger'), api.getToSourceTriggerProps() as Record<string, unknown>)\n\n for (const side of SIDES) {\n const panel = this.getPart(`${side}-panel`)\n if (!panel)\n continue\n const props = { side }\n this.spreader.spread(panel, api.getPanelProps(props) as Record<string, unknown>)\n for (const el of this.partsIn(panel, 'panel-header'))\n this.spreader.spread(el, api.getPanelHeaderProps(props) as Record<string, unknown>)\n for (const el of this.partsIn(panel, 'panel-title'))\n this.spreader.spread(el, api.getPanelTitleProps(props) as Record<string, unknown>)\n for (const el of this.partsIn(panel, 'panel-count'))\n this.spreader.spread(el, api.getPanelCountProps(props) as Record<string, unknown>)\n for (const el of this.partsIn(panel, 'select-all-trigger'))\n this.spreader.spread(el, api.getSelectAllTriggerProps(props) as Record<string, unknown>)\n\n // Light DOM 常驻,WC 自管可见性:作者层若给这些 part 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来。\n // 收不收起的判据一律取 connect 的产出,不在这里重算一遍——重算就会分叉。\n for (const el of this.partsIn(panel, 'search')) {\n const search = api.getSearchProps(props) as Record<string, unknown>\n this.spreader.spread(el, search)\n this.setPartHidden(el, search.hidden === true)\n }\n\n for (const el of this.partsIn(panel, 'list'))\n this.spreader.spread(el, api.getListProps(props) as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value,归属取它落在哪个面板里\n for (const el of this.partsIn(panel, 'item')) {\n stripNativeDisabled(el)\n const item = { value: el.getAttribute('value') ?? '', side }\n const itemProps = api.getItemProps(item) as Record<string, unknown>\n this.spreader.spread(el, itemProps)\n this.setPartHidden(el, itemProps.hidden === true)\n // 条目内的文本与勾选标记跟着同一份声明走,样式层各处状态一致\n for (const text of this.partsIn(el, 'item-text'))\n this.spreader.spread(text, api.getItemTextProps(item) as Record<string, unknown>)\n for (const box of this.partsIn(el, 'item-checkbox')) {\n const boxProps = api.getItemCheckboxProps(item) as Record<string, unknown>\n this.spreader.spread(box, boxProps)\n this.setPartHidden(box, boxProps.hidden === true)\n }\n }\n }\n }\n}\n","import type { TreeExpandedChangeDetails, TreeNode, TreeNodeProps, TreeSchema, TreeSelectionChangeDetails, TreeSelectionMode } from '@xihan-ui/headless'\nimport type { Direction } from '@xihan-ui/kernel'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTree, treeAnatomy, treeMachine, treeMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// 缺省为真的开关(点行展开、连打检索)只有三态才关得掉——\n// Lit 默认的 Boolean 转换器是 v !== null,写 expand-on-click=\"false\" 照样是真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 叶子一系的归属容器。 */\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n/** 分支一系的归属容器;嵌套分支各认最近的那个。 */\nconst BRANCH_SELECTOR = '[data-xh-part=\"branch\"]'\n\n/**\n * `<xh-tree>` —— Light-DOM 行为宿主:作者写 root/label/tree 与若干 item / branch 角色节点,\n * 元素跑 tree 机器并把 connect 产出打上去。节点身份取自节点上的 value 属性。\n *\n * 层级(aria-level / aria-posinset / aria-setsize)与禁用都不从 DOM 反推,而是查 `collection`\n * 这份树数据——它是元信息的唯一事实源,作者的标记只管长相,两个适配器也就不会各推各的。\n * 因此 collection 必须与标记同源:标记里有、collection 里没有的节点报不出层级,也进不了导航。\n *\n * 树数据与展开/选中集合都是数组,属性表达不了,只能走 property(`el.collection = [...]`)。\n *\n * @customElement xh-tree\n * @attr {'single'|'multiple'} selection-mode - 选择模式,默认 single\n * @attr {boolean} expand-on-click - 点分支行顺带展开/收起,默认开;写 expand-on-click=\"false\" 关掉\n * @attr {boolean} disabled - 整棵树禁用:所有节点转 aria-disabled,键盘与点击都改不了展开与选中\n * @attr {boolean} loop - 上下键走到首尾回绕,默认关;写 loop=\"true\" 打开\n * @attr {boolean} typeahead - 连打检索,默认开;写 typeahead=\"false\" 关掉\n * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的展开/收起语义,默认 ltr\n * @fires expanded-change - 展开集合变化;detail 为 `{ value: string[] }`\n * @fires selection-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @csspart root - 组件根容器\n * @csspart label - 树标题(aria-labelledby 目标)\n * @csspart tree - role=tree 容器,键盘在此收口,也是 roving tabindex 的兜底位\n * @csspart item - role=treeitem 叶子,须自带 value 属性标识身份\n * @csspart item-text - 叶子文本\n * @csspart item-indicator - 叶子选中标记(aria-hidden)\n * @csspart branch - role=treeitem 分支,须自带 value 属性;它裹着自己的 branch-content\n * @csspart branch-control - 分支可点行(选中 + 按 expand-on-click 切换展开)\n * @csspart branch-trigger - 展开箭头(aria-hidden 且不占 Tab 位,只切换展开态)\n * @csspart branch-indicator - 展开方向指示符(aria-hidden)\n * @csspart branch-text - 分支文本\n * @csspart branch-content - role=group 子层容器,收起时隐藏\n */\nexport class XhTreeElement extends XhElement {\n static override partContract = { anatomy: treeAnatomy, meta: treeMeta }\n\n // dir 只占属性名、字段改叫 direction:HTMLElement 原生 dir 是 string 访问器,\n // 同名声明既与基类类型冲突,也会盖掉原生反射。别名保留原生行为,\n // 同时让 dir 进 observedAttributes——运行期改 dir 才会重跑 wire 换掉按键处理器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n collection: { attribute: false },\n expandedValue: { attribute: false },\n defaultExpandedValue: { attribute: false },\n selectedValue: { attribute: false },\n defaultSelectedValue: { attribute: false },\n selectionMode: { converter: STRING_CONVERTER, attribute: 'selection-mode' },\n expandOnClick: { converter: BOOLEAN_CONVERTER, attribute: 'expand-on-click' },\n disabled: { type: Boolean },\n loop: { converter: BOOLEAN_CONVERTER },\n typeahead: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n }\n\n declare collection?: TreeNode[]\n declare expandedValue?: string[]\n declare defaultExpandedValue?: string[]\n declare selectedValue?: string[]\n declare defaultSelectedValue?: string[]\n declare selectionMode?: TreeSelectionMode\n declare expandOnClick?: boolean\n declare disabled?: boolean\n declare loop?: boolean\n declare typeahead?: boolean\n declare direction?: Direction\n\n private readonly notifyExpanded = (details: TreeExpandedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('expanded-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifySelection = (details: TreeSelectionChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('selection-change', { detail: details, bubbles: true, composed: true }))\n }\n\n // tree 机器无副作用(连打缓冲住在 refs 里、由机器自己建),\n // 不需要 config/layer/定位引擎,故 controller 只带 props。\n private readonly ctrl = new MachineController<TreeSchema>(this, treeMachine, () => this.machineProps())\n\n private machineProps(): Partial<TreeSchema['props']> {\n return {\n collection: this.collection,\n expandedValue: this.expandedValue,\n // 机器自己兜 undefined,这里不补 []:props 每次读都新建数组会造成无谓的引用变动\n defaultExpandedValue: this.defaultExpandedValue,\n selectedValue: this.selectedValue,\n defaultSelectedValue: this.defaultSelectedValue,\n selectionMode: this.selectionMode,\n expandOnClick: this.expandOnClick,\n disabled: this.disabled ?? false,\n loop: this.loop,\n typeahead: this.typeahead,\n dir: this.direction,\n onExpandedChange: this.notifyExpanded,\n onSelectionChange: this.notifySelection,\n }\n }\n\n /**\n * 承载焦点的节点被移出 DOM 时浏览器不派 focusout,焦点锚点会停在一个已消失的值上:\n * 容器判自己\"焦点在树内\"退出 Tab 序列,又没有节点认领得了这个锚点,\n * 整棵树零个 Tab 停靠点,键盘用户再也进不来。这里替 DOM 把焦点离场如实上报。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, send } = this.ctrl.service\n // 宿主断开时机器已停机,此刻无焦点可言(送事件还会在 dev 下抛)\n if (getStatus() !== 'Started')\n return\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n // data-value 只写在 item 与 branch 上,行内的文本与标记离场不会误判;\n // 只有走的正是持有锚点的那个节点才报,否则删任一无关节点都会清掉方向键起点\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'TREE.BLUR' })\n }\n\n /**\n * 取角色节点所属的节点身份:value 写在 item / branch 上,行内的文本、标记、箭头与子层容器\n * 向上找最近的那个(item / branch 自身 closest 命中的就是它自己)。\n * 没有包裹层时退回读节点自身,扁平写法也能用。\n * 越出本宿主的容器不算数——嵌套 xh-tree 的内层节点不会认外层的分支。\n */\n private nodeOf(el: HTMLElement, selector: string): TreeNodeProps {\n const owner = el.closest<HTMLElement>(selector)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n return { value: source.getAttribute('value') ?? '' }\n }\n\n protected wire(): void {\n const api = connectTree(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('tree', api.getTreeProps() as Record<string, unknown>)\n\n // 集合类 part 逐个 spread:身份由节点自报,不依赖下标,节点增删无需记账。\n // wire 跑在事件之前(element-base 的 updated),因此按键那一刻 data-scope/data-part/data-value\n // 已经在 DOM 上,连接层查得到本棵树的节点集合。\n const putAll = (name: string, selector: string, get: (node: TreeNodeProps) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(this.nodeOf(el, selector)) as Record<string, unknown>)\n }\n putAll('item', ITEM_SELECTOR, node => api.getItemProps(node))\n putAll('item-text', ITEM_SELECTOR, node => api.getItemTextProps(node))\n putAll('item-indicator', ITEM_SELECTOR, node => api.getItemIndicatorProps(node))\n putAll('branch', BRANCH_SELECTOR, node => api.getBranchProps(node))\n putAll('branch-control', BRANCH_SELECTOR, node => api.getBranchControlProps(node))\n putAll('branch-trigger', BRANCH_SELECTOR, node => api.getBranchTriggerProps(node))\n putAll('branch-indicator', BRANCH_SELECTOR, node => api.getBranchIndicatorProps(node))\n putAll('branch-text', BRANCH_SELECTOR, node => api.getBranchTextProps(node))\n putAll('branch-content', BRANCH_SELECTOR, node => api.getBranchContentProps(node))\n\n // Light DOM 子层常驻,WC 自管可见性:收起时隐藏 branch-content。\n // connect 已置 hidden,但 styled 给 [data-part=branch-content] 设了 display,\n // 会盖过 UA 的 [hidden]{display:none};内联 style.display 优先级更高,压得住。\n for (const el of this.getParts('branch-content'))\n this.setPartHidden(el, !api.isExpanded(this.nodeOf(el, BRANCH_SELECTOR).value))\n }\n}\n","import type {\n TreeNode,\n TreeSelectExpandedChangeDetails,\n TreeSelectNodeProps,\n TreeSelectOpenChangeDetails,\n TreeSelectSchema,\n TreeSelectValueChangeDetails,\n} from '@xihan-ui/headless'\nimport type { Cleanup, ControlVariant, Direction, IdGenerator, Layer, Placement, PositionEnginePort, RuntimeConfig, Size, Tone } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { ITEM_VALUE_ATTR } from '@xihan-ui/behavior'\nimport { connectTreeSelect, treeSelectAnatomy, treeSelectMachine, treeSelectMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createRuntimeConfig, createScope } from '@xihan-ui/kernel'\nimport { createPositionEngine } from '@xihan-ui/position'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定;Lit 自带转换器把缺席落成 null/false,\n// value 落成 null 就分不出\"非受控\"与\"受控且当前无选中\"。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : Number(v)) }\n// 三态布尔:缺席=undefined(走缺省)、在场=true、显式写 \"false\"=false。\n// Lit 默认的 Boolean 转换器是 v !== null,写 loop=\"false\" 照样是真。\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 叶子一系的归属容器。 */\nconst ITEM_SELECTOR = '[data-xh-part=\"item\"]'\n/** 分支一系的归属容器;嵌套分支各认最近的那个。 */\nconst BRANCH_SELECTOR = '[data-xh-part=\"branch\"]'\n\n/**\n * `<xh-tree-select>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/tree\n * 与若干 item / branch 角色节点,元素跑 tree-select 机器并把 connect 产出打上去。\n * 浮层定位引擎在本元素里建好、经 refs 注入机器,锚点取 trigger、被定位的浮层取 positioner;\n * 节点身份取节点上的 value 属性。\n *\n * 层级(aria-level / aria-posinset / aria-setsize)、禁用与显示文本都查 `collection` 这份树数据,\n * 不从 DOM 反推,故 collection 必须与标记同源。\n *\n * value-text 的显示文字由元素代填;作者在该节点里写了内容就归作者,元素不再改写。\n *\n * 树数据与展开/选中集合都是数组,只走 property(`el.collection = [...]`);\n * 单选的选中值可用 value 属性写成裸串。\n *\n * @customElement xh-tree-select\n * @attr {string} value - 受控选中值(单选简写);缺省该属性即非受控,多选请用 property 传数组\n * @attr {string} default-value - 非受控初始选中值\n * @attr {boolean} open - 受控开合;缺省该属性即非受控\n * @attr {boolean} default-open - 非受控初始为展开\n * @attr {boolean} multiple - 多选:选中后浮层不收起,焦点留在树里\n * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,表单出口不参与提交\n * @attr {boolean} read-only - 只读:浮层照常展开、树照常浏览,但选中值改不动、也清不掉\n * @attr {boolean} invalid - 校验失败标注\n * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体\n * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气\n * @attr {'sm'|'md'|'lg'} size - 尺寸\n * @attr {string} placeholder - 无选中时 value-text 显示的占位文字\n * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上\n * @attr {number} offset - 浮层与锚点的间距(px)\n * @attr {boolean} loop - 上下键走到首尾回绕,默认关;写 loop=\"true\" 打开\n * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的展开/收起语义,默认 ltr\n * @attr {string} name - 表单字段名;给了 hidden-input 才参与提交(多选按逗号拼成一串)\n * @fires value-change - 选中集合变化;detail 为 `{ value: string[] }`\n * @fires expanded-change - 展开集合变化;detail 为 `{ value: string[] }`\n * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`\n * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly/data-invalid)\n * @csspart label - 标题(aria-labelledby 目标)\n * @csspart trigger - role=combobox 的触发按钮,同时是定位锚点,须是原生 button\n * @csspart value-text - 选中项文本的显示位;留空即由元素填入 displayText,作者写了内容则归作者\n * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)\n * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏\n * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式\n * @csspart content - 浮层壳(焦点域与消解层的根节点),收起时带 hidden\n * @csspart tree - role=tree 容器,键盘在此收口,也是没有锚点时的 Tab 兜底位\n * @csspart item - role=treeitem 叶子,须自带 value 属性标识身份\n * @csspart item-text - 叶子文本\n * @csspart item-indicator - 叶子选中标记(aria-hidden)\n * @csspart branch - role=treeitem 分支,须自带 value 属性;它裹着自己的 branch-content\n * @csspart branch-control - 分支可点行(点它只改选中值,展开归箭头与左右方向键)\n * @csspart branch-trigger - 展开箭头(aria-hidden 且不占 Tab 位,只切换展开态)\n * @csspart branch-indicator - 展开方向指示符(aria-hidden)\n * @csspart branch-text - 分支文本\n * @csspart branch-content - role=group 子层容器,收起时隐藏\n * @csspart hidden-input - type=hidden 的表单出口,省略该节点即不参与表单\n */\nexport class XhTreeSelectElement extends XhElement {\n static override partContract = { anatomy: treeSelectAnatomy, meta: treeSelectMeta }\n\n // dir 只占属性名、字段改叫 direction,避开 HTMLElement 原生 dir 访问器。\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n collection: { attribute: false },\n value: { converter: STRING_CONVERTER },\n defaultValue: { converter: STRING_CONVERTER, attribute: 'default-value' },\n expandedValue: { attribute: false },\n defaultExpandedValue: { attribute: false },\n open: { converter: BOOLEAN_CONVERTER },\n defaultOpen: { type: Boolean, attribute: 'default-open' },\n multiple: { type: Boolean },\n disabled: { type: Boolean },\n readOnly: { converter: BOOLEAN_CONVERTER, attribute: 'read-only' },\n invalid: { converter: BOOLEAN_CONVERTER },\n variant: { converter: STRING_CONVERTER },\n tone: { converter: STRING_CONVERTER },\n size: { converter: STRING_CONVERTER },\n placeholder: { converter: STRING_CONVERTER },\n placement: { converter: STRING_CONVERTER },\n offset: { converter: NUMBER_CONVERTER },\n loop: { converter: BOOLEAN_CONVERTER },\n direction: { converter: STRING_CONVERTER, attribute: 'dir' },\n name: { converter: STRING_CONVERTER },\n }\n\n declare collection?: TreeNode[]\n declare value?: string | string[]\n declare defaultValue?: string | string[]\n declare expandedValue?: string[]\n declare defaultExpandedValue?: string[]\n declare open?: boolean\n declare defaultOpen?: boolean\n declare multiple?: boolean\n declare disabled?: boolean\n declare readOnly?: boolean\n declare invalid?: boolean\n declare variant?: ControlVariant\n declare tone?: Tone\n declare size?: Size\n declare placeholder?: string\n declare placement?: Placement\n declare offset?: number\n declare loop?: boolean\n declare direction?: Direction\n declare name?: string\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly treeSelectScope = createScope(null, this.idGen)\n private readonly positionEngine: PositionEnginePort = createPositionEngine()\n private config: RuntimeConfig | null = null\n\n /** value-text 是否归元素填:首次见到该节点时定,之后不再回读(回读到的会是自己写的字)。 */\n private readonly ownsValueText = new WeakMap<HTMLElement, boolean>()\n\n private readonly notifyValue = (details: TreeSelectValueChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('value-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyExpanded = (details: TreeSelectExpandedChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('expanded-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly notifyOpen = (details: TreeSelectOpenChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('open-change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<TreeSelectSchema>(\n this,\n treeSelectMachine,\n () => this.machineProps(),\n { scope: this.treeSelectScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<TreeSelectSchema['props']> {\n return {\n collection: this.collection,\n value: this.value,\n defaultValue: this.defaultValue,\n expandedValue: this.expandedValue,\n // 不补 [],缺省由机器兜\n defaultExpandedValue: this.defaultExpandedValue,\n open: this.open,\n defaultOpen: this.defaultOpen ?? false,\n multiple: this.multiple ?? false,\n disabled: this.disabled ?? false,\n readOnly: this.readOnly ?? false,\n invalid: this.invalid ?? false,\n variant: this.variant,\n tone: this.tone,\n size: this.size,\n placeholder: this.placeholder,\n placement: this.placement,\n offset: this.offset,\n loop: this.loop,\n dir: this.direction,\n name: this.name,\n onValueChange: this.notifyValue,\n onExpandedChange: this.notifyExpanded,\n onOpenChange: this.notifyOpen,\n }\n }\n\n private ensureConfig(): void {\n if (this.config)\n return\n this.config = createRuntimeConfig({ scope: this.treeSelectScope, idGenerator: this.idGen })\n }\n\n // 只交注册函数、不在连接期注册:层的入栈出栈跟着展开态走(机器的 trackLayer 效应负责)。\n private readonly registerLayer = (): { layer: Layer, dispose: Cleanup } => {\n this.ensureConfig()\n return this.config!.layerRegistry.register({\n kind: 'popover',\n node: () => this.getPart('content'),\n // trigger 记为本层分支:点它算层内交互,开合交给 trigger 自己切换。\n branches: () => [this.getPart('trigger')].filter(Boolean) as Element[],\n isModal: () => false,\n setModal: () => {},\n // 浮层不带遮罩,无可点关闭的表面\n surfaces: () => [],\n })\n }\n\n // onBuilt 在 ctrl 构造期就跑,service 由参数传入。\n private injectRefs(svc: Service<TreeSelectSchema>): void {\n this.ensureConfig()\n svc.refs.set('config', this.config)\n svc.refs.set('registerLayer', this.registerLayer)\n svc.refs.set('position', this.positionEngine)\n svc.refs.set('getAnchorEl', () => this.getPart('trigger'))\n svc.refs.set('getFloatingEl', () => this.getPart('positioner'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /** 提前发现一次角色节点:default-open 时机器在 hostConnected 当场要去 content 里挑焦点锚点。 */\n override connectedCallback(): void {\n this.refreshParts()\n super.connectedCallback()\n }\n\n /**\n * 承载焦点的节点被移出 DOM 时上报 NODE.LOST,让机器按当前数据重挑锚点。\n * 判据是「焦点已不在浮层内」且离场的正是持有锚点的那个节点。\n */\n protected override onPartsReleased(nodes: readonly HTMLElement[]): void {\n const { context, getStatus, scope, send } = this.ctrl.service\n // 机器已停机则跳过\n if (getStatus() !== 'Started')\n return\n // 收起态无焦点锚点\n const focusedValue = context.get('focusedValue')\n if (focusedValue == null)\n return\n const content = this.getPart('content')\n const active = scope.getActiveElement()\n if (content && active && content.contains(active))\n return\n // data-value 只写在 item 与 branch 上,行内的文本与标记离场不会误判\n if (nodes.some(el => el.getAttribute(ITEM_VALUE_ATTR) === focusedValue))\n send({ type: 'NODE.LOST' })\n }\n\n /**\n * 取角色节点所属的节点身份:value 写在 item / branch 上,行内的文本、标记、箭头与子层容器\n * 向上找本宿主内最近的那个,没有则读节点自身。\n */\n private nodeOf(el: HTMLElement, selector: string): TreeSelectNodeProps {\n const owner = el.closest<HTMLElement>(selector)\n const source = owner && owner !== this && this.contains(owner) ? owner : el\n return { value: source.getAttribute('value') ?? '' }\n }\n\n /** 填入选中项显示文字;首次见到该节点时若已有内容则归作者,之后不再改写。 */\n private fillValueText(el: HTMLElement, text: string): void {\n let owned = this.ownsValueText.get(el)\n if (owned === undefined) {\n owned = (el.textContent ?? '').trim() === ''\n this.ownsValueText.set(el, owned)\n }\n if (!owned || el.textContent === text)\n return\n el.textContent = text\n }\n\n protected wire(): void {\n const api = connectTreeSelect(this.ctrl.service, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('label', api.getLabelProps() as Record<string, unknown>)\n put('trigger', api.getTriggerProps() as Record<string, unknown>)\n put('indicator', api.getIndicatorProps() as Record<string, unknown>)\n put('clear-trigger', api.getClearTriggerProps() as Record<string, unknown>)\n // positioner 的 style 是对象,spreader 会逐条写成内联样式\n put('positioner', api.getPositionerProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n put('tree', api.getTreeProps() as Record<string, unknown>)\n // 表单出口可缺省\n put('hidden-input', api.getHiddenInputProps() as Record<string, unknown>)\n\n // 属性先落,再填显示文字\n const valueText = this.getPart('value-text')\n if (valueText) {\n this.spreader.spread(valueText, api.getValueTextProps() as Record<string, unknown>)\n this.fillValueText(valueText, api.displayText)\n }\n\n // 集合类 part 逐个 spread,身份由节点自报,不依赖下标。\n // wire 跑在事件之前,按键时 data-scope/data-part/data-value 已在 DOM 上供连接层现查。\n const putAll = (name: string, selector: string, get: (node: TreeSelectNodeProps) => unknown): void => {\n for (const el of this.getParts(name))\n this.spreader.spread(el, get(this.nodeOf(el, selector)) as Record<string, unknown>)\n }\n putAll('item', ITEM_SELECTOR, node => api.getItemProps(node))\n putAll('item-text', ITEM_SELECTOR, node => api.getItemTextProps(node))\n putAll('item-indicator', ITEM_SELECTOR, node => api.getItemIndicatorProps(node))\n putAll('branch', BRANCH_SELECTOR, node => api.getBranchProps(node))\n putAll('branch-control', BRANCH_SELECTOR, node => api.getBranchControlProps(node))\n putAll('branch-trigger', BRANCH_SELECTOR, node => api.getBranchTriggerProps(node))\n putAll('branch-indicator', BRANCH_SELECTOR, node => api.getBranchIndicatorProps(node))\n putAll('branch-text', BRANCH_SELECTOR, node => api.getBranchTextProps(node))\n putAll('branch-content', BRANCH_SELECTOR, node => api.getBranchContentProps(node))\n\n // 节点常驻,用内联 display 收起(作者层的 display 声明会盖过 [hidden])\n this.setPartHidden(this.getPart('content'), !api.open)\n for (const el of this.getParts('branch-content'))\n this.setPartHidden(el, !api.isExpanded(this.nodeOf(el, BRANCH_SELECTOR).value))\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n // 层随机器停机一并撤掉,此处不再管\n this.config = null // 重连时 ensureConfig 重建\n }\n}\n","import type { TypographyProps, TypographyVariant } from '@xihan-ui/headless'\nimport type { Size, Tone } from '@xihan-ui/kernel'\nimport { connectTypography, typographyAnatomy, typographyMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\n\n/**\n * 读作者写在角色节点上的声明;属性缺席即 undefined。\n *\n * 期望类型由调用方给:值来自 HTML,类型系统够不着,所以这里是断言不是校验。\n * 写错值的后果是软的——它不匹配任何皮肤选择器,那一档样式不生效,不抛错也不降级。\n */\nfunction authorValue<T extends string = string>(el: HTMLElement, name: string): T | undefined {\n return (el.getAttribute(name) as T | null) ?? undefined\n}\n\n/**\n * `<xh-typography>` —— Light-DOM 行为宿主,无状态机,把 connectTypography 产出打到各角色节点。\n *\n * 标签全由作者写:`<h2 data-xh-part=\"heading\">`、`<p data-xh-part=\"paragraph\">`、\n * `<span data-xh-part=\"text\">`、`<a data-xh-part=\"link\">`,皮肤认的是 data-scope + data-part。\n * 标题的字号档位取节点上的 `level`,行内文字的形态与语气取节点上的 `variant` 与 `tone`。\n * 运行期改写这三个属性不触发重新接线,需作者自行 requestUpdate。\n *\n * @customElement xh-typography\n * @attr {'sm'|'md'|'lg'} size - 尺寸,整块正文的字号与段间距跟着换档\n * @csspart root - 正文块容器,管段间距与最大行宽,承载 data-size\n * @csspart heading - 标题,写 level=\"1\"..\"6\" 换字号档位\n * @csspart paragraph - 段落\n * @csspart text - 行内文字,写 variant=\"muted|strong|code\" 换形态、tone 换语气色\n * @csspart link - 行内链接\n */\nexport class XhTypographyElement extends XhElement {\n static override partContract = { anatomy: typographyAnatomy, meta: typographyMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n size: { converter: STRING_CONVERTER },\n }\n\n declare size?: Size\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectTypography({ size: this.size } satisfies TypographyProps, wcNormalize)\n\n const root = this.getPart('root')\n if (root)\n this.spreader.spread(root, api.getRootProps() as Record<string, unknown>)\n\n // 四类内容部件都能有多份,逐个打;档位、形态、语气取作者写在各自节点上的声明\n for (const el of this.getParts('heading')) {\n const attrs = api.getHeadingProps({ level: authorValue(el, 'level') })\n this.spreader.spread(el, attrs as Record<string, unknown>)\n }\n\n for (const el of this.getParts('paragraph'))\n this.spreader.spread(el, api.getParagraphProps() as Record<string, unknown>)\n\n for (const el of this.getParts('text')) {\n const attrs = api.getTextProps({\n tone: authorValue<Tone>(el, 'tone'),\n variant: authorValue<TypographyVariant>(el, 'variant'),\n })\n this.spreader.spread(el, attrs as Record<string, unknown>)\n }\n\n for (const el of this.getParts('link'))\n this.spreader.spread(el, api.getLinkProps() as Record<string, unknown>)\n }\n}\n","import type {\n VirtualizerAlign,\n VirtualizerChangeDetails,\n VirtualizerItemState,\n VirtualizerSchema,\n} from '@xihan-ui/headless'\nimport type { IdGenerator } from '@xihan-ui/kernel'\nimport type { Service } from '@xihan-ui/machine'\nimport { connectVirtualizer, virtualizerAnatomy, virtualizerMachine, virtualizerMeta } from '@xihan-ui/headless'\nimport { createCounterIdGenerator, createScope } from '@xihan-ui/kernel'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\nimport { MachineController } from '../runtime/machine-controller'\n\n// 属性缺席翻成 undefined,缺省值由机器与 connect 决定。\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n// 三态:缺席 = undefined(用默认值),=\"false\" = false,其余(含空串)= true。\n// Lit 自带的 Boolean 转换器是 v !== null,缺省为真的开关用它会永远关不掉\nconst BOOLEAN_CONVERTER = { fromAttribute: (v: string | null) => (v === null ? undefined : v !== 'false') }\n\n/** 条目自报的下标;缺失或空串一律给 NaN(见 wire 里的说明)。 */\nfunction itemIndex(el: HTMLElement): number {\n const raw = el.getAttribute('value')\n return raw == null || raw === '' ? Number.NaN : Number(raw)\n}\n\n/** 这个条目要不要把真实尺寸回喂给内核。三态语义与 horizontal 属性一致。 */\nfunction wantsMeasure(el: HTMLElement): boolean {\n const raw = el.getAttribute('measure')\n return raw !== null && raw !== 'false'\n}\n\n/**\n * `<xh-virtualizer>` —— Light-DOM 行为宿主:作者写 root/viewport/content/item 角色节点,\n * 元素跑 virtualizer 机器并把 connect 产出打上去。\n *\n * 区间与尺寸的计算走 headless 的虚拟滚动内核:它在机器的效应里建起来,挂着视口的\n * ResizeObserver 与 scroll 监听,算出\"此刻该渲哪些下标、各自落在哪儿\"。\n * 滚动本身一概不接管:viewport 是原生的 overflow 容器,滚轮、方向键、PageUp/PageDown、\n * Home/End 全部走浏览器原生通路。\n *\n * 条目节点不替作者生成:生成节点就等于收走模板控制权,外层结构、图标、业务内容都再塞不进来。\n * 作者监听 `change` 事件,按 `virtualItems` 渲出该渲的那几条,每条用 `value` 属性写明自己是第几条;\n * 元素据此把位移写进它的内联样式,并把不在窗口里的条目收起来。\n *\n * @customElement xh-virtualizer\n * @attr {number} count - 总条数,默认 0\n * @attr {number} estimate-size - 每条的估算主轴尺寸(px);不等高的列表改用 estimateSize property 传函数\n * @attr {number} overscan - 可视区前后各多渲几条,默认 5\n * @attr {boolean} horizontal - 横向列表(主轴是行内轴),默认 false\n * @attr {number} gap - 相邻两条之间的主轴间距(px),默认 0\n * @attr {number} scroll-margin - 列表起点距滚动容器起点的距离(px),默认 0\n * @attr {number} padding-start - 列表前内边距(px),默认 0\n * @attr {number} padding-end - 列表后内边距(px),默认 0\n * @attr {number} lanes - 多列网格的列数,默认 1\n * @fires change - 该渲什么变了;detail 为 `{ virtualItems, totalSize, startIndex, endIndex }`\n * @csspart root - 组件根容器,承载 data-orientation 与 data-scrolling\n * @csspart viewport - 真正 overflow:auto 的那层,带 tabindex=0 让键盘用户落得进来\n * @csspart content - 撑出总长的那层(内联样式给主轴长度),条目的定位上下文\n * @csspart item - 条目,须自带 value 属性写明下标;位移由内联逻辑属性给出,不在窗口里时带 hidden\n */\nexport class XhVirtualizerElement extends XhElement {\n static override partContract = { anatomy: virtualizerAnatomy, meta: virtualizerMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开。\n static override properties = {\n count: { converter: NUMBER_CONVERTER },\n estimateSize: { converter: NUMBER_CONVERTER, attribute: 'estimate-size' },\n overscan: { converter: NUMBER_CONVERTER },\n horizontal: { converter: BOOLEAN_CONVERTER },\n gap: { converter: NUMBER_CONVERTER },\n scrollMargin: { converter: NUMBER_CONVERTER, attribute: 'scroll-margin' },\n paddingStart: { converter: NUMBER_CONVERTER, attribute: 'padding-start' },\n paddingEnd: { converter: NUMBER_CONVERTER, attribute: 'padding-end' },\n lanes: { converter: NUMBER_CONVERTER },\n // 函数走不了属性;只作为 property 暴露,与 Vue 侧的同名 prop 对齐\n getItemKey: { attribute: false },\n }\n\n declare count?: number\n declare estimateSize?: number | ((index: number) => number)\n declare overscan?: number\n declare horizontal?: boolean\n declare gap?: number\n declare scrollMargin?: number\n declare paddingStart?: number\n declare paddingEnd?: number\n declare lanes?: number\n declare getItemKey?: (index: number) => string | number\n\n private readonly idGen: IdGenerator = createCounterIdGenerator()\n private readonly virtualizerScope = createScope(null, this.idGen)\n\n private readonly notify = (details: VirtualizerChangeDetails): void => {\n this.dispatchEvent(new CustomEvent('change', { detail: details, bubbles: true, composed: true }))\n }\n\n private readonly ctrl = new MachineController<VirtualizerSchema>(\n this,\n virtualizerMachine,\n () => this.machineProps(),\n { scope: this.virtualizerScope, onBuilt: svc => this.injectRefs(svc) },\n )\n\n private machineProps(): Partial<VirtualizerSchema['props']> {\n return {\n count: this.count,\n estimateSize: this.estimateSize,\n overscan: this.overscan,\n horizontal: this.horizontal,\n gap: this.gap,\n scrollMargin: this.scrollMargin,\n paddingStart: this.paddingStart,\n paddingEnd: this.paddingEnd,\n lanes: this.lanes,\n getItemKey: this.getItemKey,\n onChange: this.notify,\n }\n }\n\n // onBuilt 在 ctrl 构造期就跑(此刻 this.ctrl 尚未赋值),故 service 由参数传入。\n // 两个 getter 都懒读:角色节点要等首次 updated 才发现得到,机器建起来的那一刻 partMap 还空着\n private injectRefs(svc: Service<VirtualizerSchema>): void {\n svc.refs.set('getViewportEl', () => this.getPart('viewport'))\n svc.refs.set('getContentEl', () => this.getPart('content'))\n }\n\n /**\n * 机器要等 hostConnected 才建(此刻属性已反射到 property)。\n * 下面几个方法是公开面,作者拿到元素就可能调——还没进 DOM 时如实给空,别炸。\n */\n private api(): ReturnType<typeof connectVirtualizer> | null {\n const service = this.ctrl.service as Service<VirtualizerSchema> | undefined\n return service ? connectVirtualizer(service, wcNormalize) : null\n }\n\n /** 此刻该渲染哪些下标,以及它们的位移与尺寸。作者据此渲条目节点。 */\n get virtualItems(): readonly VirtualizerItemState[] {\n return this.api()?.virtualItems ?? []\n }\n\n /** 整份列表的主轴总长(px)。 */\n get totalSize(): number {\n return this.api()?.totalSize ?? 0\n }\n\n /** 滚到第几条。越界下标由内核夹住。 */\n scrollToIndex(index: number, options?: { align?: VirtualizerAlign }): void {\n this.api()?.scrollToIndex(index, options)\n }\n\n /** 把条目节点的真实尺寸回喂给内核(动态高度用)。 */\n measureElement(element: HTMLElement | null): void {\n this.api()?.measureElement(element)\n }\n\n /** 重新量视口、丢掉实测尺寸整份重排。方法名避开 Lit 的生命周期钩子。 */\n measure(): void {\n this.api()?.measure()\n }\n\n protected wire(): void {\n const api = this.api()\n if (!api)\n return\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n put('root', api.getRootProps() as Record<string, unknown>)\n put('viewport', api.getViewportProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n\n // 条目是多实例 part,逐个打:身份取作者写的 value。\n // 漏写时给 NaN 而不是 Number(null) 的 0:NaN 与任何下标都不相等,条目会被当成\n // \"不在窗口里\"收起来,但绝不会冒充第 0 条;Vue 侧漏写 value 拿到的同样是 NaN,两侧一致\n for (const el of this.getParts('item')) {\n const index = itemIndex(el)\n this.spreader.spread(el, api.getItemProps({ index }) as Record<string, unknown>)\n // Light DOM 常驻,WC 自管可见性:作者层若给这个 part 声明了 display,\n // 会盖过 UA 的 [hidden]{display:none},光靠 hidden 属性收不起来。\n // 本包的样式自带 [hidden]{display:none} 压得住,但宿主不能指望作者装了这份样式\n this.setPartHidden(el, !api.virtualItems.some(item => item.index === index))\n // 量尺寸放在这里而不是连接期:wire 跑在 updated 之后,此刻节点的布局才是这一帧的。\n // 收起来的条目要不要量由 connect 判(两侧同一份规则);\n // 尺寸没变时内核不会再通知,这条回路会自己停下来,不会来回震荡\n if (wantsMeasure(el))\n api.measureElement(el)\n }\n }\n}\n","import type { WatermarkProps } from '@xihan-ui/headless'\nimport { connectWatermark, watermarkAnatomy, watermarkMeta } from '@xihan-ui/headless'\nimport { wcNormalize } from '../dom/normalize'\nimport { XhElement } from '../element-base'\n\n// 属性缺席翻成 undefined,缺省值由 connect 决定。\nconst STRING_CONVERTER = { fromAttribute: (v: string | null) => v ?? undefined }\nconst NUMBER_CONVERTER = { fromAttribute: (v: string | null) => (v == null || v === '' ? undefined : Number(v)) }\n\n/**\n * `<xh-watermark>` —— Light-DOM 行为宿主,无状态机,把 connectWatermark 产出打到 root 与 content 上。\n *\n * 图样是一张按 props 算出来的 SVG,整段百分号编码成 data URI 写进 root 的内联 CSS 变量;\n * 铺成一层盖在内容之上的伪元素归皮肤管,因此印子不进无障碍树、不吃点击、也选不中。\n *\n * 多行水印用 text 属性里的换行,或把 text 当 property 传一个字符串数组。\n * 没有可印的文字时 root 落 data-state=\"empty\",皮肤整层不画。\n *\n * 给了文字时 root 的内联 style 归本元素管,作者自己的内联样式请写在宿主元素上。\n *\n * @customElement xh-watermark\n * @attr {string} text - 水印文字,换行即多行\n * @attr {number} rotate - 倾斜角度(度),缺省 -22\n * @attr {number} gap - 两块图样之间的空白(像素),缺省 24\n * @attr {number} font-size - 字号(像素),缺省 14\n * @attr {number} opacity - 印子的深浅,0 到 1,缺省 0.15\n * @csspart root - 盖水印的那块地,承载 data-state 与图样、步距两个变量\n * @csspart content - 被盖住的那段内容\n */\nexport class XhWatermarkElement extends XhElement {\n static override partContract = { anatomy: watermarkAnatomy, meta: watermarkMeta }\n\n // 描述符逐个写全,CEM 分析器读不了对象展开\n static override properties = {\n text: { converter: STRING_CONVERTER },\n rotate: { converter: NUMBER_CONVERTER },\n gap: { converter: NUMBER_CONVERTER },\n fontSize: { converter: NUMBER_CONVERTER, attribute: 'font-size' },\n opacity: { converter: NUMBER_CONVERTER },\n }\n\n declare text?: string | string[]\n declare rotate?: number\n declare gap?: number\n declare fontSize?: number\n declare opacity?: number\n\n protected wire(): void {\n // 读响应式 property,不回读 DOM 特性\n const api = connectWatermark({\n text: this.text,\n rotate: this.rotate,\n gap: this.gap,\n fontSize: this.fontSize,\n opacity: this.opacity,\n } satisfies WatermarkProps, wcNormalize)\n\n const put = (name: string, props: Record<string, unknown>): void => {\n const el = this.getPart(name)\n if (el)\n this.spreader.spread(el, props)\n }\n\n put('root', api.getRootProps() as Record<string, unknown>)\n put('content', api.getContentProps() as Record<string, unknown>)\n }\n}\n","import { version as VERSION } from '../package.json'\nimport { XhAccordionElement } from './elements/accordion'\nimport { XhAffixElement } from './elements/affix'\nimport { XhAlertElement } from './elements/alert'\nimport { XhAnchorElement } from './elements/anchor'\nimport { XhAvatarElement } from './elements/avatar'\nimport { XhAvatarGroupElement } from './elements/avatar-group'\nimport { XhBackTopElement } from './elements/back-top'\nimport { XhBadgeElement } from './elements/badge'\nimport { XhBreadcrumbElement } from './elements/breadcrumb'\nimport { XhButtonElement } from './elements/button'\nimport { XhButtonGroupElement } from './elements/button-group'\nimport { XhCalendarElement } from './elements/calendar'\nimport { XhCardElement } from './elements/card'\nimport { XhCarouselElement } from './elements/carousel'\nimport { XhCascaderElement } from './elements/cascader'\nimport { XhCheckboxElement } from './elements/checkbox'\nimport { XhCheckboxGroupElement } from './elements/checkbox-group'\nimport { XhClipboardElement } from './elements/clipboard'\nimport { XhCodeBlockElement } from './elements/code-block'\nimport { XhCollapsibleElement } from './elements/collapsible'\nimport { XhColorPickerElement } from './elements/color-picker'\nimport { XhComboboxElement } from './elements/combobox'\nimport { XhComposerElement } from './elements/composer'\nimport { XhContextMenuElement } from './elements/context-menu'\nimport { XhCountdownElement } from './elements/countdown'\nimport { XhDateFieldElement } from './elements/date-field'\nimport { XhDatePickerElement } from './elements/date-picker'\nimport { XhDescriptionsElement } from './elements/descriptions'\nimport { XhDialogElement } from './elements/dialog'\nimport { XhDrawerElement } from './elements/drawer'\nimport { XhDynamicInputElement } from './elements/dynamic-input'\nimport { XhEditableElement } from './elements/editable'\nimport { XhEllipsisElement } from './elements/ellipsis'\nimport { XhEmptyStateElement } from './elements/empty-state'\nimport { XhFieldElement } from './elements/field'\nimport { XhFileUploadElement } from './elements/file-upload'\nimport { XhFlexElement } from './elements/flex'\nimport { XhFloatButtonElement } from './elements/float-button'\nimport { XhFormElement } from './elements/form'\nimport { XhGradientTextElement } from './elements/gradient-text'\nimport { XhGridElement } from './elements/grid'\nimport { XhHighlightElement } from './elements/highlight'\nimport { XhHoverCardElement } from './elements/hover-card'\nimport { XhIconElement } from './elements/icon'\nimport { XhIconWrapperElement } from './elements/icon-wrapper'\nimport { XhImageElement } from './elements/image'\nimport { XhInfiniteScrollElement } from './elements/infinite-scroll'\nimport { XhLayoutElement } from './elements/layout'\nimport { XhListElement } from './elements/list'\nimport { XhListboxElement } from './elements/listbox'\nimport { XhLoadingBarElement } from './elements/loading-bar'\nimport { XhLogElement } from './elements/log'\nimport { XhMarqueeElement } from './elements/marquee'\nimport { XhMentionElement } from './elements/mention'\nimport { XhMenuElement } from './elements/menu'\nimport { XhMenubarElement } from './elements/menubar'\nimport { XhNavigationMenuElement } from './elements/navigation-menu'\nimport { XhNumberAnimationElement } from './elements/number-animation'\nimport { XhNumberFieldElement } from './elements/number-field'\nimport { XhPageHeaderElement } from './elements/page-header'\nimport { XhPaginationElement } from './elements/pagination'\nimport { XhPinInputElement } from './elements/pin-input'\nimport { XhPopconfirmElement } from './elements/popconfirm'\nimport { XhPopoverElement } from './elements/popover'\nimport { XhPopselectElement } from './elements/popselect'\nimport { XhProgressElement } from './elements/progress'\nimport { XhQrCodeElement } from './elements/qr-code'\nimport { XhRadioGroupElement } from './elements/radio-group'\nimport { XhRatingElement } from './elements/rating'\nimport { XhResultElement } from './elements/result'\nimport { XhScrollAreaElement } from './elements/scroll-area'\nimport { XhSelectElement } from './elements/select'\nimport { XhSeparatorElement } from './elements/separator'\nimport { XhSkeletonElement } from './elements/skeleton'\nimport { XhSliderElement } from './elements/slider'\nimport { XhSpinnerElement } from './elements/spinner'\nimport { XhSplitterElement } from './elements/splitter'\nimport { XhStatisticElement } from './elements/statistic'\nimport { XhStepsElement } from './elements/steps'\nimport { XhSwitchElement } from './elements/switch'\nimport { XhTableElement } from './elements/table'\nimport { XhTabsElement } from './elements/tabs'\nimport { XhTagsInputElement } from './elements/tags-input'\nimport { XhTextFieldElement } from './elements/text-field'\nimport { XhThreadElement } from './elements/thread'\nimport { XhTimeElement } from './elements/time'\nimport { XhTimeFieldElement } from './elements/time-field'\nimport { XhTimePickerElement } from './elements/time-picker'\nimport { XhTimelineElement } from './elements/timeline'\nimport { XhToastElement } from './elements/toast'\nimport { XhToasterElement } from './elements/toaster'\nimport { XhToggleElement } from './elements/toggle'\nimport { XhToggleGroupElement } from './elements/toggle-group'\nimport { XhToolbarElement } from './elements/toolbar'\nimport { XhTooltipElement } from './elements/tooltip'\nimport { XhTourElement } from './elements/tour'\nimport { XhTransferElement } from './elements/transfer'\nimport { XhTreeElement } from './elements/tree'\nimport { XhTreeSelectElement } from './elements/tree-select'\nimport { XhTypographyElement } from './elements/typography'\nimport { XhVirtualizerElement } from './elements/virtualizer'\nimport { XhWatermarkElement } from './elements/watermark'\nimport { defineElement } from './runtime/registry'\n\n// 注册全部 xh-* 元素,需显式调用,主入口 import 不注册。\nexport function defineXhElements(): void {\n defineElement('xh-affix', XhAffixElement, VERSION)\n defineElement('xh-alert', XhAlertElement, VERSION)\n defineElement('xh-avatar-group', XhAvatarGroupElement, VERSION)\n defineElement('xh-back-top', XhBackTopElement, VERSION)\n defineElement('xh-button-group', XhButtonGroupElement, VERSION)\n defineElement('xh-countdown', XhCountdownElement, VERSION)\n defineElement('xh-descriptions', XhDescriptionsElement, VERSION)\n defineElement('xh-dynamic-input', XhDynamicInputElement, VERSION)\n defineElement('xh-ellipsis', XhEllipsisElement, VERSION)\n defineElement('xh-empty-state', XhEmptyStateElement, VERSION)\n defineElement('xh-flex', XhFlexElement, VERSION)\n defineElement('xh-float-button', XhFloatButtonElement, VERSION)\n defineElement('xh-gradient-text', XhGradientTextElement, VERSION)\n defineElement('xh-grid', XhGridElement, VERSION)\n defineElement('xh-highlight', XhHighlightElement, VERSION)\n defineElement('xh-icon-wrapper', XhIconWrapperElement, VERSION)\n defineElement('xh-infinite-scroll', XhInfiniteScrollElement, VERSION)\n defineElement('xh-layout', XhLayoutElement, VERSION)\n defineElement('xh-list', XhListElement, VERSION)\n defineElement('xh-log', XhLogElement, VERSION)\n defineElement('xh-marquee', XhMarqueeElement, VERSION)\n defineElement('xh-mention', XhMentionElement, VERSION)\n defineElement('xh-number-animation', XhNumberAnimationElement, VERSION)\n defineElement('xh-page-header', XhPageHeaderElement, VERSION)\n defineElement('xh-popconfirm', XhPopconfirmElement, VERSION)\n defineElement('xh-popselect', XhPopselectElement, VERSION)\n defineElement('xh-qr-code', XhQrCodeElement, VERSION)\n defineElement('xh-result', XhResultElement, VERSION)\n defineElement('xh-skeleton', XhSkeletonElement, VERSION)\n defineElement('xh-spinner', XhSpinnerElement, VERSION)\n defineElement('xh-accordion', XhAccordionElement, VERSION)\n defineElement('xh-anchor', XhAnchorElement, VERSION)\n defineElement('xh-avatar', XhAvatarElement, VERSION)\n defineElement('xh-badge', XhBadgeElement, VERSION)\n defineElement('xh-breadcrumb', XhBreadcrumbElement, VERSION)\n defineElement('xh-button', XhButtonElement, VERSION)\n defineElement('xh-calendar', XhCalendarElement, VERSION)\n defineElement('xh-card', XhCardElement, VERSION)\n defineElement('xh-carousel', XhCarouselElement, VERSION)\n defineElement('xh-cascader', XhCascaderElement, VERSION)\n defineElement('xh-checkbox', XhCheckboxElement, VERSION)\n defineElement('xh-checkbox-group', XhCheckboxGroupElement, VERSION)\n defineElement('xh-clipboard', XhClipboardElement, VERSION)\n defineElement('xh-code-block', XhCodeBlockElement, VERSION)\n defineElement('xh-collapsible', XhCollapsibleElement, VERSION)\n defineElement('xh-color-picker', XhColorPickerElement, VERSION)\n defineElement('xh-combobox', XhComboboxElement, VERSION)\n defineElement('xh-composer', XhComposerElement, VERSION)\n defineElement('xh-context-menu', XhContextMenuElement, VERSION)\n defineElement('xh-date-field', XhDateFieldElement, VERSION)\n defineElement('xh-date-picker', XhDatePickerElement, VERSION)\n defineElement('xh-dialog', XhDialogElement, VERSION)\n defineElement('xh-drawer', XhDrawerElement, VERSION)\n defineElement('xh-editable', XhEditableElement, VERSION)\n defineElement('xh-field', XhFieldElement, VERSION)\n defineElement('xh-file-upload', XhFileUploadElement, VERSION)\n defineElement('xh-form', XhFormElement, VERSION)\n defineElement('xh-hover-card', XhHoverCardElement, VERSION)\n defineElement('xh-icon', XhIconElement, VERSION)\n defineElement('xh-image', XhImageElement, VERSION)\n defineElement('xh-listbox', XhListboxElement, VERSION)\n defineElement('xh-loading-bar', XhLoadingBarElement, VERSION)\n defineElement('xh-menu', XhMenuElement, VERSION)\n defineElement('xh-menubar', XhMenubarElement, VERSION)\n defineElement('xh-navigation-menu', XhNavigationMenuElement, VERSION)\n defineElement('xh-pagination', XhPaginationElement, VERSION)\n defineElement('xh-pin-input', XhPinInputElement, VERSION)\n defineElement('xh-popover', XhPopoverElement, VERSION)\n defineElement('xh-progress', XhProgressElement, VERSION)\n defineElement('xh-radio-group', XhRadioGroupElement, VERSION)\n defineElement('xh-number-field', XhNumberFieldElement, VERSION)\n defineElement('xh-rating', XhRatingElement, VERSION)\n defineElement('xh-scroll-area', XhScrollAreaElement, VERSION)\n defineElement('xh-select', XhSelectElement, VERSION)\n defineElement('xh-separator', XhSeparatorElement, VERSION)\n defineElement('xh-slider', XhSliderElement, VERSION)\n defineElement('xh-splitter', XhSplitterElement, VERSION)\n defineElement('xh-statistic', XhStatisticElement, VERSION)\n defineElement('xh-steps', XhStepsElement, VERSION)\n defineElement('xh-switch', XhSwitchElement, VERSION)\n defineElement('xh-table', XhTableElement, VERSION)\n defineElement('xh-tabs', XhTabsElement, VERSION)\n defineElement('xh-tags-input', XhTagsInputElement, VERSION)\n defineElement('xh-text-field', XhTextFieldElement, VERSION)\n defineElement('xh-thread', XhThreadElement, VERSION)\n defineElement('xh-time', XhTimeElement, VERSION)\n defineElement('xh-time-field', XhTimeFieldElement, VERSION)\n defineElement('xh-time-picker', XhTimePickerElement, VERSION)\n defineElement('xh-timeline', XhTimelineElement, VERSION)\n defineElement('xh-toast', XhToastElement, VERSION)\n defineElement('xh-toaster', XhToasterElement, VERSION)\n defineElement('xh-toggle', XhToggleElement, VERSION)\n defineElement('xh-toggle-group', XhToggleGroupElement, VERSION)\n defineElement('xh-toolbar', XhToolbarElement, VERSION)\n defineElement('xh-tooltip', XhTooltipElement, VERSION)\n defineElement('xh-tour', XhTourElement, VERSION)\n defineElement('xh-transfer', XhTransferElement, VERSION)\n defineElement('xh-tree', XhTreeElement, VERSION)\n defineElement('xh-tree-select', XhTreeSelectElement, VERSION)\n defineElement('xh-typography', XhTypographyElement, VERSION)\n defineElement('xh-virtualizer', XhVirtualizerElement, VERSION)\n defineElement('xh-watermark', XhWatermarkElement, VERSION)\n}\n\nexport {\n XhAccordionElement,\n XhAlertElement,\n XhAnchorElement,\n XhAvatarElement,\n XhBadgeElement,\n XhBreadcrumbElement,\n XhButtonElement,\n XhCalendarElement,\n XhCarouselElement,\n XhCascaderElement,\n XhCheckboxElement,\n XhCheckboxGroupElement,\n XhClipboardElement,\n XhCodeBlockElement,\n XhCollapsibleElement,\n XhColorPickerElement,\n XhComboboxElement,\n XhComposerElement,\n XhContextMenuElement,\n XhDateFieldElement,\n XhDatePickerElement,\n XhDialogElement,\n XhDrawerElement,\n XhEditableElement,\n XhEmptyStateElement,\n XhFieldElement,\n XhFileUploadElement,\n XhFormElement,\n XhHoverCardElement,\n XhIconElement,\n XhImageElement,\n XhListboxElement,\n XhLoadingBarElement,\n XhMenubarElement,\n XhMenuElement,\n XhNavigationMenuElement,\n XhNumberFieldElement,\n XhPaginationElement,\n XhPinInputElement,\n XhPopoverElement,\n XhProgressElement,\n XhRadioGroupElement,\n XhRatingElement,\n XhScrollAreaElement,\n XhSelectElement,\n XhSeparatorElement,\n XhSkeletonElement,\n XhSliderElement,\n XhSpinnerElement,\n XhSplitterElement,\n XhStepsElement,\n XhSwitchElement,\n XhTableElement,\n XhTabsElement,\n XhTagsInputElement,\n XhTextFieldElement,\n XhThreadElement,\n XhTimeFieldElement,\n XhTimePickerElement,\n XhToastElement,\n XhToasterElement,\n XhToggleElement,\n XhToggleGroupElement,\n XhToolbarElement,\n XhTooltipElement,\n XhTourElement,\n XhTransferElement,\n XhTreeElement,\n XhTreeSelectElement,\n XhVirtualizerElement,\n}\n"],"mappings":"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"}