@greypan/web-ui 11.0.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.CN.md +105 -41
  2. package/README.md +69 -0
  3. package/dist/assets/overlay-motion.js +1 -1
  4. package/dist/assets/overlay-motion.js.map +1 -1
  5. package/dist/assets/selection-control.js +1 -1
  6. package/dist/assets/selection-control.js.map +1 -1
  7. package/dist/classes/glass.js +6 -0
  8. package/dist/classes/glass.js.map +1 -0
  9. package/dist/classes/glow.js +6 -0
  10. package/dist/classes/glow.js.map +1 -0
  11. package/dist/classes/style.css +1 -0
  12. package/dist/components/autocomplete/index.d.ts +7 -0
  13. package/dist/components/autocomplete/index.js +33 -13
  14. package/dist/components/autocomplete/index.js.map +1 -1
  15. package/dist/components/autocomplete/style.js +1 -1
  16. package/dist/components/autocomplete/style.js.map +1 -1
  17. package/dist/components/avatar/index.js +2 -2
  18. package/dist/components/avatar/index.js.map +1 -1
  19. package/dist/components/avatar/style.js +1 -1
  20. package/dist/components/avatar/style.js.map +1 -1
  21. package/dist/components/back-top/index.d.ts +4 -0
  22. package/dist/components/back-top/index.js +60 -22
  23. package/dist/components/back-top/index.js.map +1 -1
  24. package/dist/components/back-top/style.js +1 -1
  25. package/dist/components/back-top/style.js.map +1 -1
  26. package/dist/components/badge/index.d.ts +3 -0
  27. package/dist/components/badge/index.js +29 -14
  28. package/dist/components/badge/index.js.map +1 -1
  29. package/dist/components/badge/style.js +1 -1
  30. package/dist/components/badge/style.js.map +1 -1
  31. package/dist/components/button/index.d.ts +3 -0
  32. package/dist/components/button/index.js +27 -18
  33. package/dist/components/button/index.js.map +1 -1
  34. package/dist/components/button/style.js +1 -1
  35. package/dist/components/button/style.js.map +1 -1
  36. package/dist/components/button-group/index.d.ts +3 -0
  37. package/dist/components/button-group/index.js +15 -2
  38. package/dist/components/button-group/index.js.map +1 -1
  39. package/dist/components/button-group/style.js +1 -1
  40. package/dist/components/button-group/style.js.map +1 -1
  41. package/dist/components/checkbox/index.js +6 -6
  42. package/dist/components/checkbox/index.js.map +1 -1
  43. package/dist/components/checkbox/style.js +1 -1
  44. package/dist/components/checkbox/style.js.map +1 -1
  45. package/dist/components/collapse/index.d.ts +15 -7
  46. package/dist/components/collapse/index.js +44 -26
  47. package/dist/components/collapse/index.js.map +1 -1
  48. package/dist/components/collapse/style.js +1 -1
  49. package/dist/components/collapse/style.js.map +1 -1
  50. package/dist/components/dialog/index.d.ts +1 -0
  51. package/dist/components/dialog/index.js +5 -2
  52. package/dist/components/dialog/index.js.map +1 -1
  53. package/dist/components/dialog/style.js +1 -1
  54. package/dist/components/dialog/style.js.map +1 -1
  55. package/dist/components/drawer/index.js +1 -1
  56. package/dist/components/drawer/index.js.map +1 -1
  57. package/dist/components/dropdown/index.d.ts +16 -0
  58. package/dist/components/dropdown/index.js +147 -18
  59. package/dist/components/dropdown/index.js.map +1 -1
  60. package/dist/components/dropdown-item/style.js +1 -1
  61. package/dist/components/dropdown-item/style.js.map +1 -1
  62. package/dist/components/editable-text/index.js +7 -3
  63. package/dist/components/editable-text/index.js.map +1 -1
  64. package/dist/components/editable-text/style.js +1 -1
  65. package/dist/components/editable-text/style.js.map +1 -1
  66. package/dist/components/empty/index.d.ts +10 -22
  67. package/dist/components/empty/index.js +19 -35
  68. package/dist/components/empty/index.js.map +1 -1
  69. package/dist/components/empty/style.js +1 -1
  70. package/dist/components/empty/style.js.map +1 -1
  71. package/dist/components/image-preview/index.js +2 -2
  72. package/dist/components/image-preview/index.js.map +1 -1
  73. package/dist/components/input/index.d.ts +1 -0
  74. package/dist/components/input/index.js +5 -2
  75. package/dist/components/input/index.js.map +1 -1
  76. package/dist/components/input/style.js +1 -1
  77. package/dist/components/input/style.js.map +1 -1
  78. package/dist/components/input-number/index.d.ts +31 -1
  79. package/dist/components/input-number/index.js +281 -22
  80. package/dist/components/input-number/index.js.map +1 -1
  81. package/dist/components/input-number/style.js +1 -1
  82. package/dist/components/input-number/style.js.map +1 -1
  83. package/dist/components/layout/index.js +44 -39
  84. package/dist/components/layout/index.js.map +1 -1
  85. package/dist/components/layout/style.js +1 -1
  86. package/dist/components/layout/style.js.map +1 -1
  87. package/dist/components/middle-ellipsis/index.d.ts +8 -1
  88. package/dist/components/middle-ellipsis/index.js +68 -10
  89. package/dist/components/middle-ellipsis/index.js.map +1 -1
  90. package/dist/components/option/style.js +1 -1
  91. package/dist/components/option/style.js.map +1 -1
  92. package/dist/components/popover/index.js +1 -1
  93. package/dist/components/popover/index.js.map +1 -1
  94. package/dist/components/popover/style.js +1 -1
  95. package/dist/components/popover/style.js.map +1 -1
  96. package/dist/components/radio/index.d.ts +5 -0
  97. package/dist/components/radio/index.js +33 -23
  98. package/dist/components/radio/index.js.map +1 -1
  99. package/dist/components/radio/interaction.d.ts +4 -0
  100. package/dist/components/radio/interaction.js +17 -0
  101. package/dist/components/radio/interaction.js.map +1 -0
  102. package/dist/components/radio/style.js +1 -1
  103. package/dist/components/radio/style.js.map +1 -1
  104. package/dist/components/radio-group/index.d.ts +22 -0
  105. package/dist/components/radio-group/index.js +219 -28
  106. package/dist/components/radio-group/index.js.map +1 -1
  107. package/dist/components/segmented/index.d.ts +2 -0
  108. package/dist/components/segmented/index.js +74 -18
  109. package/dist/components/segmented/index.js.map +1 -1
  110. package/dist/components/segmented/style.js +1 -1
  111. package/dist/components/segmented/style.js.map +1 -1
  112. package/dist/components/segmented-trigger/index.js +3 -2
  113. package/dist/components/segmented-trigger/index.js.map +1 -1
  114. package/dist/components/segmented-trigger/style.js +1 -1
  115. package/dist/components/segmented-trigger/style.js.map +1 -1
  116. package/dist/components/select/index.d.ts +8 -0
  117. package/dist/components/select/index.js +76 -25
  118. package/dist/components/select/index.js.map +1 -1
  119. package/dist/components/select/style.js +1 -1
  120. package/dist/components/select/style.js.map +1 -1
  121. package/dist/components/slider/index.d.ts +15 -0
  122. package/dist/components/slider/index.js +175 -39
  123. package/dist/components/slider/index.js.map +1 -1
  124. package/dist/components/slider/style.js +1 -1
  125. package/dist/components/slider/style.js.map +1 -1
  126. package/dist/components/spinner/index.d.ts +15 -0
  127. package/dist/components/spinner/index.js +79 -22
  128. package/dist/components/spinner/index.js.map +1 -1
  129. package/dist/components/spinner/style.js +1 -1
  130. package/dist/components/spinner/style.js.map +1 -1
  131. package/dist/components/svg-draw-lines/index.js +48 -12
  132. package/dist/components/svg-draw-lines/index.js.map +1 -1
  133. package/dist/components/switch/index.d.ts +11 -3
  134. package/dist/components/switch/index.js +57 -53
  135. package/dist/components/switch/index.js.map +1 -1
  136. package/dist/components/switch/style.js +1 -1
  137. package/dist/components/switch/style.js.map +1 -1
  138. package/dist/components/textarea/index.js +2 -2
  139. package/dist/components/textarea/index.js.map +1 -1
  140. package/dist/components/textarea/style.js +1 -1
  141. package/dist/components/textarea/style.js.map +1 -1
  142. package/dist/components/theme/index.d.ts +1 -0
  143. package/dist/components/theme/index.js +26 -15
  144. package/dist/components/theme/index.js.map +1 -1
  145. package/dist/components/theme/style.js +1 -1
  146. package/dist/components/theme/style.js.map +1 -1
  147. package/dist/components/toast/style.js +1 -1
  148. package/dist/components/toast/style.js.map +1 -1
  149. package/dist/components/toast/toast.js +1 -1
  150. package/dist/components/toast/toast.js.map +1 -1
  151. package/dist/components/tooltip/index.d.ts +1 -0
  152. package/dist/components/tooltip/index.js +10 -5
  153. package/dist/components/tooltip/index.js.map +1 -1
  154. package/dist/icons/generated/andrsrxn-inbox.d.ts +6 -0
  155. package/dist/icons/generated/andrsrxn-inbox.js +10 -0
  156. package/dist/icons/generated/andrsrxn-inbox.js.map +1 -0
  157. package/dist/icons/index.d.ts +1 -0
  158. package/dist/icons/index.js +75 -74
  159. package/dist/shared/focus/pointer-focus.js +12 -10
  160. package/dist/shared/focus/pointer-focus.js.map +1 -1
  161. package/dist/shared/gesture/drag-gesture.js +4 -4
  162. package/dist/shared/gesture/drag-gesture.js.map +1 -1
  163. package/dist/shared/group-management/index.js +43 -18
  164. package/dist/shared/group-management/index.js.map +1 -1
  165. package/dist/shared/menu-portal/menu-portal.js +1 -1
  166. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  167. package/dist/shared/overlay/overlay-root.js +1 -1
  168. package/dist/shared/overlay/overlay-root.js.map +1 -1
  169. package/dist/shared/overlay/overlay.js +7 -1
  170. package/dist/shared/overlay/overlay.js.map +1 -1
  171. package/package.json +5 -1
  172. package/dist/assets/glass.js +0 -6
  173. package/dist/assets/glass.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import '@/components/input'\n\nimport { html, LitElement, nothing, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport type { WebUiOption } from '@/components/option'\nimport internalScrollbars from '@/scrollbars/internal.css?inline'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport {\n createComboboxOpenController,\n createOptionListenerBinding,\n defineComboboxTrigger,\n defineOptionPortal,\n handleComboboxFocusOut,\n nextWrappingIndex\n} from '@/shared/option-portal'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOpenOverlay } from '@/shared/overlay/open-overlay'\nimport {\n applyOverlayVariables,\n defineOverlayPortal,\n type OverlayContainer,\n type OverlayPortal\n} from '@/shared/overlay/portal'\nimport { defineScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\nconst FILTER_MODES = ['none', 'prefix', 'contains'] as const\ntype FilterMode = (typeof FILTER_MODES)[number]\n\n// 自定义 trigger 与 select 同判据:必须留在宿主,不随 options 迁入 portal panel\nfunction isTriggerSlotNode(node: Node): node is Element {\n return node instanceof Element && node.slot === 'trigger'\n}\n\n// 已移除的 empty slot 仍可能留在既有消费者 light DOM;不得把它作为普通内容迁入 portal。\nfunction isEmptySlotNode(node: Node): node is Element {\n return node instanceof Element && node.slot === 'empty'\n}\n\n/**\n * `web-ui-autocomplete`:可输入并过滤候选的单值选择器。\n *\n * 与 `web-ui-select` 共用 `<web-ui-option>` 子项注册协议与 overlay 能力,但触发区是\n * 可编辑 input:`value` 即当前输入文本(表单值),键入时按 `filter` 模式过滤候选,\n * 选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value。\n * `allow-custom-value` 开启后,Enter 可把不匹配候选的原文作为 custom value 显式提交。\n *\n * trigger 跟随 select 的 wrapper div 模式:`slot[name=\"trigger\"]` 可替换默认 trigger\n * (shadow 内的 `web-ui-input`);多行 trigger(如 `web-ui-textarea`)保留 Enter 换行语义,\n * 关闭 panel 用 Escape 或 blur。\n * tab 位只属于 trigger 自身:默认 trigger 是 shadow 内 input,自定义 trigger 由消费者提供\n * 可聚焦元素(README 契约);包装 div 恒为 tabindex=\"-1\",不占顺序焦点,避免双 tab 位。\n */\n@customElement('web-ui-autocomplete')\nexport class WebUiAutocomplete extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(internalScrollbars), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' })\n noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'allow-custom-value' })\n allowCustomValue = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n private _filter: FilterMode = 'contains'\n\n @property({ type: String, reflect: true })\n get filter(): FilterMode {\n return this._filter\n }\n set filter(v: string) {\n const old = this._filter\n this._filter = normalizeLiteral(v, FILTER_MODES, 'contains')\n this.requestUpdate('filter', old)\n }\n\n // value 不反射 attribute,attribute 只参与首次声明式初始化。\n @state() private _value = ''\n\n get value(): string {\n return this._value\n }\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n // selected-value:文本精确匹配 option label 时派生出的 option value(只读反射)。\n @state() private _selectedValue = ''\n\n get selectedValue(): string {\n return this._selectedValue\n }\n\n private _setSelectedValue(value: string) {\n const old = this._selectedValue\n if (old === value && this.getAttribute('selected-value') === value) return\n\n this._selectedValue = value\n this.setAttribute('selected-value', value)\n if (old !== value) this.requestUpdate('selectedValue', old)\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n // 同步 HTML 属性中预设的 value,补全访问器模式不处理 attribute 反射。\n const attrValue = this.getAttribute('value')\n if (attrValue !== null) this._value = attrValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n @state() private _isOpen = false\n @state() private _activeIndex = -1\n @state() private _focused = false\n @state() private _hasTriggerSlot = false\n\n private static _nextInstanceId = 0\n private readonly _idPrefix = `web-ui-autocomplete-${++WebUiAutocomplete._nextInstanceId}`\n private readonly _a11yOptionIds = new WeakMap<WebUiOption, string>()\n private _nextA11yOptionId = 0\n private _options: WebUiOption[] = []\n private _portal?: OverlayPortal\n private _portalContent?: HTMLElement\n private readonly _scrollLock = defineScrollLockLease().make()\n\n // option 注册表 / portal 同步 / 微任务调度收敛到 shared 模块(select 同款)\n private readonly _optionPortal = defineOptionPortal().make({\n element: this,\n idPrefix: `${this._idPrefix}-option`,\n getPortal: () => this._portal,\n getPortalContent: () => this._portalContent,\n isOpen: () => this.portal && this._isOpen,\n // 默认 slot 内容随 panel 迁移;trigger 与已移除的 empty slot 留在宿主,不进 panel。\n getMigratableNodes: () =>\n Array.from(this.childNodes).filter(node => !isTriggerSlotNode(node) && !isEmptySlotNode(node)),\n hasUpdated: () => this.hasUpdated,\n requestUpdate: () => this.requestUpdate(),\n bindOption: option => this._bindOption(option),\n unbindOption: option => this._unbindOption(option)\n })\n /*\n * trigger 委托层:默认 trigger(shadow 内 web-ui-input)与 slot[name=\"trigger\"] 自定义\n * trigger 对组件暴露同一形状,监听统一挂在 trigger 包装 div 上,两条路径不特判。\n */\n private readonly _trigger = defineComboboxTrigger().make({\n getWrapper: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-trigger') ?? null,\n getCustomTrigger: () => {\n const assigned = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')?.assignedElements()[0]\n return assigned instanceof HTMLElement ? assigned : null\n },\n getFallbackTrigger: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-input') ?? null,\n onInput: value => this._onTriggerInput(value),\n onClick: () => this._onTriggerClick(),\n onFocusIn: event => this._onTriggerFocusIn(event),\n onFocusOut: event => this._onTriggerFocusOut(event)\n })\n /*\n * 开启态 overlay 承载「我开着吗」(issue #120 Block 1):宿主级 keydown 在 portal 模式下\n * 收不到 panel 内的 Escape,改由唯一仲裁者在 document 捕获阶段判定最内层。\n * 宿主接口除 requestClose 外只再提供一个 isConnected(仅供惰性回收读取):开启状态是\n * 声明而非询问。\n */\n private readonly _overlay = defineOpenOverlay().make({\n requestClose: () => this._close(),\n isConnected: () => this.isConnected\n })\n private readonly _panel = defineAnchoredPanel().make({\n // 锚点取当前生效的 trigger host:默认 trigger 或自定义 trigger slot 内容\n getAnchor: () =>\n this._trigger.getTrigger() ?? this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-overlay') ?? null,\n getPositioning: () => ({\n placement: 'bottom-start',\n offset: 4,\n minAnchorWidth: true,\n strategy: this.portal ? 'fixed' : 'absolute'\n }),\n isPortal: () => this.portal,\n createPortal: () => this._createPortal(),\n openOverlay: this._overlay\n })\n\n get isOpen(): boolean {\n return this._isOpen\n }\n\n get open(): boolean {\n return this._isOpen\n }\n\n /*\n * 公共焦点委托:聚焦/失焦当前生效的 trigger(默认 web-ui-input 或自定义 trigger)。\n * 组件自带 focus 重定向时落到内部原生控件;自定义 trigger 没有该能力时,\n * 原生 focus() 聚焦 host 自身。无 trigger(尚未首渲或已断开)时静默返回。\n */\n override focus(options?: FocusOptions): void {\n this._trigger.focusTrigger(options)\n }\n\n override blur(): void {\n this._trigger.blurTrigger()\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen) return\n\n // 在监听器内部判定:composedPath() 在派发结束后会被清空。\n const isInside = e.composedPath().includes(this) || !!this._panel.getHandle()?.containsEvent(e)\n if (!isInside) this._close()\n }\n\n private _onFocusOut = () => {\n handleComboboxFocusOut(\n this,\n () => this._panel.getHandle(),\n () => this._isOpen,\n () => this._close()\n )\n }\n\n private _handlePanelPointerDown = (e: PointerEvent) => {\n // 非 option 区域不可聚焦;阻止 pointerdown 的默认聚焦行为,保持 combobox 焦点,\n // 使点击 empty state、滚动区和 panel padding 不会被 focusout 误判为外部交互。\n e.preventDefault()\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._optionPortal.bindHost()\n // 宿主可能被上层 overlay portal 迁移(断开重连):shadow 内的包装 div 仍在,重新绑定委托监听\n this._trigger.bind()\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('focusout', this._onFocusOut)\n document.addEventListener('click', this._onClickOutside)\n }\n\n private _onTriggerSlotChange = () => {\n this._syncTriggerSlot()\n }\n\n /*\n * 自定义 trigger 判定必须同步:slotchange 在首次渲染之后才派发,只依赖它会让默认\n * web-ui-input 先渲染一帧再被替换,自定义 trigger 出现时会闪一下默认 input。\n * 判据与 portal 迁移排除(isTriggerSlotNode)同源:宿主直接子节点带 slot=\"trigger\"。\n */\n private _syncTriggerSlot() {\n const hasTriggerSlot = Array.from(this.children).some(isTriggerSlotNode)\n if (this._hasTriggerSlot === hasTriggerSlot) return\n this._hasTriggerSlot = hasTriggerSlot\n // trigger 在默认与自定义之间切换:anchor 与 portal 会话按新 trigger 重建。\n // 首次渲染前尚无 portal 会话,无需重建。\n if (this.hasUpdated) this._reconfigureOverlay()\n }\n\n override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n super.attributeChangedCallback(name, oldValue, newValue)\n if (name === 'selected-value' && this.isConnected && newValue !== this._selectedValue) {\n queueMicrotask(() => {\n if (this.isConnected) this._syncSelectedValue()\n })\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._optionPortal.dispose()\n this._trigger.dispose()\n this.removeEventListener('keydown', this._onKeydown)\n this.removeEventListener('focusout', this._onFocusOut)\n document.removeEventListener('click', this._onClickOutside)\n this._options.forEach(this._unbindOption)\n this._close()\n this._portal = undefined\n this._portalContent = undefined\n // 撤销登记由 _panel.dispose() 完成(handle 归它持有),不再需要单独 dispose 仲裁者。\n this._panel.dispose()\n this._scrollLock.release()\n }\n\n override firstUpdated() {\n this._trigger.bind()\n requestAnimationFrame(() => {\n if (this.isConnected) this._optionPortal.scheduleRefresh()\n })\n }\n\n override willUpdate() {\n this._syncTriggerSlot()\n this._refreshOptions()\n this._optionPortal.ensureOptionIds(this._options)\n this._syncSelectedValue()\n this._applyFilter()\n this._syncOptionA11y()\n this._syncActiveOption()\n }\n\n override updated(changed: PropertyValues) {\n // 文本回写经委托层落到当前 trigger(默认 web-ui-input 或自定义 trigger)\n this._trigger.setValue(this._value)\n if (changed.has('portal') || changed.has('overlayContainer'))\n requestAnimationFrame(() => this._reconfigureOverlay())\n if (changed.has('noScrollLock')) this._syncScrollLock()\n this.toggleAttribute('focused', this._focused)\n this._syncOpenAttribute()\n this._syncOverlayInert()\n this._syncValidity()\n this._syncOpenWithMatches()\n }\n\n override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n if (disabled && this._isOpen) this._close()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n // readonly 与 disabled 一致:值不可由用户修改,视为通过校验(原生 barred-from-validation 语义)\n if (this._isDisabled || this.readonly || !this.required || this._value) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, 'Enter a value')\n }\n\n private _syncOpenAttribute() {\n this.toggleAttribute('open', this._isOpen)\n }\n\n /*\n * 禁用/只读态不响应 Escape。仲裁者仍在(吞掉按键并压掉原生 cancel),只是不走关闭\n * 入口 —— 与旧的「跳过候选」语义不同:旧语义放任事件落到下层 overlay,把外层一起关掉。\n * 每次渲染后同步即可覆盖 disabled / readonly 属性与表单禁用三条来源。\n */\n private _syncOverlayInert() {\n this._panel.getHandle()?.setInert(this._isDisabled || this.readonly)\n }\n\n private _syncSelectedValue() {\n const query = this._value.trim().toLowerCase()\n const next = query\n ? (this._options.find(o => !o.disabled && o.label.trim().toLowerCase() === query)?.value ?? '')\n : ''\n this._setSelectedValue(next)\n }\n\n private _syncOptionA11y() {\n this._options.forEach(o => {\n o.setAttribute('role', 'option')\n o.setAttribute('aria-selected', o.value === this._selectedValue ? 'true' : 'false')\n o.setAttribute('aria-hidden', 'true')\n })\n }\n\n private _getA11yOptionId(option: WebUiOption): string {\n let id = this._a11yOptionIds.get(option)\n if (!id) {\n id = `${this._idPrefix}-a11y-option-${++this._nextA11yOptionId}`\n this._a11yOptionIds.set(option, id)\n }\n return id\n }\n\n // 按当前文本与 filter 模式过滤候选,非匹配项以 data-filtered 隐藏并跳过导航\n private _applyFilter() {\n const query = this._value.trim().toLowerCase()\n const mode = this._filter\n this._options.forEach(o => {\n const label = o.label.trim().toLowerCase()\n const match = mode === 'none' || !query || (mode === 'prefix' ? label.startsWith(query) : label.includes(query))\n o.toggleAttribute('data-filtered', !match)\n })\n // 活动项被过滤或禁用时清除键盘激活,避免激活不可见项\n const active = this._options[this._activeIndex]\n if (this._activeIndex >= 0 && (!active || active.hasAttribute('data-filtered') || active.disabled)) {\n this._activeIndex = -1\n this._syncActiveOption()\n }\n }\n\n private _hasMatchingOptions() {\n return this._options.some(option => !option.hasAttribute('data-filtered'))\n }\n\n private _syncOpenWithMatches() {\n if (this._isOpen && !this._hasMatchingOptions()) this._close()\n }\n\n private readonly _optionListeners = createOptionListenerBinding({\n // 惰性解引用:handler 字段声明在后者仍可在调用期取到\n onClick: event => this._handleOptionClick(event),\n onPointerOver: event => this._handleOptionPointerOver(event),\n onPointerDown: event => this._handleOptionPointerDown(event),\n onUpdate: () => this._onOptionUpdate()\n })\n private _bindOption = (option: WebUiOption) => this._optionListeners.bind(option)\n private _unbindOption = (option: WebUiOption) => this._optionListeners.unbind(option)\n\n private _refreshOptions() {\n const activeOption = this._options[this._activeIndex]\n // diff 绑定/解绑与激活索引按 option 身份保持在 shared 内完成\n const next = this._optionPortal.refresh(this._options, activeOption)\n this._options = next.options\n this._activeIndex = next.activeIndex\n }\n\n private _handleOptionClick = (e: Event) => {\n if (!(e.currentTarget instanceof HTMLElement)) return\n const option = e.currentTarget as WebUiOption\n if (option.disabled) return\n this._selectOption(option)\n }\n\n private _onOptionUpdate = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _handleOptionPointerOver = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (!this._isOpen || !(e.currentTarget instanceof HTMLElement)) return\n\n // 指针接管后只保留 :hover,避免键盘激活项与悬停项同时高亮。\n this._activeIndex = -1\n this._syncActiveOption()\n }\n\n private _handleOptionPointerDown = (e: PointerEvent) => {\n // 保持 input 焦点,避免 focusout 在 click 前关闭 overlay。\n e.preventDefault()\n }\n\n // slotchange 不冒泡,只能由模板内 slot 自行监听;稳定引用避免 Lit 重挂载\n private _onSlotChange = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (this._isDisabled || this.readonly) return\n this._applyFilter()\n this._syncOpenWithMatches()\n\n // Escape 不在本组件处理:由共享仲裁者在 document 捕获阶段归属(issue #120 Block 1)。\n switch (e.key) {\n /*\n * 多行 trigger(textarea)的方向键归光标移动:panel 打开时不接管、不\n * preventDefault,与 Enter 的 multiline 例外同判据。panel 关闭时方向键\n * 仍是打开入口(键盘可达性不依赖指针)。\n */\n case 'ArrowDown':\n case 'ArrowUp': {\n if (this._isOpen && this._trigger.isMultilineEdit(e)) break\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(e.key === 'ArrowDown' ? 1 : -1)\n break\n }\n case 'Enter': {\n /*\n * panel 打开时接管 Enter:选择候选或提交 custom value。\n * 零匹配时 panel 会被过滤状态收敛关闭,但 allow-custom-value 仍需在关闭态提交。\n * 多行 trigger(textarea)保留换行语义,不接管为选中高亮项。\n */\n const canSubmitCustomValue = this._canSubmitCustomValue()\n if (\n !this._trigger.isMultilineEdit(e) &&\n (this._isOpen || (!this._hasMatchingOptions() && canSubmitCustomValue))\n ) {\n e.preventDefault()\n if (this._isOpen) {\n const option = this._options[this._activeIndex]\n if (option && !option.disabled && !option.hasAttribute('data-filtered')) {\n this._selectOption(option)\n return\n }\n\n const exactOption = this._findExactOption(this._value)\n if (exactOption) {\n this._selectOption(exactOption)\n return\n }\n }\n\n if (canSubmitCustomValue) this._selectCustomValue()\n }\n break\n }\n }\n }\n\n private _navigateActive(delta: number) {\n const enabled = this._options.filter(o => !o.disabled && !o.hasAttribute('data-filtered'))\n if (!enabled.length) return\n\n const currentIdx = this._activeIndex >= 0 ? enabled.indexOf(this._options[this._activeIndex]) : delta > 0 ? -1 : 0\n this._activeIndex = this._options.indexOf(enabled[nextWrappingIndex(enabled.length, currentIdx, delta)])\n this._syncActiveOption()\n }\n\n private _setInitialActiveOption() {\n const firstEnabled = this._options.findIndex(o => !o.disabled && !o.hasAttribute('data-filtered'))\n this._activeIndex = firstEnabled\n this._syncActiveOption()\n }\n\n private _syncActiveOption() {\n this._options.forEach((option, index) => option.toggleAttribute('active', index === this._activeIndex))\n }\n\n private _selectOption(option: WebUiOption) {\n if (this.readonly) return\n // value 即输入文本:选择后回填为 option label,selected-value 取 option value\n this.value = option.label\n this._setSelectedValue(option.value)\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _findExactOption(value: string): WebUiOption | undefined {\n const query = value.trim().toLowerCase()\n if (!query) return undefined\n\n return this._options.find(option => !option.disabled && option.label.trim().toLowerCase() === query)\n }\n\n private _hasExactOption(value: string): boolean {\n const query = value.trim().toLowerCase()\n return this._options.some(option => option.label.trim().toLowerCase() === query)\n }\n\n private _canSubmitCustomValue() {\n return this.allowCustomValue && !!this._value && !this._hasExactOption(this._value)\n }\n\n private _selectCustomValue() {\n // Custom value 的 identity 由消费端管理;组件不隐式创建 option,selected-value 保持派生空值。\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _onTriggerInput = (value: string) => {\n if (this._isDisabled || this.readonly) return\n if (value === this._value) return\n this.value = value\n this._activeIndex = -1\n this._syncActiveOption()\n this._open()\n }\n\n private _onTriggerClick = () => {\n if (this._isDisabled || this.readonly) return\n this._open()\n }\n\n /*\n * focus/blur 不冒泡,委托层监听等价且冒泡的 focusin/focusout。\n * 自定义 trigger 位于 light DOM,其焦点变化不会跨 shadow 边界到达宿主,这里补发\n * 公共 focus/blur 兑现 README 事件契约;默认 trigger 在 shadow 内,原生事件已能\n * 到达宿主,重复派发会让消费端收到两次。\n */\n private _onTriggerFocusIn = (event: FocusEvent) => {\n if (this._isDisabled) return\n this._focused = true\n // composed 与原生 focus 一致(宿主内 retarget):跨 shadow 边界的消费者能收到,\n // 但不 bubbles —— focus/blur 的公共契约本来就不冒泡。\n // relatedTarget 透传:消费端靠它判断焦点来回,补发事件不该丢这个信息\n if (this._isSlottedFocus(event))\n this.dispatchEvent(new FocusEvent('focus', { composed: true, relatedTarget: event.relatedTarget }))\n }\n\n private _onTriggerFocusOut = (event: FocusEvent) => {\n this._focused = false\n if (this._isSlottedFocus(event))\n this.dispatchEvent(new FocusEvent('blur', { composed: true, relatedTarget: event.relatedTarget }))\n }\n\n private _isSlottedFocus(event: FocusEvent): boolean {\n const target = event.target\n return target instanceof Node && !!this.shadowRoot && !this.shadowRoot.contains(target)\n }\n\n // 开合生命周期不变量收敛在 shared combobox-shell;autocomplete 注入\n // readonly guard 与 close 前的 portal 内容收敛钩子\n private readonly _openController = createComboboxOpenController({\n canOpen: () => !this._isDisabled && !this.readonly,\n getIsOpen: () => this._isOpen,\n setIsOpen: open => {\n this._isOpen = open\n },\n dispatchOpenChange: () => this._dispatchOpenChange(),\n syncScrollLock: open => this._syncScrollLock(open),\n isPortal: () => this.portal,\n openOverlay: isKeyboardNavigation => this._openOverlay(isKeyboardNavigation),\n closeOverlay: () => void this._closeOverlay(),\n onOpen: isKeyboardNavigation => {\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n },\n onBeforeClose: () => {\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._optionPortal.syncPortalContent()\n },\n onAfterClose: () => {\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n }\n })\n\n private _open(isKeyboardNavigation = false) {\n this._applyFilter()\n if (!this._hasMatchingOptions()) {\n if (this._isOpen) this._close()\n return\n }\n this._openController.open(isKeyboardNavigation)\n }\n\n private _close() {\n this._openController.close()\n }\n\n private _dispatchOpenChange() {\n dispatchOpenChangeEvent(this, this._isOpen)\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n // 新会话的 handle 刚建立,惰性状态需按当前 disabled/readonly 重新同步。\n this._syncOverlayInert()\n }\n\n private async _closeOverlay() {\n const closed = await this._panel.close(() => this._isOpen)\n if (closed) {\n this._portal = undefined\n this._portalContent = undefined\n }\n }\n\n private _reconfigureOverlay() {\n this._portal = undefined\n this._portalContent = undefined\n this._panel.reconfigure(this._isOpen)\n /*\n * reconfigure 重新 claim = 新会话,inert 回到 false。实测这条重推是**冗余**的(摘掉本行\n * 全部用例仍绿):这条路径后面跟着一轮渲染,而 `updated()` 每次渲染都会调\n * `_syncOverlayInert()`。留在这里是不想依赖「这条路径必然跟着一次渲染」这个隐含前提。\n */\n this._syncOverlayInert()\n }\n\n private _syncScrollLock(isOpen = this._isOpen) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _createPortal(): OverlayPortal {\n const portal = defineOverlayPortal().make({\n container: this.overlayContainer,\n target: this,\n style: `${glass}\\n${overlayMotion}\\n${style}`,\n className: 'wui-glass autocomplete-overlay portal wui-floating-panel',\n onContentChange: () => {\n this._optionPortal.scheduleRefresh()\n }\n })\n this._portal = portal\n applyOverlayVariables(portal.panel, this, [\n '--wui-overlay-min-width',\n '--wui-autocomplete-max-width',\n '--wui-autocomplete-max-height'\n ])\n portal.panel.setAttribute('aria-hidden', 'true')\n portal.panel.addEventListener('pointerdown', this._handlePanelPointerDown)\n const scroll = document.createElement('div')\n scroll.className = 'autocomplete-scroll wui-scroll'\n const content = document.createElement('div')\n content.className = 'autocomplete-content'\n this._portalContent = content\n scroll.append(content)\n portal.panel.append(scroll)\n for (const node of Array.from(this.childNodes)) {\n // 框架注释锚点(v-if/v-for 占位)必须留在宿主:锚点进 panel 后 Vue 下次翻转\n // 会以 panel 内节点为插入基准;portal 的 marker 注释同理不参与迁移。\n if (node instanceof Comment) continue\n // 自定义 trigger 与 select(:461)同判据:留在宿主,不随 options 迁入 overlay\n if (isTriggerSlotNode(node)) continue\n // 已移除的 empty slot 不能作为普通内容出现在新 portal panel 中\n if (isEmptySlotNode(node)) continue\n portal.appendContent([node], content)\n }\n return portal\n }\n\n private _getLabelledbyText(): string {\n if (!this.ariaLabelledby) return ''\n\n const root = this.getRootNode()\n if (!(root instanceof Document || root instanceof ShadowRoot)) return ''\n\n return this.ariaLabelledby\n .trim()\n .split(/\\s+/)\n .map(id => {\n const escapedId = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(id) : id\n return root.querySelector(`#${escapedId}`)?.textContent?.trim() ?? ''\n })\n .filter(Boolean)\n .join(' ')\n }\n\n override render() {\n const listboxId = `${this._idPrefix}-listbox`\n const labelId = `${this._idPrefix}-label`\n const labelledbyText = this._getLabelledbyText()\n const visibleOptions = this._options.filter(option => !option.hasAttribute('data-filtered'))\n const activeOption = this._isOpen && this._activeIndex >= 0 ? this._options[this._activeIndex] : undefined\n const activeDescendant = activeOption ? this._getA11yOptionId(activeOption) : nothing\n\n return html`\n <div class=\"wui-autocomplete-inner\">\n ${labelledbyText ? html`<span class=\"autocomplete-a11y-only\" id=${labelId}>${labelledbyText}</span>` : nothing}\n <div\n class=\"autocomplete-trigger\"\n ?data-custom-trigger=${this._hasTriggerSlot}\n role=\"combobox\"\n aria-expanded=${this._isOpen}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls=${listboxId}\n aria-disabled=${String(this._isDisabled)}\n aria-readonly=${this.readonly ? 'true' : nothing}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${labelledbyText ? labelId : nothing}\n aria-activedescendant=${activeDescendant}\n tabindex=\"-1\"\n >\n <slot name=\"trigger\" @slotchange=${this._onTriggerSlotChange}></slot>\n ${\n !this._hasTriggerSlot\n ? html`<web-ui-input\n class=\"autocomplete-input\"\n .value=${this._value}\n placeholder=${this.placeholder}\n name=${this.name}\n ?borderless=${this.borderless}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n aria-label=${ifDefined(this.ariaLabel || labelledbyText || undefined)}\n ></web-ui-input>`\n : nothing\n }\n </div>\n <div\n class=\"autocomplete-a11y-listbox\"\n id=${listboxId}\n role=\"listbox\"\n ?hidden=${!this._isOpen}\n aria-hidden=${String(!this._isOpen)}\n >\n ${visibleOptions.map(\n option =>\n html`<div\n id=${this._getA11yOptionId(option)}\n role=\"option\"\n aria-selected=${option.value === this._selectedValue ? 'true' : 'false'}\n aria-hidden=${String(!this._isOpen)}\n aria-disabled=${String(option.disabled)}\n >\n ${option.label}\n </div>`\n )}\n </div>\n <div\n class=\"autocomplete-overlay wui-floating-panel wui-glass\"\n hidden\n aria-hidden=\"true\"\n @pointerdown=${this._handlePanelPointerDown}\n >\n <div class=\"autocomplete-scroll wui-scroll\">\n <div class=\"autocomplete-content\">\n <slot @slotchange=${this._onSlotChange}></slot>\n </div>\n </div>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n focus: FocusEvent\n blur: FocusEvent\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-autocomplete': WebUiAutocomplete\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;OAiCM,IAAe;CAAC;CAAQ;CAAU;AAAU;AAIlD,SAAS,EAAkB,GAA6B;CACtD,OAAO,aAAgB,WAAW,EAAK,SAAS;AAClD;AAGA,SAAS,EAAgB,GAA6B;CACpD,OAAO,aAAgB,WAAW,EAAK,SAAS;AAClD;AAiBO,IAAM,IAAN,cAAgC,EAAe,CAAU,CAAC,CAAC;;;;;EA0iB7B,aAviBsB,KAAA,cAAA,IACA,KAAA,aAAA,IACF,KAAA,WAAA,IACA,KAAA,WAAA,IACA,KAAA,WAAA,IACF,KAAA,SAAA,IAEtC,KAAA,eAAA,IAEI,KAAA,mBAAA,IAE+B,KAAA,OAAA,IACuC,KAAA,YAAA,MAG3D,KAAA,UAAA,YAaJ,KAAA,SAAA,IAaQ,KAAA,iBAAA,IAeE,KAAA,mBAAA,EAA8B;GAChE,MAAM;GACN,kBAAkB;IAEhB,IAAM,IAAY,KAAK,aAAa,OAAO;IAC3C,AAAI,MAAc,SAAM,KAAK,SAAS;GACxC;GACA,gBAAgB,KAAK;GACrB,WAAU,MAAS;IACjB,KAAK,QAAQ;GACf;GACA,oBAAoB,KAAK;GACzB,oBAAoB,KAAK;GACzB,eAAc,MAAS;IACrB,AAAI,OAAO,KAAU,aAAU,KAAK,QAAQ;GAC9C;GACA,oBAAoB,KAAK,cAAc;EACzC,CAAC,CAAC,CAAC,KAAK,GAEsC,KAAA,6BAAA,IAAI,EAA0B,MAAM,KAAK,gBAAgB,GAM5E,KAAA,UAAA,IACK,KAAA,eAAA,IACJ,KAAA,WAAA,IACO,KAAA,kBAAA,IAGN,KAAA,YAAA,uBAAuB,EAAA,EAAoB,mBACtC,KAAA,iCAAA,IAAI,QAA6B,GACvC,KAAA,oBAAA,GACM,KAAA,WAAA,CAAC,GAGJ,KAAA,cAAA,EAAsB,CAAC,CAAC,KAAK,GAG3B,KAAA,gBAAA,EAAmB,CAAC,CAAC,KAAK;GACzD,SAAS;GACT,UAAU,GAAG,KAAK,UAAU;GAC5B,iBAAiB,KAAK;GACtB,wBAAwB,KAAK;GAC7B,cAAc,KAAK,UAAU,KAAK;GAElC,0BACE,MAAM,KAAK,KAAK,UAAU,CAAC,CAAC,QAAO,MAAQ,CAAC,EAAkB,CAAI,KAAK,CAAC,EAAgB,CAAI,CAAC;GAC/F,kBAAkB,KAAK;GACvB,qBAAqB,KAAK,cAAc;GACxC,aAAY,MAAU,KAAK,YAAY,CAAM;GAC7C,eAAc,MAAU,KAAK,cAAc,CAAM;EACnD,CAAC,GAK2B,KAAA,WAAA,EAAsB,CAAC,CAAC,KAAK;GACvD,kBAAkB,KAAK,YAAY,cAA2B,uBAAuB,KAAK;GAC1F,wBAAwB;IACtB,IAAM,IAAW,KAAK,YAAY,cAA+B,wBAAsB,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC7G,OAAO,aAAoB,cAAc,IAAW;GACtD;GACA,0BAA0B,KAAK,YAAY,cAA2B,qBAAqB,KAAK;GAChG,UAAS,MAAS,KAAK,gBAAgB,CAAK;GAC5C,eAAe,KAAK,gBAAgB;GACpC,YAAW,MAAS,KAAK,kBAAkB,CAAK;GAChD,aAAY,MAAS,KAAK,mBAAmB,CAAK;EACpD,CAAC,GAO2B,KAAA,WAAA,EAAkB,CAAC,CAAC,KAAK;GACnD,oBAAoB,KAAK,OAAO;GAChC,mBAAmB,KAAK;EAC1B,CAAC,GACyB,KAAA,SAAA,EAAoB,CAAC,CAAC,KAAK;GAEnD,iBACE,KAAK,SAAS,WAAW,KAAK,KAAK,YAAY,cAA2B,uBAAuB,KAAK;GACxG,qBAAqB,KAAK,YAAY,cAA2B,uBAAuB,KAAK;GAC7F,uBAAuB;IACrB,WAAW;IACX,QAAQ;IACR,gBAAgB;IAChB,UAAU,KAAK,SAAS,UAAU;GACpC;GACA,gBAAgB,KAAK;GACrB,oBAAoB,KAAK,cAAc;GACvC,aAAa,KAAK;EACpB,CAAC,GAuB0B,KAAA,mBAAA,MAAkB;GACtC,KAAK,YAGO,EAAE,aAAa,CAAC,CAAC,SAAS,IAAI,KAAO,KAAK,OAAO,UAAU,CAAC,EAAE,cAAc,CAAC,KAC/E,KAAK,OAAO;EAC7B,GAE4B,KAAA,oBAAA;GAC1B,EACE,YACM,KAAK,OAAO,UAAU,SACtB,KAAK,eACL,KAAK,OAAO,CACpB;EACF,GAEmC,KAAA,2BAAA,MAAoB;GAGrD,EAAE,eAAe;EACnB,GAYqC,KAAA,6BAAA;GACnC,KAAK,iBAAiB;EACxB,GAmJoC,KAAA,mBAAA,EAA4B;GAE9D,UAAS,MAAS,KAAK,mBAAmB,CAAK;GAC/C,gBAAe,MAAS,KAAK,yBAAyB,CAAK;GAC3D,gBAAe,MAAS,KAAK,yBAAyB,CAAK;GAC3D,gBAAgB,KAAK,gBAAgB;EACvC,CAAC,GACsB,KAAA,eAAA,MAAwB,KAAK,iBAAiB,KAAK,CAAM,GACvD,KAAA,iBAAA,MAAwB,KAAK,iBAAiB,OAAO,CAAM,GAUtD,KAAA,sBAAA,MAAa;GACzC,IAAI,EAAE,EAAE,yBAAyB,cAAc;GAC/C,IAAM,IAAS,EAAE;GACb,EAAO,YACX,KAAK,cAAc,CAAM;EAC3B,GAEgC,KAAA,wBAAA;GAC9B,KAAK,cAAc,gBAAgB;EACrC,GAEoC,KAAA,4BAAA,MAAoB;GAClD,EAAE,gBAAgB,WACjB,KAAK,WAAa,EAAE,yBAAyB,gBAGlD,KAAK,eAAe,IACpB,KAAK,kBAAkB;EACzB,GAEoC,KAAA,4BAAA,MAAoB;GAEtD,EAAE,eAAe;EACnB,GAG8B,KAAA,sBAAA;GAC5B,KAAK,cAAc,gBAAgB;EACrC,GAEsB,KAAA,cAAA,MAAqB;GACrC,WAAK,eAAe,KAAK,WAK7B,QAJA,KAAK,aAAa,GAClB,KAAK,qBAAqB,GAGlB,EAAE,KAAV;IAME,KAAK;IACL,KAAK;KACH,IAAI,KAAK,WAAW,KAAK,SAAS,gBAAgB,CAAC,GAAG;KAEtD,AADA,EAAE,eAAe,GACZ,KAAK,UACL,KAAK,gBAAgB,EAAE,QAAQ,cAAc,IAAI,EAAE,IADrC,KAAK,MAAM,EAAI;KAElC;IAEF,KAAK,SAAS;KAMZ,IAAM,IAAuB,KAAK,sBAAsB;KACxD,IACE,CAAC,KAAK,SAAS,gBAAgB,CAAC,MAC/B,KAAK,WAAY,CAAC,KAAK,oBAAoB,KAAK,IACjD;MAEA,IADA,EAAE,eAAe,GACb,KAAK,SAAS;OAChB,IAAM,IAAS,KAAK,SAAS,KAAK;OAClC,IAAI,KAAU,CAAC,EAAO,YAAY,CAAC,EAAO,aAAa,eAAe,GAAG;QACvE,KAAK,cAAc,CAAM;QACzB;OACF;OAEA,IAAM,IAAc,KAAK,iBAAiB,KAAK,MAAM;OACrD,IAAI,GAAa;QACf,KAAK,cAAc,CAAW;QAC9B;OACF;MACF;MAEA,AAAI,KAAsB,KAAK,mBAAmB;KACpD;KACA;IACF;GACF;EACF,GAsD2B,KAAA,mBAAA,MAAkB;GACvC,KAAK,eAAe,KAAK,YACzB,MAAU,KAAK,WACnB,KAAK,QAAQ,GACb,KAAK,eAAe,IACpB,KAAK,kBAAkB,GACvB,KAAK,MAAM;EACb,GAEgC,KAAA,wBAAA;GAC1B,KAAK,eAAe,KAAK,YAC7B,KAAK,MAAM;EACb,GAQ6B,KAAA,qBAAA,MAAsB;GAC7C,KAAK,gBACT,KAAK,WAAW,IAIZ,KAAK,gBAAgB,CAAK,KAC5B,KAAK,cAAc,IAAI,WAAW,SAAS;IAAE,UAAU;IAAM,eAAe,EAAM;GAAc,CAAC,CAAC;EACtG,GAE8B,KAAA,sBAAA,MAAsB;GAElD,AADA,KAAK,WAAW,IACZ,KAAK,gBAAgB,CAAK,KAC5B,KAAK,cAAc,IAAI,WAAW,QAAQ;IAAE,UAAU;IAAM,eAAe,EAAM;GAAc,CAAC,CAAC;EACrG,GASmC,KAAA,kBAAA,EAA6B;GAC9D,eAAe,CAAC,KAAK,eAAe,CAAC,KAAK;GAC1C,iBAAiB,KAAK;GACtB,YAAW,MAAQ;IACjB,KAAK,UAAU;GACjB;GACA,0BAA0B,KAAK,oBAAoB;GACnD,iBAAgB,MAAQ,KAAK,gBAAgB,CAAI;GACjD,gBAAgB,KAAK;GACrB,cAAa,MAAwB,KAAK,aAAa,CAAoB;GAC3E,oBAAoB,KAAK,KAAK,cAAc;GAC5C,SAAQ,MAAwB;IAC9B,AAAI,IAAsB,KAAK,wBAAwB,IAClD,KAAK,kBAAkB;GAC9B;GACA,qBAAqB;IAInB,KAAK,cAAc,kBAAkB;GACvC;GACA,oBAAoB;IAElB,AADA,KAAK,eAAe,IACpB,KAAK,SAAS,SAAQ,MAAK,EAAE,gBAAgB,QAAQ,CAAC;GACxD;EACF,CAAC;;;EAlkBwB,KAAA,SAAA;GAAC,EAAU,CAAK;GAAG,EAAU,CAAa;GAAG,EAAU,CAAkB;GAAG,EAAU,CAAK;EAAC;;CAmBrH,IACI,SAAqB;EACvB,OAAO,KAAK;CACd;CACA,IAAI,OAAO,GAAW;EACpB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,UAAU,EAAiB,GAAG,GAAc,UAAU,GAC3D,KAAK,cAAc,UAAU,CAAG;CAClC;CAKA,IAAI,QAAgB;EAClB,OAAO,KAAK;CACd;CACA,IAAI,MAAM,GAAW;EACnB,IAAM,IAAM,KAAK;EAGjB,AAFA,KAAK,SAAS,GACd,KAAK,iBAAiB,KAAK,GAC3B,KAAK,cAAc,SAAS,CAAG;CACjC;CAKA,IAAI,gBAAwB;EAC1B,OAAO,KAAK;CACd;CAEA,kBAA0B,GAAe;EACvC,IAAM,IAAM,KAAK;EACb,OAAQ,KAAS,KAAK,aAAa,gBAAgB,MAAM,OAE7D,KAAK,iBAAiB,GACtB,KAAK,aAAa,kBAAkB,CAAK,GACrC,MAAQ,KAAO,KAAK,cAAc,iBAAiB,CAAG;CAC5D;CAuBA,IAAY,cAAuB;EACjC,OAAO,KAAK,YAAY,KAAK,iBAAiB,eAAe;CAC/D;;EAOiC,KAAA,kBAAA;;CAkEjC,IAAI,SAAkB;EACpB,OAAO,KAAK;CACd;CAEA,IAAI,OAAgB;EAClB,OAAO,KAAK;CACd;CAOA,MAAe,GAA8B;EAC3C,KAAK,SAAS,aAAa,CAAO;CACpC;CAEA,OAAsB;EACpB,KAAK,SAAS,YAAY;CAC5B;CAyBA,oBAA6B;EAO3B,AANA,MAAM,kBAAkB,GACxB,KAAK,cAAc,SAAS,GAE5B,KAAK,SAAS,KAAK,GACnB,KAAK,iBAAiB,WAAW,KAAK,UAAU,GAChD,KAAK,iBAAiB,YAAY,KAAK,WAAW,GAClD,SAAS,iBAAiB,SAAS,KAAK,eAAe;CACzD;CAWA,mBAA2B;EACzB,IAAM,IAAiB,MAAM,KAAK,KAAK,QAAQ,CAAC,CAAC,KAAK,CAAiB;EACnE,KAAK,oBAAoB,MAC7B,KAAK,kBAAkB,GAGnB,KAAK,cAAY,KAAK,oBAAoB;CAChD;CAEA,yBAAkC,GAAc,GAAyB,GAAyB;EAEhG,AADA,MAAM,yBAAyB,GAAM,GAAU,CAAQ,GACnD,MAAS,oBAAoB,KAAK,eAAe,MAAa,KAAK,kBACrE,qBAAqB;GACnB,AAAI,KAAK,eAAa,KAAK,mBAAmB;EAChD,CAAC;CAEL;CAEA,uBAAgC;EAa9B,AAZA,MAAM,qBAAqB,GAC3B,KAAK,cAAc,QAAQ,GAC3B,KAAK,SAAS,QAAQ,GACtB,KAAK,oBAAoB,WAAW,KAAK,UAAU,GACnD,KAAK,oBAAoB,YAAY,KAAK,WAAW,GACrD,SAAS,oBAAoB,SAAS,KAAK,eAAe,GAC1D,KAAK,SAAS,QAAQ,KAAK,aAAa,GACxC,KAAK,OAAO,GACZ,KAAK,UAAU,KAAA,GACf,KAAK,iBAAiB,KAAA,GAEtB,KAAK,OAAO,QAAQ,GACpB,KAAK,YAAY,QAAQ;CAC3B;CAEA,eAAwB;EAEtB,AADA,KAAK,SAAS,KAAK,GACnB,4BAA4B;GAC1B,AAAI,KAAK,eAAa,KAAK,cAAc,gBAAgB;EAC3D,CAAC;CACH;CAEA,aAAsB;EAOpB,AANA,KAAK,iBAAiB,GACtB,KAAK,gBAAgB,GACrB,KAAK,cAAc,gBAAgB,KAAK,QAAQ,GAChD,KAAK,mBAAmB,GACxB,KAAK,aAAa,GAClB,KAAK,gBAAgB,GACrB,KAAK,kBAAkB;CACzB;CAEA,QAAiB,GAAyB;EAUxC,AARA,KAAK,SAAS,SAAS,KAAK,MAAM,IAC9B,EAAQ,IAAI,QAAQ,KAAK,EAAQ,IAAI,kBAAkB,MACzD,4BAA4B,KAAK,oBAAoB,CAAC,GACpD,EAAQ,IAAI,cAAc,KAAG,KAAK,gBAAgB,GACtD,KAAK,gBAAgB,WAAW,KAAK,QAAQ,GAC7C,KAAK,mBAAmB,GACxB,KAAK,kBAAkB,GACvB,KAAK,cAAc,GACnB,KAAK,qBAAqB;CAC5B;CAEA,qBAA8B,GAAmB;EAE/C,AADA,KAAK,iBAAiB,YAAY,CAAQ,GACtC,KAAY,KAAK,WAAS,KAAK,OAAO;CAC5C;CAEA,gBAAwB;EACtB,IAAM,IAAY,KAAK,iBAAiB,aAAa;EACjD,AAAC,KAAa,OAAO,EAAU,eAAgB,eAE/C,KAAK,eAAe,KAAK,YAAY,CAAC,KAAK,YAAY,KAAK,SAAQ,EAAU,YAAY,CAAC,CAAC,IAC3F,EAAU,YAAY,EAAE,cAAc,GAAK,GAAG,eAAe;CACpE;CAEA,qBAA6B;EAC3B,KAAK,gBAAgB,QAAQ,KAAK,OAAO;CAC3C;CAOA,oBAA4B;EAC1B,KAAK,OAAO,UAAU,CAAC,EAAE,SAAS,KAAK,eAAe,KAAK,QAAQ;CACrE;CAEA,qBAA6B;EAC3B,IAAM,IAAQ,KAAK,OAAO,KAAK,CAAC,CAAC,YAAY,GACvC,IAAO,IACR,KAAK,SAAS,MAAK,MAAK,CAAC,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC,CAAC,YAAY,MAAM,CAAK,CAAC,EAAE,SAAS,KAC1F;EACJ,KAAK,kBAAkB,CAAI;CAC7B;CAEA,kBAA0B;EACxB,KAAK,SAAS,SAAQ,MAAK;GAGzB,AAFA,EAAE,aAAa,QAAQ,QAAQ,GAC/B,EAAE,aAAa,iBAAiB,EAAE,UAAU,KAAK,iBAAiB,SAAS,OAAO,GAClF,EAAE,aAAa,eAAe,MAAM;EACtC,CAAC;CACH;CAEA,iBAAyB,GAA6B;EACpD,IAAI,IAAK,KAAK,eAAe,IAAI,CAAM;EAKvC,OAJK,MACH,IAAK,GAAG,KAAK,UAAU,eAAe,EAAE,KAAK,qBAC7C,KAAK,eAAe,IAAI,GAAQ,CAAE,IAE7B;CACT;CAGA,eAAuB;EACrB,IAAM,IAAQ,KAAK,OAAO,KAAK,CAAC,CAAC,YAAY,GACvC,IAAO,KAAK;EAClB,KAAK,SAAS,SAAQ,MAAK;GACzB,IAAM,IAAQ,EAAE,MAAM,KAAK,CAAC,CAAC,YAAY,GACnC,IAAQ,MAAS,UAAU,CAAC,MAAU,MAAS,WAAW,EAAM,WAAW,CAAK,IAAI,EAAM,SAAS,CAAK;GAC9G,EAAE,gBAAgB,iBAAiB,CAAC,CAAK;EAC3C,CAAC;EAED,IAAM,IAAS,KAAK,SAAS,KAAK;EAClC,AAAI,KAAK,gBAAgB,MAAM,CAAC,KAAU,EAAO,aAAa,eAAe,KAAK,EAAO,cACvF,KAAK,eAAe,IACpB,KAAK,kBAAkB;CAE3B;CAEA,sBAA8B;EAC5B,OAAO,KAAK,SAAS,MAAK,MAAU,CAAC,EAAO,aAAa,eAAe,CAAC;CAC3E;CAEA,uBAA+B;EAC7B,AAAI,KAAK,WAAW,CAAC,KAAK,oBAAoB,KAAG,KAAK,OAAO;CAC/D;CAYA,kBAA0B;EACxB,IAAM,IAAe,KAAK,SAAS,KAAK,eAElC,IAAO,KAAK,cAAc,QAAQ,KAAK,UAAU,CAAY;EAEnE,AADA,KAAK,WAAW,EAAK,SACrB,KAAK,eAAe,EAAK;CAC3B;CAqFA,gBAAwB,GAAe;EACrC,IAAM,IAAU,KAAK,SAAS,QAAO,MAAK,CAAC,EAAE,YAAY,CAAC,EAAE,aAAa,eAAe,CAAC;EACzF,IAAI,CAAC,EAAQ,QAAQ;EAErB,IAAM,IAAa,KAAK,gBAAgB,IAAI,EAAQ,QAAQ,KAAK,SAAS,KAAK,aAAa,IAAI,IAAQ,IAAI,KAAK;EAEjH,AADA,KAAK,eAAe,KAAK,SAAS,QAAQ,EAAQ,EAAkB,EAAQ,QAAQ,GAAY,CAAK,EAAE,GACvG,KAAK,kBAAkB;CACzB;CAEA,0BAAkC;EAChC,IAAM,IAAe,KAAK,SAAS,WAAU,MAAK,CAAC,EAAE,YAAY,CAAC,EAAE,aAAa,eAAe,CAAC;EAEjG,AADA,KAAK,eAAe,GACpB,KAAK,kBAAkB;CACzB;CAEA,oBAA4B;EAC1B,KAAK,SAAS,SAAS,GAAQ,MAAU,EAAO,gBAAgB,UAAU,MAAU,KAAK,YAAY,CAAC;CACxG;CAEA,cAAsB,GAAqB;EACrC,KAAK,aAET,KAAK,QAAQ,EAAO,OACpB,KAAK,kBAAkB,EAAO,KAAK,GACnC,KAAK,OAAO,GACZ,KAAK,cAAc,IAAI,MAAM,SAAS;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC,GACxE,KAAK,cAAc,IAAI,MAAM,UAAU;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC;CAC3E;CAEA,iBAAyB,GAAwC;EAC/D,IAAM,IAAQ,EAAM,KAAK,CAAC,CAAC,YAAY;EAClC,OAEL,OAAO,KAAK,SAAS,MAAK,MAAU,CAAC,EAAO,YAAY,EAAO,MAAM,KAAK,CAAC,CAAC,YAAY,MAAM,CAAK;CACrG;CAEA,gBAAwB,GAAwB;EAC9C,IAAM,IAAQ,EAAM,KAAK,CAAC,CAAC,YAAY;EACvC,OAAO,KAAK,SAAS,MAAK,MAAU,EAAO,MAAM,KAAK,CAAC,CAAC,YAAY,MAAM,CAAK;CACjF;CAEA,wBAAgC;EAC9B,OAAO,KAAK,oBAAoB,CAAC,CAAC,KAAK,UAAU,CAAC,KAAK,gBAAgB,KAAK,MAAM;CACpF;CAEA,qBAA6B;EAI3B,AAFA,KAAK,OAAO,GACZ,KAAK,cAAc,IAAI,MAAM,SAAS;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC,GACxE,KAAK,cAAc,IAAI,MAAM,UAAU;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC;CAC3E;CAsCA,gBAAwB,GAA4B;EAClD,IAAM,IAAS,EAAM;EACrB,OAAO,aAAkB,QAAQ,CAAC,CAAC,KAAK,cAAc,CAAC,KAAK,WAAW,SAAS,CAAM;CACxF;CA+BA,MAAc,IAAuB,IAAO;EAE1C,IADA,KAAK,aAAa,GACd,CAAC,KAAK,oBAAoB,GAAG;GAC/B,AAAI,KAAK,WAAS,KAAK,OAAO;GAC9B;EACF;EACA,KAAK,gBAAgB,KAAK,CAAoB;CAChD;CAEA,SAAiB;EACf,KAAK,gBAAgB,MAAM;CAC7B;CAEA,sBAA8B;EAC5B,EAAwB,MAAM,KAAK,OAAO;CAC5C;CAEA,aAAqB,IAAuB,IAAO;EAGjD,AAFA,KAAK,OAAO,KAAK,CAAoB,GAErC,KAAK,kBAAkB;CACzB;CAEA,MAAc,gBAAgB;EAE5B,AAAI,MADiB,KAAK,OAAO,YAAY,KAAK,OAAO,MAEvD,KAAK,UAAU,KAAA,GACf,KAAK,iBAAiB,KAAA;CAE1B;CAEA,sBAA8B;EAS5B,AARA,KAAK,UAAU,KAAA,GACf,KAAK,iBAAiB,KAAA,GACtB,KAAK,OAAO,YAAY,KAAK,OAAO,GAMpC,KAAK,kBAAkB;CACzB;CAEA,gBAAwB,IAAS,KAAK,SAAS;EAC7C,KAAK,YAAY,KAAK,KAAU,CAAC,KAAK,YAAY;CACpD;CAEA,gBAAuC;EACrC,IAAM,IAAS,EAAoB,CAAC,CAAC,KAAK;GACxC,WAAW,KAAK;GAChB,QAAQ;GACR,OAAO,GAAG,EAAM,IAAI,EAAc,IAAI;GACtC,WAAW;GACX,uBAAuB;IACrB,KAAK,cAAc,gBAAgB;GACrC;EACF,CAAC;EAQD,AAPA,KAAK,UAAU,GACf,EAAsB,EAAO,OAAO,MAAM;GACxC;GACA;GACA;EACF,CAAC,GACD,EAAO,MAAM,aAAa,eAAe,MAAM,GAC/C,EAAO,MAAM,iBAAiB,eAAe,KAAK,uBAAuB;EACzE,IAAM,IAAS,SAAS,cAAc,KAAK;EAC3C,EAAO,YAAY;EACnB,IAAM,IAAU,SAAS,cAAc,KAAK;EAI5C,AAHA,EAAQ,YAAY,wBACpB,KAAK,iBAAiB,GACtB,EAAO,OAAO,CAAO,GACrB,EAAO,MAAM,OAAO,CAAM;EAC1B,KAAK,IAAM,KAAQ,MAAM,KAAK,KAAK,UAAU,GAGvC,aAAgB,WAEhB,EAAkB,CAAI,KAEtB,EAAgB,CAAI,KACxB,EAAO,cAAc,CAAC,CAAI,GAAG,CAAO;EAEtC,OAAO;CACT;CAEA,qBAAqC;EACnC,IAAI,CAAC,KAAK,gBAAgB,OAAO;EAEjC,IAAM,IAAO,KAAK,YAAY;EAG9B,OAFM,aAAgB,YAAY,aAAgB,aAE3C,KAAK,eACT,KAAK,CAAC,CACN,MAAM,KAAK,CAAC,CACZ,KAAI,MAAM;GACT,IAAM,IAAY,OAAO,MAAQ,OAAe,IAAI,SAAS,IAAI,OAAO,CAAE,IAAI;GAC9E,OAAO,EAAK,cAAc,IAAI,GAAW,CAAC,EAAE,aAAa,KAAK,KAAK;EACrE,CAAC,CAAC,CACD,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,IAV2D;CAWxE;CAEA,SAAkB;EAChB,IAAM,IAAY,GAAG,KAAK,UAAU,WAC9B,IAAU,GAAG,KAAK,UAAU,SAC5B,IAAiB,KAAK,mBAAmB,GACzC,IAAiB,KAAK,SAAS,QAAO,MAAU,CAAC,EAAO,aAAa,eAAe,CAAC,GACrF,IAAe,KAAK,WAAW,KAAK,gBAAgB,IAAI,KAAK,SAAS,KAAK,gBAAgB,KAAA,GAC3F,IAAmB,IAAe,KAAK,iBAAiB,CAAY,IAAI;EAE9E,OAAO,CAAI;;UAEL,IAAiB,CAAI,2CAA2C,EAAQ,GAAG,EAAe,WAAW,EAAQ;;;iCAGtF,KAAK,gBAAgB;;0BAE5B,KAAK,QAAQ;;;0BAGb,EAAU;0BACV,OAAO,KAAK,WAAW,EAAE;0BACzB,KAAK,WAAW,SAAS,EAAQ;uBACpC,EAAU,KAAK,SAAS,EAAE;4BACrB,IAAiB,IAAU,EAAQ;kCAC7B,EAAiB;;;6CAGN,KAAK,qBAAqB;YAE1D,KAAK,kBAYF,IAXA,CAAI;;2BAEO,KAAK,OAAO;gCACP,KAAK,YAAY;yBACxB,KAAK,KAAK;gCACH,KAAK,WAAW;8BAClB,KAAK,YAAY;8BACjB,KAAK,SAAS;8BACd,KAAK,SAAS;+BACb,EAAU,KAAK,aAAa,KAAkB,KAAA,CAAS,EAAE;kCAG7E;;;;eAII,EAAU;;oBAEL,CAAC,KAAK,QAAQ;wBACV,OAAO,CAAC,KAAK,OAAO,EAAE;;YAElC,EAAe,KACf,MACE,CAAI;qBACG,KAAK,iBAAiB,CAAM,EAAE;;gCAEnB,EAAO,UAAU,KAAK,iBAAiB,SAAS,QAAQ;8BAC1D,OAAO,CAAC,KAAK,OAAO,EAAE;gCACpB,OAAO,EAAO,QAAQ,EAAE;;kBAEtC,EAAO,MAAM;qBAErB,EAAE;;;;;;yBAMa,KAAK,wBAAwB;;;;kCAIpB,KAAK,cAAc;;;;;;CAMnD;AASF;AA9vBG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAiB,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GAEtE,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAqB,CAAC,CAAA,GAAA,EAAA,WAAA,oBAAA,KAAA,CAAA,GAE1E,EAAA,CAAA,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,oBAAA,KAAA,CAAA,GAC7B,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAa,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,KAAA,CAAA,GAClD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,WAAW;AAAkB,CAAC,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAIvD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,UAAA,IAAA,GAWxC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,GAaN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAwCN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GACN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GAxFR,IAAA,IAAA,EAAA,CAAA,EAAc,qBAAqB,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import '@/components/input'\n\nimport { html, LitElement, nothing, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport glass from '@/classes/glass.css?inline'\nimport type { WebUiOption } from '@/components/option'\nimport internalScrollbars from '@/scrollbars/internal.css?inline'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport {\n createComboboxOpenController,\n createOptionListenerBinding,\n defineComboboxTrigger,\n defineOptionPortal,\n handleComboboxFocusOut,\n nextWrappingIndex\n} from '@/shared/option-portal'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOpenOverlay } from '@/shared/overlay/open-overlay'\nimport {\n applyOverlayVariables,\n defineOverlayPortal,\n type OverlayContainer,\n type OverlayPortal\n} from '@/shared/overlay/portal'\nimport { defineScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\nconst FILTER_MODES = ['none', 'prefix', 'contains'] as const\ntype FilterMode = (typeof FILTER_MODES)[number]\n\n// 自定义 trigger 与 select 同判据:必须留在宿主,不随 options 迁入 portal panel\nfunction isTriggerSlotNode(node: Node): node is Element {\n return node instanceof Element && node.slot === 'trigger'\n}\n\n// 已移除的 empty slot 仍可能留在既有消费者 light DOM;不得把它作为普通内容迁入 portal。\nfunction isEmptySlotNode(node: Node): node is Element {\n return node instanceof Element && node.slot === 'empty'\n}\n\n/**\n * `web-ui-autocomplete`:可输入并过滤候选的单值选择器。\n *\n * 与 `web-ui-select` 共用 `<web-ui-option>` 子项注册协议与 overlay 能力,但触发区是\n * 可编辑 input:`value` 即当前输入文本(表单值),键入时按 `filter` 模式过滤候选,\n * 选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value。\n * `allow-custom-value` 开启后,Enter 可把不匹配候选的原文作为 custom value 显式提交。\n *\n * trigger 跟随 select 的 wrapper div 模式:`slot[name=\"trigger\"]` 可替换默认 trigger\n * (shadow 内的 `web-ui-input`);多行 trigger(如 `web-ui-textarea`)保留 Enter 换行语义,\n * 关闭 panel 用 Escape 或 blur。\n * tab 位只属于 trigger 自身:默认 trigger 是 shadow 内 input,自定义 trigger 由消费者提供\n * 可聚焦元素(README 契约);包装 div 恒为 tabindex=\"-1\",不占顺序焦点,避免双 tab 位。\n */\n@customElement('web-ui-autocomplete')\nexport class WebUiAutocomplete extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(internalScrollbars), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' })\n noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'allow-custom-value' })\n allowCustomValue = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n private _filter: FilterMode = 'contains'\n\n @property({ type: String, reflect: true })\n get filter(): FilterMode {\n return this._filter\n }\n set filter(v: string) {\n const old = this._filter\n this._filter = normalizeLiteral(v, FILTER_MODES, 'contains')\n this.requestUpdate('filter', old)\n }\n\n // value 不反射 attribute,attribute 只参与首次声明式初始化。\n @state() private _value = ''\n\n get value(): string {\n return this._value\n }\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n // selected-value:文本精确匹配 option label 时派生出的 option value(只读反射)。\n @state() private _selectedValue = ''\n\n get selectedValue(): string {\n return this._selectedValue\n }\n\n private _setSelectedValue(value: string) {\n const old = this._selectedValue\n if (old === value && this.getAttribute('selected-value') === value) return\n\n this._selectedValue = value\n this.setAttribute('selected-value', value)\n if (old !== value) this.requestUpdate('selectedValue', old)\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n // 同步 HTML 属性中预设的 value,补全访问器模式不处理 attribute 反射。\n const attrValue = this.getAttribute('value')\n if (attrValue !== null) this._value = attrValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n @state() private _isOpen = false\n @state() private _activeIndex = -1\n @state() private _focused = false\n @state() private _hasTriggerSlot = false\n\n private static _nextInstanceId = 0\n private readonly _idPrefix = `web-ui-autocomplete-${++WebUiAutocomplete._nextInstanceId}`\n private readonly _a11yOptionIds = new WeakMap<WebUiOption, string>()\n private _nextA11yOptionId = 0\n private _options: WebUiOption[] = []\n private _portal?: OverlayPortal\n private _portalContent?: HTMLElement\n private _keyboardNavigationActive = false\n private _scrollInteractionElement?: HTMLElement\n private readonly _scrollLock = defineScrollLockLease().make()\n\n // option 注册表 / portal 同步 / 微任务调度收敛到 shared 模块(select 同款)\n private readonly _optionPortal = defineOptionPortal().make({\n element: this,\n idPrefix: `${this._idPrefix}-option`,\n getPortal: () => this._portal,\n getPortalContent: () => this._portalContent,\n isOpen: () => this.portal && this._isOpen,\n // 默认 slot 内容随 panel 迁移;trigger 与已移除的 empty slot 留在宿主,不进 panel。\n getMigratableNodes: () =>\n Array.from(this.childNodes).filter(node => !isTriggerSlotNode(node) && !isEmptySlotNode(node)),\n hasUpdated: () => this.hasUpdated,\n requestUpdate: () => this.requestUpdate(),\n bindOption: option => this._bindOption(option),\n unbindOption: option => this._unbindOption(option)\n })\n /*\n * trigger 委托层:默认 trigger(shadow 内 web-ui-input)与 slot[name=\"trigger\"] 自定义\n * trigger 对组件暴露同一形状,监听统一挂在 trigger 包装 div 上,两条路径不特判。\n */\n private readonly _trigger = defineComboboxTrigger().make({\n getWrapper: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-trigger') ?? null,\n getCustomTrigger: () => {\n const assigned = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')?.assignedElements()[0]\n return assigned instanceof HTMLElement ? assigned : null\n },\n getFallbackTrigger: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-input') ?? null,\n onInput: value => this._onTriggerInput(value),\n onClick: () => this._onTriggerClick(),\n onFocusIn: event => this._onTriggerFocusIn(event),\n onFocusOut: event => this._onTriggerFocusOut(event)\n })\n /*\n * 开启态 overlay 承载「我开着吗」(issue #120 Block 1):宿主级 keydown 在 portal 模式下\n * 收不到 panel 内的 Escape,改由唯一仲裁者在 document 捕获阶段判定最内层。\n * 宿主接口除 requestClose 外只再提供一个 isConnected(仅供惰性回收读取):开启状态是\n * 声明而非询问。\n */\n private readonly _overlay = defineOpenOverlay().make({\n requestClose: () => this._close(),\n isConnected: () => this.isConnected\n })\n private readonly _panel = defineAnchoredPanel().make({\n // 锚点取当前生效的 trigger host:默认 trigger 或自定义 trigger slot 内容\n getAnchor: () =>\n this._trigger.getTrigger() ?? this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-overlay') ?? null,\n getPositioning: () => ({\n placement: 'bottom-start',\n offset: 4,\n minAnchorWidth: true,\n strategy: this.portal ? 'fixed' : 'absolute'\n }),\n isPortal: () => this.portal,\n createPortal: () => this._createPortal(),\n openOverlay: this._overlay\n })\n\n get isOpen(): boolean {\n return this._isOpen\n }\n\n get open(): boolean {\n return this._isOpen\n }\n\n /*\n * 公共焦点委托:聚焦/失焦当前生效的 trigger(默认 web-ui-input 或自定义 trigger)。\n * 组件自带 focus 重定向时落到内部原生控件;自定义 trigger 没有该能力时,\n * 原生 focus() 聚焦 host 自身。无 trigger(尚未首渲或已断开)时静默返回。\n */\n override focus(options?: FocusOptions): void {\n this._trigger.focusTrigger(options)\n }\n\n override blur(): void {\n this._trigger.blurTrigger()\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen) return\n\n // 在监听器内部判定:composedPath() 在派发结束后会被清空。\n const isInside = e.composedPath().includes(this) || !!this._panel.getHandle()?.containsEvent(e)\n if (!isInside) this._close()\n }\n\n private _onFocusOut = () => {\n handleComboboxFocusOut(\n this,\n () => this._panel.getHandle(),\n () => this._isOpen,\n () => this._close()\n )\n }\n\n private _handlePanelPointerDown = (e: PointerEvent) => {\n // 非 option 区域不可聚焦;阻止 pointerdown 的默认聚焦行为,保持 combobox 焦点,\n // 使点击 empty state、滚动区和 panel padding 不会被 focusout 误判为外部交互。\n e.preventDefault()\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._optionPortal.bindHost()\n // 宿主可能被上层 overlay portal 迁移(断开重连):shadow 内的包装 div 仍在,重新绑定委托监听\n this._trigger.bind()\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('focusout', this._onFocusOut)\n document.addEventListener('click', this._onClickOutside)\n }\n\n private _onTriggerSlotChange = () => {\n this._syncTriggerSlot()\n }\n\n /*\n * 自定义 trigger 判定必须同步:slotchange 在首次渲染之后才派发,只依赖它会让默认\n * web-ui-input 先渲染一帧再被替换,自定义 trigger 出现时会闪一下默认 input。\n * 判据与 portal 迁移排除(isTriggerSlotNode)同源:宿主直接子节点带 slot=\"trigger\"。\n */\n private _syncTriggerSlot() {\n const hasTriggerSlot = Array.from(this.children).some(isTriggerSlotNode)\n if (this._hasTriggerSlot === hasTriggerSlot) return\n this._hasTriggerSlot = hasTriggerSlot\n // trigger 在默认与自定义之间切换:anchor 与 portal 会话按新 trigger 重建。\n // 首次渲染前尚无 portal 会话,无需重建。\n if (this.hasUpdated) this._reconfigureOverlay()\n }\n\n override attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n super.attributeChangedCallback(name, oldValue, newValue)\n if (name === 'selected-value' && this.isConnected && newValue !== this._selectedValue) {\n queueMicrotask(() => {\n if (this.isConnected) this._syncSelectedValue()\n })\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._optionPortal.dispose()\n this._trigger.dispose()\n this.removeEventListener('keydown', this._onKeydown)\n this.removeEventListener('focusout', this._onFocusOut)\n document.removeEventListener('click', this._onClickOutside)\n this._options.forEach(this._unbindOption)\n this._close()\n this._syncScrollInteractionListeners()\n this._portal = undefined\n this._portalContent = undefined\n // 撤销登记由 _panel.dispose() 完成(handle 归它持有),不再需要单独 dispose 仲裁者。\n this._panel.dispose()\n this._scrollLock.release()\n }\n\n override firstUpdated() {\n this._trigger.bind()\n requestAnimationFrame(() => {\n if (this.isConnected) this._optionPortal.scheduleRefresh()\n })\n }\n\n override willUpdate() {\n this._syncTriggerSlot()\n this._refreshOptions()\n this._optionPortal.ensureOptionIds(this._options)\n this._syncSelectedValue()\n this._applyFilter()\n this._syncOptionA11y()\n this._syncActiveOption()\n }\n\n override updated(changed: PropertyValues) {\n // 文本回写经委托层落到当前 trigger(默认 web-ui-input 或自定义 trigger)\n this._trigger.setValue(this._value)\n if (changed.has('portal') || changed.has('overlayContainer'))\n requestAnimationFrame(() => this._reconfigureOverlay())\n if (changed.has('noScrollLock')) this._syncScrollLock()\n this.toggleAttribute('focused', this._focused)\n this._syncOpenAttribute()\n this._syncOverlayInert()\n this._syncValidity()\n this._syncOpenWithMatches()\n }\n\n override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n if (disabled && this._isOpen) this._close()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n // readonly 与 disabled 一致:值不可由用户修改,视为通过校验(原生 barred-from-validation 语义)\n if (this._isDisabled || this.readonly || !this.required || this._value) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, 'Enter a value')\n }\n\n private _syncOpenAttribute() {\n this.toggleAttribute('open', this._isOpen)\n }\n\n /*\n * 禁用/只读态不响应 Escape。仲裁者仍在(吞掉按键并压掉原生 cancel),只是不走关闭\n * 入口 —— 与旧的「跳过候选」语义不同:旧语义放任事件落到下层 overlay,把外层一起关掉。\n * 每次渲染后同步即可覆盖 disabled / readonly 属性与表单禁用三条来源。\n */\n private _syncOverlayInert() {\n this._panel.getHandle()?.setInert(this._isDisabled || this.readonly)\n }\n\n private _syncSelectedValue() {\n const query = this._value.trim().toLowerCase()\n const next = query\n ? (this._options.find(o => !o.disabled && o.label.trim().toLowerCase() === query)?.value ?? '')\n : ''\n this._setSelectedValue(next)\n }\n\n private _syncOptionA11y() {\n this._options.forEach(o => {\n o.setAttribute('role', 'option')\n o.setAttribute('aria-selected', o.value === this._selectedValue ? 'true' : 'false')\n o.setAttribute('aria-hidden', 'true')\n })\n }\n\n private _getA11yOptionId(option: WebUiOption): string {\n let id = this._a11yOptionIds.get(option)\n if (!id) {\n id = `${this._idPrefix}-a11y-option-${++this._nextA11yOptionId}`\n this._a11yOptionIds.set(option, id)\n }\n return id\n }\n\n // 按当前文本与 filter 模式过滤候选,非匹配项以 data-filtered 隐藏并跳过导航\n private _applyFilter() {\n const query = this._value.trim().toLowerCase()\n const mode = this._filter\n this._options.forEach(o => {\n const label = o.label.trim().toLowerCase()\n const match = mode === 'none' || !query || (mode === 'prefix' ? label.startsWith(query) : label.includes(query))\n o.toggleAttribute('data-filtered', !match)\n })\n // 活动项被过滤或禁用时清除键盘激活,避免激活不可见项\n const active = this._options[this._activeIndex]\n if (this._activeIndex >= 0 && (!active || active.hasAttribute('data-filtered') || active.disabled)) {\n this._activeIndex = -1\n this._syncActiveOption()\n }\n }\n\n private _hasMatchingOptions() {\n return this._options.some(option => !option.hasAttribute('data-filtered'))\n }\n\n private _syncOpenWithMatches() {\n if (this._isOpen && !this._hasMatchingOptions()) this._close()\n }\n\n private readonly _optionListeners = createOptionListenerBinding({\n // 惰性解引用:handler 字段声明在后者仍可在调用期取到\n onClick: event => this._handleOptionClick(event),\n onPointerOver: event => this._handleOptionPointerOver(event),\n onPointerDown: event => this._handleOptionPointerDown(event),\n onUpdate: () => this._onOptionUpdate()\n })\n private _bindOption = (option: WebUiOption) => this._optionListeners.bind(option)\n private _unbindOption = (option: WebUiOption) => this._optionListeners.unbind(option)\n\n private _refreshOptions() {\n const activeOption = this._options[this._activeIndex]\n // diff 绑定/解绑与激活索引按 option 身份保持在 shared 内完成\n const next = this._optionPortal.refresh(this._options, activeOption)\n this._options = next.options\n this._activeIndex = next.activeIndex\n }\n\n private _handleOptionClick = (e: Event) => {\n if (!(e.currentTarget instanceof HTMLElement)) return\n const option = e.currentTarget as WebUiOption\n if (option.disabled) return\n this._selectOption(option)\n }\n\n private _onOptionUpdate = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _handleOptionPointerOver = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (!this._isOpen || !(e.currentTarget instanceof HTMLElement)) return\n if (this._keyboardNavigationActive) return\n\n // 指针接管后只保留 :hover,避免键盘激活项与悬停项同时高亮。\n this._activeIndex = -1\n this._syncActiveOption()\n }\n\n private _syncScrollInteractionListeners() {\n const next = this._isOpen ? this._panel.getPanel()?.querySelector<HTMLElement>('.autocomplete-scroll') : undefined\n if (next === this._scrollInteractionElement) return\n\n this._scrollInteractionElement?.removeEventListener('pointermove', this._handleListPointerMove)\n this._scrollInteractionElement?.removeEventListener('wheel', this._handleListWheel)\n this._scrollInteractionElement = next ?? undefined\n this._scrollInteractionElement?.addEventListener('pointermove', this._handleListPointerMove)\n this._scrollInteractionElement?.addEventListener('wheel', this._handleListWheel)\n }\n\n private _clearKeyboardNavigation() {\n if (!this._keyboardNavigationActive) return\n\n this._keyboardNavigationActive = false\n this._activeIndex = -1\n this._syncActiveOption()\n }\n\n private _handleListPointerMove = () => {\n if (!this._isOpen) return\n this._clearKeyboardNavigation()\n }\n\n private _handleListWheel = () => {\n if (!this._isOpen) return\n // 滚轮是新的用户意图:清除旧键盘激活,避免滚动后 Enter 提交屏幕外选项。\n this._clearKeyboardNavigation()\n }\n\n private _handleOptionPointerDown = (e: PointerEvent) => {\n // 保持 input 焦点,避免 focusout 在 click 前关闭 overlay。\n e.preventDefault()\n }\n\n // slotchange 不冒泡,只能由模板内 slot 自行监听;稳定引用避免 Lit 重挂载\n private _onSlotChange = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (this._isDisabled || this.readonly) return\n this._applyFilter()\n this._syncOpenWithMatches()\n\n // Escape 不在本组件处理:由共享仲裁者在 document 捕获阶段归属(issue #120 Block 1)。\n switch (e.key) {\n /*\n * 多行 trigger(textarea)的方向键归光标移动:panel 打开时不接管、不\n * preventDefault,与 Enter 的 multiline 例外同判据。panel 关闭时方向键\n * 仍是打开入口(键盘可达性不依赖指针)。\n */\n case 'ArrowDown':\n case 'ArrowUp': {\n if (this._isOpen && this._trigger.isMultilineEdit(e)) break\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(e.key === 'ArrowDown' ? 1 : -1)\n break\n }\n case 'Enter': {\n /*\n * panel 打开时接管 Enter:选择候选或提交 custom value。\n * 零匹配时 panel 会被过滤状态收敛关闭,但 allow-custom-value 仍需在关闭态提交。\n * 多行 trigger(textarea)保留换行语义,不接管为选中高亮项。\n */\n const canSubmitCustomValue = this._canSubmitCustomValue()\n if (\n !this._trigger.isMultilineEdit(e) &&\n (this._isOpen || (!this._hasMatchingOptions() && canSubmitCustomValue))\n ) {\n e.preventDefault()\n if (this._isOpen) {\n const option = this._options[this._activeIndex]\n if (option && !option.disabled && !option.hasAttribute('data-filtered')) {\n this._selectOption(option)\n return\n }\n\n const exactOption = this._findExactOption(this._value)\n if (exactOption) {\n this._selectOption(exactOption)\n return\n }\n }\n\n if (canSubmitCustomValue) this._selectCustomValue()\n }\n break\n }\n }\n }\n\n private _navigateActive(delta: number) {\n const enabled = this._options.filter(o => !o.disabled && !o.hasAttribute('data-filtered'))\n if (!enabled.length) return\n\n this._keyboardNavigationActive = true\n const currentIdx = this._activeIndex >= 0 ? enabled.indexOf(this._options[this._activeIndex]) : delta > 0 ? -1 : 0\n this._activeIndex = this._options.indexOf(enabled[nextWrappingIndex(enabled.length, currentIdx, delta)])\n this._syncActiveOption()\n }\n\n private _setInitialActiveOption() {\n const firstEnabled = this._options.findIndex(o => !o.disabled && !o.hasAttribute('data-filtered'))\n this._keyboardNavigationActive = true\n this._activeIndex = firstEnabled\n this._syncActiveOption()\n }\n\n private _syncActiveOption() {\n this._options.forEach((option, index) => option.toggleAttribute('active', index === this._activeIndex))\n\n if (this._isOpen) this._scrollActiveOptionIntoView()\n }\n\n private _scrollActiveOptionIntoView() {\n const activeOption = this._options[this._activeIndex]\n const scroll = this._panel.getPanel()?.querySelector<HTMLElement>('.autocomplete-scroll')\n if (!activeOption || !scroll?.clientHeight) return\n\n const optionRect = activeOption.getBoundingClientRect()\n const scrollRect = scroll.getBoundingClientRect()\n // Overlay 入场时会 scale;把视口中的溢出量换算回 scrollTop 使用的未缩放坐标。\n const scaleY = scroll.offsetHeight ? scrollRect.height / scroll.offsetHeight : 1\n if (!scaleY) return\n\n const visibleTop = scrollRect.top + scroll.clientTop * scaleY\n const visibleBottom = visibleTop + scroll.clientHeight * scaleY\n if (optionRect.top < visibleTop) scroll.scrollTop -= (visibleTop - optionRect.top) / scaleY\n else if (optionRect.bottom > visibleBottom) scroll.scrollTop += (optionRect.bottom - visibleBottom) / scaleY\n }\n\n private _selectOption(option: WebUiOption) {\n if (this.readonly) return\n // value 即输入文本:选择后回填为 option label,selected-value 取 option value\n this.value = option.label\n this._setSelectedValue(option.value)\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _findExactOption(value: string): WebUiOption | undefined {\n const query = value.trim().toLowerCase()\n if (!query) return undefined\n\n return this._options.find(option => !option.disabled && option.label.trim().toLowerCase() === query)\n }\n\n private _hasExactOption(value: string): boolean {\n const query = value.trim().toLowerCase()\n return this._options.some(option => option.label.trim().toLowerCase() === query)\n }\n\n private _canSubmitCustomValue() {\n return this.allowCustomValue && !!this._value && !this._hasExactOption(this._value)\n }\n\n private _selectCustomValue() {\n // Custom value 的 identity 由消费端管理;组件不隐式创建 option,selected-value 保持派生空值。\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _onTriggerInput = (value: string) => {\n if (this._isDisabled || this.readonly) return\n if (value === this._value) return\n this.value = value\n this._keyboardNavigationActive = false\n this._activeIndex = -1\n this._syncActiveOption()\n this._open()\n }\n\n private _onTriggerClick = () => {\n if (this._isDisabled || this.readonly) return\n this._open()\n }\n\n /*\n * focus/blur 不冒泡,委托层监听等价且冒泡的 focusin/focusout。\n * 自定义 trigger 位于 light DOM,其焦点变化不会跨 shadow 边界到达宿主,这里补发\n * 公共 focus/blur 兑现 README 事件契约;默认 trigger 在 shadow 内,原生事件已能\n * 到达宿主,重复派发会让消费端收到两次。\n */\n private _onTriggerFocusIn = (event: FocusEvent) => {\n if (this._isDisabled) return\n this._focused = true\n // composed 与原生 focus 一致(宿主内 retarget):跨 shadow 边界的消费者能收到,\n // 但不 bubbles —— focus/blur 的公共契约本来就不冒泡。\n // relatedTarget 透传:消费端靠它判断焦点来回,补发事件不该丢这个信息\n if (this._isSlottedFocus(event))\n this.dispatchEvent(new FocusEvent('focus', { composed: true, relatedTarget: event.relatedTarget }))\n }\n\n private _onTriggerFocusOut = (event: FocusEvent) => {\n this._focused = false\n if (this._isSlottedFocus(event))\n this.dispatchEvent(new FocusEvent('blur', { composed: true, relatedTarget: event.relatedTarget }))\n }\n\n private _isSlottedFocus(event: FocusEvent): boolean {\n const target = event.target\n return target instanceof Node && !!this.shadowRoot && !this.shadowRoot.contains(target)\n }\n\n // 开合生命周期不变量收敛在 shared combobox-shell;autocomplete 注入\n // readonly guard 与 close 前的 portal 内容收敛钩子\n private readonly _openController = createComboboxOpenController({\n canOpen: () => !this._isDisabled && !this.readonly,\n getIsOpen: () => this._isOpen,\n setIsOpen: open => {\n this._isOpen = open\n },\n dispatchOpenChange: () => this._dispatchOpenChange(),\n syncScrollLock: open => this._syncScrollLock(open),\n isPortal: () => this.portal,\n openOverlay: isKeyboardNavigation => this._openOverlay(isKeyboardNavigation),\n closeOverlay: () => void this._closeOverlay(),\n onOpen: isKeyboardNavigation => {\n this._keyboardNavigationActive = isKeyboardNavigation\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n },\n onBeforeClose: () => {\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._optionPortal.syncPortalContent()\n },\n onAfterClose: () => {\n this._keyboardNavigationActive = false\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n this._syncScrollInteractionListeners()\n }\n })\n\n private _open(isKeyboardNavigation = false) {\n this._applyFilter()\n if (!this._hasMatchingOptions()) {\n if (this._isOpen) this._close()\n return\n }\n this._openController.open(isKeyboardNavigation)\n }\n\n private _close() {\n this._openController.close()\n }\n\n private _dispatchOpenChange() {\n dispatchOpenChangeEvent(this, this._isOpen)\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n this._syncScrollInteractionListeners()\n // keyboard-open 会先建立 active option;overlay 打开后再同步一次,确保首次激活也能滚入列表区。\n this._syncActiveOption()\n // 新会话的 handle 刚建立,惰性状态需按当前 disabled/readonly 重新同步。\n this._syncOverlayInert()\n }\n\n private async _closeOverlay() {\n const closed = await this._panel.close(() => this._isOpen)\n if (closed) {\n this._syncScrollInteractionListeners()\n this._portal = undefined\n this._portalContent = undefined\n }\n }\n\n private _reconfigureOverlay() {\n this._portal = undefined\n this._portalContent = undefined\n this._panel.reconfigure(this._isOpen)\n this._syncScrollInteractionListeners()\n /*\n * reconfigure 重新 claim = 新会话,inert 回到 false。实测这条重推是**冗余**的(摘掉本行\n * 全部用例仍绿):这条路径后面跟着一轮渲染,而 `updated()` 每次渲染都会调\n * `_syncOverlayInert()`。留在这里是不想依赖「这条路径必然跟着一次渲染」这个隐含前提。\n */\n this._syncOverlayInert()\n }\n\n private _syncScrollLock(isOpen = this._isOpen) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _createPortal(): OverlayPortal {\n const portal = defineOverlayPortal().make({\n container: this.overlayContainer,\n target: this,\n style: `${glass}\\n${overlayMotion}\\n${internalScrollbars}\\n${style}`,\n className: 'wui-glass autocomplete-overlay portal wui-floating-panel',\n onContentChange: () => {\n this._optionPortal.scheduleRefresh()\n }\n })\n this._portal = portal\n applyOverlayVariables(portal.panel, this, [\n '--wui-overlay-min-width',\n '--wui-autocomplete-max-width',\n '--wui-autocomplete-max-height'\n ])\n portal.panel.setAttribute('aria-hidden', 'true')\n portal.panel.addEventListener('pointerdown', this._handlePanelPointerDown)\n const scroll = document.createElement('div')\n scroll.className = 'autocomplete-scroll wui-scroll'\n const content = document.createElement('div')\n content.className = 'autocomplete-content'\n this._portalContent = content\n scroll.append(content)\n portal.panel.append(scroll)\n for (const node of Array.from(this.childNodes)) {\n // 框架注释锚点(v-if/v-for 占位)必须留在宿主:锚点进 panel 后 Vue 下次翻转\n // 会以 panel 内节点为插入基准;portal 的 marker 注释同理不参与迁移。\n if (node instanceof Comment) continue\n // 自定义 trigger 与 select(:461)同判据:留在宿主,不随 options 迁入 overlay\n if (isTriggerSlotNode(node)) continue\n // 已移除的 empty slot 不能作为普通内容出现在新 portal panel 中\n if (isEmptySlotNode(node)) continue\n portal.appendContent([node], content)\n }\n return portal\n }\n\n private _getLabelledbyText(): string {\n if (!this.ariaLabelledby) return ''\n\n const root = this.getRootNode()\n if (!(root instanceof Document || root instanceof ShadowRoot)) return ''\n\n return this.ariaLabelledby\n .trim()\n .split(/\\s+/)\n .map(id => {\n const escapedId = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(id) : id\n return root.querySelector(`#${escapedId}`)?.textContent?.trim() ?? ''\n })\n .filter(Boolean)\n .join(' ')\n }\n\n override render() {\n const listboxId = `${this._idPrefix}-listbox`\n const labelId = `${this._idPrefix}-label`\n const labelledbyText = this._getLabelledbyText()\n const visibleOptions = this._options.filter(option => !option.hasAttribute('data-filtered'))\n const activeOption = this._isOpen && this._activeIndex >= 0 ? this._options[this._activeIndex] : undefined\n const activeDescendant = activeOption ? this._getA11yOptionId(activeOption) : nothing\n\n return html`\n <div class=\"wui-autocomplete-inner\">\n ${labelledbyText ? html`<span class=\"autocomplete-a11y-only\" id=${labelId}>${labelledbyText}</span>` : nothing}\n <div\n class=\"autocomplete-trigger\"\n ?data-custom-trigger=${this._hasTriggerSlot}\n role=\"combobox\"\n aria-expanded=${this._isOpen}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls=${listboxId}\n aria-disabled=${String(this._isDisabled)}\n aria-readonly=${this.readonly ? 'true' : nothing}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${labelledbyText ? labelId : nothing}\n aria-activedescendant=${activeDescendant}\n tabindex=\"-1\"\n >\n <slot name=\"trigger\" @slotchange=${this._onTriggerSlotChange}></slot>\n ${\n !this._hasTriggerSlot\n ? html`<web-ui-input\n class=\"autocomplete-input\"\n .value=${this._value}\n placeholder=${this.placeholder}\n name=${this.name}\n ?borderless=${this.borderless}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n aria-label=${ifDefined(this.ariaLabel || labelledbyText || undefined)}\n ></web-ui-input>`\n : nothing\n }\n </div>\n <div\n class=\"autocomplete-a11y-listbox\"\n id=${listboxId}\n role=\"listbox\"\n ?hidden=${!this._isOpen}\n aria-hidden=${String(!this._isOpen)}\n >\n ${visibleOptions.map(\n option =>\n html`<div\n id=${this._getA11yOptionId(option)}\n role=\"option\"\n aria-selected=${option.value === this._selectedValue ? 'true' : 'false'}\n aria-hidden=${String(!this._isOpen)}\n aria-disabled=${String(option.disabled)}\n >\n ${option.label}\n </div>`\n )}\n </div>\n <div\n class=\"autocomplete-overlay wui-floating-panel wui-glass\"\n hidden\n aria-hidden=\"true\"\n @pointerdown=${this._handlePanelPointerDown}\n >\n <div class=\"autocomplete-scroll wui-scroll\">\n <div class=\"autocomplete-content\">\n <slot @slotchange=${this._onSlotChange}></slot>\n </div>\n </div>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n focus: FocusEvent\n blur: FocusEvent\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-autocomplete': WebUiAutocomplete\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/autocomplete/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{--wui-autocomplete-max-width:500px;display:inline-block}:host([disabled]){cursor:not-allowed;opacity:.4}.wui-autocomplete-inner{position:relative}.autocomplete-trigger{box-sizing:border-box;width:var(--wui-input-width,200px);min-width:var(--wui-control-size,36px);background:0 0;border:none;align-items:center;display:flex}.autocomplete-trigger[data-custom-trigger]{width:auto}.autocomplete-trigger web-ui-input{flex:1;min-width:0}::slotted([slot=trigger]){min-width:0}.autocomplete-trigger:focus-visible{outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#08f) 40%, transparent));outline-offset:2px}:host([disabled]) .autocomplete-trigger web-ui-input{opacity:1}.autocomplete-overlay{--wui-option-check-display:none;--wui-internal-glass-shadow:var(--wui-shadow-panel,0 3px 9px #00000045);--wui-glass-corner-radius:var(--wui-radius-menu,18px);--wui-color-glass-ring:transparent;--wui-internal-duration-float-enter:var(--wui-duration-float-enter,.24s);--wui-internal-duration-float-exit:var(--wui-duration-float-exit,.16s);z-index:var(--wui-layer-inline-overlay,1);box-sizing:border-box;min-width:var(--wui-overlay-min-width,200px);max-width:var(--wui-autocomplete-max-width,500px);border-radius:var(--wui-radius-menu,18px);background-color:var(--wui-color-surface-menu,#fafafac2);position:absolute;overflow:hidden}.autocomplete-overlay.portal{z-index:var(--wui-layer-menu,100);position:fixed}.autocomplete-overlay.hidden{display:none}.autocomplete-scroll{max-height:var(--wui-autocomplete-max-height,200px);overflow-y:auto}.autocomplete-content{padding:var(--wui-space-1,4px)}::slotted(web-ui-option[data-filtered]),.autocomplete-content web-ui-option[data-filtered],:host([portal]) .autocomplete-overlay{display:none}.autocomplete-a11y-only,.autocomplete-a11y-listbox{white-space:nowrap;clip-path:inset(50%);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{--wui-autocomplete-max-width:500px;display:inline-block}:host([disabled]){cursor:not-allowed;opacity:.4}.wui-autocomplete-inner{position:relative}.autocomplete-trigger{box-sizing:border-box;width:var(--wui-input-width,200px);min-width:var(--wui-control-size,36px);background:0 0;border:none;align-items:center;display:flex}.autocomplete-trigger[data-custom-trigger]{width:auto}.autocomplete-trigger web-ui-input{flex:1;min-width:0}::slotted([slot=trigger]){min-width:0}.autocomplete-trigger:focus-visible{outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#0071e3) 40%, transparent));outline-offset:2px}:host([disabled]) .autocomplete-trigger web-ui-input{opacity:1}.autocomplete-overlay{--wui-option-check-display:none;--wui-internal-glass-shadow:var(--wui-shadow-panel,0 3px 9px #00000045);--wui-glass-corner-radius:var(--wui-radius-menu,18px);--wui-color-glass-ring:transparent;--wui-internal-duration-float-enter:var(--wui-duration-float-enter,.24s);--wui-internal-duration-float-exit:var(--wui-duration-float-exit,.16s);z-index:var(--wui-layer-inline-overlay,1);box-sizing:border-box;min-width:var(--wui-overlay-min-width,200px);max-width:var(--wui-autocomplete-max-width,500px);border-radius:var(--wui-radius-menu,18px);background-color:var(--wui-color-surface-menu,#fafafac2);position:absolute;overflow:hidden}.autocomplete-overlay.portal{z-index:var(--wui-layer-menu,100);position:fixed}.autocomplete-overlay.hidden{display:none}.autocomplete-scroll{max-height:var(--wui-autocomplete-max-height,200px);overflow-y:auto}.autocomplete-content{padding:var(--wui-space-1,4px)}::slotted(web-ui-option[data-filtered]),.autocomplete-content web-ui-option[data-filtered],:host([portal]) .autocomplete-overlay{display:none}.autocomplete-a11y-only,.autocomplete-a11y-listbox{white-space:nowrap;clip-path:inset(50%);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/autocomplete/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-autocomplete-max-width: 500px;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-autocomplete-inner {\n /* 与 select 的 .wui-select-inner 对齐:为本地绝对定位 panel 提供包含块,\n 避免 panel offsetParent(BODY)与实际包含块(远端定位祖先,如 layout header)不一致导致定位偏移。 */\n position: relative;\n}\n\n/*\n * trigger 包装 div:持 combobox ARIA、slot[name=\"trigger\"] 与事件委托监听。\n * 玻璃胶囊由默认 trigger web-ui-input 自带(与重构前的 .input-wrapper 同一套 token\n * 与度量:--wui-input-width / --wui-control-size / --wui-radius-control),这里只定义\n * 容器宽度与自定义 trigger 时的自适应。\n */\n.autocomplete-trigger {\n display: flex;\n align-items: center;\n\n box-sizing: border-box;\n width: var(--wui-input-width, 200px);\n min-width: var(--wui-control-size, 36px);\n border: none;\n\n background: transparent;\n}\n\n.autocomplete-trigger[data-custom-trigger] {\n width: auto;\n}\n\n/* 默认 trigger 填满容器:高度、内边距、玻璃底与 focus ring 由它自带 */\n.autocomplete-trigger web-ui-input {\n flex: 1;\n min-width: 0;\n}\n\n::slotted([slot='trigger']) {\n min-width: 0;\n}\n\n/* 自定义 trigger 场景下包装 div 可能成为 tab 位,补 focus ring(默认 trigger 自带) */\n.autocomplete-trigger:focus-visible {\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #08f) 40%, transparent));\n outline-offset: 2px;\n}\n\n/* 禁用态:宿主已整体降透明度,默认 trigger 自身的 disabled 降透明度在此抵消,\n 保持与重构前(宿主 × 内部 input 两层)一致的观感 */\n:host([disabled]) .autocomplete-trigger web-ui-input {\n opacity: 1;\n}\n\n.autocomplete-overlay {\n /* autocomplete 不表示选中状态;隐藏共享 option 的勾选 icon 及其布局占位 */\n --wui-option-check-display: none;\n --wui-internal-glass-shadow: var(--wui-shadow-panel, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n\n /* 环底色转 transparent,宽 panel 的长边中段不留铺底,见 menu-portal.css 同处注释。 */\n --wui-color-glass-ring: transparent;\n --wui-internal-duration-float-enter: var(--wui-duration-float-enter, 240ms);\n --wui-internal-duration-float-exit: var(--wui-duration-float-exit, 160ms);\n position: absolute;\n z-index: var(--wui-layer-inline-overlay, 1);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 200px);\n max-width: var(--wui-autocomplete-max-width, 500px);\n border-radius: var(--wui-radius-menu, 18px);\n\n /* 玻璃背景:wui-glass 在 panel 自身,这里覆盖其默认玻璃底为 menu surface 色 */\n background-color: var(--wui-color-surface-menu, rgb(250 250 250 / 0.76));\n\n &.portal {\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n }\n\n &.hidden {\n display: none;\n }\n}\n\n.autocomplete-scroll {\n overflow-y: auto;\n max-height: var(--wui-autocomplete-max-height, 200px);\n}\n\n.autocomplete-content {\n padding: var(--wui-space-1, 4px);\n}\n\n/* 非匹配候选隐藏:本地模式经 slot 投影,portal 模式为 panel 直接子元素 */\n::slotted(web-ui-option[data-filtered]) {\n display: none;\n}\n\n.autocomplete-content web-ui-option[data-filtered] {\n display: none;\n}\n\n:host([portal]) .autocomplete-overlay {\n display: none;\n}\n\n/* Shadow DOM idref 不能跨越 Portal 或 light DOM;保留同根可访问的语义镜像。 */\n.autocomplete-a11y-only,\n.autocomplete-a11y-listbox {\n position: absolute;\n\n overflow: hidden;\n\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n\n white-space: nowrap;\n\n clip-path: inset(50%);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/autocomplete/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-autocomplete-max-width: 500px;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-autocomplete-inner {\n /* 与 select 的 .wui-select-inner 对齐:为本地绝对定位 panel 提供包含块,\n 避免 panel offsetParent(BODY)与实际包含块(远端定位祖先,如 layout header)不一致导致定位偏移。 */\n position: relative;\n}\n\n/*\n * trigger 包装 div:持 combobox ARIA、slot[name=\"trigger\"] 与事件委托监听。\n * 玻璃胶囊由默认 trigger web-ui-input 自带(与重构前的 .input-wrapper 同一套 token\n * 与度量:--wui-input-width / --wui-control-size / --wui-radius-control),这里只定义\n * 容器宽度与自定义 trigger 时的自适应。\n */\n.autocomplete-trigger {\n display: flex;\n align-items: center;\n\n box-sizing: border-box;\n width: var(--wui-input-width, 200px);\n min-width: var(--wui-control-size, 36px);\n border: none;\n\n background: transparent;\n}\n\n.autocomplete-trigger[data-custom-trigger] {\n width: auto;\n}\n\n/* 默认 trigger 填满容器:高度、内边距、玻璃底与 focus ring 由它自带 */\n.autocomplete-trigger web-ui-input {\n flex: 1;\n min-width: 0;\n}\n\n::slotted([slot='trigger']) {\n min-width: 0;\n}\n\n/* 自定义 trigger 场景下包装 div 可能成为 tab 位,补 focus ring(默认 trigger 自带) */\n.autocomplete-trigger:focus-visible {\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #0071e3) 40%, transparent));\n outline-offset: 2px;\n}\n\n/* 禁用态:宿主已整体降透明度,默认 trigger 自身的 disabled 降透明度在此抵消,\n 保持与重构前(宿主 × 内部 input 两层)一致的观感 */\n:host([disabled]) .autocomplete-trigger web-ui-input {\n opacity: 1;\n}\n\n.autocomplete-overlay {\n /* autocomplete 不表示选中状态;隐藏共享 option 的勾选 icon 及其布局占位 */\n --wui-option-check-display: none;\n --wui-internal-glass-shadow: var(--wui-shadow-panel, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-glass-corner-radius: var(--wui-radius-menu, 18px);\n\n /* 环底色转 transparent,宽 panel 的长边中段不留铺底,见 menu-portal.css 同处注释。 */\n --wui-color-glass-ring: transparent;\n --wui-internal-duration-float-enter: var(--wui-duration-float-enter, 240ms);\n --wui-internal-duration-float-exit: var(--wui-duration-float-exit, 160ms);\n position: absolute;\n z-index: var(--wui-layer-inline-overlay, 1);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 200px);\n max-width: var(--wui-autocomplete-max-width, 500px);\n border-radius: var(--wui-radius-menu, 18px);\n\n /* 玻璃背景:wui-glass 在 panel 自身,这里覆盖其默认玻璃底为 menu surface 色 */\n background-color: var(--wui-color-surface-menu, rgb(250 250 250 / 0.76));\n\n &.portal {\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n }\n\n &.hidden {\n display: none;\n }\n}\n\n.autocomplete-scroll {\n overflow-y: auto;\n max-height: var(--wui-autocomplete-max-height, 200px);\n}\n\n.autocomplete-content {\n padding: var(--wui-space-1, 4px);\n}\n\n/* 非匹配候选隐藏:本地模式经 slot 投影,portal 模式为 panel 直接子元素 */\n::slotted(web-ui-option[data-filtered]) {\n display: none;\n}\n\n.autocomplete-content web-ui-option[data-filtered] {\n display: none;\n}\n\n:host([portal]) .autocomplete-overlay {\n display: none;\n}\n\n/* Shadow DOM idref 不能跨越 Portal 或 light DOM;保留同根可访问的语义镜像。 */\n.autocomplete-a11y-only,\n.autocomplete-a11y-listbox {\n position: absolute;\n\n overflow: hidden;\n\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n\n white-space: nowrap;\n\n clip-path: inset(50%);\n}\n"],"mappings":""}
@@ -1,6 +1,6 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
2
2
  import "../icon/index.js";
3
- import t from "../../assets/glass.js";
3
+ import t from "../../classes/glass.js";
4
4
  import n from "../../icons/generated/lucide-user.js";
5
5
  import { normalizeLiteral as r } from "../../shared/normalize/index.js";
6
6
  import i from "./style.js";
@@ -67,7 +67,7 @@ var p = ["circle", "square"], m = class extends a {
67
67
  })}
68
68
  role=${e ? "presentation" : "img"}
69
69
  aria-label=${f(this._ariaLabel)}
70
- aria-hidden=${e ? "true" : void 0}
70
+ aria-hidden=${f(e ? "true" : void 0)}
71
71
  style="width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px"
72
72
  >
73
73
  ${this._showImage ? o`<img
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["// 注册 web-ui-icon:本组件模板直接渲染该 tag,消费者模板里不会出现它,\n// 因此没有别处会引入。产物保留模块(build.rollupOptions.output.preserveModules)\n// 并由 package.json 的 sideEffects 保证这段副作用 import 不被 tree-shake 掉。\nimport '@/components/icon'\n\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport { lucideUser } from '@/icons'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_SHAPES = ['circle', 'square'] as const\n\n@customElement('web-ui-avatar')\nexport class WebUiAvatar extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n set src(value: string) {\n const old = this._src\n this._src = value\n if (old !== value) {\n this._imgError = false\n this.requestUpdate('src', old)\n }\n }\n\n get src(): string {\n return this._src\n }\n\n private _src = ''\n\n @property({ type: String, reflect: true }) alt = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Number, reflect: true }) size = 40\n\n @property({ type: String, reflect: true })\n set shape(value: string) {\n const normalized = normalizeLiteral(value, ALLOWED_SHAPES, 'circle')\n if (this._shape !== normalized) {\n const old = this._shape\n this._shape = normalized\n this.requestUpdate('shape', old)\n }\n // 外部 setAttribute 非法值后,宿主 attribute 与规范化后的值不同步,立即修正\n if (this.getAttribute('shape') !== normalized) {\n this.setAttribute('shape', normalized)\n }\n }\n\n get shape(): 'circle' | 'square' {\n return this._shape\n }\n\n private _shape: 'circle' | 'square' = 'circle'\n\n @state() private _imgError = false\n @state() private _hasDefaultSlot = false\n\n private _checkSlot() {\n const slot = this.shadowRoot?.querySelector('slot:not([name])')\n const has = slot instanceof HTMLSlotElement && slot.assignedElements().length > 0\n if (this._hasDefaultSlot !== has) {\n this._hasDefaultSlot = has\n }\n }\n\n private get _initials(): string {\n const words = this.name.trim().split(/\\s+/)\n return words\n .slice(0, 2)\n .map(w => Array.from(w)[0])\n .join('')\n .toUpperCase()\n }\n\n private get _iconSize(): number {\n return Math.round(this.size * 0.4)\n }\n\n private get _showImage(): boolean {\n return !!this.src && !this._imgError\n }\n\n private get _showFallback(): boolean {\n return !this._showImage && !this._hasDefaultSlot\n }\n\n private _onImgError() {\n this._imgError = true\n }\n\n private get _ariaLabel(): string | undefined {\n if (this.alt) return this.alt\n if (this.name) return this.name\n return undefined\n }\n\n override render() {\n const isDecorative = !this._ariaLabel\n\n return html`\n <div\n class=${classMap({ 'avatar-inner': true, 'wui-glass': this._showFallback })}\n role=${isDecorative ? 'presentation' : 'img'}\n aria-label=${ifDefined(this._ariaLabel)}\n aria-hidden=${isDecorative ? 'true' : undefined}\n style=\"width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px\"\n >\n ${\n this._showImage\n ? html`<img\n class=\"avatar-img\"\n src=${this.src}\n alt=${ifDefined(this.alt || undefined)}\n @error=${this._onImgError}\n />`\n : ''\n }\n <slot @slotchange=${this._checkSlot}></slot>\n ${\n this._showFallback && this._initials\n ? html`<span class=\"avatar-fallback avatar-initials\">${this._initials}</span>`\n : ''\n }\n ${\n this._showFallback && !this._initials\n ? html`<span class=\"avatar-fallback\"\n ><web-ui-icon .icon=${lucideUser} .size=${this._iconSize}></web-ui-icon\n ></span>`\n : ''\n }\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-avatar': WebUiAvatar\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["// 注册 web-ui-icon:本组件模板直接渲染该 tag,消费者模板里不会出现它,\n// 因此没有别处会引入。产物保留模块(build.rollupOptions.output.preserveModules)\n// 并由 package.json 的 sideEffects 保证这段副作用 import 不被 tree-shake 掉。\nimport '@/components/icon'\n\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport glass from '@/classes/glass.css?inline'\nimport { lucideUser } from '@/icons'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_SHAPES = ['circle', 'square'] as const\n\n@customElement('web-ui-avatar')\nexport class WebUiAvatar extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n set src(value: string) {\n const old = this._src\n this._src = value\n if (old !== value) {\n this._imgError = false\n this.requestUpdate('src', old)\n }\n }\n\n get src(): string {\n return this._src\n }\n\n private _src = ''\n\n @property({ type: String, reflect: true }) alt = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Number, reflect: true }) size = 40\n\n @property({ type: String, reflect: true })\n set shape(value: string) {\n const normalized = normalizeLiteral(value, ALLOWED_SHAPES, 'circle')\n if (this._shape !== normalized) {\n const old = this._shape\n this._shape = normalized\n this.requestUpdate('shape', old)\n }\n // 外部 setAttribute 非法值后,宿主 attribute 与规范化后的值不同步,立即修正\n if (this.getAttribute('shape') !== normalized) {\n this.setAttribute('shape', normalized)\n }\n }\n\n get shape(): 'circle' | 'square' {\n return this._shape\n }\n\n private _shape: 'circle' | 'square' = 'circle'\n\n @state() private _imgError = false\n @state() private _hasDefaultSlot = false\n\n private _checkSlot() {\n const slot = this.shadowRoot?.querySelector('slot:not([name])')\n const has = slot instanceof HTMLSlotElement && slot.assignedElements().length > 0\n if (this._hasDefaultSlot !== has) {\n this._hasDefaultSlot = has\n }\n }\n\n private get _initials(): string {\n const words = this.name.trim().split(/\\s+/)\n return words\n .slice(0, 2)\n .map(w => Array.from(w)[0])\n .join('')\n .toUpperCase()\n }\n\n private get _iconSize(): number {\n return Math.round(this.size * 0.4)\n }\n\n private get _showImage(): boolean {\n return !!this.src && !this._imgError\n }\n\n private get _showFallback(): boolean {\n return !this._showImage && !this._hasDefaultSlot\n }\n\n private _onImgError() {\n this._imgError = true\n }\n\n private get _ariaLabel(): string | undefined {\n if (this.alt) return this.alt\n if (this.name) return this.name\n return undefined\n }\n\n override render() {\n const isDecorative = !this._ariaLabel\n\n return html`\n <div\n class=${classMap({ 'avatar-inner': true, 'wui-glass': this._showFallback })}\n role=${isDecorative ? 'presentation' : 'img'}\n aria-label=${ifDefined(this._ariaLabel)}\n aria-hidden=${ifDefined(isDecorative ? 'true' : undefined)}\n style=\"width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px\"\n >\n ${\n this._showImage\n ? html`<img\n class=\"avatar-img\"\n src=${this.src}\n alt=${ifDefined(this.alt || undefined)}\n @error=${this._onImgError}\n />`\n : ''\n }\n <slot @slotchange=${this._checkSlot}></slot>\n ${\n this._showFallback && this._initials\n ? html`<span class=\"avatar-fallback avatar-initials\">${this._initials}</span>`\n : ''\n }\n ${\n this._showFallback && !this._initials\n ? html`<span class=\"avatar-fallback\"\n ><web-ui-icon .icon=${lucideUser} .size=${this._iconSize}></web-ui-icon\n ></span>`\n : ''\n }\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-avatar': WebUiAvatar\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/avatar/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{line-height:0;display:inline-block}.avatar-inner{--wui-glass-corner-radius:calc(var(--wui-avatar-size,40px) / 2);border-radius:var(--wui-radius-control,calc(infinity * 1px));background-color:#e5e5e599;justify-content:center;align-items:center;display:inline-flex;position:relative;overflow:hidden}:host([shape=square]) .avatar-inner{--wui-glass-corner-radius:var(--wui-internal-avatar-square-radius,12px);border-radius:var(--wui-internal-avatar-square-radius,12px)}.avatar-img{object-fit:cover;width:100%;height:100%}.avatar-fallback{justify-content:center;align-items:center;display:flex;position:absolute;inset:0}slot{justify-content:center;align-items:center;line-height:1;display:flex;position:absolute;inset:0}.avatar-initials{-webkit-user-select:none;user-select:none;font-size:calc(var(--wui-avatar-size,40px) * .4);font-weight:var(--wui-font-weight-medium,500);color:#1b1b1bb3;line-height:1}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{line-height:0;display:inline-block}.avatar-inner{--wui-glass-corner-radius:calc(var(--wui-avatar-size,40px) / 2);border-radius:var(--wui-radius-control,calc(infinity * 1px));background-color:var(--wui-color-surface-raised,#f2f2f7);justify-content:center;align-items:center;display:inline-flex;position:relative;overflow:hidden}:host([shape=square]) .avatar-inner{--wui-glass-corner-radius:min(var(--wui-internal-avatar-square-radius,12px), max(0px, calc(var(--wui-avatar-size,40px) * .25)));border-radius:var(--wui-glass-corner-radius)}.avatar-img{object-fit:cover;width:100%;height:100%}.avatar-fallback{color:var(--wui-color-text,#1b1b1b);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}slot{justify-content:center;align-items:center;line-height:1;display:flex;position:absolute;inset:0}.avatar-initials{-webkit-user-select:none;user-select:none;font-size:calc(var(--wui-avatar-size,40px) * .4);font-weight:var(--wui-font-weight-medium,500);line-height:1}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/avatar/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n line-height: 0;\n}\n\n.avatar-inner {\n --wui-glass-corner-radius: calc(var(--wui-avatar-size, 40px) / 2);\n\n position: relative;\n\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n background-color: rgb(229 229 229 / 0.6);\n}\n\n:host([shape='square']) .avatar-inner {\n --wui-glass-corner-radius: var(--wui-internal-avatar-square-radius, 12px);\n\n border-radius: var(--wui-internal-avatar-square-radius, 12px);\n}\n\n.avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.avatar-fallback {\n position: absolute;\n inset: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\nslot {\n position: absolute;\n inset: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n line-height: 1;\n}\n\n.avatar-initials {\n user-select: none;\n\n font-size: calc(var(--wui-avatar-size, 40px) * 0.4);\n font-weight: var(--wui-font-weight-medium, 500);\n line-height: 1;\n color: rgb(27 27 27 / 0.7);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/avatar/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n line-height: 0;\n}\n\n.avatar-inner {\n --wui-glass-corner-radius: calc(var(--wui-avatar-size, 40px) / 2);\n\n position: relative;\n\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n background-color: var(--wui-color-surface-raised, #f2f2f7);\n}\n\n:host([shape='square']) .avatar-inner {\n --wui-glass-corner-radius: min(\n var(--wui-internal-avatar-square-radius, 12px),\n max(0px, calc(var(--wui-avatar-size, 40px) * 0.25))\n );\n\n border-radius: var(--wui-glass-corner-radius);\n}\n\n.avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.avatar-fallback {\n position: absolute;\n inset: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n color: var(--wui-color-text, #1b1b1b);\n}\n\nslot {\n position: absolute;\n inset: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n line-height: 1;\n}\n\n.avatar-initials {\n user-select: none;\n font-size: calc(var(--wui-avatar-size, 40px) * 0.4);\n font-weight: var(--wui-font-weight-medium, 500);\n line-height: 1;\n}\n"],"mappings":""}
@@ -6,10 +6,13 @@ export declare class WebUiBackTop extends LitElement {
6
6
  private _scrollBehavior;
7
7
  visible: boolean;
8
8
  scrollTarget: HTMLElement | Window;
9
+ ariaLabel: string | null;
9
10
  get threshold(): number;
10
11
  set threshold(v: number);
11
12
  private _threshold;
12
13
  private eventController?;
14
+ private readonly slottedTextObserver;
15
+ private readonly onSlotChange;
13
16
  connectedCallback(): void;
14
17
  disconnectedCallback(): void;
15
18
  protected willUpdate(props: PropertyValues): void;
@@ -18,6 +21,7 @@ export declare class WebUiBackTop extends LitElement {
18
21
  private computeVisible;
19
22
  toTop(): void;
20
23
  private onEnter;
24
+ private hasDefaultSlotContent;
21
25
  render(): import('lit').TemplateResult<1>;
22
26
  }
23
27
  declare global {
@@ -3,17 +3,18 @@ import "../icon/index.js";
3
3
  import t from "../../icons/generated/lucide-arrow-up-to-line.js";
4
4
  import { normalizeLiteral as n, normalizeNumber as r } from "../../shared/normalize/index.js";
5
5
  import "../button/index.js";
6
- import i from "./style.js";
7
- import { LitElement as a, html as o, unsafeCSS as s } from "lit";
8
- import { customElement as c, property as l, state as u } from "lit/decorators.js";
9
- import { getRootScrollTop as d } from "@greypan/browser-kit";
6
+ import { prefersReducedMotion as i } from "../../shared/theme/reduced-motion.js";
7
+ import a from "./style.js";
8
+ import { LitElement as o, html as s, nothing as c, unsafeCSS as l } from "lit";
9
+ import { customElement as u, property as d, state as f } from "lit/decorators.js";
10
+ import { getRootScrollTop as p } from "@greypan/browser-kit";
10
11
  //#region src/components/back-top/index.ts
11
- var f = class extends a {
12
+ var m = class extends o {
12
13
  constructor(...e) {
13
- super(...e), this._scrollBehavior = "smooth", this.visible = !1, this.scrollTarget = window, this._threshold = 200;
14
+ super(...e), this._scrollBehavior = "smooth", this.visible = !1, this.scrollTarget = window, this.ariaLabel = null, this._threshold = 200, this.slottedTextObserver = new MutationObserver(() => this.requestUpdate()), this.onSlotChange = () => this.requestUpdate();
14
15
  }
15
16
  static {
16
- this.styles = s(i);
17
+ this.styles = l(a);
17
18
  }
18
19
  get scrollBehavior() {
19
20
  return this._scrollBehavior;
@@ -30,10 +31,13 @@ var f = class extends a {
30
31
  this._threshold = r(e, 0, 1e4, 200), this.requestUpdate("threshold", t);
31
32
  }
32
33
  connectedCallback() {
33
- super.connectedCallback(), this.computeVisible(), this.onScrollTarget();
34
+ super.connectedCallback(), this.slottedTextObserver.observe(this, {
35
+ characterData: !0,
36
+ subtree: !0
37
+ }), this.computeVisible(), this.onScrollTarget();
34
38
  }
35
39
  disconnectedCallback() {
36
- super.disconnectedCallback(), this.eventController?.abort();
40
+ this.slottedTextObserver.disconnect(), super.disconnectedCallback(), this.eventController?.abort();
37
41
  }
38
42
  willUpdate(e) {
39
43
  super.willUpdate(e), (e.has("threshold") || e.has("scrollTarget")) && this.computeVisible(), e.has("scrollTarget") && (this.toggleAttribute("container-mode", this.target !== window), this.onScrollTarget());
@@ -51,23 +55,54 @@ var f = class extends a {
51
55
  }
52
56
  computeVisible() {
53
57
  let e = this.target;
54
- if (e === window) this.visible = d() >= this.threshold;
58
+ if (e === window) this.visible = p() >= this.threshold;
55
59
  else if (e instanceof HTMLElement) this.visible = e.scrollTop >= this.threshold;
56
60
  else throw Error("Prop scrollTarget must be HTMLElement or Window.");
57
61
  }
58
62
  toTop() {
59
- this.target.scrollTo({
60
- top: 0,
61
- behavior: this.scrollBehavior
62
- });
63
+ let e = this.target;
64
+ if (!i(this)) {
65
+ e.scrollTo({
66
+ top: 0,
67
+ behavior: this.scrollBehavior
68
+ });
69
+ return;
70
+ }
71
+ let t = e instanceof HTMLElement ? e : document.documentElement, n = t.style.getPropertyValue("scroll-behavior"), r = t.style.getPropertyPriority("scroll-behavior");
72
+ t.style.setProperty("scroll-behavior", "auto", "important");
73
+ try {
74
+ e.scrollTo({
75
+ top: 0,
76
+ behavior: "auto"
77
+ });
78
+ } finally {
79
+ n ? t.style.setProperty("scroll-behavior", n, r) : t.style.removeProperty("scroll-behavior");
80
+ }
63
81
  }
64
82
  onEnter(e) {
65
83
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.toTop());
66
84
  }
85
+ hasDefaultSlotContent() {
86
+ return [...this.childNodes].some((e) => {
87
+ if (e.nodeType === Node.ELEMENT_NODE) {
88
+ let t = e;
89
+ return !t.hasAttribute("slot") || t.getAttribute("slot") === "";
90
+ }
91
+ return e.nodeType === Node.TEXT_NODE && !!e.textContent?.trim();
92
+ });
93
+ }
67
94
  render() {
68
- return o`
69
- <div class="back-top-inner" role="button" tabindex="0" @click=${this.toTop} @keydown=${this.onEnter}>
70
- <slot>
95
+ let e = this.ariaLabel?.trim() || (this.hasDefaultSlotContent() ? c : "Back to top");
96
+ return s`
97
+ <div
98
+ class="back-top-inner"
99
+ role="button"
100
+ aria-label=${e}
101
+ tabindex="0"
102
+ @click=${this.toTop}
103
+ @keydown=${this.onEnter}
104
+ >
105
+ <slot @slotchange=${this.onSlotChange}>
71
106
  <web-ui-button variant="glass" tabindex="-1" icon>
72
107
  <web-ui-icon .icon=${t}></web-ui-icon>
73
108
  </web-ui-button>
@@ -76,18 +111,21 @@ var f = class extends a {
76
111
  `;
77
112
  }
78
113
  };
79
- e([l({
114
+ e([d({
80
115
  reflect: !0,
81
116
  attribute: "scroll-behavior",
82
117
  useDefault: !0
83
- })], f.prototype, "scrollBehavior", null), e([l({
118
+ })], m.prototype, "scrollBehavior", null), e([d({
84
119
  type: Boolean,
85
120
  reflect: !0
86
- })], f.prototype, "visible", void 0), e([l({ attribute: !1 })], f.prototype, "scrollTarget", void 0), e([l({
121
+ })], m.prototype, "visible", void 0), e([d({ attribute: !1 })], m.prototype, "scrollTarget", void 0), e([d({
122
+ type: String,
123
+ attribute: "aria-label"
124
+ })], m.prototype, "ariaLabel", void 0), e([d({
87
125
  type: Number,
88
126
  reflect: !0
89
- })], f.prototype, "threshold", null), e([u()], f.prototype, "eventController", void 0), f = e([c("web-ui-back-top")], f);
127
+ })], m.prototype, "threshold", null), e([f()], m.prototype, "eventController", void 0), m = e([u("web-ui-back-top")], m);
90
128
  //#endregion
91
- export { f as WebUiBackTop };
129
+ export { m as WebUiBackTop };
92
130
 
93
131
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/back-top/index.ts"],"sourcesContent":["import '@/components/button'\nimport '@/components/icon'\n\nimport { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { lucideArrowUpToLine } from '@/icons'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-back-top')\nexport class WebUiBackTop extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ reflect: true, attribute: 'scroll-behavior', useDefault: true })\n get scrollBehavior(): 'smooth' | 'auto' {\n return this._scrollBehavior\n }\n set scrollBehavior(value: string) {\n const old = this._scrollBehavior\n this._scrollBehavior = normalizeLiteral(value, ['smooth', 'auto'] as const, 'smooth')\n this.requestUpdate('scrollBehavior', old)\n }\n private _scrollBehavior: 'smooth' | 'auto' = 'smooth'\n @property({ type: Boolean, reflect: true }) visible = false\n @property({ attribute: false }) scrollTarget: HTMLElement | Window = window\n\n @property({ type: Number, reflect: true })\n get threshold(): number {\n return this._threshold\n }\n set threshold(v: number) {\n const old = this._threshold\n this._threshold = normalizeNumber(v, 0, 10000, 200)\n this.requestUpdate('threshold', old)\n }\n private _threshold = 200\n\n @state() private eventController?: AbortController\n\n override connectedCallback() {\n super.connectedCallback()\n this.computeVisible()\n this.onScrollTarget()\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.eventController?.abort()\n }\n\n protected override willUpdate(props: PropertyValues) {\n super.willUpdate(props)\n\n if (props.has('threshold') || props.has('scrollTarget')) {\n this.computeVisible()\n }\n // 不设 hasUpdated 门控:scrollTarget 可能在首次更新完成前赋值(如框架 onMounted 中),\n // 此时 connectedCallback 已按 window 绑定,必须重绑到新容器;onScrollTarget 幂等,重复调用安全\n if (props.has('scrollTarget')) {\n // 容器模式:scrollTarget 为元素时 button 通过 sticky 悬浮于容器底部,而非固定视口角落\n this.toggleAttribute('container-mode', this.target !== window)\n this.onScrollTarget()\n }\n }\n\n private get target() {\n if (!this.scrollTarget) return window\n const isRoot =\n this.scrollTarget === window ||\n this.scrollTarget === document.documentElement ||\n this.scrollTarget === document.body\n return isRoot ? window : this.scrollTarget\n }\n\n private onScrollTarget() {\n this.eventController?.abort()\n this.eventController = new AbortController()\n\n this.target.addEventListener(\n 'scroll',\n () => {\n this.computeVisible()\n },\n { signal: this.eventController.signal, passive: true }\n )\n }\n\n private computeVisible() {\n const target = this.target\n if (target === window) {\n this.visible = getRootScrollTop() >= this.threshold\n } else if (target instanceof HTMLElement) {\n this.visible = target.scrollTop >= this.threshold\n } else {\n throw new Error('Prop scrollTarget must be HTMLElement or Window.')\n }\n }\n\n toTop() {\n this.target.scrollTo({\n top: 0,\n behavior: this.scrollBehavior\n })\n }\n\n // ARIA button 契约要求 Enter 与 Space 均能激活\n private onEnter(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.toTop()\n }\n }\n\n override render() {\n return html`\n <div class=\"back-top-inner\" role=\"button\" tabindex=\"0\" @click=${this.toTop} @keydown=${this.onEnter}>\n <slot>\n <web-ui-button variant=\"glass\" tabindex=\"-1\" icon>\n <web-ui-icon .icon=${lucideArrowUpToLine}></web-ui-icon>\n </web-ui-button>\n </slot>\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-back-top': WebUiBackTop\n }\n}\n"],"mappings":";;;;;;;;;;AAaO,IAAM,IAAN,cAA2B,EAAW;;EAyBtB,aAbwB,KAAA,kBAAA,UACS,KAAA,UAAA,IACe,KAAA,eAAA,QAWhD,KAAA,aAAA;;;EAxBI,KAAA,SAAA,EAAU,CAAK;;CAExC,IACI,iBAAoC;EACtC,OAAO,KAAK;CACd;CACA,IAAI,eAAe,GAAe;EAChC,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,kBAAkB,EAAiB,GAAO,CAAC,UAAU,MAAM,GAAY,QAAQ,GACpF,KAAK,cAAc,kBAAkB,CAAG;CAC1C;CAKA,IACI,YAAoB;EACtB,OAAO,KAAK;CACd;CACA,IAAI,UAAU,GAAW;EACvB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,aAAa,EAAgB,GAAG,GAAG,KAAO,GAAG,GAClD,KAAK,cAAc,aAAa,CAAG;CACrC;CAKA,oBAA6B;EAG3B,AAFA,MAAM,kBAAkB,GACxB,KAAK,eAAe,GACpB,KAAK,eAAe;CACtB;CAEA,uBAAgC;EAE9B,AADA,MAAM,qBAAqB,GAC3B,KAAK,iBAAiB,MAAM;CAC9B;CAEA,WAA8B,GAAuB;EAQnD,AAPA,MAAM,WAAW,CAAK,IAElB,EAAM,IAAI,WAAW,KAAK,EAAM,IAAI,cAAc,MACpD,KAAK,eAAe,GAIlB,EAAM,IAAI,cAAc,MAE1B,KAAK,gBAAgB,kBAAkB,KAAK,WAAW,MAAM,GAC7D,KAAK,eAAe;CAExB;CAEA,IAAY,SAAS;EAMnB,OALK,KAAK,eAER,KAAK,iBAAiB,UACtB,KAAK,iBAAiB,SAAS,mBAC/B,KAAK,iBAAiB,SAAS,OACjB,SAAS,KAAK,eALC;CAMjC;CAEA,iBAAyB;EAIvB,AAHA,KAAK,iBAAiB,MAAM,GAC5B,KAAK,kBAAkB,IAAI,gBAAgB,GAE3C,KAAK,OAAO,iBACV,gBACM;GACJ,KAAK,eAAe;EACtB,GACA;GAAE,QAAQ,KAAK,gBAAgB;GAAQ,SAAS;EAAK,CACvD;CACF;CAEA,iBAAyB;EACvB,IAAM,IAAS,KAAK;EACpB,IAAI,MAAW,QACb,KAAK,UAAU,EAAiB,KAAK,KAAK;OACrC,IAAI,aAAkB,aAC3B,KAAK,UAAU,EAAO,aAAa,KAAK;OAExC,MAAU,MAAM,kDAAkD;CAEtE;CAEA,QAAQ;EACN,KAAK,OAAO,SAAS;GACnB,KAAK;GACL,UAAU,KAAK;EACjB,CAAC;CACH;CAGA,QAAgB,GAAkB;EAChC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,MAAM;CAEf;CAEA,SAAkB;EAChB,OAAO,CAAI;sEACuD,KAAK,MAAM,YAAY,KAAK,QAAQ;;;iCAGzE,EAAoB;;;;;CAKnD;AACF;AA/GG,EAAA,CAAA,EAAS;CAAE,SAAS;CAAM,WAAW;CAAmB,YAAY;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,kBAAA,IAAA,GAU1E,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GAE7B,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,IAAA,GAWxC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GA5BR,IAAA,EAAA,CAAA,EAAc,iBAAiB,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/back-top/index.ts"],"sourcesContent":["import '@/components/button'\nimport '@/components/icon'\n\nimport { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, nothing, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { lucideArrowUpToLine } from '@/icons'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { prefersReducedMotion } from '@/shared/theme/reduced-motion'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-back-top')\nexport class WebUiBackTop extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ reflect: true, attribute: 'scroll-behavior', useDefault: true })\n get scrollBehavior(): 'smooth' | 'auto' {\n return this._scrollBehavior\n }\n set scrollBehavior(value: string) {\n const old = this._scrollBehavior\n this._scrollBehavior = normalizeLiteral(value, ['smooth', 'auto'] as const, 'smooth')\n this.requestUpdate('scrollBehavior', old)\n }\n private _scrollBehavior: 'smooth' | 'auto' = 'smooth'\n @property({ type: Boolean, reflect: true }) visible = false\n @property({ attribute: false }) scrollTarget: HTMLElement | Window = window\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n\n @property({ type: Number, reflect: true })\n get threshold(): number {\n return this._threshold\n }\n set threshold(v: number) {\n const old = this._threshold\n this._threshold = normalizeNumber(v, 0, 10000, 200)\n this.requestUpdate('threshold', old)\n }\n private _threshold = 200\n\n @state() private eventController?: AbortController\n // `slotchange` 不覆盖同一个 Text 节点的内容变化,需要同步重新计算 fallback name。\n private readonly slottedTextObserver = new MutationObserver(() => this.requestUpdate())\n private readonly onSlotChange = () => this.requestUpdate()\n\n override connectedCallback() {\n super.connectedCallback()\n this.slottedTextObserver.observe(this, { characterData: true, subtree: true })\n this.computeVisible()\n this.onScrollTarget()\n }\n\n override disconnectedCallback() {\n this.slottedTextObserver.disconnect()\n super.disconnectedCallback()\n this.eventController?.abort()\n }\n\n protected override willUpdate(props: PropertyValues) {\n super.willUpdate(props)\n\n if (props.has('threshold') || props.has('scrollTarget')) {\n this.computeVisible()\n }\n // 不设 hasUpdated 门控:scrollTarget 可能在首次更新完成前赋值(如框架 onMounted 中),\n // 此时 connectedCallback 已按 window 绑定,必须重绑到新容器;onScrollTarget 幂等,重复调用安全\n if (props.has('scrollTarget')) {\n // 容器模式:scrollTarget 为元素时 button 通过 sticky 悬浮于容器底部,而非固定视口角落\n this.toggleAttribute('container-mode', this.target !== window)\n this.onScrollTarget()\n }\n }\n\n private get target() {\n if (!this.scrollTarget) return window\n const isRoot =\n this.scrollTarget === window ||\n this.scrollTarget === document.documentElement ||\n this.scrollTarget === document.body\n return isRoot ? window : this.scrollTarget\n }\n\n private onScrollTarget() {\n this.eventController?.abort()\n this.eventController = new AbortController()\n\n this.target.addEventListener(\n 'scroll',\n () => {\n this.computeVisible()\n },\n { signal: this.eventController.signal, passive: true }\n )\n }\n\n private computeVisible() {\n const target = this.target\n if (target === window) {\n this.visible = getRootScrollTop() >= this.threshold\n } else if (target instanceof HTMLElement) {\n this.visible = target.scrollTop >= this.threshold\n } else {\n throw new Error('Prop scrollTarget must be HTMLElement or Window.')\n }\n }\n\n toTop() {\n const target = this.target\n if (!prefersReducedMotion(this)) {\n target.scrollTo({ top: 0, behavior: this.scrollBehavior })\n return\n }\n\n // `auto` 会跟随 CSS scroll-behavior,因此仅在启动减少动效的滚动时临时覆盖目标元素。\n const scrollElement = target instanceof HTMLElement ? target : document.documentElement\n const previousBehavior = scrollElement.style.getPropertyValue('scroll-behavior')\n const previousPriority = scrollElement.style.getPropertyPriority('scroll-behavior')\n scrollElement.style.setProperty('scroll-behavior', 'auto', 'important')\n try {\n target.scrollTo({ top: 0, behavior: 'auto' })\n } finally {\n if (previousBehavior) scrollElement.style.setProperty('scroll-behavior', previousBehavior, previousPriority)\n else scrollElement.style.removeProperty('scroll-behavior')\n }\n }\n\n // ARIA button 契约要求 Enter 与 Space 均能激活\n private onEnter(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.toTop()\n }\n }\n\n private hasDefaultSlotContent() {\n return [...this.childNodes].some(node => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element\n return !element.hasAttribute('slot') || element.getAttribute('slot') === ''\n }\n return node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim())\n })\n }\n\n override render() {\n const ariaLabel = this.ariaLabel?.trim() || (this.hasDefaultSlotContent() ? nothing : 'Back to top')\n\n return html`\n <div\n class=\"back-top-inner\"\n role=\"button\"\n aria-label=${ariaLabel}\n tabindex=\"0\"\n @click=${this.toTop}\n @keydown=${this.onEnter}\n >\n <slot @slotchange=${this.onSlotChange}>\n <web-ui-button variant=\"glass\" tabindex=\"-1\" icon>\n <web-ui-icon .icon=${lucideArrowUpToLine}></web-ui-icon>\n </web-ui-button>\n </slot>\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-back-top': WebUiBackTop\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/back-top/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:block}:host([container-mode]){bottom:var(--wui-back-top-bottom,20px);position:sticky}.back-top-inner{pointer-events:none;position:var(--wui-back-top-position,fixed);z-index:var(--wui-back-top-z-index,var(--wui-layer-auxiliary,20));top:var(--wui-back-top-top,auto);right:var(--wui-back-top-right,20px);bottom:var(--wui-back-top-bottom,20px);left:var(--wui-back-top-left,auto);visibility:hidden;opacity:0}.back-top-inner .back-top-inner:focus-visible{border-radius:var(--wui-radius-control,calc(infinity * 1px));outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#08f) 40%, transparent));outline-offset:2px}:host([container-mode]) .back-top-inner{margin-right:var(--wui-back-top-right,20px);margin-left:var(--wui-back-top-left,auto);position:static}:host([visible]) .back-top-inner{pointer-events:auto;visibility:visible;opacity:1}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{display:block}:host([container-mode]){bottom:var(--wui-back-top-bottom,20px);position:sticky}.back-top-inner{pointer-events:none;position:var(--wui-back-top-position,fixed);z-index:var(--wui-back-top-z-index,var(--wui-layer-auxiliary,20));top:var(--wui-back-top-top,auto);right:var(--wui-back-top-right,20px);bottom:var(--wui-back-top-bottom,20px);left:var(--wui-back-top-left,auto);visibility:hidden;opacity:0}.back-top-inner:focus-visible{border-radius:var(--wui-radius-control,calc(infinity * 1px));outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,color-mix(in srgb, var(--wui-color-accent,#0071e3) 40%, transparent));outline-offset:2px}:host([container-mode]) .back-top-inner{width:fit-content;margin-right:var(--wui-back-top-right,20px);margin-left:var(--wui-back-top-left,auto);position:static}:host([visible]) .back-top-inner{pointer-events:auto;visibility:visible;opacity:1}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/back-top/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n}\n\n/* 容器模式:scrollTarget 为元素时 button 悬浮于容器底部(元素需置于容器内部),\n 横向偏移沿用 --wui-back-top-left/right,纵向沿用 --wui-back-top-bottom */\n:host([container-mode]) {\n position: sticky;\n bottom: var(--wui-back-top-bottom, 20px);\n}\n\n.back-top-inner {\n pointer-events: none;\n\n position: var(--wui-back-top-position, fixed);\n z-index: var(--wui-back-top-z-index, var(--wui-layer-auxiliary, 20));\n top: var(--wui-back-top-top, auto);\n right: var(--wui-back-top-right, 20px);\n bottom: var(--wui-back-top-bottom, 20px);\n left: var(--wui-back-top-left, auto);\n\n visibility: hidden;\n opacity: 0;\n\n .back-top-inner:focus-visible {\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #08f) 40%, transparent));\n outline-offset: 2px;\n }\n}\n\n:host([container-mode]) .back-top-inner {\n position: static;\n margin-right: var(--wui-back-top-right, 20px);\n margin-left: var(--wui-back-top-left, auto);\n}\n\n:host([visible]) .back-top-inner {\n pointer-events: auto;\n visibility: visible;\n opacity: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/back-top/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n}\n\n/* 容器模式:scrollTarget 为元素时 button 悬浮于容器底部(元素需置于容器内部),\n 横向偏移沿用 --wui-back-top-left/right,纵向沿用 --wui-back-top-bottom;不使用 top */\n:host([container-mode]) {\n position: sticky;\n bottom: var(--wui-back-top-bottom, 20px);\n}\n\n.back-top-inner {\n pointer-events: none;\n\n position: var(--wui-back-top-position, fixed);\n z-index: var(--wui-back-top-z-index, var(--wui-layer-auxiliary, 20));\n top: var(--wui-back-top-top, auto);\n right: var(--wui-back-top-right, 20px);\n bottom: var(--wui-back-top-bottom, 20px);\n left: var(--wui-back-top-left, auto);\n\n visibility: hidden;\n opacity: 0;\n\n &:focus-visible {\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n outline: var(--wui-focus-ring-width, 3px) solid\n var(--wui-color-focus-ring, color-mix(in srgb, var(--wui-color-accent, #0071e3) 40%, transparent));\n outline-offset: 2px;\n }\n}\n\n:host([container-mode]) .back-top-inner {\n position: static;\n width: fit-content;\n margin-right: var(--wui-back-top-right, 20px);\n margin-left: var(--wui-back-top-left, auto);\n}\n\n:host([visible]) .back-top-inner {\n pointer-events: auto;\n visibility: visible;\n opacity: 1;\n}\n"],"mappings":""}
@@ -16,8 +16,11 @@ export declare class WebUiBadge extends LitElement {
16
16
  get placement(): 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
17
17
  private _placement;
18
18
  private _hasContent;
19
+ private readonly _contentObserver;
19
20
  private readonly _handleSlotChange;
21
+ private _syncHasContent;
20
22
  connectedCallback(): void;
23
+ disconnectedCallback(): void;
21
24
  render(): import('lit').TemplateResult<1>;
22
25
  }
23
26
  declare global {