@greypan/web-ui 3.0.1 → 5.0.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 (238) hide show
  1. package/README.CN.md +495 -125
  2. package/README.md +504 -125
  3. package/dist/_virtual/{_@oxc-project_runtime@0.140.0 → _@oxc-project_runtime@0.146.0}/helpers/esm/decorate.js +1 -1
  4. package/dist/assets/glass.js +1 -1
  5. package/dist/assets/glass.js.map +1 -1
  6. package/dist/assets/menu-portal.js +1 -1
  7. package/dist/assets/menu-portal.js.map +1 -1
  8. package/dist/assets/overlay-motion.js +1 -1
  9. package/dist/assets/overlay-motion.js.map +1 -1
  10. package/dist/assets/toast-containers.js +1 -1
  11. package/dist/assets/toast-containers.js.map +1 -1
  12. package/dist/components/autocomplete/index.d.ts +12 -12
  13. package/dist/components/autocomplete/index.js +162 -111
  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.d.ts +0 -1
  18. package/dist/components/avatar/index.js +8 -13
  19. package/dist/components/avatar/index.js.map +1 -1
  20. package/dist/components/back-top/index.js +2 -2
  21. package/dist/components/back-top/index.js.map +1 -1
  22. package/dist/components/back-top/style.js +1 -1
  23. package/dist/components/back-top/style.js.map +1 -1
  24. package/dist/components/badge/index.d.ts +1 -0
  25. package/dist/components/badge/index.js +12 -14
  26. package/dist/components/badge/index.js.map +1 -1
  27. package/dist/components/button/index.d.ts +2 -0
  28. package/dist/components/button/index.js +52 -38
  29. package/dist/components/button/index.js.map +1 -1
  30. package/dist/components/button/style.js +1 -1
  31. package/dist/components/button/style.js.map +1 -1
  32. package/dist/components/button-group/index.d.ts +1 -2
  33. package/dist/components/button-group/index.js +21 -23
  34. package/dist/components/button-group/index.js.map +1 -1
  35. package/dist/components/button-group/style.js +1 -1
  36. package/dist/components/button-group/style.js.map +1 -1
  37. package/dist/components/checkbox/index.d.ts +4 -7
  38. package/dist/components/checkbox/index.js +56 -38
  39. package/dist/components/checkbox/index.js.map +1 -1
  40. package/dist/components/checkbox/style.js +1 -1
  41. package/dist/components/checkbox/style.js.map +1 -1
  42. package/dist/components/checkbox-group/index.d.ts +4 -10
  43. package/dist/components/checkbox-group/index.js +74 -60
  44. package/dist/components/checkbox-group/index.js.map +1 -1
  45. package/dist/components/collapse/index.d.ts +66 -0
  46. package/dist/components/collapse/index.js +159 -0
  47. package/dist/components/collapse/index.js.map +1 -0
  48. package/dist/components/collapse/style.js +6 -0
  49. package/dist/components/collapse/style.js.map +1 -0
  50. package/dist/components/context-menu/index.d.ts +29 -0
  51. package/dist/components/context-menu/index.js +168 -53
  52. package/dist/components/context-menu/index.js.map +1 -1
  53. package/dist/components/dialog/index.d.ts +6 -0
  54. package/dist/components/dialog/index.js +34 -13
  55. package/dist/components/dialog/index.js.map +1 -1
  56. package/dist/components/dialog/style.js +1 -1
  57. package/dist/components/dialog/style.js.map +1 -1
  58. package/dist/components/drawer/index.d.ts +45 -0
  59. package/dist/components/drawer/index.js +270 -56
  60. package/dist/components/drawer/index.js.map +1 -1
  61. package/dist/components/drawer/style.js +1 -1
  62. package/dist/components/drawer/style.js.map +1 -1
  63. package/dist/components/dropdown/index.d.ts +2 -0
  64. package/dist/components/dropdown/index.js +24 -14
  65. package/dist/components/dropdown/index.js.map +1 -1
  66. package/dist/components/dropdown-divider/index.js +1 -1
  67. package/dist/components/dropdown-header/index.js +1 -1
  68. package/dist/components/dropdown-header/style.js +1 -1
  69. package/dist/components/dropdown-header/style.js.map +1 -1
  70. package/dist/components/dropdown-item/index.js +3 -2
  71. package/dist/components/dropdown-item/index.js.map +1 -1
  72. package/dist/components/dropdown-item/style.js +1 -1
  73. package/dist/components/dropdown-item/style.js.map +1 -1
  74. package/dist/components/empty/index.d.ts +1 -0
  75. package/dist/components/empty/index.js +24 -22
  76. package/dist/components/empty/index.js.map +1 -1
  77. package/dist/components/empty/style.js +1 -1
  78. package/dist/components/empty/style.js.map +1 -1
  79. package/dist/components/icon/index.js +1 -1
  80. package/dist/components/index.d.ts +1 -0
  81. package/dist/components/index.js +21 -20
  82. package/dist/components/input/index.d.ts +2 -3
  83. package/dist/components/input/index.js +62 -52
  84. package/dist/components/input/index.js.map +1 -1
  85. package/dist/components/input/style.js +1 -1
  86. package/dist/components/input/style.js.map +1 -1
  87. package/dist/components/input-number/index.d.ts +2 -3
  88. package/dist/components/input-number/index.js +58 -38
  89. package/dist/components/input-number/index.js.map +1 -1
  90. package/dist/components/input-number/style.js +1 -1
  91. package/dist/components/input-number/style.js.map +1 -1
  92. package/dist/components/layout/index.d.ts +76 -3
  93. package/dist/components/layout/index.js +250 -39
  94. package/dist/components/layout/index.js.map +1 -1
  95. package/dist/components/layout/style.js +1 -1
  96. package/dist/components/layout/style.js.map +1 -1
  97. package/dist/components/option/index.js +1 -1
  98. package/dist/components/option/style.js +1 -1
  99. package/dist/components/option/style.js.map +1 -1
  100. package/dist/components/popover/index.d.ts +2 -1
  101. package/dist/components/popover/index.js +14 -8
  102. package/dist/components/popover/index.js.map +1 -1
  103. package/dist/components/popover/style.js +1 -1
  104. package/dist/components/popover/style.js.map +1 -1
  105. package/dist/components/radio/index.d.ts +4 -7
  106. package/dist/components/radio/index.js +51 -37
  107. package/dist/components/radio/index.js.map +1 -1
  108. package/dist/components/radio/style.js +1 -1
  109. package/dist/components/radio/style.js.map +1 -1
  110. package/dist/components/radio-group/index.d.ts +4 -10
  111. package/dist/components/radio-group/index.js +70 -52
  112. package/dist/components/radio-group/index.js.map +1 -1
  113. package/dist/components/segmented/index.d.ts +14 -12
  114. package/dist/components/segmented/index.js +132 -54
  115. package/dist/components/segmented/index.js.map +1 -1
  116. package/dist/components/segmented/style.js +1 -1
  117. package/dist/components/segmented/style.js.map +1 -1
  118. package/dist/components/segmented-trigger/index.d.ts +1 -2
  119. package/dist/components/segmented-trigger/index.js +23 -21
  120. package/dist/components/segmented-trigger/index.js.map +1 -1
  121. package/dist/components/segmented-trigger/style.js +1 -1
  122. package/dist/components/segmented-trigger/style.js.map +1 -1
  123. package/dist/components/select/index.d.ts +13 -8
  124. package/dist/components/select/index.js +114 -75
  125. package/dist/components/select/index.js.map +1 -1
  126. package/dist/components/select/style.js +1 -1
  127. package/dist/components/select/style.js.map +1 -1
  128. package/dist/components/slider/index.d.ts +6 -7
  129. package/dist/components/slider/index.js +99 -64
  130. package/dist/components/slider/index.js.map +1 -1
  131. package/dist/components/slider/style.js +1 -1
  132. package/dist/components/slider/style.js.map +1 -1
  133. package/dist/components/spinner/index.d.ts +0 -2
  134. package/dist/components/spinner/index.js +14 -13
  135. package/dist/components/spinner/index.js.map +1 -1
  136. package/dist/components/spinner/style.js +1 -1
  137. package/dist/components/spinner/style.js.map +1 -1
  138. package/dist/components/svg-draw-lines/index.js +1 -1
  139. package/dist/components/switch/index.d.ts +13 -6
  140. package/dist/components/switch/index.js +102 -41
  141. package/dist/components/switch/index.js.map +1 -1
  142. package/dist/components/switch/style.js +1 -1
  143. package/dist/components/switch/style.js.map +1 -1
  144. package/dist/components/textarea/index.d.ts +5 -6
  145. package/dist/components/textarea/index.js +74 -67
  146. package/dist/components/textarea/index.js.map +1 -1
  147. package/dist/components/textarea/style.js +1 -1
  148. package/dist/components/textarea/style.js.map +1 -1
  149. package/dist/components/theme/index.js +1 -1
  150. package/dist/components/theme/style.js +1 -1
  151. package/dist/components/theme/style.js.map +1 -1
  152. package/dist/components/toast/style.js +1 -1
  153. package/dist/components/toast/style.js.map +1 -1
  154. package/dist/components/toast/toast.js +12 -12
  155. package/dist/components/toast/toast.js.map +1 -1
  156. package/dist/components/tooltip/index.js +3 -3
  157. package/dist/components/tooltip/index.js.map +1 -1
  158. package/dist/components/tooltip/style.js +1 -1
  159. package/dist/components/tooltip/style.js.map +1 -1
  160. package/dist/icons/generated/heroicons-arrow-down-16-solid.d.ts +6 -0
  161. package/dist/icons/generated/heroicons-arrow-up-16-solid.d.ts +6 -0
  162. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts +6 -0
  163. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js +10 -0
  164. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js.map +1 -0
  165. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts +6 -0
  166. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js +10 -0
  167. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js.map +1 -0
  168. package/dist/icons/generated/lucide-clapperboard.d.ts +6 -0
  169. package/dist/icons/generated/lucide-clapperboard.js +10 -0
  170. package/dist/icons/generated/lucide-clapperboard.js.map +1 -0
  171. package/dist/icons/generated/lucide-code.d.ts +6 -0
  172. package/dist/icons/generated/lucide-code.js +10 -0
  173. package/dist/icons/generated/lucide-code.js.map +1 -0
  174. package/dist/icons/generated/lucide-ellipsis-vertical.d.ts +6 -0
  175. package/dist/icons/generated/lucide-ellipsis-vertical.js +10 -0
  176. package/dist/icons/generated/lucide-ellipsis-vertical.js.map +1 -0
  177. package/dist/icons/generated/lucide-eye.d.ts +6 -0
  178. package/dist/icons/generated/lucide-eye.js +10 -0
  179. package/dist/icons/generated/lucide-eye.js.map +1 -0
  180. package/dist/icons/generated/lucide-headphones.d.ts +6 -0
  181. package/dist/icons/generated/lucide-headphones.js +10 -0
  182. package/dist/icons/generated/lucide-headphones.js.map +1 -0
  183. package/dist/icons/generated/lucide-link.d.ts +6 -0
  184. package/dist/icons/generated/lucide-link.js +10 -0
  185. package/dist/icons/generated/lucide-link.js.map +1 -0
  186. package/dist/icons/generated/lucide-list-filter.d.ts +6 -0
  187. package/dist/icons/generated/lucide-list-filter.js +10 -0
  188. package/dist/icons/generated/lucide-list-filter.js.map +1 -0
  189. package/dist/icons/generated/lucide-list-restart.d.ts +6 -0
  190. package/dist/icons/generated/lucide-list-restart.js +10 -0
  191. package/dist/icons/generated/lucide-list-restart.js.map +1 -0
  192. package/dist/icons/generated/lucide-pen-line.d.ts +6 -0
  193. package/dist/icons/generated/lucide-pen-line.js +10 -0
  194. package/dist/icons/generated/lucide-pen-line.js.map +1 -0
  195. package/dist/icons/generated/lucide-play.d.ts +6 -0
  196. package/dist/icons/generated/lucide-play.js +10 -0
  197. package/dist/icons/generated/lucide-play.js.map +1 -0
  198. package/dist/icons/generated/lucide-sliders-horizontal.d.ts +6 -0
  199. package/dist/icons/generated/lucide-sliders-horizontal.js +10 -0
  200. package/dist/icons/generated/lucide-sliders-horizontal.js.map +1 -0
  201. package/dist/icons/generated/lucide-tag.d.ts +6 -0
  202. package/dist/icons/generated/lucide-tag.js +10 -0
  203. package/dist/icons/generated/lucide-tag.js.map +1 -0
  204. package/dist/icons/generated/tabler-sort-ascending-letters.d.ts +6 -0
  205. package/dist/icons/generated/tabler-sort-ascending-letters.js +10 -0
  206. package/dist/icons/generated/tabler-sort-ascending-letters.js.map +1 -0
  207. package/dist/icons/index.d.ts +15 -0
  208. package/dist/icons/index.js +18 -3
  209. package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js +1 -3
  210. package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js.map +1 -1
  211. package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +2 -1
  212. package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -1
  213. package/dist/shared/events/user-change.js.map +1 -1
  214. package/dist/shared/form-association/index.js +41 -0
  215. package/dist/shared/form-association/index.js.map +1 -0
  216. package/dist/shared/gesture/drag-gesture.js +133 -0
  217. package/dist/shared/gesture/drag-gesture.js.map +1 -0
  218. package/dist/shared/gesture/physics.js +45 -0
  219. package/dist/shared/gesture/physics.js.map +1 -0
  220. package/dist/shared/group-management/index.js +111 -0
  221. package/dist/shared/group-management/index.js.map +1 -0
  222. package/dist/shared/menu-portal/menu-portal.js +22 -10
  223. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  224. package/dist/shared/menu-portal/menu-tree.js +22 -7
  225. package/dist/shared/menu-portal/menu-tree.js.map +1 -1
  226. package/dist/shared/option-portal/index.js +65 -0
  227. package/dist/shared/option-portal/index.js.map +1 -0
  228. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  229. package/dist/shared/overlay/nested-drawer-layers.js +55 -0
  230. package/dist/shared/overlay/nested-drawer-layers.js.map +1 -0
  231. package/dist/shared/overlay/overlay.js +1 -1
  232. package/dist/shared/overlay/overlay.js.map +1 -1
  233. package/dist/shared/overlay/portal.js +47 -13
  234. package/dist/shared/overlay/portal.js.map +1 -1
  235. package/dist/shared/overlay/presence.js.map +1 -1
  236. package/dist/shared/visible-area/index.js +69 -0
  237. package/dist/shared/visible-area/index.js.map +1 -0
  238. package/package.json +8 -4
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import { 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 '@/components/option'\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport type { WebUiOption } from '@/components/option'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } 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/**\n * `web-ui-autocomplete`:可输入并过滤候选的单值选择器。\n *\n * 与 `web-ui-select` 共用 `<web-ui-option>` 子项注册协议与浮层能力,但触发区是\n * 可编辑输入框:`value` 即当前输入文本(表单值),键入时按 `filter` 模式过滤候选,\n * 选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value。\n */\n@customElement('web-ui-autocomplete')\nexport class WebUiAutocomplete extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n static formAssociated = true\n\n // ElementInternals 实例,在 connectedCallback 中初始化\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n\n @property({ type: String, reflect: true }) placeholder = ''\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({ 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 使用内部状态 + 访问器模式,在变更时同步 ElementInternals。\n // 与 Select 一致不反射 attribute:value attribute 保留为表单重置的初始默认值,\n // 避免设置属性时回写 attribute 导致 formResetCallback 读取到当前值。\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._internals?.setFormValue?.(v)\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 get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n @state() private _isOpen = false\n @state() private _activeIndex = -1\n @state() private _focused = false\n\n private static _nextInstanceId = 0\n private readonly _idPrefix = `web-ui-autocomplete-${++WebUiAutocomplete._nextInstanceId}`\n private readonly _optionIds = new WeakMap<WebUiOption, string>()\n private readonly _a11yOptionIds = new WeakMap<WebUiOption, string>()\n private _nextOptionId = 0\n private _nextA11yOptionId = 0\n private _options: WebUiOption[] = []\n private _portal?: OverlayPortal\n private _portalContent?: HTMLElement\n private readonly _pendingUnregisteredOptions = new Set<WebUiOption>()\n private readonly _scrollLock = defineScrollLockLease().make()\n private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.input-wrapper') ?? 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 })\n\n get isOpen(): boolean {\n return this._isOpen\n }\n\n get open(): boolean {\n return this._isOpen\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen) return\n\n const path = e.composedPath()\n const panel = this._panel.getPanel()\n if (!path.includes(this) && (!panel || !path.includes(panel))) this._close()\n }\n\n private _onFocusOut = () => {\n requestAnimationFrame(() => {\n if (this._isOpen && !this.matches(':focus-within') && !this._panel.getPanel()?.matches(':focus-within')) {\n this._close()\n }\n })\n }\n\n private _handlePanelPointerDown = (e: PointerEvent) => {\n // 非 option 区域不可聚焦;阻止 pointerdown 的默认聚焦行为,保持 combobox 焦点,\n // 使点击 empty state、滚动区和面板 padding 不会被 focusout 误判为外部交互。\n e.preventDefault()\n }\n\n override connectedCallback() {\n super.connectedCallback()\n // 元素被移动时会重连,ElementInternals 只能 attach 一次\n if (!this._internals) {\n this._internals = this.attachInternals()\n }\n // 同步 HTML 属性中预设的 value,补全访问器模式不处理 attribute 反射\n const attrValue = this.getAttribute('value')\n if (attrValue !== null) {\n this._value = attrValue\n this._internals?.setFormValue?.(attrValue)\n }\n this.addEventListener('option-register', this._onOptionRegister)\n this.addEventListener('option-unregister', this._onOptionUnregister)\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('focusout', this._onFocusOut)\n document.addEventListener('click', this._onClickOutside)\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.removeEventListener('option-register', this._onOptionRegister)\n this.removeEventListener('option-unregister', this._onOptionUnregister)\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._pendingUnregisteredOptions.clear()\n this._close()\n this._portal = undefined\n this._portalContent = undefined\n this._panel.dispose()\n this._scrollLock.release()\n }\n\n override firstUpdated() {\n requestAnimationFrame(() => {\n if (this.isConnected) this._onSlotChange()\n })\n }\n\n private _queryOptions(): WebUiOption[] {\n const panel = this.portal ? this._panel.getPanel() : null\n const panelOptions = panel ? [...panel.querySelectorAll<WebUiOption>('web-ui-option')] : []\n // 面板内容仅在浮层打开、moveContent 之后存在;关闭时回退 light DOM,\n // 否则 portal 模式首次加载时 _options 为空。\n return panelOptions.length > 0 ? panelOptions : [...this.querySelectorAll<WebUiOption>('web-ui-option')]\n }\n\n override willUpdate() {\n this._refreshOptions()\n this._ensureOptionIds()\n this._syncSelectedValue()\n this._applyFilter()\n this._syncOptionA11y()\n this._syncActiveOption()\n }\n\n override updated(changed: PropertyValues) {\n const input = this.shadowRoot?.querySelector<HTMLInputElement>('.autocomplete-input')\n if (input && input.value !== this._value) input.value = 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._syncValidity()\n this._syncEmptyState()\n }\n\n formResetCallback() {\n this.value = this.getAttribute('value') || ''\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n if (disabled && this._isOpen) this._close()\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n if (typeof state === 'string') this.value = state\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n // readonly 与 disabled 一致:值不可由用户修改,视为通过校验(原生 barred-from-validation 语义)\n if (this._isDisabled || this.readonly || !this.required || this._value) this._internals.setValidity({})\n else this._internals.setValidity({ valueMissing: true }, '请输入内容')\n }\n\n private _syncOpenAttribute() {\n this.toggleAttribute('open', this._isOpen)\n }\n\n private _syncSelectedValue() {\n const query = this._value.trim().toLowerCase()\n const next = query ? (this._options.find(o => o.label.trim().toLowerCase() === query)?.value ?? '') : ''\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 _ensureOptionIds() {\n const usedIds = new Set(this._options.map(option => option.id).filter(Boolean))\n this._options.forEach(option => {\n if (option.id) return\n\n let id = this._optionIds.get(option)\n if (!id || usedIds.has(id)) {\n do {\n id = `${this._idPrefix}-option-${++this._nextOptionId}`\n } while (usedIds.has(id))\n this._optionIds.set(option, id)\n }\n option.id = id\n usedIds.add(id)\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 _syncEmptyState() {\n const panel = this._panel.getPanel()\n if (!panel) return\n const empty = panel.querySelector<HTMLElement>('.autocomplete-empty')\n if (!empty) return\n const matching = this._options.filter(o => !o.hasAttribute('data-filtered'))\n empty.hidden = !(this._options.length > 0 && matching.length === 0)\n }\n\n private _bindOption = (option: WebUiOption) => {\n option.addEventListener('click', this._handleOptionClick)\n option.addEventListener('pointerover', this._handleOptionPointerOver)\n option.addEventListener('pointerdown', this._handleOptionPointerDown)\n option.addEventListener('option-update', this._onOptionUpdate)\n // Portal 迁移后 option 不再向宿主冒泡事件,直接监听以覆盖真实删除。\n option.addEventListener('option-unregister', this._onOptionUnregister)\n }\n\n private _unbindOption = (option: WebUiOption) => {\n option.removeEventListener('click', this._handleOptionClick)\n option.removeEventListener('pointerover', this._handleOptionPointerOver)\n option.removeEventListener('pointerdown', this._handleOptionPointerDown)\n option.removeEventListener('option-update', this._onOptionUpdate)\n option.removeEventListener('option-unregister', this._onOptionUnregister)\n }\n\n private _refreshOptions() {\n const activeOption = this._options[this._activeIndex]\n const nextOptions = this._queryOptions()\n\n this._options.filter(option => !nextOptions.includes(option)).forEach(this._unbindOption)\n nextOptions.forEach(this._bindOption)\n this._options = nextOptions\n this._activeIndex = activeOption && nextOptions.includes(activeOption) ? nextOptions.indexOf(activeOption) : -1\n }\n\n private _syncPortalContent() {\n if (!this._portal || !this._portalContent) return\n\n for (const option of this._pendingUnregisteredOptions) {\n if (!this._portalContent.contains(option) && !this.contains(option)) this._portal.removeContent([option])\n }\n this._pendingUnregisteredOptions.clear()\n\n if (!this._isOpen) return\n\n const lightDomNodes = Array.from(this.childNodes)\n if (lightDomNodes.length) this._portal.appendContent(lightDomNodes, this._portalContent)\n }\n\n private _scheduleOptionsRefresh() {\n // disconnectedCallback 在 Portal 迁移与实际删除时都会触发。延迟到当前微任务结束,\n // 才能根据 option 的最终位置区分二者并同时同步 active/selected/ARIA 状态。\n queueMicrotask(() => {\n if (!this.isConnected) return\n this._syncPortalContent()\n this.requestUpdate()\n })\n }\n\n private _onOptionRegister = () => {\n this._scheduleOptionsRefresh()\n }\n\n private _onOptionUnregister = (e: Event) => {\n if (e.target instanceof HTMLElement && e.target.localName === 'web-ui-option')\n this._pendingUnregisteredOptions.add(e.target as WebUiOption)\n this._scheduleOptionsRefresh()\n }\n\n private _onSlotChange = () => {\n this._scheduleOptionsRefresh()\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._scheduleOptionsRefresh()\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 // 保持输入框焦点,避免 focusout 在 click 前关闭浮层。\n e.preventDefault()\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (this._isDisabled || this.readonly) return\n\n switch (e.key) {\n case 'Escape':\n if (this._isOpen) {\n this._close()\n e.preventDefault()\n }\n break\n case 'ArrowDown':\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(1)\n break\n case 'ArrowUp':\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(-1)\n break\n case 'Enter':\n // 面板打开时接管 Enter:选中活动项或拦截表单提交;关闭时不拦截\n if (this._isOpen) {\n e.preventDefault()\n const option = this._options[this._activeIndex]\n if (option && !option.disabled && !option.hasAttribute('data-filtered')) {\n this._selectOption(option)\n }\n }\n break\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 let nextIdx = currentIdx + delta\n if (nextIdx < 0) nextIdx = enabled.length - 1\n if (nextIdx >= enabled.length) nextIdx = 0\n\n this._activeIndex = this._options.indexOf(enabled[nextIdx])\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 _onInput = (e: Event) => {\n if (this._isDisabled || this.readonly) return\n const input = e.target as HTMLInputElement\n if (input.value === this._value) return\n this.value = input.value\n this._activeIndex = -1\n this._syncActiveOption()\n if (!this._isOpen) this._open()\n }\n\n // 内部原生 input 在失焦时也会派发 change;组件契约中 change 仅表示「选中提交」,\n // 阻止原生 change 冒泡到宿主,避免消费端收到未选择时的 change。\n private _onInnerChange = (e: Event) => {\n e.stopPropagation()\n }\n\n private _onFocus = () => {\n if (this._isDisabled) return\n this._focused = true\n // readonly 仅可聚焦选中,不展开候选\n if (this.readonly) return\n if (this._options.length > 0) this._open()\n }\n\n private _onBlur = () => {\n this._focused = false\n }\n\n private _open(isKeyboardNavigation = false) {\n if (this._isDisabled || this.readonly || this._isOpen) return\n this._isOpen = true\n this._dispatchOpenChange()\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n this._syncScrollLock()\n if (this.portal) {\n requestAnimationFrame(() => {\n if (this._isOpen) this._openOverlay(isKeyboardNavigation)\n })\n } else {\n this._openOverlay(isKeyboardNavigation)\n }\n }\n\n private _close() {\n if (!this._isOpen) return\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._syncPortalContent()\n this._isOpen = false\n this._dispatchOpenChange()\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n this._syncScrollLock(false)\n void this._closeOverlay()\n }\n\n private _dispatchOpenChange() {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open: this._isOpen },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n this._syncEmptyState()\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\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 })\n this._portal = portal\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'\n const content = document.createElement('div')\n content.className = 'autocomplete-content'\n this._portalContent = content\n const empty = document.createElement('div')\n empty.className = 'autocomplete-empty'\n empty.hidden = true\n empty.textContent = '无匹配选项'\n scroll.append(content)\n content.append(empty)\n portal.panel.append(scroll)\n portal.moveContent(Array.from(this.children), content)\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 class=\"wui-glass input-wrapper\">\n <input\n class=\"autocomplete-input\"\n type=\"text\"\n placeholder=${this.placeholder}\n name=${this.name}\n .value=${this._value}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${labelledbyText ? labelId : nothing}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\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-activedescendant=${activeDescendant}\n @input=${this._onInput}\n @change=${this._onInnerChange}\n @focus=${this._onFocus}\n @blur=${this._onBlur}\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=\"wui-glass autocomplete-overlay wui-floating-panel\"\n hidden\n aria-hidden=\"true\"\n @pointerdown=${this._handlePanelPointerDown}\n >\n <div class=\"autocomplete-scroll\">\n <div class=\"autocomplete-content\">\n <slot @slotchange=${this._onSlotChange}></slot>\n <div class=\"autocomplete-empty\" hidden>无匹配选项</div>\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
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/autocomplete/index.ts"],"sourcesContent":["import { 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 '@/components/option'\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport type { WebUiOption } from '@/components/option'\nimport { defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { defineOptionPortal } from '@/shared/option-portal'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { applyOverlayVariables, defineOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } 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\nfunction isEmptySlotNode(node: Node): node is Element {\n return node instanceof Element && node.getAttribute('slot') === 'empty'\n}\n\n/**\n * `web-ui-autocomplete`:可输入并过滤候选的单值选择器。\n *\n * 与 `web-ui-select` 共用 `<web-ui-option>` 子项注册协议与浮层能力,但触发区是\n * 可编辑输入框:`value` 即当前输入文本(表单值),键入时按 `filter` 模式过滤候选,\n * 选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value。\n * `allow-custom-value` 开启后,Enter 可把不匹配候选的原文作为 custom value 显式提交。\n */\n@customElement('web-ui-autocomplete')\nexport class WebUiAutocomplete extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n static formAssociated = true\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\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 内容随面板迁移;slot=\"empty\" 由 autocomplete 单独迁移并恢复。\n getMigratableNodes: () => Array.from(this.childNodes).filter(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 private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.input-wrapper') ?? 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 })\n\n get isOpen(): boolean {\n return this._isOpen\n }\n\n get open(): boolean {\n return this._isOpen\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen) return\n\n const path = e.composedPath()\n const panel = this._panel.getPanel()\n if (!path.includes(this) && (!panel || !path.includes(panel))) this._close()\n }\n\n private _onFocusOut = () => {\n requestAnimationFrame(() => {\n if (this._isOpen && !this.matches(':focus-within') && !this._panel.getPanel()?.matches(':focus-within')) {\n this._close()\n }\n })\n }\n\n private _handlePanelPointerDown = (e: PointerEvent) => {\n // 非 option 区域不可聚焦;阻止 pointerdown 的默认聚焦行为,保持 combobox 焦点,\n // 使点击 empty state、滚动区和面板 padding 不会被 focusout 误判为外部交互。\n e.preventDefault()\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._optionPortal.bindHost()\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('focusout', this._onFocusOut)\n document.addEventListener('click', this._onClickOutside)\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.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 this._panel.dispose()\n this._scrollLock.release()\n }\n\n override firstUpdated() {\n requestAnimationFrame(() => {\n if (this.isConnected) this._optionPortal.scheduleRefresh()\n })\n }\n\n override willUpdate() {\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 const input = this.shadowRoot?.querySelector<HTMLInputElement>('.autocomplete-input')\n if (input && input.value !== this._value) input.value = 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._syncValidity()\n this._syncEmptyState()\n }\n\n formResetCallback() {\n this._formAssociation.reset()\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n if (disabled && this._isOpen) this._close()\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n this._formAssociation.restore(state)\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 }, '请输入内容')\n }\n\n private _syncOpenAttribute() {\n this.toggleAttribute('open', this._isOpen)\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 _syncEmptyState() {\n const panel = this._panel.getPanel()\n const empty = panel?.querySelector<HTMLElement>('.autocomplete-empty')\n const matching = this._options.filter(o => !o.hasAttribute('data-filtered'))\n const hasEmpty = this._isOpen && this._options.length > 0 && matching.length === 0\n if (empty) empty.hidden = !hasEmpty\n\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"empty\"]')\n const customText = slot\n ?.assignedElements()\n .map(element => element.textContent?.trim())\n .filter(Boolean)\n .join(' ')\n .trim()\n const message = customText || empty?.dataset.wuiA11yEmpty || '无匹配选项'\n const a11yEmpty = this.shadowRoot?.querySelector<HTMLElement>('.autocomplete-empty-a11y')\n if (a11yEmpty) {\n a11yEmpty.textContent = message\n a11yEmpty.hidden = !hasEmpty\n }\n }\n\n private _bindOption = (option: WebUiOption) => {\n option.addEventListener('click', this._handleOptionClick)\n option.addEventListener('pointerover', this._handleOptionPointerOver)\n option.addEventListener('pointerdown', this._handleOptionPointerDown)\n option.addEventListener('option-update', this._onOptionUpdate)\n }\n\n private _unbindOption = (option: WebUiOption) => {\n option.removeEventListener('click', this._handleOptionClick)\n option.removeEventListener('pointerover', this._handleOptionPointerOver)\n option.removeEventListener('pointerdown', this._handleOptionPointerDown)\n option.removeEventListener('option-update', this._onOptionUpdate)\n }\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 // 保持输入框焦点,避免 focusout 在 click 前关闭浮层。\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\n switch (e.key) {\n case 'Escape':\n if (this._isOpen) {\n this._close()\n e.preventDefault()\n }\n break\n case 'ArrowDown':\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(1)\n break\n case 'ArrowUp':\n e.preventDefault()\n if (!this._isOpen) this._open(true)\n else this._navigateActive(-1)\n break\n case 'Enter':\n // 面板打开时接管 Enter:选择候选或提交 custom value;关闭时不拦截表单提交。\n if (this._isOpen) {\n e.preventDefault()\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 if (this.allowCustomValue && this._value && !this._hasExactOption(this._value)) {\n this._selectCustomValue()\n }\n }\n break\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 let nextIdx = currentIdx + delta\n if (nextIdx < 0) nextIdx = enabled.length - 1\n if (nextIdx >= enabled.length) nextIdx = 0\n\n this._activeIndex = this._options.indexOf(enabled[nextIdx])\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 _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 _onInput = (e: Event) => {\n if (this._isDisabled || this.readonly) return\n const input = e.target as HTMLInputElement\n if (input.value === this._value) return\n this.value = input.value\n this._activeIndex = -1\n this._syncActiveOption()\n if (!this._isOpen) this._open()\n }\n\n // 内部原生 input 在失焦时也会派发 change;组件契约中 change 仅表示「选中提交」,\n // 阻止原生 change 冒泡到宿主,避免消费端收到未选择时的 change。\n private _onInnerChange = (e: Event) => {\n e.stopPropagation()\n }\n\n private _onFocus = () => {\n if (this._isDisabled) return\n this._focused = true\n }\n\n private _onInputClick = () => {\n if (this._isDisabled || this.readonly) return\n if (this._options.length > 0) this._open()\n }\n\n private _onBlur = () => {\n this._focused = false\n }\n\n private _open(isKeyboardNavigation = false) {\n if (this._isDisabled || this.readonly || this._isOpen) return\n this._isOpen = true\n this._dispatchOpenChange()\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n this._syncScrollLock()\n if (this.portal) {\n requestAnimationFrame(() => {\n if (this._isOpen) this._openOverlay(isKeyboardNavigation)\n })\n } else {\n this._openOverlay(isKeyboardNavigation)\n }\n }\n\n private _close() {\n if (!this._isOpen) return\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._optionPortal.syncPortalContent()\n this._isOpen = false\n this._dispatchOpenChange()\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n this._syncScrollLock(false)\n void this._closeOverlay()\n }\n\n private _dispatchOpenChange() {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open: this._isOpen },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n this._syncEmptyState()\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\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: mutations => {\n this._optionPortal.scheduleRefresh()\n const removedEmptyNodes = mutations.flatMap(mutation => [...mutation.removedNodes]).filter(isEmptySlotNode)\n if (removedEmptyNodes.length) {\n this._portal?.removeContent(removedEmptyNodes)\n const empty = this._portal?.panel.querySelector<HTMLElement>('.autocomplete-empty')\n if (empty) {\n empty.textContent = '无匹配选项'\n empty.dataset.wuiA11yEmpty = '无匹配选项'\n }\n }\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'\n const content = document.createElement('div')\n content.className = 'autocomplete-content'\n this._portalContent = content\n const empty = document.createElement('div')\n empty.className = 'autocomplete-empty'\n empty.hidden = true\n empty.dataset.wuiA11yEmpty = this._getEmptySlotText()\n scroll.append(content)\n content.append(empty)\n portal.panel.append(scroll)\n for (const node of Array.from(this.childNodes)) {\n if (isEmptySlotNode(node)) portal.appendContent([node], empty)\n else 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 private _getEmptySlotText(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"empty\"]')\n const text = slot\n ?.assignedElements()\n .map(element => element.textContent?.trim())\n .filter(Boolean)\n .join(' ')\n .trim()\n return text || '无匹配选项'\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 class=\"wui-glass input-wrapper\">\n <input\n class=\"autocomplete-input\"\n type=\"text\"\n placeholder=${this.placeholder}\n name=${this.name}\n .value=${this._value}\n aria-label=${ifDefined(this.ariaLabel)}\n aria-labelledby=${labelledbyText ? labelId : nothing}\n ?disabled=${this._isDisabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\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-activedescendant=${activeDescendant}\n @input=${this._onInput}\n @change=${this._onInnerChange}\n @click=${this._onInputClick}\n @focus=${this._onFocus}\n @blur=${this._onBlur}\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 class=\"autocomplete-a11y-only autocomplete-empty-a11y\" role=\"status\" hidden></div>\n <div\n class=\"wui-glass autocomplete-overlay wui-floating-panel\"\n hidden\n aria-hidden=\"true\"\n @pointerdown=${this._handlePanelPointerDown}\n >\n <div class=\"autocomplete-scroll\">\n <div class=\"autocomplete-content\">\n <slot @slotchange=${this._onSlotChange}></slot>\n <div class=\"autocomplete-empty\" hidden>\n <slot name=\"empty\">无匹配选项</slot>\n </div>\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{display:inline-block}:host([disabled]){cursor:not-allowed;opacity:.4}.input-wrapper{box-sizing:border-box;width:var(--wui-input-width,200px);min-width:var(--wui-button-size,40px);height:var(--wui-button-size,40px);transition:border-color var(--wui-duration-focus,.2s), box-shadow var(--wui-duration-focus,.2s);border-radius:2147483647px;align-items:center;gap:8px;padding:0 12px;display:flex}:host([focused]) .input-wrapper{--wui-glass-shadow:var(--wui-shadow-glass,0 2px 16px #0000000f), 0 0 0 3px var(--wui-focus-ring,#08f6);border-color:var(--wui-color-border-strong,#006ee680)}.autocomplete-input{min-width:0;height:100%;font:inherit;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);background:0 0;border:none;outline:none;flex:1;margin:0;padding:0}.autocomplete-input::placeholder{color:var(--wui-color-text-muted,#6a6a6a)}.autocomplete-input:disabled{cursor:not-allowed;opacity:.4}.autocomplete-overlay{--wui-glass-shadow:var(--wui-shadow-pop,0 3px 9px #00000045);--wui-duration-overlay-enter:var(--wui-duration-menu-enter,.14s);--wui-duration-overlay-exit:var(--wui-duration-menu-exit,.1s);--wui-overlay-min-width:200px;z-index:var(--wui-layer-local-overlay,1);box-sizing:border-box;min-width:var(--wui-overlay-min-width,120px);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);border-radius:20px;max-width:500px;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:320px;overflow-y:auto}.autocomplete-content{padding:4px}.autocomplete-empty{font-size:var(--wui-font-size,14px);color:var(--wui-color-text-muted,#6a6a6a);text-align:center;padding:8px 12px}::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}.input-wrapper{box-sizing:border-box;width:var(--wui-input-width,200px);min-width:var(--wui-control-size,36px);height:var(--wui-control-size,36px);transition:border-color var(--wui-duration-focus,.2s), box-shadow var(--wui-duration-focus,.2s);border-radius:2147483647px;align-items:center;gap:8px;padding:0 12px;display:flex}:host([focused]) .input-wrapper{--wui-internal-glass-focus-ring:inset 0 0 0 1px var(--wui-color-accent,#08f), 0 0 0 var(--wui-focus-ring-width,3px) var(--wui-color-focus-ring,#08f6)}:host([borderless]) .input-wrapper{-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;background:0 0;border:none}:host([borderless]) .input-wrapper:before{content:none}:host([borderless][focused]) .input-wrapper{box-shadow:var(--wui-internal-glass-focus-ring,0 0 0 0 transparent)}.autocomplete-input{min-width:0;height:100%;font:inherit;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);background:0 0;border:none;outline:none;flex:1;margin:0;padding:0}.autocomplete-input::placeholder{color:var(--wui-color-text-secondary,#6a6a6a)}.autocomplete-input:disabled{cursor:not-allowed;opacity:.4}.autocomplete-overlay{--wui-option-check-display:none;--wui-internal-glass-shadow:var(--wui-shadow-panel,0 3px 9px #00000045);--wui-glass-corner-radius:20px;--wui-internal-duration-overlay-enter:var(--wui-duration-menu-enter,.14s);--wui-internal-duration-overlay-exit:var(--wui-duration-menu-exit,.1s);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);background-color:var(--wui-color-surface-menu,#f6f6f6d1);border-radius:20px;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:4px}.autocomplete-empty{font-size:var(--wui-font-size,14px);color:var(--wui-color-text-secondary,#6a6a6a);text-align:center;padding:8px 12px}::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 display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.input-wrapper {\n display: flex;\n gap: 8px;\n align-items: center;\n\n box-sizing: border-box;\n width: var(--wui-input-width, 200px);\n min-width: var(--wui-button-size, 40px);\n height: var(--wui-button-size, 40px);\n padding: 0 12px;\n border-radius: calc(infinity * 1px);\n\n transition:\n border-color var(--wui-duration-focus, 200ms),\n box-shadow var(--wui-duration-focus, 200ms);\n}\n\n:host([focused]) .input-wrapper {\n --wui-glass-shadow:\n var(--wui-shadow-glass, 0 2px 16px rgb(0 0 0 / 0.06)), 0 0 0 3px var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n border-color: var(--wui-color-border-strong, rgb(0 110 230 / 0.5));\n}\n\n.autocomplete-input {\n flex: 1;\n\n min-width: 0;\n height: 100%;\n margin: 0;\n padding: 0;\n border: none;\n\n /* 表单控件不继承字体;显式继承以对齐宿主排版,避免 UA 默认字体差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n outline: none;\n\n &::placeholder {\n color: var(--wui-color-text-muted, #6a6a6a);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n}\n\n/* ===== 浮层(glass 样式参考 select) ===== */\n\n.autocomplete-overlay {\n --wui-glass-shadow: var(--wui-shadow-pop, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-duration-overlay-enter: var(--wui-duration-menu-enter, 140ms);\n --wui-duration-overlay-exit: var(--wui-duration-menu-exit, 100ms);\n --wui-overlay-min-width: 200px;\n position: absolute;\n z-index: var(--wui-layer-local-overlay, 1);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 120px);\n max-width: 500px;\n border-radius: 20px;\n\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\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: 320px;\n}\n\n.autocomplete-content {\n padding: 4px;\n}\n\n.autocomplete-empty {\n padding: 8px 12px;\n font-size: var(--wui-font-size, 14px);\n color: var(--wui-color-text-muted, #6a6a6a);\n text-align: center;\n}\n\n/* 非匹配候选隐藏:本地模式经 slot 投影,portal 模式为面板直接子元素 */\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 对齐:为本地绝对定位面板提供包含块,\n 避免面板 offsetParent(BODY)与实际包含块(远端定位祖先,如 layout header)不一致导致定位偏移。 */\n position: relative;\n}\n\n.input-wrapper {\n display: flex;\n gap: 8px;\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 height: var(--wui-control-size, 36px);\n padding: 0 12px;\n border-radius: calc(infinity * 1px);\n\n transition:\n border-color var(--wui-duration-focus, 200ms),\n box-shadow var(--wui-duration-focus, 200ms);\n}\n\n:host([focused]) .input-wrapper {\n --wui-internal-glass-focus-ring:\n inset 0 0 0 1px var(--wui-color-accent, #08f),\n 0 0 0 var(--wui-focus-ring-width, 3px) var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n}\n\n/* ===== Borderless ===== */\n\n:host([borderless]) .input-wrapper {\n border: none;\n\n background: transparent;\n\n /* stylelint-disable-next-line property-no-vendor-prefix */\n -webkit-backdrop-filter: none;\n backdrop-filter: none;\n box-shadow: none;\n}\n\n/* borderless 只移除输入容器的 glass 描边环(.wui-glass::before),\n 下拉浮层 .autocomplete-overlay 的 glass 描边不受影响 */\n:host([borderless]) .input-wrapper::before {\n content: none;\n}\n\n/* borderless 基线的 box-shadow: none 压掉了 .wui-glass 的整列阴影,\n 聚焦时改为直接消费 focus ring 变量,与 normal 变体同款并走既有 box-shadow 过渡 */\n:host([borderless][focused]) .input-wrapper {\n box-shadow: var(--wui-internal-glass-focus-ring, 0 0 0 0 transparent);\n}\n\n.autocomplete-input {\n flex: 1;\n\n min-width: 0;\n height: 100%;\n margin: 0;\n padding: 0;\n border: none;\n\n /* 表单控件不继承字体;显式继承以对齐宿主排版,避免 UA 默认字体差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n outline: none;\n\n &::placeholder {\n color: var(--wui-color-text-secondary, #6a6a6a);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n}\n\n/* ===== 浮层(glass 样式参考 select) ===== */\n\n.autocomplete-overlay {\n /* autocomplete 不表示选中状态;隐藏共享 option 的勾选图标及其布局占位 */\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: 20px;\n --wui-internal-duration-overlay-enter: var(--wui-duration-menu-enter, 140ms);\n --wui-internal-duration-overlay-exit: var(--wui-duration-menu-exit, 100ms);\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: 20px;\n\n background-color: var(--wui-color-surface-menu, rgb(246 246 246 / 0.82));\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: 4px;\n}\n\n.autocomplete-empty {\n padding: 8px 12px;\n font-size: var(--wui-font-size, 14px);\n color: var(--wui-color-text-secondary, #6a6a6a);\n text-align: center;\n}\n\n/* 非匹配候选隐藏:本地模式经 slot 投影,portal 模式为面板直接子元素 */\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":""}
@@ -12,7 +12,6 @@ export declare class WebUiAvatar extends LitElement {
12
12
  private _shape;
13
13
  private _imgError;
14
14
  private _hasDefaultSlot;
15
- connectedCallback(): void;
16
15
  private _checkSlot;
17
16
  private get _initials();
18
17
  private get _iconSize();
@@ -1,4 +1,4 @@
1
- import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
1
+ import e from "../../_virtual/_@oxc-project_runtime@0.146.0/helpers/esm/decorate.js";
2
2
  import "../icon/index.js";
3
3
  import t from "../../icons/generated/lucide-user.js";
4
4
  import n from "../../assets/glass.js";
@@ -34,11 +34,6 @@ var p = ["circle", "square"], m = class extends a {
34
34
  get shape() {
35
35
  return this._shape;
36
36
  }
37
- connectedCallback() {
38
- super.connectedCallback(), this.updateComplete.then(() => {
39
- this.shadowRoot?.querySelector("slot:not([name])")?.addEventListener("slotchange", () => this._checkSlot());
40
- });
41
- }
42
37
  _checkSlot() {
43
38
  let e = this.shadowRoot?.querySelector("slot:not([name])"), t = e instanceof HTMLSlotElement && e.assignedElements().length > 0;
44
39
  this._hasDefaultSlot !== t && (this._hasDefaultSlot = t);
@@ -76,16 +71,16 @@ var p = ["circle", "square"], m = class extends a {
76
71
  style="width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px"
77
72
  >
78
73
  ${this._showImage ? o`<img
79
- class="avatar-img"
80
- src=${this.src}
81
- alt=${d(this.alt || void 0)}
82
- @error=${this._onImgError}
83
- />` : ""}
74
+ class="avatar-img"
75
+ src=${this.src}
76
+ alt=${d(this.alt || void 0)}
77
+ @error=${this._onImgError}
78
+ />` : ""}
84
79
  <slot @slotchange=${this._checkSlot}></slot>
85
80
  ${this._showFallback && this._initials ? o`<span class="avatar-fallback avatar-initials">${this._initials}</span>` : ""}
86
81
  ${this._showFallback && !this._initials ? o`<span class="avatar-fallback"
87
- ><web-ui-icon .icon=${t} .size=${this._iconSize}></web-ui-icon
88
- ></span>` : ""}
82
+ ><web-ui-icon .icon=${t} .size=${this._iconSize}></web-ui-icon
83
+ ></span>` : ""}
89
84
  </div>
90
85
  `;
91
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["import { 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\n// 注册 web-ui-icon(Rolldown tree-shake 副作用 import,引用类名阻止删除)\nimport '@/components/icon'\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 override connectedCallback() {\n super.connectedCallback()\n void this.updateComplete.then(() => {\n this.shadowRoot?.querySelector('slot:not([name])')?.addEventListener('slotchange', () => this._checkSlot())\n })\n }\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 ${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 <slot @slotchange=${this._checkSlot}></slot>\n ${this._showFallback && this._initials\n ? html`<span class=\"avatar-fallback avatar-initials\">${this._initials}</span>`\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 </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-avatar': WebUiAvatar\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,IAAiB,CAAC,UAAU,QAAQ,GAG7B,IAAN,cAA0B,EAAW;;EA4CP,aA3BpB,KAAA,OAAA,IAEkC,KAAA,MAAA,IACC,KAAA,OAAA,IACA,KAAA,OAAA,IAoBZ,KAAA,SAAA,UAET,KAAA,YAAA,IACM,KAAA,kBAAA;;;EA3CV,KAAA,SAAA,CAAC,EAAU,CAAK,GAAG,EAAU,CAAK,CAAC;;CAE5D,IACI,IAAI,GAAe;EACrB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,OAAO,GACR,MAAQ,MACV,KAAK,YAAY,IACjB,KAAK,cAAc,OAAO,CAAG;CAEjC;CAEA,IAAI,MAAc;EAChB,OAAO,KAAK;CACd;CAQA,IACI,MAAM,GAAe;EACvB,IAAM,IAAa,EAAiB,GAAO,GAAgB,QAAQ;EACnE,IAAI,KAAK,WAAW,GAAY;GAC9B,IAAM,IAAM,KAAK;GAEjB,AADA,KAAK,SAAS,GACd,KAAK,cAAc,SAAS,CAAG;EACjC;EAEA,AAAI,KAAK,aAAa,OAAO,MAAM,KACjC,KAAK,aAAa,SAAS,CAAU;CAEzC;CAEA,IAAI,QAA6B;EAC/B,OAAO,KAAK;CACd;CAOA,oBAA6B;EAE3B,AADA,MAAM,kBAAkB,GACxB,KAAU,eAAe,WAAW;GAClC,KAAK,YAAY,cAAc,kBAAkB,CAAC,EAAE,iBAAiB,oBAAoB,KAAK,WAAW,CAAC;EAC5G,CAAC;CACH;CAEA,aAAqB;EACnB,IAAM,IAAO,KAAK,YAAY,cAAc,kBAAkB,GACxD,IAAM,aAAgB,mBAAmB,EAAK,iBAAiB,CAAC,CAAC,SAAS;EAChF,AAAI,KAAK,oBAAoB,MAC3B,KAAK,kBAAkB;CAE3B;CAEA,IAAY,YAAoB;EAE9B,OADc,KAAK,KAAK,KAAK,CAAC,CAAC,MAAM,KAC9B,CAAA,CACJ,MAAM,GAAG,CAAC,CAAC,CACX,KAAI,MAAK,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1B,KAAK,EAAE,CAAC,CACR,YAAY;CACjB;CAEA,IAAY,YAAoB;EAC9B,OAAO,KAAK,MAAM,KAAK,OAAO,EAAG;CACnC;CAEA,IAAY,aAAsB;EAChC,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK;CAC7B;CAEA,IAAY,gBAAyB;EACnC,OAAO,CAAC,KAAK,cAAc,CAAC,KAAK;CACnC;CAEA,cAAsB;EACpB,KAAK,YAAY;CACnB;CAEA,IAAY,aAAiC;EAC3C,IAAI,KAAK,KAAK,OAAO,KAAK;EAC1B,IAAI,KAAK,MAAM,OAAO,KAAK;CAE7B;CAEA,SAAkB;EAChB,IAAM,IAAe,CAAC,KAAK;EAE3B,OAAO,CAAI;;gBAEC,EAAS;GAAE,gBAAgB;GAAM,aAAa,KAAK;EAAc,CAAC,EAAE;eACrE,IAAe,iBAAiB,MAAM;qBAChC,EAAU,KAAK,UAAU,EAAE;sBAC1B,IAAe,SAAS,KAAA,EAAU;uBACjC,KAAK,KAAK,YAAY,KAAK,KAAK,uBAAuB,KAAK,KAAK;;UAE9E,KAAK,aACH,CAAI;;oBAEI,KAAK,IAAI;oBACT,EAAU,KAAK,OAAO,KAAA,CAAS,EAAE;uBAC9B,KAAK,YAAY;kBAE5B,GAAG;4BACa,KAAK,WAAW;UAClC,KAAK,iBAAiB,KAAK,YACzB,CAAI,iDAAiD,KAAK,UAAU,WACpE,GAAG;UACL,KAAK,iBAAiB,CAAC,KAAK,YAC1B,CAAI;oCACoB,EAAW,SAAS,KAAK,UAAU;wBAE3D,GAAG;;;CAGb;AACF;AAxHG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,OAAA,IAAA,GAgBxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,OAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GAExC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,IAAA,GAoBxC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,aAAA,KAAA,CAAA,GACN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GA7CR,IAAA,EAAA,CAAA,EAAc,eAAe,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["import { 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\n// 注册 web-ui-icon(Rolldown tree-shake 副作用 import,引用类名阻止删除)\nimport '@/components/icon'\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,4 +1,4 @@
1
- import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
1
+ import e from "../../_virtual/_@oxc-project_runtime@0.146.0/helpers/esm/decorate.js";
2
2
  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";
@@ -68,7 +68,7 @@ var f = class extends a {
68
68
  return o`
69
69
  <div class="back-top-inner" role="button" tabindex="0" @click=${this.toTop} @keydown=${this.onEnter}>
70
70
  <slot>
71
- <web-ui-button tabindex="-1" icon>
71
+ <web-ui-button variant="glass" tabindex="-1" icon>
72
72
  <web-ui-icon .icon=${t}></web-ui-icon>
73
73
  </web-ui-button>
74
74
  </slot>
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/back-top/index.ts"],"sourcesContent":["import { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/icon'\nimport '@/components/button'\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 为元素时按钮通过 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 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":";;;;;;;;;;AAYO,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 { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/icon'\nimport '@/components/button'\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 为元素时按钮通过 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":";;;;;;;;;;AAYO,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,5 +1,5 @@
1
1
  //#region src/components/back-top/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{--wui-shadow-glass:var(--wui-shadow-pop);display:block}:host([container-mode]){bottom:var(--web-ui-back-top-bottom,20px);position:sticky}.back-top-inner{pointer-events:none;position:var(--web-ui-back-top-position,fixed);z-index:var(--web-ui-back-top-z-index,var(--wui-layer-auxiliary,20));top:var(--web-ui-back-top-top,auto);right:var(--web-ui-back-top-right,20px);bottom:var(--web-ui-back-top-bottom,20px);left:var(--web-ui-back-top-left,auto);visibility:hidden;opacity:0}.back-top-inner .back-top-inner:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px;border-radius:2147483647px}:host([container-mode]) .back-top-inner{margin-right:var(--web-ui-back-top-right,20px);margin-left:var(--web-ui-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 .back-top-inner:focus-visible{outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,#08f6);outline-offset:2px;border-radius:2147483647px}: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}";
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 --wui-shadow-glass: var(--wui-shadow-pop);\n display: block;\n}\n\n/* 容器模式:scrollTarget 为元素时按钮悬浮于容器底部(元素需置于容器内部),\n 横向偏移沿用 --web-ui-back-top-left/right,纵向沿用 --web-ui-back-top-bottom */\n:host([container-mode]) {\n position: sticky;\n bottom: var(--web-ui-back-top-bottom, 20px);\n}\n\n.back-top-inner {\n pointer-events: none;\n\n position: var(--web-ui-back-top-position, fixed);\n z-index: var(--web-ui-back-top-z-index, var(--wui-layer-auxiliary, 20));\n top: var(--web-ui-back-top-top, auto);\n right: var(--web-ui-back-top-right, 20px);\n bottom: var(--web-ui-back-top-bottom, 20px);\n left: var(--web-ui-back-top-left, auto);\n\n visibility: hidden;\n opacity: 0;\n\n .back-top-inner:focus-visible {\n border-radius: calc(infinity * 1px);\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n/* 容器模式下按钮脱离 fixed,改为流内布局并按偏移变量左/右对齐 */\n:host([container-mode]) .back-top-inner {\n position: static;\n margin-right: var(--web-ui-back-top-right, 20px);\n margin-left: var(--web-ui-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 为元素时按钮悬浮于容器底部(元素需置于容器内部),\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: calc(infinity * 1px);\n outline: var(--wui-focus-ring-width, 3px) solid var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n/* 容器模式下按钮脱离 fixed,改为流内布局并按偏移变量左/右对齐 */\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":""}
@@ -16,6 +16,7 @@ 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 _handleSlotChange;
19
20
  connectedCallback(): void;
20
21
  render(): import('lit').TemplateResult<1>;
21
22
  }
@@ -1,4 +1,4 @@
1
- import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
1
+ import e from "../../_virtual/_@oxc-project_runtime@0.146.0/helpers/esm/decorate.js";
2
2
  import t from "../../assets/glass.js";
3
3
  import { normalizeLiteral as n, normalizeNumber as r } from "../../shared/normalize/index.js";
4
4
  import i from "./style.js";
@@ -15,7 +15,9 @@ var m = [
15
15
  "bottom-left"
16
16
  ], h = 2 ** 53 - 1, g = class extends a {
17
17
  constructor(...e) {
18
- super(...e), this._count = 0, this._max = 99, this.dot = !1, this.showZero = !1, this.badgeHidden = !1, this.offsetX = 0, this.offsetY = 0, this._placement = "top-right", this._hasContent = !1;
18
+ super(...e), this._count = 0, this._max = 99, this.dot = !1, this.showZero = !1, this.badgeHidden = !1, this.offsetX = 0, this.offsetY = 0, this._placement = "top-right", this._hasContent = !1, this._handleSlotChange = () => {
19
+ this._hasContent = this.children.length > 0;
20
+ };
19
21
  }
20
22
  static {
21
23
  this.styles = [s(t), s(i)];
@@ -54,11 +56,7 @@ var m = [
54
56
  return this._placement;
55
57
  }
56
58
  connectedCallback() {
57
- super.connectedCallback(), this._hasContent = this.children.length > 0, this.updateComplete.then(() => {
58
- this.shadowRoot?.querySelector("slot")?.addEventListener("slotchange", () => {
59
- this._hasContent = this.children.length > 0;
60
- });
61
- });
59
+ super.connectedCallback(), this._hasContent = this.children.length > 0;
62
60
  }
63
61
  render() {
64
62
  let e = this.badgeHidden ? !1 : this.dot ? !0 : this.count > 0 || this.showZero, t = this.dot ? "" : this.count > this.max ? `${this.max}+` : String(this.count), n = this.dot ? "未读" : this.count > 0 ? `${this.count} 条未读消息` : this.showZero ? "无未读消息" : void 0, r = {
@@ -74,14 +72,14 @@ var m = [
74
72
  };
75
73
  return o`
76
74
  <div class=${f(r)}>
77
- <slot></slot>
75
+ <slot @slotchange=${this._handleSlotChange}></slot>
78
76
  ${e ? o`<span
79
- class=${f(i)}
80
- style=${p(a)}
81
- role="status"
82
- aria-label=${d(n)}
83
- >${t}</span
84
- >` : ""}
77
+ class=${f(i)}
78
+ style=${p(a)}
79
+ role="status"
80
+ aria-label=${d(n)}
81
+ >${t}</span
82
+ >` : ""}
85
83
  </div>
86
84
  `;
87
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/badge/index.ts"],"sourcesContent":["import { 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'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = ['top-right', 'top-left', 'bottom-right', 'bottom-left'] as const\nconst MAX_SAFE = Number.MAX_SAFE_INTEGER\n\n@customElement('web-ui-badge')\nexport class WebUiBadge extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: Number, reflect: true })\n set count(value: number) {\n const normalized = normalizeNumber(value, 0, MAX_SAFE, 0)\n if (this._count !== normalized) {\n const old = this._count\n this._count = normalized\n this.requestUpdate('count', old)\n }\n if (this.getAttribute('count') !== String(normalized)) {\n this.setAttribute('count', String(normalized))\n }\n }\n\n get count(): number {\n return this._count\n }\n\n private _count = 0\n\n @property({ type: Number, reflect: true })\n set max(value: number) {\n const normalized = normalizeNumber(value, 0, MAX_SAFE, 99)\n if (this._max !== normalized) {\n const old = this._max\n this._max = normalized\n this.requestUpdate('max', old)\n }\n if (this.getAttribute('max') !== String(normalized)) {\n this.setAttribute('max', String(normalized))\n }\n }\n\n get max(): number {\n return this._max\n }\n\n private _max = 99\n\n @property({ type: Boolean, reflect: true }) dot = false\n @property({ type: Boolean, reflect: true, attribute: 'show-zero' }) showZero = false\n @property({ type: Boolean, reflect: true, attribute: 'badge-hidden' }) badgeHidden = false\n @property({ type: Number, reflect: true, attribute: 'offset-x' }) offsetX = 0\n @property({ type: Number, reflect: true, attribute: 'offset-y' }) offsetY = 0\n\n @property({ type: String, reflect: true })\n set placement(value: string) {\n const normalized = normalizeLiteral(value, ALLOWED_PLACEMENTS, 'top-right')\n if (this._placement !== normalized) {\n const old = this._placement\n this._placement = normalized\n this.requestUpdate('placement', old)\n }\n if (this.getAttribute('placement') !== normalized) {\n this.setAttribute('placement', normalized)\n }\n }\n\n get placement(): 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {\n return this._placement\n }\n\n private _placement: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' = 'top-right'\n\n @state() private _hasContent = false\n\n override connectedCallback() {\n super.connectedCallback()\n this._hasContent = this.children.length > 0\n void this.updateComplete.then(() => {\n this.shadowRoot?.querySelector('slot')?.addEventListener('slotchange', () => {\n this._hasContent = this.children.length > 0\n })\n })\n }\n\n override render() {\n const showBadge = this.badgeHidden ? false : this.dot ? true : this.count > 0 || this.showZero\n const display = this.dot ? '' : this.count > this.max ? `${this.max}+` : String(this.count)\n const ariaLabel = this.dot\n ? '未读'\n : this.count > 0\n ? `${this.count} 条未读消息`\n : this.showZero\n ? '无未读消息'\n : undefined\n const wrapperClass = { 'badge-wrapper': true, 'badge-wrapper-fixed': this._hasContent }\n const badgeClass = { badge: true, 'badge-dot': this.dot, 'badge-fixed': this._hasContent }\n const badgeStyle = {\n '--badge-offset-x': `${this.offsetX}px`,\n '--badge-offset-y': `${this.offsetY}px`\n }\n\n return html`\n <div class=${classMap(wrapperClass)}>\n <slot></slot>\n ${showBadge\n ? html`<span\n class=${classMap(badgeClass)}\n style=${styleMap(badgeStyle)}\n role=\"status\"\n aria-label=${ifDefined(ariaLabel)}\n >${display}</span\n >`\n : ''}\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-badge': WebUiBadge\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/badge/index.ts"],"sourcesContent":["import { 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'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = ['top-right', 'top-left', 'bottom-right', 'bottom-left'] as const\nconst MAX_SAFE = Number.MAX_SAFE_INTEGER\n\n@customElement('web-ui-badge')\nexport class WebUiBadge extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: Number, reflect: true })\n set count(value: number) {\n const normalized = normalizeNumber(value, 0, MAX_SAFE, 0)\n if (this._count !== normalized) {\n const old = this._count\n this._count = normalized\n this.requestUpdate('count', old)\n }\n if (this.getAttribute('count') !== String(normalized)) {\n this.setAttribute('count', String(normalized))\n }\n }\n\n get count(): number {\n return this._count\n }\n\n private _count = 0\n\n @property({ type: Number, reflect: true })\n set max(value: number) {\n const normalized = normalizeNumber(value, 0, MAX_SAFE, 99)\n if (this._max !== normalized) {\n const old = this._max\n this._max = normalized\n this.requestUpdate('max', old)\n }\n if (this.getAttribute('max') !== String(normalized)) {\n this.setAttribute('max', String(normalized))\n }\n }\n\n get max(): number {\n return this._max\n }\n\n private _max = 99\n\n @property({ type: Boolean, reflect: true }) dot = false\n @property({ type: Boolean, reflect: true, attribute: 'show-zero' }) showZero = false\n @property({ type: Boolean, reflect: true, attribute: 'badge-hidden' }) badgeHidden = false\n @property({ type: Number, reflect: true, attribute: 'offset-x' }) offsetX = 0\n @property({ type: Number, reflect: true, attribute: 'offset-y' }) offsetY = 0\n\n @property({ type: String, reflect: true })\n set placement(value: string) {\n const normalized = normalizeLiteral(value, ALLOWED_PLACEMENTS, 'top-right')\n if (this._placement !== normalized) {\n const old = this._placement\n this._placement = normalized\n this.requestUpdate('placement', old)\n }\n if (this.getAttribute('placement') !== normalized) {\n this.setAttribute('placement', normalized)\n }\n }\n\n get placement(): 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {\n return this._placement\n }\n\n private _placement: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' = 'top-right'\n\n @state() private _hasContent = false\n\n private readonly _handleSlotChange = () => {\n this._hasContent = this.children.length > 0\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._hasContent = this.children.length > 0\n }\n\n override render() {\n const showBadge = this.badgeHidden ? false : this.dot ? true : this.count > 0 || this.showZero\n const display = this.dot ? '' : this.count > this.max ? `${this.max}+` : String(this.count)\n const ariaLabel = this.dot\n ? '未读'\n : this.count > 0\n ? `${this.count} 条未读消息`\n : this.showZero\n ? '无未读消息'\n : undefined\n const wrapperClass = { 'badge-wrapper': true, 'badge-wrapper-fixed': this._hasContent }\n const badgeClass = { badge: true, 'badge-dot': this.dot, 'badge-fixed': this._hasContent }\n const badgeStyle = {\n '--badge-offset-x': `${this.offsetX}px`,\n '--badge-offset-y': `${this.offsetY}px`\n }\n\n return html`\n <div class=${classMap(wrapperClass)}>\n <slot @slotchange=${this._handleSlotChange}></slot>\n ${\n showBadge\n ? html`<span\n class=${classMap(badgeClass)}\n style=${styleMap(badgeStyle)}\n role=\"status\"\n aria-label=${ifDefined(ariaLabel)}\n >${display}</span\n >`\n : ''\n }\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-badge': WebUiBadge\n }\n}\n"],"mappings":"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"}
@@ -14,6 +14,8 @@ export declare class WebUiButton extends LitElement {
14
14
  set type(value: unknown);
15
15
  private _type;
16
16
  ariaLabel: string | null;
17
+ private readonly _groupManagement;
18
+ private get _groupContext();
17
19
  private get _sizeStyle();
18
20
  private handleClick;
19
21
  render(): import('lit').TemplateResult<1>;