@greypan/web-ui 6.4.0 → 7.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.
- package/README.CN.md +134 -40
- package/README.md +145 -51
- package/dist/assets/glass.js +1 -1
- package/dist/assets/glass.js.map +1 -1
- package/dist/assets/selection-control.js +6 -0
- package/dist/assets/selection-control.js.map +1 -0
- package/dist/assets/toast-containers.js.map +1 -1
- package/dist/components/autocomplete/index.d.ts +2 -0
- package/dist/components/autocomplete/index.js +19 -20
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/autocomplete/style.js.map +1 -1
- package/dist/components/badge/style.js.map +1 -1
- package/dist/components/button/style.js.map +1 -1
- package/dist/components/checkbox/index.d.ts +9 -2
- package/dist/components/checkbox/index.js +50 -26
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/checkbox/style.js +1 -1
- package/dist/components/checkbox/style.js.map +1 -1
- package/dist/components/checkbox-group/index.d.ts +3 -0
- package/dist/components/checkbox-group/index.js +24 -13
- package/dist/components/checkbox-group/index.js.map +1 -1
- package/dist/components/checkbox-group/style.js +1 -1
- package/dist/components/checkbox-group/style.js.map +1 -1
- package/dist/components/collapse/index.js.map +1 -1
- package/dist/components/context-menu/index.d.ts +10 -0
- package/dist/components/context-menu/index.js +48 -34
- package/dist/components/context-menu/index.js.map +1 -1
- package/dist/components/dialog/index.d.ts +6 -0
- package/dist/components/dialog/index.js +45 -20
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/dialog/style.js +1 -1
- package/dist/components/dialog/style.js.map +1 -1
- package/dist/components/drawer/index.d.ts +22 -4
- package/dist/components/drawer/index.js +134 -106
- package/dist/components/drawer/index.js.map +1 -1
- package/dist/components/drawer/style.js +1 -1
- package/dist/components/drawer/style.js.map +1 -1
- package/dist/components/dropdown/index.d.ts +21 -1
- package/dist/components/dropdown/index.js +74 -51
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/image-preview/index.js +86 -66
- package/dist/components/image-preview/index.js.map +1 -1
- package/dist/components/image-preview/style.js +1 -1
- package/dist/components/image-preview/style.js.map +1 -1
- package/dist/components/index.js +29 -29
- package/dist/components/input/index.js +2 -2
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input/style.js.map +1 -1
- package/dist/components/layout/index.js +2 -2
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/style.js +1 -1
- package/dist/components/layout/style.js.map +1 -1
- package/dist/components/popover/index.d.ts +8 -2
- package/dist/components/popover/index.js +47 -52
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/radio/index.d.ts +1 -1
- package/dist/components/radio/index.js +14 -13
- package/dist/components/radio/index.js.map +1 -1
- package/dist/components/radio/style.js +1 -1
- package/dist/components/radio/style.js.map +1 -1
- package/dist/components/radio-group/index.d.ts +3 -0
- package/dist/components/radio-group/index.js +24 -13
- package/dist/components/radio-group/index.js.map +1 -1
- package/dist/components/radio-group/style.js +1 -1
- package/dist/components/radio-group/style.js.map +1 -1
- package/dist/components/segmented/style.js +1 -1
- package/dist/components/segmented/style.js.map +1 -1
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +20 -19
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/slider/index.js.map +1 -1
- package/dist/components/slider/style.js +1 -1
- package/dist/components/slider/style.js.map +1 -1
- package/dist/components/svg-draw-lines/index.d.ts +13 -2
- package/dist/components/svg-draw-lines/index.js +44 -31
- package/dist/components/svg-draw-lines/index.js.map +1 -1
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/switch/style.js.map +1 -1
- package/dist/components/textarea/index.js +2 -2
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/textarea/style.js.map +1 -1
- package/dist/components/theme/index.d.ts +17 -0
- package/dist/components/theme/index.js +180 -20
- package/dist/components/theme/index.js.map +1 -1
- package/dist/components/theme/style.js +1 -1
- package/dist/components/theme/style.js.map +1 -1
- package/dist/components/toast/index.d.ts +1 -1
- package/dist/components/toast/manager.d.ts +1 -3
- package/dist/components/toast/manager.js +92 -49
- package/dist/components/toast/manager.js.map +1 -1
- package/dist/components/toast/style.js.map +1 -1
- package/dist/components/toast/toast.d.ts +37 -0
- package/dist/components/toast/toast.js +61 -8
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toast/types.d.ts +0 -4
- package/dist/components/tooltip/index.d.ts +6 -1
- package/dist/components/tooltip/index.js +11 -12
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/shared/gesture/drag-gesture.js +66 -64
- package/dist/shared/gesture/drag-gesture.js.map +1 -1
- package/dist/shared/gesture/physics.js +7 -29
- package/dist/shared/gesture/physics.js.map +1 -1
- package/dist/shared/menu-behavior/index.js +3 -4
- package/dist/shared/menu-behavior/index.js.map +1 -1
- package/dist/shared/option-portal/combobox-shell.js +7 -8
- package/dist/shared/option-portal/combobox-shell.js.map +1 -1
- package/dist/shared/overlay/anchored-panel.js +36 -31
- package/dist/shared/overlay/anchored-panel.js.map +1 -1
- package/dist/shared/overlay/native-dialog-presence.js +16 -0
- package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
- package/dist/shared/overlay/nested-drawer-layers.js +7 -4
- package/dist/shared/overlay/nested-drawer-layers.js.map +1 -1
- package/dist/shared/overlay/open-overlay.js +182 -0
- package/dist/shared/overlay/open-overlay.js.map +1 -0
- package/dist/shared/overlay/presence.js +19 -22
- package/dist/shared/overlay/presence.js.map +1 -1
- package/dist/shared/theme/duration.js +9 -0
- package/dist/shared/theme/duration.js.map +1 -0
- package/dist/shared/theme/reduced-motion.js +15 -0
- package/dist/shared/theme/reduced-motion.js.map +1 -0
- package/package.json +1 -1
- package/dist/shared/overlay/composition.js +0 -57
- package/dist/shared/overlay/composition.js.map +0 -1
- package/dist/shared/overlay/lifecycle.js +0 -41
- package/dist/shared/overlay/lifecycle.js.map +0 -1
- package/dist/vite.svg +0 -1
|
@@ -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 { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport {\n createComboboxOpenController,\n createOptionListenerBinding,\n handleComboboxFocusOut,\n nextWrappingIndex\n} from '@/shared/option-portal'\nimport { defineOptionPortal } from '@/shared/option-portal'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { overlayComposition } from '@/shared/overlay/composition'\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 FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' })\n noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'allow-custom-value' })\n allowCustomValue = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n private _filter: FilterMode = 'contains'\n\n @property({ type: String, reflect: true })\n get filter(): FilterMode {\n return this._filter\n }\n set filter(v: string) {\n const old = this._filter\n this._filter = normalizeLiteral(v, FILTER_MODES, 'contains')\n this.requestUpdate('filter', old)\n }\n\n // value 不反射 attribute,attribute 只参与首次声明式初始化。\n @state() private _value = ''\n\n get value(): string {\n return this._value\n }\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n // selected-value:文本精确匹配 option label 时派生出的 option value(只读反射)。\n @state() private _selectedValue = ''\n\n get selectedValue(): string {\n return this._selectedValue\n }\n\n private _setSelectedValue(value: string) {\n const old = this._selectedValue\n if (old === value && this.getAttribute('selected-value') === value) return\n\n this._selectedValue = value\n this.setAttribute('selected-value', value)\n if (old !== value) this.requestUpdate('selectedValue', old)\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n // 同步 HTML 属性中预设的 value,补全访问器模式不处理 attribute 反射。\n const attrValue = this.getAttribute('value')\n if (attrValue !== null) this._value = attrValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n @state() private _isOpen = false\n @state() private _activeIndex = -1\n @state() private _focused = false\n\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 && overlayComposition.containsEvent(panel, e))) this._close()\n }\n\n private _onFocusOut = () => {\n handleComboboxFocusOut(\n this,\n () => this._panel.getPanel(),\n () => this._isOpen,\n () => this._close()\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 override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n if (disabled && this._isOpen) this._close()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n // readonly 与 disabled 一致:值不可由用户修改,视为通过校验(原生 barred-from-validation 语义)\n if (this._isDisabled || this.readonly || !this.required || this._value) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, '请输入内容')\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 readonly _optionListeners = createOptionListenerBinding({\n // 惰性解引用:handler 字段声明在后者仍可在调用期取到\n onClick: event => this._handleOptionClick(event),\n onPointerOver: event => this._handleOptionPointerOver(event),\n onPointerDown: event => this._handleOptionPointerDown(event),\n onUpdate: () => this._onOptionUpdate()\n })\n private _bindOption = (option: WebUiOption) => this._optionListeners.bind(option)\n private _unbindOption = (option: WebUiOption) => this._optionListeners.unbind(option)\n\n private _refreshOptions() {\n const activeOption = this._options[this._activeIndex]\n // diff 绑定/解绑与激活索引按 option 身份保持在 shared 内完成\n const next = this._optionPortal.refresh(this._options, activeOption)\n this._options = next.options\n this._activeIndex = next.activeIndex\n }\n\n private _handleOptionClick = (e: Event) => {\n if (!(e.currentTarget instanceof HTMLElement)) return\n const option = e.currentTarget as WebUiOption\n if (option.disabled) return\n this._selectOption(option)\n }\n\n private _onOptionUpdate = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _handleOptionPointerOver = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (!this._isOpen || !(e.currentTarget instanceof HTMLElement)) return\n\n // 指针接管后只保留 :hover,避免键盘激活项与悬停项同时高亮。\n this._activeIndex = -1\n this._syncActiveOption()\n }\n\n private _handleOptionPointerDown = (e: PointerEvent) => {\n // 保持输入框焦点,避免 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 this._activeIndex = this._options.indexOf(enabled[nextWrappingIndex(enabled.length, currentIdx, delta)])\n this._syncActiveOption()\n }\n\n private _setInitialActiveOption() {\n const firstEnabled = this._options.findIndex(o => !o.disabled && !o.hasAttribute('data-filtered'))\n this._activeIndex = firstEnabled\n this._syncActiveOption()\n }\n\n private _syncActiveOption() {\n this._options.forEach((option, index) => option.toggleAttribute('active', index === this._activeIndex))\n }\n\n private _selectOption(option: WebUiOption) {\n if (this.readonly) return\n // value 即输入文本:选择后回填为 option label,selected-value 取 option value\n this.value = option.label\n this._setSelectedValue(option.value)\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _findExactOption(value: string): WebUiOption | undefined {\n const query = value.trim().toLowerCase()\n if (!query) return undefined\n\n return this._options.find(option => !option.disabled && option.label.trim().toLowerCase() === query)\n }\n\n private _hasExactOption(value: string): boolean {\n const query = value.trim().toLowerCase()\n return this._options.some(option => option.label.trim().toLowerCase() === query)\n }\n\n private _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 // 开合生命周期不变量收敛在 shared combobox-shell;autocomplete 注入\n // readonly guard 与 close 前的 portal 内容收敛钩子\n private readonly _openController = createComboboxOpenController({\n canOpen: () => !this._isDisabled && !this.readonly,\n getIsOpen: () => this._isOpen,\n setIsOpen: open => {\n this._isOpen = open\n },\n dispatchOpenChange: () => this._dispatchOpenChange(),\n syncScrollLock: open => this._syncScrollLock(open),\n isPortal: () => this.portal,\n openOverlay: isKeyboardNavigation => this._openOverlay(isKeyboardNavigation),\n closeOverlay: () => void this._closeOverlay(),\n onOpen: isKeyboardNavigation => {\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n },\n onBeforeClose: () => {\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._optionPortal.syncPortalContent()\n },\n onAfterClose: () => {\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n }\n })\n\n private _open(isKeyboardNavigation = false) {\n this._openController.open(isKeyboardNavigation)\n }\n\n private _close() {\n this._openController.close()\n }\n\n private _dispatchOpenChange() {\n dispatchOpenChangeEvent(this, this._isOpen)\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n this._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 // 只改 panel 内 dataset 不会触发 Lit update;同步刷新 shadow 内 role=status 空态。\n this._syncEmptyState()\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 // 框架注释锚点(v-if/v-for 占位)必须留在宿主:锚点进面板后 Vue 下次翻转\n // 会以面板内节点为插入基准;portal 的 marker 注释同理不参与迁移。\n if (node instanceof Comment) continue\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=\"autocomplete-overlay wui-floating-panel wui-glass\"\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
|
+
{"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 { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport {\n createComboboxOpenController,\n createOptionListenerBinding,\n handleComboboxFocusOut,\n nextWrappingIndex\n} from '@/shared/option-portal'\nimport { defineOptionPortal } from '@/shared/option-portal'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOpenOverlay } from '@/shared/overlay/open-overlay'\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 FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: String, reflect: true }) placeholder = ''\n @property({ type: Boolean, reflect: true }) borderless = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) readonly = false\n @property({ type: Boolean, reflect: true }) required = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' })\n noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'allow-custom-value' })\n allowCustomValue = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n @property({ type: String, reflect: true }) name = ''\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n @property({ type: String, attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined\n\n private _filter: FilterMode = 'contains'\n\n @property({ type: String, reflect: true })\n get filter(): FilterMode {\n return this._filter\n }\n set filter(v: string) {\n const old = this._filter\n this._filter = normalizeLiteral(v, FILTER_MODES, 'contains')\n this.requestUpdate('filter', old)\n }\n\n // value 不反射 attribute,attribute 只参与首次声明式初始化。\n @state() private _value = ''\n\n get value(): string {\n return this._value\n }\n set value(v: string) {\n const old = this._value\n this._value = v\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n // selected-value:文本精确匹配 option label 时派生出的 option value(只读反射)。\n @state() private _selectedValue = ''\n\n get selectedValue(): string {\n return this._selectedValue\n }\n\n private _setSelectedValue(value: string) {\n const old = this._selectedValue\n if (old === value && this.getAttribute('selected-value') === value) return\n\n this._selectedValue = value\n this.setAttribute('selected-value', value)\n if (old !== value) this.requestUpdate('selectedValue', old)\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n // 同步 HTML 属性中预设的 value,补全访问器模式不处理 attribute 反射。\n const attrValue = this.getAttribute('value')\n if (attrValue !== null) this._value = attrValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => this._value,\n getFormState: () => this._value,\n restoreState: state => {\n if (typeof state === 'string') this.value = state\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n @state() private _isOpen = false\n @state() private _activeIndex = -1\n @state() private _focused = false\n\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 /*\n * 开启态浮层承载「我开着吗」(issue #120 Block 1):宿主级 keydown 在 portal 模式下\n * 收不到面板内的 Escape,改由唯一仲裁者在 document 捕获阶段判定最内层。\n * 宿主接口只剩 requestClose:开启状态是声明而非询问。\n */\n private readonly _overlay = defineOpenOverlay().make({\n requestClose: () => this._close()\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 openOverlay: this._overlay\n })\n\n get isOpen(): boolean {\n return this._isOpen\n }\n\n get open(): boolean {\n return this._isOpen\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen) return\n\n // 在监听器内部判定:composedPath() 在派发结束后会被清空。\n const isInside = e.composedPath().includes(this) || !!this._panel.getHandle()?.containsEvent(e)\n if (!isInside) this._close()\n }\n\n private _onFocusOut = () => {\n handleComboboxFocusOut(\n this,\n () => this._panel.getHandle(),\n () => this._isOpen,\n () => this._close()\n )\n }\n\n private _handlePanelPointerDown = (e: PointerEvent) => {\n // 非 option 区域不可聚焦;阻止 pointerdown 的默认聚焦行为,保持 combobox 焦点,\n // 使点击 empty state、滚动区和面板 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 // 撤销登记由 _panel.dispose() 完成(句柄归它持有),不再需要单独 dispose 仲裁者。\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._syncOverlayInert()\n this._syncValidity()\n this._syncEmptyState()\n }\n\n override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n if (disabled && this._isOpen) this._close()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n // readonly 与 disabled 一致:值不可由用户修改,视为通过校验(原生 barred-from-validation 语义)\n if (this._isDisabled || this.readonly || !this.required || this._value) internals.setValidity({})\n else internals.setValidity({ valueMissing: true }, '请输入内容')\n }\n\n private _syncOpenAttribute() {\n this.toggleAttribute('open', this._isOpen)\n }\n\n /*\n * 禁用/只读态不响应 Escape。仲裁者仍在(吞掉按键并压掉原生 cancel),只是不走关闭\n * 入口 —— 与旧的「跳过候选」语义不同:旧语义放任事件落到下层浮层,把外层一起关掉。\n * 每次渲染后同步即可覆盖 disabled / readonly 属性与表单禁用三条来源。\n */\n private _syncOverlayInert() {\n this._panel.getHandle()?.setInert(this._isDisabled || this.readonly)\n }\n\n private _syncSelectedValue() {\n const query = this._value.trim().toLowerCase()\n const next = query\n ? (this._options.find(o => !o.disabled && o.label.trim().toLowerCase() === query)?.value ?? '')\n : ''\n this._setSelectedValue(next)\n }\n\n private _syncOptionA11y() {\n this._options.forEach(o => {\n o.setAttribute('role', 'option')\n o.setAttribute('aria-selected', o.value === this._selectedValue ? 'true' : 'false')\n o.setAttribute('aria-hidden', 'true')\n })\n }\n\n private _getA11yOptionId(option: WebUiOption): string {\n let id = this._a11yOptionIds.get(option)\n if (!id) {\n id = `${this._idPrefix}-a11y-option-${++this._nextA11yOptionId}`\n this._a11yOptionIds.set(option, id)\n }\n return id\n }\n\n // 按当前文本与 filter 模式过滤候选,非匹配项以 data-filtered 隐藏并跳过导航\n private _applyFilter() {\n const query = this._value.trim().toLowerCase()\n const mode = this._filter\n this._options.forEach(o => {\n const label = o.label.trim().toLowerCase()\n const match = mode === 'none' || !query || (mode === 'prefix' ? label.startsWith(query) : label.includes(query))\n o.toggleAttribute('data-filtered', !match)\n })\n // 活动项被过滤或禁用时清除键盘激活,避免激活不可见项\n const active = this._options[this._activeIndex]\n if (this._activeIndex >= 0 && (!active || active.hasAttribute('data-filtered') || active.disabled)) {\n this._activeIndex = -1\n this._syncActiveOption()\n }\n }\n\n private _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 readonly _optionListeners = createOptionListenerBinding({\n // 惰性解引用:handler 字段声明在后者仍可在调用期取到\n onClick: event => this._handleOptionClick(event),\n onPointerOver: event => this._handleOptionPointerOver(event),\n onPointerDown: event => this._handleOptionPointerDown(event),\n onUpdate: () => this._onOptionUpdate()\n })\n private _bindOption = (option: WebUiOption) => this._optionListeners.bind(option)\n private _unbindOption = (option: WebUiOption) => this._optionListeners.unbind(option)\n\n private _refreshOptions() {\n const activeOption = this._options[this._activeIndex]\n // diff 绑定/解绑与激活索引按 option 身份保持在 shared 内完成\n const next = this._optionPortal.refresh(this._options, activeOption)\n this._options = next.options\n this._activeIndex = next.activeIndex\n }\n\n private _handleOptionClick = (e: Event) => {\n if (!(e.currentTarget instanceof HTMLElement)) return\n const option = e.currentTarget as WebUiOption\n if (option.disabled) return\n this._selectOption(option)\n }\n\n private _onOptionUpdate = () => {\n this._optionPortal.scheduleRefresh()\n }\n\n private _handleOptionPointerOver = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (!this._isOpen || !(e.currentTarget instanceof HTMLElement)) return\n\n // 指针接管后只保留 :hover,避免键盘激活项与悬停项同时高亮。\n this._activeIndex = -1\n this._syncActiveOption()\n }\n\n private _handleOptionPointerDown = (e: PointerEvent) => {\n // 保持输入框焦点,避免 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 // Escape 不在本组件处理:由共享仲裁者在 document 捕获阶段归属(issue #120 Block 1)。\n switch (e.key) {\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 this._activeIndex = this._options.indexOf(enabled[nextWrappingIndex(enabled.length, currentIdx, delta)])\n this._syncActiveOption()\n }\n\n private _setInitialActiveOption() {\n const firstEnabled = this._options.findIndex(o => !o.disabled && !o.hasAttribute('data-filtered'))\n this._activeIndex = firstEnabled\n this._syncActiveOption()\n }\n\n private _syncActiveOption() {\n this._options.forEach((option, index) => option.toggleAttribute('active', index === this._activeIndex))\n }\n\n private _selectOption(option: WebUiOption) {\n if (this.readonly) return\n // value 即输入文本:选择后回填为 option label,selected-value 取 option value\n this.value = option.label\n this._setSelectedValue(option.value)\n this._close()\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _findExactOption(value: string): WebUiOption | undefined {\n const query = value.trim().toLowerCase()\n if (!query) return undefined\n\n return this._options.find(option => !option.disabled && option.label.trim().toLowerCase() === query)\n }\n\n private _hasExactOption(value: string): boolean {\n const query = value.trim().toLowerCase()\n return this._options.some(option => option.label.trim().toLowerCase() === query)\n }\n\n private _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 // 开合生命周期不变量收敛在 shared combobox-shell;autocomplete 注入\n // readonly guard 与 close 前的 portal 内容收敛钩子\n private readonly _openController = createComboboxOpenController({\n canOpen: () => !this._isDisabled && !this.readonly,\n getIsOpen: () => this._isOpen,\n setIsOpen: open => {\n this._isOpen = open\n },\n dispatchOpenChange: () => this._dispatchOpenChange(),\n syncScrollLock: open => this._syncScrollLock(open),\n isPortal: () => this.portal,\n openOverlay: isKeyboardNavigation => this._openOverlay(isKeyboardNavigation),\n closeOverlay: () => void this._closeOverlay(),\n onOpen: isKeyboardNavigation => {\n if (isKeyboardNavigation) this._setInitialActiveOption()\n else this._syncActiveOption()\n },\n onBeforeClose: () => {\n // Portal 内容可能在当前微任务尚未完成同步;先把 light DOM 中新增或重排的节点\n // 收回当前 content,再关闭并 restore,避免 restoreContent() 按旧 tracking 顺序把\n // 新 option 插到旧 option 前面。\n this._optionPortal.syncPortalContent()\n },\n onAfterClose: () => {\n this._activeIndex = -1\n this._options.forEach(o => o.removeAttribute('active'))\n }\n })\n\n private _open(isKeyboardNavigation = false) {\n this._openController.open(isKeyboardNavigation)\n }\n\n private _close() {\n this._openController.close()\n }\n\n private _dispatchOpenChange() {\n dispatchOpenChangeEvent(this, this._isOpen)\n }\n\n private _openOverlay(isKeyboardNavigation = false) {\n this._panel.open(isKeyboardNavigation)\n // 新会话的句柄刚建立,惰性状态需按当前 disabled/readonly 重新同步。\n this._syncOverlayInert()\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 * reconfigure 重新 claim = 新会话,inert 回到 false。实测这条重推是**冗余**的(摘掉本行\n * 全部用例仍绿):这条路径后面跟着一轮渲染,而 `updated()` 每次渲染都会调\n * `_syncOverlayInert()`。留在这里是不想依赖「这条路径必然跟着一次渲染」这个隐含前提。\n */\n this._syncOverlayInert()\n }\n\n private _syncScrollLock(isOpen = this._isOpen) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _createPortal(): OverlayPortal {\n const portal = defineOverlayPortal().make({\n container: this.overlayContainer,\n target: this,\n style: `${glass}\\n${overlayMotion}\\n${style}`,\n className: 'wui-glass autocomplete-overlay portal wui-floating-panel',\n onContentChange: 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 // 只改 panel 内 dataset 不会触发 Lit update;同步刷新 shadow 内 role=status 空态。\n this._syncEmptyState()\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 // 框架注释锚点(v-if/v-for 占位)必须留在宿主:锚点进面板后 Vue 下次翻转\n // 会以面板内节点为插入基准;portal 的 marker 注释同理不参与迁移。\n if (node instanceof Comment) continue\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=\"autocomplete-overlay wui-floating-panel wui-glass\"\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/autocomplete/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-autocomplete-max-width: 500px;\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.wui-autocomplete-inner {\n /* 与 select 的 .wui-select-inner 对齐:为本地绝对定位面板提供包含块,\n 避免面板 offsetParent(BODY)与实际包含块(远端定位祖先,如 layout header)不一致导致定位偏移。 */\n position: relative;\n}\n\n.input-wrapper {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n\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: var(--wui-radius-control, calc(infinity * 1px));\n}\n\n
|
|
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 --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n\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: var(--wui-radius-control, calc(infinity * 1px));\n}\n\n:host([borderless]) .input-wrapper {\n border: none;\n background: transparent;\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.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/* Coarse pointers include iOS Safari, where a sub-16px font triggers focus zoom. */\n@media (pointer: coarse) {\n .autocomplete-input {\n font-size: max(16px, var(--wui-font-size, 14px));\n }\n}\n\n/* Focus ring 独立成 ::after 层:base/focused 都是显式 box-shadow,保证所有变体都能过渡 */\n.input-wrapper::after {\n pointer-events: none;\n content: '';\n\n position: absolute;\n inset: 0;\n\n border-radius: inherit;\n\n box-shadow:\n inset 0 0 0 1px transparent,\n 0 0 0 var(--wui-focus-ring-width, 3px) transparent;\n\n transition: box-shadow var(--wui-duration-focus, 200ms);\n}\n\n:host([focused]) .input-wrapper::after {\n box-shadow:\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/* ===== 浮层(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: var(--wui-radius-menu, 18px);\n --wui-internal-duration-float-enter: var(--wui-duration-float-enter, 240ms);\n --wui-internal-duration-float-exit: var(--wui-duration-float-exit, 160ms);\n position: absolute;\n z-index: var(--wui-layer-inline-overlay, 1);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 200px);\n max-width: var(--wui-autocomplete-max-width, 500px);\n border-radius: var(--wui-radius-menu, 18px);\n\n /* 玻璃背景:wui-glass 在面板自身,这里覆盖其默认玻璃底为菜单表面色 */\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":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/badge/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-block;\n}\n\n.badge-wrapper {\n display: inline-flex;\n}\n\n.badge-wrapper-fixed {\n position: relative;\n}\n\n.badge {\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--wui-color-page, #fff);\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n color: var(--wui-color-on-accent, #fff);\n white-space: nowrap;\n\n background-color: var(--wui-color-danger, #dc2626);\n}\n\n.badge-fixed {\n position: absolute;\n transform: translate(\n calc(var(--badge-x, 50%) + var(--badge-offset-x, 0px)),\n calc(var(--badge-y, -50%) + var(--badge-offset-y, 0px))\n );\n}\n\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/badge/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-block;\n}\n\n.badge-wrapper {\n display: inline-flex;\n}\n\n.badge-wrapper-fixed {\n position: relative;\n}\n\n.badge {\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n border: 1px solid var(--wui-color-page, #fff);\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n font-size: 12px;\n font-weight: 500;\n line-height: 1;\n color: var(--wui-color-on-accent, #fff);\n white-space: nowrap;\n\n background-color: var(--wui-color-danger, #dc2626);\n}\n\n.badge-fixed {\n position: absolute;\n transform: translate(\n calc(var(--badge-x, 50%) + var(--badge-offset-x, 0px)),\n calc(var(--badge-y, -50%) + var(--badge-offset-y, 0px))\n );\n}\n\n:host([placement='top-right']) .badge {\n --badge-x: 50%;\n --badge-y: -50%;\n top: 0;\n right: 0;\n}\n\n:host([placement='top-left']) .badge {\n --badge-x: -50%;\n --badge-y: -50%;\n top: 0;\n left: 0;\n}\n\n:host([placement='bottom-right']) .badge {\n --badge-x: 50%;\n --badge-y: 50%;\n right: 0;\n bottom: 0;\n}\n\n:host([placement='bottom-left']) .badge {\n --badge-x: -50%;\n --badge-y: 50%;\n bottom: 0;\n left: 0;\n}\n\n.badge-dot {\n min-width: 8px;\n height: 8px;\n padding: 0;\n font-size: 0;\n}\n\n/* ===== Fixed mode (has slotted content) ===== */\n\n.badge-fixed.badge-dot {\n --badge-x: 40%;\n --badge-y: -40%;\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n position: relative;\n\n /* inline-flex 让内层按钮在宿主内完全居中,避免继承的行高撑高宿主、导致图标偏移 */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n:host([full]) {\n display: block;\n width: 100%;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\nbutton {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n cursor: default;\n user-select: none;\n\n position: relative;\n\n overflow: clip;\n display: inline-flex;\n gap: var(--wui-button-gap, 8px);\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n width: var(--wui-button-width, max-content);\n min-width: var(--wui-control-size, 36px);\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-button-px, 12px);\n border: none;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n /* 原生 button 不继承字体;显式继承以对齐宿主排版,避免 UA 默认 Arial 差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-button-color);\n white-space: nowrap;\n\n background-color: var(--wui-button-bg);\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n\n &:focus-visible {\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@media (hover: hover) and (pointer: fine) {\n button:hover:not(:disabled) {\n background-color: var(--wui-button-bg-hover);\n }\n}\n\nbutton:active:not(:disabled) {\n background-color: var(--wui-button-bg-active);\n}\n\n
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n position: relative;\n\n /* inline-flex 让内层按钮在宿主内完全居中,避免继承的行高撑高宿主、导致图标偏移 */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n:host([full]) {\n display: block;\n width: 100%;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\nbutton {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n cursor: default;\n user-select: none;\n\n position: relative;\n\n overflow: clip;\n display: inline-flex;\n gap: var(--wui-button-gap, 8px);\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n width: var(--wui-button-width, max-content);\n min-width: var(--wui-control-size, 36px);\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-button-px, 12px);\n border: none;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n /* 原生 button 不继承字体;显式继承以对齐宿主排版,避免 UA 默认 Arial 差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-button-color);\n white-space: nowrap;\n\n background-color: var(--wui-button-bg);\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n\n &:focus-visible {\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@media (hover: hover) and (pointer: fine) {\n button:hover:not(:disabled) {\n background-color: var(--wui-button-bg-hover);\n }\n}\n\nbutton:active:not(:disabled) {\n background-color: var(--wui-button-bg-active);\n}\n\n:host([full]) button {\n display: flex;\n width: 100%;\n}\n\n:host([icon]) button {\n padding: 0;\n}\n\n/* pointer-focus helper 把标记写到 shadow host 上;这里抑制 Shadow DOM 内按钮的 focus ring。 */\n:host([data-wui-pointer-focus]) button:focus-visible {\n outline-color: transparent;\n}\n\n/* ===== Variant: primary (默认) ===== */\n\n:host([variant='primary']) {\n --wui-button-color: var(--wui-color-on-accent, #fff);\n --wui-button-bg: var(--wui-color-accent, #08f);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #08f) 88%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #08f) 76%, black);\n}\n\n:host([variant='secondary']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: var(--wui-color-surface-control, #dfdfdf);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 92%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 82%, black);\n}\n\n:host([variant='ghost']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n:host([variant='danger']) {\n --wui-button-color: var(--wui-color-danger, #dc2626);\n --wui-button-bg: color-mix(in srgb, var(--wui-color-danger, #dc2626) 18%, var(--wui-color-surface, #fff));\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-color-danger, #dc2626) 26%, var(--wui-color-surface, #fff));\n --wui-button-bg-active: color-mix(in srgb, var(--wui-color-danger, #dc2626) 45%, var(--wui-color-surface, #fff));\n}\n\n/* .wui-glass 样式由 @/assets/glass.css 提供 */\n:host([variant='glass']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n\n /* standalone glass 底色由 .wui-glass 提供;hover/active 需要还原玻璃底,避免被按钮状态色整块替换 */\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-surface-glass-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n --wui-button-bg-active: var(\n --wui-color-surface-glass-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n}\n\nbutton.is-grouped {\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n.group-divider {\n position: absolute;\n z-index: 1;\n top: 50%;\n right: -2px;\n transform: translateY(-50%);\n\n width: 1px;\n height: 24px;\n\n background-color: var(--wui-color-border, rgb(0 0 0 / 0.1));\n}\n\n.group-divider.vertical {\n top: auto;\n right: auto;\n bottom: -2px;\n left: 50%;\n transform: translateX(-50%);\n\n width: 24px;\n height: 1px;\n}\n"],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement } from 'lit';
|
|
1
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
2
2
|
declare const WebUiCheckbox_base: {
|
|
3
3
|
new (...args: any[]): {
|
|
4
4
|
formResetCallback(): void;
|
|
@@ -364,9 +364,11 @@ declare const WebUiCheckbox_base: {
|
|
|
364
364
|
formAssociated: boolean;
|
|
365
365
|
} & typeof LitElement;
|
|
366
366
|
export declare class WebUiCheckbox extends WebUiCheckbox_base {
|
|
367
|
-
static styles: import('lit').CSSResult;
|
|
367
|
+
static styles: import('lit').CSSResult[];
|
|
368
368
|
private readonly _groupManagement;
|
|
369
369
|
private _checked;
|
|
370
|
+
/** 描边收回期间把勾按在可见档,见 willUpdate。 */
|
|
371
|
+
private _retracting;
|
|
370
372
|
get checked(): boolean;
|
|
371
373
|
set checked(v: boolean);
|
|
372
374
|
value: string;
|
|
@@ -377,9 +379,14 @@ export declare class WebUiCheckbox extends WebUiCheckbox_base {
|
|
|
377
379
|
private get _isManagedByGroup();
|
|
378
380
|
private readonly _formAssociation;
|
|
379
381
|
private readonly _formAssociationController;
|
|
382
|
+
private readonly _drawLines?;
|
|
383
|
+
/** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */
|
|
384
|
+
private _drawDurationMs;
|
|
380
385
|
private _syncValidity;
|
|
381
386
|
private handleClick;
|
|
382
387
|
private handleKeyDown;
|
|
388
|
+
willUpdate(changed: PropertyValues): void;
|
|
389
|
+
updated(changed: PropertyValues): void;
|
|
383
390
|
render(): import('lit').TemplateResult<1>;
|
|
384
391
|
readonly $events: {
|
|
385
392
|
input: Event;
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
|
-
import "
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { defineGroupManaged as
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
2
|
+
import { FormAssociated as t, FormAssociationController as n, defineFormAssociation as r } from "../../shared/form-association/index.js";
|
|
3
|
+
import { parseDuration as i } from "../../shared/theme/duration.js";
|
|
4
|
+
import { installPointerFocusSuppression as a } from "../../shared/focus/pointer-focus.js";
|
|
5
|
+
import { defineGroupManaged as o, selectionGroupContextKey as s } from "../../shared/group-management/index.js";
|
|
6
|
+
import c from "../../assets/selection-control.js";
|
|
7
|
+
import { prefersReducedMotion as l } from "../../shared/theme/reduced-motion.js";
|
|
8
|
+
import "../svg-draw-lines/index.js";
|
|
9
|
+
import u from "./style.js";
|
|
10
|
+
import { LitElement as d, html as f, unsafeCSS as p } from "lit";
|
|
11
|
+
import { customElement as m, property as h, query as g, state as _ } from "lit/decorators.js";
|
|
12
|
+
import { classMap as v } from "lit/directives/class-map.js";
|
|
10
13
|
//#region src/components/checkbox/index.ts
|
|
11
|
-
|
|
14
|
+
a();
|
|
15
|
+
function y(e) {
|
|
16
|
+
let t = i(getComputedStyle(e).getPropertyValue("--wui-duration-trigger"));
|
|
17
|
+
return t === null ? 160 : Math.max(0, t);
|
|
18
|
+
}
|
|
19
|
+
var b = class extends t(d) {
|
|
12
20
|
constructor(...e) {
|
|
13
|
-
super(...e), this._groupManagement =
|
|
14
|
-
context:
|
|
21
|
+
super(...e), this._groupManagement = o(this, {
|
|
22
|
+
context: s,
|
|
15
23
|
requestUpdate: () => this.requestUpdate()
|
|
16
|
-
}).make(), this._checked = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation =
|
|
24
|
+
}).make(), this._checked = !1, this._retracting = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation = r({
|
|
17
25
|
host: this,
|
|
18
26
|
initialize: () => {
|
|
19
27
|
this.hasAttribute("checked") && (this._checked = !0);
|
|
@@ -29,10 +37,10 @@ var h = class extends n(c) {
|
|
|
29
37
|
},
|
|
30
38
|
isStateManaged: () => this._isManagedByGroup,
|
|
31
39
|
syncValidity: () => this._syncValidity()
|
|
32
|
-
}).make(), this._formAssociationController = new
|
|
40
|
+
}).make(), this._formAssociationController = new n(this, this._formAssociation), this._drawDurationMs = 160;
|
|
33
41
|
}
|
|
34
42
|
static {
|
|
35
|
-
this.styles =
|
|
43
|
+
this.styles = [p(c), p(u)];
|
|
36
44
|
}
|
|
37
45
|
get checked() {
|
|
38
46
|
return this._checked;
|
|
@@ -73,15 +81,26 @@ var h = class extends n(c) {
|
|
|
73
81
|
handleKeyDown(e) {
|
|
74
82
|
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.handleClick());
|
|
75
83
|
}
|
|
84
|
+
willUpdate(e) {
|
|
85
|
+
super.willUpdate(e), this._drawDurationMs = y(this);
|
|
86
|
+
let t = e.get("_checked");
|
|
87
|
+
typeof t == "boolean" && (this._retracting = t && !l(this));
|
|
88
|
+
}
|
|
89
|
+
updated(e) {
|
|
90
|
+
super.updated(e);
|
|
91
|
+
let t = e.get("_checked");
|
|
92
|
+
typeof t == "boolean" && (t ? this._drawLines?.replay({ reverse: !0 }) : this._drawLines?.replay());
|
|
93
|
+
}
|
|
76
94
|
render() {
|
|
77
95
|
let e = {
|
|
78
96
|
"wui-checkbox": !0,
|
|
79
97
|
"is-checked": this._checked,
|
|
98
|
+
"is-retracting": this._retracting,
|
|
80
99
|
"is-disabled": this._isDisabled
|
|
81
100
|
};
|
|
82
|
-
return
|
|
101
|
+
return f`
|
|
83
102
|
<label
|
|
84
|
-
class=${
|
|
103
|
+
class=${v(e)}
|
|
85
104
|
tabindex=${this._isDisabled ? "-1" : "0"}
|
|
86
105
|
role="checkbox"
|
|
87
106
|
aria-checked=${String(this._checked)}
|
|
@@ -91,11 +110,16 @@ var h = class extends n(c) {
|
|
|
91
110
|
>
|
|
92
111
|
<span class="wui-checkbox-box">
|
|
93
112
|
<span class="wui-checkbox-icon"
|
|
94
|
-
><web-ui-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
113
|
+
><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay
|
|
114
|
+
><svg class="wui-checkbox-check" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
115
|
+
<path
|
|
116
|
+
d="M5 12.5l4.5 4.5L19 7"
|
|
117
|
+
fill="none"
|
|
118
|
+
stroke="currentColor"
|
|
119
|
+
stroke-width="3"
|
|
120
|
+
stroke-linecap="round"
|
|
121
|
+
stroke-linejoin="round"
|
|
122
|
+
/></svg></web-ui-svg-draw-lines
|
|
99
123
|
></span>
|
|
100
124
|
</span>
|
|
101
125
|
<span class="wui-checkbox-label"><slot></slot></span>
|
|
@@ -103,17 +127,17 @@ var h = class extends n(c) {
|
|
|
103
127
|
`;
|
|
104
128
|
}
|
|
105
129
|
};
|
|
106
|
-
e([
|
|
130
|
+
e([_()], b.prototype, "_checked", void 0), e([_()], b.prototype, "_retracting", void 0), e([h({ type: String })], b.prototype, "value", void 0), e([h({
|
|
107
131
|
type: String,
|
|
108
132
|
reflect: !0
|
|
109
|
-
})],
|
|
133
|
+
})], b.prototype, "name", void 0), e([h({
|
|
110
134
|
type: Boolean,
|
|
111
135
|
reflect: !0
|
|
112
|
-
})],
|
|
136
|
+
})], b.prototype, "disabled", void 0), e([h({
|
|
113
137
|
type: Boolean,
|
|
114
138
|
reflect: !0
|
|
115
|
-
})],
|
|
139
|
+
})], b.prototype, "required", void 0), e([g("web-ui-svg-draw-lines")], b.prototype, "_drawLines", void 0), b = e([m("web-ui-checkbox")], b);
|
|
116
140
|
//#endregion
|
|
117
|
-
export {
|
|
141
|
+
export { b as WebUiCheckbox };
|
|
118
142
|
|
|
119
143
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/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'\n\nimport '@/components/
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport selectionControl from '@/assets/selection-control.css?inline'\nimport { WebUiSvgDrawLines } from '@/components/svg-draw-lines'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\nimport { parseDuration } from '@/shared/theme/duration'\nimport { prefersReducedMotion } from '@/shared/theme/reduced-motion'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n/*\n * 描边时长取 `--wui-duration-trigger`,让勾和指示器底色那条 transition 落在同一拍。\n * 读不到 token 或格式不符时兜底 160,负值钳到 0。\n */\nfunction triggerDuration(el: HTMLElement): number {\n const parsed = parseDuration(getComputedStyle(el).getPropertyValue('--wui-duration-trigger'))\n return parsed === null ? 160 : Math.max(0, parsed)\n}\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(selectionControl), unsafeCSS(style)]\n private readonly _groupManagement = defineGroupManaged<SelectionGroupContext>(this, {\n context: selectionGroupContextKey,\n requestUpdate: () => this.requestUpdate()\n }).make()\n\n @state() private _checked = false\n\n /** 描边收回期间把勾按在可见档,见 willUpdate。 */\n @state() private _retracting = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return (\n this.disabled || this._formAssociation.isFormDisabled() || this._groupManagement.getContext()?.disabled === true\n )\n }\n\n private get _isManagedByGroup(): boolean {\n return this._groupManagement.getContext() !== undefined\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (!this._isManagedByGroup && this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n isStateManaged: () => this._isManagedByGroup,\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n @query('web-ui-svg-draw-lines') private readonly _drawLines?: WebUiSvgDrawLines\n\n /** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */\n private _drawDurationMs = 160\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请选择此项')\n }\n\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n // group-managed 时事件不冒泡/不组合,由 group 统一派发一次 host 事件,避免同名事件外泄\n const opts: EventInit = this._isManagedByGroup\n ? { bubbles: false, composed: false }\n : { bubbles: true, composed: true }\n this.dispatchEvent(new Event('input', opts))\n this.dispatchEvent(new Event('change', opts))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n /*\n * 收回期间勾要留在可见档,否则 160ms 淡出抢在描边收回之前把它藏掉。翻转放在 willUpdate:\n * 与 checked 同一次 update 落地,渲染后不再改状态。收回的终点是留在内联样式上的空白,所以这一位\n * 不需要在动画结束后复位,下一次勾选会清掉;reduced motion 下收回根本不跑,按住可见位就是把勾\n * 永久留在未勾选的框里,所以那里必须让位给淡出。\n */\n override willUpdate(changed: PropertyValues) {\n super.willUpdate(changed)\n this._drawDurationMs = triggerDuration(this)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked === 'boolean') {\n this._retracting = wasChecked && !prefersReducedMotion(this)\n }\n }\n\n /*\n * 挂载时就勾选是初始状态而非用户勾选,不画线:_checked 的字段初始化器在构造阶段写过一次,\n * Lit 对同一轮里已记录过旧值的键不再覆盖,所以首帧拿到的是 undefined,之后的每次真实切换才带\n * boolean 旧值——包括 group 在子项首帧前把选中态写回去那一种。\n */\n override updated(changed: PropertyValues) {\n super.updated(changed)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked !== 'boolean') return\n\n if (wasChecked) void this._drawLines?.replay({ reverse: true })\n else void this._drawLines?.replay()\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-retracting': this._retracting,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"checkbox\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-checkbox-box\">\n <span class=\"wui-checkbox-icon\"\n ><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay\n ><svg class=\"wui-checkbox-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n d=\"M5 12.5l4.5 4.5L19 7\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n /></svg></web-ui-svg-draw-lines\n ></span>\n </span>\n <span class=\"wui-checkbox-label\"><slot></slot></span>\n </label>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox': WebUiCheckbox\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/checkbox/style.css?inline
|
|
2
|
-
var e = "
|
|
2
|
+
var e = ".wui-checkbox-box{border-radius:var(--wui-internal-checkbox-radius,6px)}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#08f);background-color:var(--wui-color-accent,#08f)}.wui-checkbox-icon{opacity:0;transition:opacity var(--wui-duration-trigger,.16s) ease;font-size:0;line-height:0;display:block;overflow:hidden}.is-checked .wui-checkbox-icon,.is-retracting .wui-checkbox-icon{opacity:1}.wui-checkbox-check{width:var(--wui-selection-control-size,18px);height:var(--wui-selection-control-size,18px);color:var(--wui-color-on-control,#fff);display:block}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":[".wui-checkbox-box {\n border-radius: var(--wui-internal-checkbox-radius, 6px);\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #08f);\n background-color: var(--wui-color-accent, #08f);\n}\n\n.wui-checkbox-icon {\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition: opacity var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * is-retracting 是描边收回的那一段:勾得留在可见档,否则这条 160ms 的淡出会抢在收回结束之前\n * 把它藏掉,收回根本看不见。收回的终点是留在内联样式上的「整条路径落在 dash 间隙里」,动画自己\n * 收尾就撤销了,所以停在这里就是看不见的勾,不必再等一次淡出;复位由下一次勾选负责(见 index.ts 的 willUpdate)。\n */\n.is-checked .wui-checkbox-icon,\n.is-retracting .wui-checkbox-icon {\n opacity: 1;\n}\n\n/*\n * 勾是控件自持的指示几何,和 radio 圆点同级,不走 @/icons 资产:画线从路径起点开始揭示,\n * 起笔方向由 d 决定,图标资产把 d 和 stroke-width 都定死在上游,两者都无法在这里调。\n * 尺寸跟随指示器 token,放大 --wui-selection-control-size 时勾按比例变大。\n */\n.wui-checkbox-check {\n display: block;\n width: var(--wui-selection-control-size, 18px);\n height: var(--wui-selection-control-size, 18px);\n color: var(--wui-color-on-control, #fff);\n}\n"],"mappings":""}
|
|
@@ -368,6 +368,9 @@ export declare class WebUiCheckboxGroup extends WebUiCheckboxGroup_base {
|
|
|
368
368
|
name: string;
|
|
369
369
|
disabled: boolean;
|
|
370
370
|
required: boolean;
|
|
371
|
+
get direction(): 'horizontal' | 'vertical';
|
|
372
|
+
set direction(v: string);
|
|
373
|
+
private _direction;
|
|
371
374
|
private _value;
|
|
372
375
|
private readonly _groupController;
|
|
373
376
|
get value(): string[];
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
2
|
import { FormAssociated as t, FormAssociationController as n, defineFormAssociation as r } from "../../shared/form-association/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import o from "
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
3
|
+
import { normalizeLiteral as i } from "../../shared/normalize/index.js";
|
|
4
|
+
import { GroupController as a, defineGroupCoordinator as o } from "../../shared/group-management/index.js";
|
|
5
|
+
import s from "./style.js";
|
|
6
|
+
import { LitElement as c, html as l, unsafeCSS as u } from "lit";
|
|
7
|
+
import { customElement as d, property as f, state as p } from "lit/decorators.js";
|
|
7
8
|
//#region src/components/checkbox-group/index.ts
|
|
8
|
-
var
|
|
9
|
+
var m = ["horizontal", "vertical"], h = class extends t(c) {
|
|
9
10
|
constructor(...e) {
|
|
10
|
-
super(...e), this.name = "", this.disabled = !1, this.required = !1, this._value = [], this._groupController = new
|
|
11
|
+
super(...e), this.name = "", this.disabled = !1, this.required = !1, this._direction = "vertical", this._value = [], this._groupController = new a(this, o({
|
|
11
12
|
host: this,
|
|
12
13
|
getItems: () => [...this.querySelectorAll("web-ui-checkbox")],
|
|
13
14
|
getValue: () => this._value,
|
|
@@ -59,7 +60,14 @@ var p = class extends t(s) {
|
|
|
59
60
|
}).make(), this._formAssociationController = new n(this, this._formAssociation);
|
|
60
61
|
}
|
|
61
62
|
static {
|
|
62
|
-
this.styles =
|
|
63
|
+
this.styles = u(s);
|
|
64
|
+
}
|
|
65
|
+
get direction() {
|
|
66
|
+
return this._direction;
|
|
67
|
+
}
|
|
68
|
+
set direction(e) {
|
|
69
|
+
let t = this._direction;
|
|
70
|
+
this._direction = i(e, m, "vertical"), this.requestUpdate("direction", t);
|
|
63
71
|
}
|
|
64
72
|
get value() {
|
|
65
73
|
return this._value;
|
|
@@ -85,20 +93,23 @@ var p = class extends t(s) {
|
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
95
|
render() {
|
|
88
|
-
return
|
|
96
|
+
return l`<div class="wui-checkbox-group"><slot></slot></div>`;
|
|
89
97
|
}
|
|
90
98
|
};
|
|
91
|
-
e([
|
|
99
|
+
e([f({
|
|
92
100
|
type: String,
|
|
93
101
|
reflect: !0
|
|
94
|
-
})],
|
|
102
|
+
})], h.prototype, "name", void 0), e([f({
|
|
95
103
|
type: Boolean,
|
|
96
104
|
reflect: !0
|
|
97
|
-
})],
|
|
105
|
+
})], h.prototype, "disabled", void 0), e([f({
|
|
98
106
|
type: Boolean,
|
|
99
107
|
reflect: !0
|
|
100
|
-
})],
|
|
108
|
+
})], h.prototype, "required", void 0), e([f({
|
|
109
|
+
type: String,
|
|
110
|
+
reflect: !0
|
|
111
|
+
})], h.prototype, "direction", null), e([p()], h.prototype, "_value", void 0), h = e([d("web-ui-checkbox-group")], h);
|
|
101
112
|
//#endregion
|
|
102
|
-
export {
|
|
113
|
+
export { h as WebUiCheckboxGroup };
|
|
103
114
|
|
|
104
115
|
//# sourceMappingURL=index.js.map
|