@greypan/web-ui 6.4.0 → 8.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 +211 -50
- package/README.md +222 -61
- 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 +19 -5
- package/dist/components/autocomplete/index.js +142 -108
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/autocomplete/style.js +1 -1
- package/dist/components/autocomplete/style.js.map +1 -1
- package/dist/components/avatar/index.js +4 -4
- package/dist/components/badge/style.js.map +1 -1
- package/dist/components/button/index.js +15 -15
- package/dist/components/button/style.js.map +1 -1
- package/dist/components/button-group/index.js +5 -5
- 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 +27 -16
- 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 +51 -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 +49 -21
- 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 +141 -110
- 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 +77 -51
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/editable-text/index.d.ts +471 -0
- package/dist/components/editable-text/index.js +206 -0
- package/dist/components/editable-text/index.js.map +1 -0
- package/dist/components/editable-text/style.js +6 -0
- package/dist/components/editable-text/style.js.map +1 -0
- package/dist/components/image-preview/index.js +103 -80
- 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.d.ts +1 -0
- package/dist/components/index.js +39 -38
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +12 -6
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input/style.js.map +1 -1
- package/dist/components/input-number/index.js +15 -15
- package/dist/components/layout/index.js +9 -9
- 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 +53 -55
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/radio/index.d.ts +1 -1
- package/dist/components/radio/index.js +22 -21
- 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 +27 -16
- 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/index.d.ts +4 -1
- package/dist/components/segmented/index.js +42 -29
- package/dist/components/segmented/index.js.map +1 -1
- package/dist/components/segmented/style.js +1 -1
- package/dist/components/segmented/style.js.map +1 -1
- package/dist/components/segmented-trigger/style.js +1 -1
- package/dist/components/segmented-trigger/style.js.map +1 -1
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +38 -34
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/slider/index.js +11 -11
- 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 +12 -12
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/switch/style.js.map +1 -1
- package/dist/components/textarea/index.js +6 -6
- 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 +15 -0
- package/dist/components/theme/index.js +178 -21
- 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 +74 -21
- 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 +21 -19
- 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 +48 -7
- package/dist/shared/option-portal/combobox-shell.js.map +1 -1
- package/dist/shared/option-portal/index.js +9 -9
- 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 +198 -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/dist/shared/theme/root-sync.js +42 -0
- package/dist/shared/theme/root-sync.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/popover/index.ts"],"sourcesContent":["import type { Placement } from '@floating-ui/dom'\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { overlayComposition } from '@/shared/overlay/composition'\nimport { defineOverlayLifecycle } from '@/shared/overlay/lifecycle'\nimport { FLOATING_PLACEMENTS } from '@/shared/overlay/placement-props'\nimport { defineOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_TRIGGERS = ['click', 'hover', 'manual'] as const\n\nlet popoverIdCounter = 0\n\n@customElement('web-ui-popover')\nexport class WebUiPopover extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true }) disabled = false\n\n @property({ type: String, reflect: true })\n get placement(): Placement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, FLOATING_PLACEMENTS, 'bottom')\n this.requestUpdate('placement', old)\n }\n private _placement: Placement = 'bottom'\n\n @property({ type: Number })\n get offset(): number {\n return this._offset\n }\n set offset(v: number) {\n const old = this._offset\n this._offset = normalizeNumber(v, 0, 100, 8)\n this.requestUpdate('offset', old)\n }\n private _offset = 8\n\n @property({ type: String, reflect: true })\n get trigger(): 'click' | 'hover' | 'manual' {\n return this._trigger\n }\n set trigger(v: string) {\n const old = this._trigger\n this._trigger = normalizeLiteral(v, ALLOWED_TRIGGERS, 'click')\n this.requestUpdate('trigger', old)\n }\n private _trigger: 'click' | 'hover' | 'manual' = 'click'\n\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n\n private _showTimer?: ReturnType<typeof setTimeout>\n private _hideTimer?: ReturnType<typeof setTimeout>\n private readonly _userOpenChange = new UserChangeController()\n private _shouldOpenInstantly = true\n\n private _panelId = `wui-popover-panel-${++popoverIdCounter}`\n private _portal?: OverlayPortal\n private readonly _lifecycle = defineOverlayLifecycle().make({\n isConnected: () => this.isConnected,\n isOpen: () => this.open\n })\n private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.popover-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.popover-panel') ?? null,\n getPositioning: () => ({\n placement: this.placement,\n offset: this.offset,\n strategy: this.portal ? 'fixed' : 'absolute'\n }),\n isPortal: () => this.portal,\n createPortal: () => this._createPortal()\n })\n\n get isOpen(): boolean {\n return this.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._lifecycle.resume()\n document.addEventListener('click', this._onClickOutside)\n document.addEventListener('keydown', this._onKeydown)\n this.addEventListener('focusout', this._onFocusOut)\n this._syncTriggerListeners()\n }\n\n override firstUpdated() {\n // trigger slot 内容增删不触发宿主响应式更新:显式请求一轮渲染,\n // 由 updated() 的 ARIA 回写覆盖晚到的 trigger 元素。\n this.shadowRoot\n ?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')\n ?.addEventListener('slotchange', () => this.requestUpdate())\n\n if (this.open) {\n this._lifecycle.scheduleFrame(\n () => {\n this._openOverlay(this._shouldOpenInstantly)\n },\n { expectedOpen: true }\n )\n this._shouldOpenInstantly = true\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n document.removeEventListener('click', this._onClickOutside)\n document.removeEventListener('keydown', this._onKeydown)\n this.removeEventListener('focusout', this._onFocusOut)\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n this._lifecycle.dispose()\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._panel.dispose()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // ARIA 回写不依赖 open 分支,任何渲染后都保持与宿主状态同步。\n this._syncTriggerAria()\n\n if (changed.has('portal') || changed.has('overlayContainer')) {\n // 同帧 open + reconfigure 可能排两个回调;先结束旧事务,让 reconfigure 成为本帧唯一入口。\n this._lifecycle.invalidate()\n this._lifecycle.scheduleFrame(() => this._reconfigureOverlay())\n } else if (changed.has('placement') || changed.has('offset'))\n requestAnimationFrame(() => this._panel.updatePosition())\n\n if (changed.has('open')) {\n if (this.open) {\n const isInstant = this._shouldOpenInstantly\n this._shouldOpenInstantly = true\n this._lifecycle.scheduleFrame(\n () => {\n this._openOverlay(isInstant)\n },\n { expectedOpen: true }\n )\n if (this._userOpenChange.consume()) this._dispatchChange(true)\n this._focusPanel()\n } else {\n this._lifecycle.invalidate()\n this._returnFocus()\n void this._closeOverlay()\n if (this._userOpenChange.consume()) this._dispatchChange(false)\n }\n }\n\n if (changed.has('trigger')) {\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._syncTriggerListeners()\n }\n }\n\n show() {\n if (this.disabled || this.open) return\n this.open = true\n }\n\n close() {\n if (!this.open) return\n this.open = false\n }\n\n toggle() {\n if (this.open) this.close()\n else this.show()\n }\n\n private _isInsideShadowRoot(e: MouseEvent): boolean {\n for (const node of e.composedPath()) {\n if (node instanceof Node && node.getRootNode() === this.shadowRoot) return true\n }\n return false\n }\n\n private _syncTriggerListeners() {\n if (this.trigger === 'hover') {\n this.addEventListener('pointerenter', this._onPointerEnter)\n this.addEventListener('pointerleave', this._onPointerLeave)\n }\n }\n\n private _openOverlay(isInstant = false) {\n this._panel.open(isInstant)\n const panel = this._panel.getPanel()\n // popover host 才是稳定组合 owner:trigger 可能被 slot 重定向,portal 面板与宿主分离。\n if (panel) overlayComposition.registerPanelFromAncestry(panel, this)\n }\n\n private _migratableContentNodes(nodes: Node[]): Node[] {\n // 框架注释锚点(v-if/v-for 占位)必须留在宿主:面板内容是实时渲染契约,\n // 框架后续 patch 以宿主内锚点为插入基准,锚点进面板会让插入落空。\n return nodes.filter(node => !(node instanceof Comment) && !(node instanceof HTMLElement && node.slot === 'trigger'))\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: 'popover-panel portal wui-glass wui-floating-panel',\n // 已迁移节点被框架删除后的解除追踪是 portal 内建默认行为,这里无需 onContentChange\n migrateAddedNodes: addedNodes => this._migratableContentNodes(addedNodes)\n })\n this._portal = portal\n portal.panel.id = this._panelId\n portal.panel.setAttribute('role', 'dialog')\n portal.panel.tabIndex = -1\n portal.panel.addEventListener('pointerenter', this._onPanelPointerEnter)\n portal.panel.addEventListener('pointerleave', this._onPanelPointerLeave)\n portal.moveContent(this._migratableContentNodes(Array.from(this.childNodes)))\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n // portal 变更也会登记 rAF;宿主卸载后不得再通过 reconfigure 重建面板。\n if (!this.isConnected) return\n this._panel.reconfigure(this.open)\n }\n\n private _dispatchChange(open: boolean) {\n dispatchOpenChangeEvent(this, open)\n }\n\n /*\n * trigger 包装 div 不可聚焦,AT 读不到其 aria 状态:把 aria-expanded /\n * aria-controls 同步回写到 trigger slot 的首个 assigned element(Q8a)。\n * 包装 div 上的同名属性保留(additive,兼容既有查询)。\n */\n private _syncTriggerAria() {\n const trigger = this._queryTrigger()\n if (!trigger) return\n trigger.setAttribute('aria-expanded', String(this.open))\n trigger.setAttribute('aria-controls', this._panelId)\n }\n\n private _focusPanel() {\n this._lifecycle.scheduleFrame(\n () => {\n const panel = this._panel.getPanel()\n const autofocus = panel?.querySelector<HTMLElement>('[autofocus]')\n if (autofocus && !autofocus.matches(':disabled, [disabled]')) autofocus.focus()\n },\n { expectedOpen: true }\n )\n }\n\n private _returnFocus() {\n const panel = this._panel.getPanel()\n if (!panel?.matches(':focus-within')) return\n const trigger = this._queryTrigger()\n trigger?.focus()\n }\n\n private _queryTrigger(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')\n const el = slot?.assignedElements()[0]\n return el instanceof HTMLElement ? el : null\n }\n\n private _onTriggerClick = (event: MouseEvent) => {\n if (this.disabled) return\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n if (this.trigger === 'hover') return\n if (!this.open) this._shouldOpenInstantly = event.detail === 0\n this._userOpenChange.mark()\n this.toggle()\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this.open) return\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n const panel = this._panel.getPanel()\n if (panel && overlayComposition.containsEvent(panel, e)) return\n if (this._isInsideShadowRoot(e)) return\n this._userOpenChange.mark()\n this.open = false\n }\n\n private _onFocusOut = () => {\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n\n this._lifecycle.scheduleFrame(\n () => {\n const panel = this._panel.getPanel()\n if (!this.matches(':focus-within') && !(panel && overlayComposition.hasFocusWithin(panel))) {\n this._userOpenChange.mark()\n this.open = false\n }\n },\n { expectedOpen: true }\n )\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (!this.open) return\n if (this.trigger === 'manual') return\n if (e.key === 'Escape') {\n this._userOpenChange.mark()\n this.open = false\n e.preventDefault()\n }\n }\n\n private _onPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled || this.trigger !== 'hover') return\n clearTimeout(this._hideTimer)\n this._showTimer = setTimeout(() => {\n this._shouldOpenInstantly = false\n if (this.open) return\n this._userOpenChange.mark()\n this.show()\n }, 100)\n }\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled || this.trigger !== 'hover') return\n clearTimeout(this._showTimer)\n this._hideTimer = setTimeout(() => {\n if (!this.open) return\n this._userOpenChange.mark()\n this.close()\n }, 100)\n }\n\n private _onPanelPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.trigger !== 'hover') return\n clearTimeout(this._hideTimer)\n }\n\n private _onPanelPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.trigger !== 'hover') return\n this._hideTimer = setTimeout(() => {\n if (!this.open) return\n this._userOpenChange.mark()\n this.close()\n }, 100)\n }\n\n override render() {\n return html`\n <div class=\"popover-anchor\">\n <div\n class=\"popover-trigger\"\n aria-expanded=${String(this.open)}\n aria-controls=${this._panelId}\n @click=${this._onTriggerClick}\n >\n <slot name=\"trigger\"></slot>\n </div>\n <div\n id=${this._panelId}\n class=\"popover-panel wui-floating-panel wui-glass\"\n hidden\n role=\"dialog\"\n tabindex=\"-1\"\n @pointerenter=${this._onPanelPointerEnter}\n @pointerleave=${this._onPanelPointerLeave}\n >\n <slot></slot>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-popover': WebUiPopover\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/popover/index.ts"],"sourcesContent":["import type { Placement } from '@floating-ui/dom'\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOpenOverlay } from '@/shared/overlay/open-overlay'\nimport { FLOATING_PLACEMENTS } from '@/shared/overlay/placement-props'\nimport { defineOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_TRIGGERS = ['click', 'hover', 'manual'] as const\n\nlet popoverIdCounter = 0\n\n@customElement('web-ui-popover')\nexport class WebUiPopover extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true }) disabled = false\n\n @property({ type: String, reflect: true })\n get placement(): Placement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, FLOATING_PLACEMENTS, 'bottom')\n this.requestUpdate('placement', old)\n }\n private _placement: Placement = 'bottom'\n\n @property({ type: Number })\n get offset(): number {\n return this._offset\n }\n set offset(v: number) {\n const old = this._offset\n this._offset = normalizeNumber(v, 0, 100, 8)\n this.requestUpdate('offset', old)\n }\n private _offset = 8\n\n @property({ type: String, reflect: true })\n get trigger(): 'click' | 'hover' | 'manual' {\n return this._trigger\n }\n set trigger(v: string) {\n const old = this._trigger\n this._trigger = normalizeLiteral(v, ALLOWED_TRIGGERS, 'click')\n this.requestUpdate('trigger', old)\n }\n private _trigger: 'click' | 'hover' | 'manual' = 'click'\n\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n\n private _showTimer?: ReturnType<typeof setTimeout>\n private _hideTimer?: ReturnType<typeof setTimeout>\n private readonly _userOpenChange = new UserChangeController()\n private _shouldOpenInstantly = true\n\n private _panelId = `wui-popover-panel-${++popoverIdCounter}`\n private _portal?: OverlayPortal\n /**\n * 开启态浮层(issue #120 Block 1):本组件不再自行监听 keydown,只声明「我开着」,\n * 由唯一仲裁者决定一次 Escape 关谁。实例作用域的帧事务入口也在这里(合并了原\n * lifecycle)—— 它的 lifetime 长于一次开合(跨 `suspend()`/`resume()`),\n * 但不长于实例本身。\n */\n private readonly _overlay = defineOpenOverlay().make({\n requestClose: () => {\n this._userOpenChange.mark()\n this.open = false\n },\n isConnected: () => this.isConnected\n })\n private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.popover-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.popover-panel') ?? null,\n getPositioning: () => ({\n placement: this.placement,\n offset: this.offset,\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.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._overlay.resume()\n document.addEventListener('click', this._onClickOutside)\n this.addEventListener('focusout', this._onFocusOut)\n this._syncTriggerListeners()\n }\n\n override firstUpdated() {\n // trigger slot 内容增删不触发宿主响应式更新:显式请求一轮渲染,\n // 由 updated() 的 ARIA 回写覆盖晚到的 trigger 元素。\n this.shadowRoot\n ?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')\n ?.addEventListener('slotchange', () => this.requestUpdate())\n\n if (this.open) {\n // 建立会话的那一帧没有句柄可作 liveness 凭据:关闭路径会 invalidate()(见 updated),\n // 微任务先于 rAF 排空,因此该帧不可能跨过一次关闭执行。\n this._overlay.scheduleFrame(() => {\n this._openOverlay(this._shouldOpenInstantly)\n })\n this._shouldOpenInstantly = true\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n document.removeEventListener('click', this._onClickOutside)\n this.removeEventListener('focusout', this._onFocusOut)\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n // 停止帧调度;撤销登记由 _panel.dispose() 完成(句柄归它持有)。\n this._overlay.suspend()\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._panel.dispose()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // ARIA 回写不依赖 open 分支,任何渲染后都保持与宿主状态同步。\n this._syncTriggerAria()\n\n if (changed.has('portal') || changed.has('overlayContainer')) {\n // 同帧 open + reconfigure 可能排两个回调;先结束旧事务,让 reconfigure 成为本帧唯一入口。\n this._overlay.invalidate()\n this._overlay.scheduleFrame(() => this._reconfigureOverlay())\n } else if (changed.has('placement') || changed.has('offset'))\n requestAnimationFrame(() => this._panel.updatePosition())\n\n if (changed.has('open')) {\n if (this.open) {\n const isInstant = this._shouldOpenInstantly\n this._shouldOpenInstantly = true\n this._overlay.scheduleFrame(() => {\n this._openOverlay(isInstant)\n })\n if (this._userOpenChange.consume()) this._dispatchChange(true)\n this._focusPanel()\n } else {\n this._overlay.invalidate()\n this._returnFocus()\n void this._closeOverlay()\n if (this._userOpenChange.consume()) this._dispatchChange(false)\n }\n }\n\n if (changed.has('trigger')) {\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._syncTriggerListeners()\n }\n this._syncOverlayInert()\n }\n\n show() {\n if (this.disabled || this.open) return\n this.open = true\n }\n\n close() {\n if (!this.open) return\n this.open = false\n }\n\n toggle() {\n if (this.open) this.close()\n else this.show()\n }\n\n private _isInsideShadowRoot(e: MouseEvent): boolean {\n for (const node of e.composedPath()) {\n if (node instanceof Node && node.getRootNode() === this.shadowRoot) return true\n }\n return false\n }\n\n private _syncTriggerListeners() {\n if (this.trigger === 'hover') {\n this.addEventListener('pointerenter', this._onPointerEnter)\n this.addEventListener('pointerleave', this._onPointerLeave)\n }\n }\n\n /*\n * `manual` 触发器的 popover 不由用户关闭,但仍是候选:Escape 被它吞掉(同时压掉\n * 原生 cancel),只是不走关闭入口。与旧的「跳过候选」语义不同 —— 旧语义放任 Escape\n * 落到下层浮层,把外层一起关掉。trigger 可在开启期间改写,所以走动态通道同步。\n */\n private _syncOverlayInert() {\n this._panel.getHandle()?.setInert(this.trigger === 'manual')\n }\n\n private _openOverlay(isInstant = false) {\n /*\n * 登记与仲裁归属由 anchored panel 完成(claim 要求 panel 已就位,祖先链才判得对)。\n * 原实现在这里额外以宿主为 owner 再登记一次:anchor 是宿主 shadow 内的\n * `.popover-trigger` 包装 div(不是会被 slot 重定向的 trigger 内容),其祖先链上\n * 首个已开启浮层与从宿主上溯结果一致,因此那一次是冗余的。\n */\n this._panel.open(isInstant)\n this._syncOverlayInert()\n }\n\n private _migratableContentNodes(nodes: Node[]): Node[] {\n // 框架注释锚点(v-if/v-for 占位)必须留在宿主:面板内容是实时渲染契约,\n // 框架后续 patch 以宿主内锚点为插入基准,锚点进面板会让插入落空。\n return nodes.filter(node => !(node instanceof Comment) && !(node instanceof HTMLElement && node.slot === 'trigger'))\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: 'popover-panel portal wui-glass wui-floating-panel',\n // 已迁移节点被框架删除后的解除追踪是 portal 内建默认行为,这里无需 onContentChange\n migrateAddedNodes: addedNodes => this._migratableContentNodes(addedNodes)\n })\n this._portal = portal\n portal.panel.id = this._panelId\n portal.panel.setAttribute('role', 'dialog')\n portal.panel.tabIndex = -1\n portal.panel.addEventListener('pointerenter', this._onPanelPointerEnter)\n portal.panel.addEventListener('pointerleave', this._onPanelPointerLeave)\n portal.moveContent(this._migratableContentNodes(Array.from(this.childNodes)))\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n // portal 变更也会登记 rAF;宿主卸载后不得再通过 reconfigure 重建面板。\n if (!this.isConnected) return\n this._panel.reconfigure(this.open)\n /*\n * reconfigure 重新 claim = 新会话,inert 回到 false。这里的重推是**承重的**,不是\n * 防御性备份:`reconfigure` 不触发 Lit 渲染,`updated()` 那次同步不会跟着来。\n * 实测摘掉本行,「portal 变更后 Escape 仍不关闭」立刻转红(select / autocomplete 的\n * 同类重推则被各自的渲染掩盖,摘掉仍绿)。\n */\n this._syncOverlayInert()\n }\n\n private _dispatchChange(open: boolean) {\n dispatchOpenChangeEvent(this, open)\n }\n\n /*\n * trigger 包装 div 不可聚焦,AT 读不到其 aria 状态:把 aria-expanded /\n * aria-controls 同步回写到 trigger slot 的首个 assigned element(Q8a)。\n * 包装 div 上的同名属性保留(additive,兼容既有查询)。\n */\n private _syncTriggerAria() {\n const trigger = this._queryTrigger()\n if (!trigger) return\n trigger.setAttribute('aria-expanded', String(this.open))\n trigger.setAttribute('aria-controls', this._panelId)\n }\n\n private _focusPanel() {\n this._overlay.scheduleFrame(() => {\n const panel = this._panel.getPanel()\n const autofocus = panel?.querySelector<HTMLElement>('[autofocus]')\n if (autofocus && !autofocus.matches(':disabled, [disabled]')) autofocus.focus()\n })\n }\n\n private _returnFocus() {\n const panel = this._panel.getPanel()\n if (!panel?.matches(':focus-within')) return\n const trigger = this._queryTrigger()\n trigger?.focus()\n }\n\n private _queryTrigger(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]')\n const el = slot?.assignedElements()[0]\n return el instanceof HTMLElement ? el : null\n }\n\n private _onTriggerClick = (event: MouseEvent) => {\n if (this.disabled) return\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n if (this.trigger === 'hover') return\n if (!this.open) this._shouldOpenInstantly = event.detail === 0\n this._userOpenChange.mark()\n this.toggle()\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this.open) return\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n // 在监听器内部判定:composedPath() 在派发结束后会被清空。\n if (this._panel.getHandle()?.containsEvent(e)) return\n if (this._isInsideShadowRoot(e)) return\n this._userOpenChange.mark()\n this.open = false\n }\n\n private _onFocusOut = () => {\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n\n this._overlay.scheduleFrame(() => {\n if (!this.matches(':focus-within') && !this._panel.getHandle()?.hasFocusWithin()) {\n this._userOpenChange.mark()\n this.open = false\n }\n })\n }\n\n private _onPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled || this.trigger !== 'hover') return\n clearTimeout(this._hideTimer)\n this._showTimer = setTimeout(() => {\n this._shouldOpenInstantly = false\n if (this.open) return\n this._userOpenChange.mark()\n this.show()\n }, 100)\n }\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled || this.trigger !== 'hover') return\n clearTimeout(this._showTimer)\n this._hideTimer = setTimeout(() => {\n if (!this.open) return\n this._userOpenChange.mark()\n this.close()\n }, 100)\n }\n\n private _onPanelPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.trigger !== 'hover') return\n clearTimeout(this._hideTimer)\n }\n\n private _onPanelPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.trigger !== 'hover') return\n this._hideTimer = setTimeout(() => {\n if (!this.open) return\n this._userOpenChange.mark()\n this.close()\n }, 100)\n }\n\n override render() {\n return html`\n <div class=\"popover-anchor\">\n <div\n class=\"popover-trigger\"\n aria-expanded=${String(this.open)}\n aria-controls=${this._panelId}\n @click=${this._onTriggerClick}\n >\n <slot name=\"trigger\"></slot>\n </div>\n <div\n id=${this._panelId}\n class=\"popover-panel wui-floating-panel wui-glass\"\n hidden\n role=\"dialog\"\n tabindex=\"-1\"\n @pointerenter=${this._onPanelPointerEnter}\n @pointerleave=${this._onPanelPointerLeave}\n >\n <slot></slot>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-popover': WebUiPopover\n }\n}\n"],"mappings":"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"}
|
|
@@ -364,7 +364,7 @@ declare const WebUiRadio_base: {
|
|
|
364
364
|
formAssociated: boolean;
|
|
365
365
|
} & typeof LitElement;
|
|
366
366
|
export declare class WebUiRadio extends WebUiRadio_base {
|
|
367
|
-
static styles: import('lit').CSSResult;
|
|
367
|
+
static styles: import('lit').CSSResult[];
|
|
368
368
|
private readonly _groupManagement;
|
|
369
369
|
private _checked;
|
|
370
370
|
get checked(): boolean;
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import s from "
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { installPointerFocusSuppression as t } from "../../shared/focus/pointer-focus.js";
|
|
3
|
+
import { defineGroupManaged as n, selectionGroupContextKey as r } from "../../shared/group-management/index.js";
|
|
4
|
+
import { FormAssociated as i, FormAssociationController as a, defineFormAssociation as o } from "../../shared/form-association/index.js";
|
|
5
|
+
import s from "../../assets/selection-control.js";
|
|
6
|
+
import c from "./style.js";
|
|
7
|
+
import { LitElement as l, html as u, unsafeCSS as d } from "lit";
|
|
8
|
+
import { customElement as f, property as p, state as m } from "lit/decorators.js";
|
|
9
|
+
import { classMap as h } from "lit/directives/class-map.js";
|
|
9
10
|
//#region src/components/radio/index.ts
|
|
10
|
-
|
|
11
|
-
var
|
|
11
|
+
t();
|
|
12
|
+
var g = class extends i(l) {
|
|
12
13
|
constructor(...e) {
|
|
13
|
-
super(...e), this._groupManagement =
|
|
14
|
-
context:
|
|
14
|
+
super(...e), this._groupManagement = n(this, {
|
|
15
|
+
context: r,
|
|
15
16
|
requestUpdate: () => this.requestUpdate()
|
|
16
|
-
}).make(), this._checked = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation =
|
|
17
|
+
}).make(), this._checked = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation = o({
|
|
17
18
|
host: this,
|
|
18
19
|
initialize: () => {
|
|
19
20
|
this.hasAttribute("checked") && (this._checked = !0);
|
|
@@ -29,10 +30,10 @@ var h = class extends t(c) {
|
|
|
29
30
|
},
|
|
30
31
|
isStateManaged: () => this._isManagedByGroup,
|
|
31
32
|
syncValidity: () => this._syncValidity()
|
|
32
|
-
}).make(), this._formAssociationController = new
|
|
33
|
+
}).make(), this._formAssociationController = new a(this, this._formAssociation);
|
|
33
34
|
}
|
|
34
35
|
static {
|
|
35
|
-
this.styles =
|
|
36
|
+
this.styles = [d(s), d(c)];
|
|
36
37
|
}
|
|
37
38
|
get checked() {
|
|
38
39
|
return this._checked;
|
|
@@ -78,9 +79,9 @@ var h = class extends t(c) {
|
|
|
78
79
|
"is-checked": this._checked,
|
|
79
80
|
"is-disabled": this._isDisabled
|
|
80
81
|
};
|
|
81
|
-
return
|
|
82
|
+
return u`
|
|
82
83
|
<label
|
|
83
|
-
class=${
|
|
84
|
+
class=${h(e)}
|
|
84
85
|
tabindex=${this._isDisabled ? "-1" : "0"}
|
|
85
86
|
role="radio"
|
|
86
87
|
aria-checked=${String(this._checked)}
|
|
@@ -96,17 +97,17 @@ var h = class extends t(c) {
|
|
|
96
97
|
`;
|
|
97
98
|
}
|
|
98
99
|
};
|
|
99
|
-
e([
|
|
100
|
+
e([m()], g.prototype, "_checked", void 0), e([p({ type: String })], g.prototype, "value", void 0), e([p({
|
|
100
101
|
type: String,
|
|
101
102
|
reflect: !0
|
|
102
|
-
})],
|
|
103
|
+
})], g.prototype, "name", void 0), e([p({
|
|
103
104
|
type: Boolean,
|
|
104
105
|
reflect: !0
|
|
105
|
-
})],
|
|
106
|
+
})], g.prototype, "disabled", void 0), e([p({
|
|
106
107
|
type: Boolean,
|
|
107
108
|
reflect: !0
|
|
108
|
-
})],
|
|
109
|
+
})], g.prototype, "required", void 0), g = e([f("web-ui-radio")], g);
|
|
109
110
|
//#endregion
|
|
110
|
-
export {
|
|
111
|
+
export { g as WebUiRadio };
|
|
111
112
|
|
|
112
113
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio/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 { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n@customElement('web-ui-radio')\nexport class WebUiRadio extends FormAssociated(LitElement) {\n static override styles = 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 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 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 || this._checked) return\n this._checked = true\n this._formAssociation.sync()\n this.requestUpdate('checked', false)\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 override render() {\n const cls = {\n 'wui-radio': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"radio\"\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-radio-circle\">\n <span class=\"wui-radio-dot\"></span>\n </span>\n <span class=\"wui-radio-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-radio': WebUiRadio\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio/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 selectionControl from '@/assets/selection-control.css?inline'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n@customElement('web-ui-radio')\nexport class WebUiRadio 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 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 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 || this._checked) return\n this._checked = true\n this._formAssociation.sync()\n this.requestUpdate('checked', false)\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 override render() {\n const cls = {\n 'wui-radio': true,\n 'is-checked': this._checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"radio\"\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-radio-circle\">\n <span class=\"wui-radio-dot\"></span>\n </span>\n <span class=\"wui-radio-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-radio': WebUiRadio\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/radio/style.css?inline
|
|
2
|
-
var e = "
|
|
2
|
+
var e = ".wui-radio-circle{border-radius:var(--wui-radius-control,calc(infinity * 1px))}.is-checked .wui-radio-circle{background-color:var(--wui-color-accent,#08f)}.wui-radio-dot{border-radius:var(--wui-radius-control,calc(infinity * 1px));opacity:0;background-color:var(--wui-color-on-control,#fff);width:6px;height:6px;transition:opacity var(--wui-duration-trigger,.16s) ease, transform var(--wui-duration-trigger,.16s) var(--wui-ease-enter,cubic-bezier(.23, 1, .32, 1));transform:scale(0);box-shadow:inset 0 -1px 2px #0000001f,inset 0 1px 2px #ffffff80,0 0 4px #0088ff4d}.is-checked .wui-radio-dot{opacity:1;transform:scale(1)}@media (prefers-reduced-motion:reduce){.wui-radio-dot,.is-checked .wui-radio-dot{transform:none}}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio/style.css?inline"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio/style.css?inline"],"sourcesContent":[".wui-radio-circle {\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n}\n\n.is-checked .wui-radio-circle {\n background-color: var(--wui-color-accent, #08f);\n}\n\n.wui-radio-dot {\n transform: scale(0);\n\n width: 6px;\n height: 6px;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n opacity: 0;\n background-color: var(--wui-color-on-control, #fff);\n box-shadow:\n inset 0 -1px 2px rgb(0 0 0 / 0.12),\n inset 0 1px 2px rgb(255 255 255 / 0.5),\n 0 0 4px rgb(0 136 255 / 0.3);\n\n transition:\n opacity var(--wui-duration-trigger, 160ms) ease,\n transform var(--wui-duration-trigger, 160ms) var(--wui-ease-enter, cubic-bezier(0.23, 1, 0.32, 1));\n}\n\n.is-checked .wui-radio-dot {\n transform: scale(1);\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .wui-radio-dot,\n .is-checked .wui-radio-dot {\n transform: none;\n }\n}\n"],"mappings":""}
|
|
@@ -368,6 +368,9 @@ export declare class WebUiRadioGroup extends WebUiRadioGroup_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
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import o from "
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
2
|
+
import { GroupController as t, defineGroupCoordinator as n } from "../../shared/group-management/index.js";
|
|
3
|
+
import { normalizeLiteral as r } from "../../shared/normalize/index.js";
|
|
4
|
+
import { FormAssociated as i, FormAssociationController as a, defineFormAssociation as o } from "../../shared/form-association/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/radio-group/index.ts
|
|
8
|
-
var
|
|
9
|
+
var m = ["horizontal", "vertical"], h = class extends i(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 t(this, n({
|
|
11
12
|
host: this,
|
|
12
13
|
getItems: () => [...this.querySelectorAll("web-ui-radio")],
|
|
13
14
|
getValue: () => this._value,
|
|
@@ -32,7 +33,7 @@ var p = class extends t(s) {
|
|
|
32
33
|
composed: !0
|
|
33
34
|
}));
|
|
34
35
|
}
|
|
35
|
-
}).make()), this._formAssociation =
|
|
36
|
+
}).make()), this._formAssociation = o({
|
|
36
37
|
host: this,
|
|
37
38
|
initialize: () => {
|
|
38
39
|
let e = this.getAttribute("value");
|
|
@@ -48,10 +49,17 @@ var p = class extends t(s) {
|
|
|
48
49
|
typeof e == "string" && (this.value = e);
|
|
49
50
|
},
|
|
50
51
|
syncValidity: () => this._syncValidity()
|
|
51
|
-
}).make(), this._formAssociationController = new
|
|
52
|
+
}).make(), this._formAssociationController = new a(this, this._formAssociation);
|
|
52
53
|
}
|
|
53
54
|
static {
|
|
54
|
-
this.styles =
|
|
55
|
+
this.styles = u(s);
|
|
56
|
+
}
|
|
57
|
+
get direction() {
|
|
58
|
+
return this._direction;
|
|
59
|
+
}
|
|
60
|
+
set direction(e) {
|
|
61
|
+
let t = this._direction;
|
|
62
|
+
this._direction = r(e, m, "vertical"), this.requestUpdate("direction", t);
|
|
55
63
|
}
|
|
56
64
|
get value() {
|
|
57
65
|
return this._value;
|
|
@@ -77,20 +85,23 @@ var p = class extends t(s) {
|
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
render() {
|
|
80
|
-
return
|
|
88
|
+
return l`<div class="wui-radio-group"><slot></slot></div>`;
|
|
81
89
|
}
|
|
82
90
|
};
|
|
83
|
-
e([
|
|
91
|
+
e([f({
|
|
84
92
|
type: String,
|
|
85
93
|
reflect: !0
|
|
86
|
-
})],
|
|
94
|
+
})], h.prototype, "name", void 0), e([f({
|
|
87
95
|
type: Boolean,
|
|
88
96
|
reflect: !0
|
|
89
|
-
})],
|
|
97
|
+
})], h.prototype, "disabled", void 0), e([f({
|
|
90
98
|
type: Boolean,
|
|
91
99
|
reflect: !0
|
|
92
|
-
})],
|
|
100
|
+
})], h.prototype, "required", void 0), e([f({
|
|
101
|
+
type: String,
|
|
102
|
+
reflect: !0
|
|
103
|
+
})], h.prototype, "direction", null), e([p()], h.prototype, "_value", void 0), h = e([d("web-ui-radio-group")], h);
|
|
93
104
|
//#endregion
|
|
94
|
-
export {
|
|
105
|
+
export { h as WebUiRadioGroup };
|
|
95
106
|
|
|
96
107
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupCoordinator, GroupController } from '@/shared/group-management'\n\nimport type { WebUiRadio } from '../radio'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-radio-group')\nexport class WebUiRadioGroup extends FormAssociated(LitElement) {\n static override styles = unsafeCSS(style)\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 @state() private _value = ''\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupCoordinator<WebUiRadio, string>({\n host: this,\n getItems: () => [...this.querySelectorAll<WebUiRadio>('web-ui-radio')],\n getValue: () => this._value,\n setValue: value => {\n this.value = value\n },\n getDisabled: () => this._isDisabled,\n isItem: (target): target is WebUiRadio => target instanceof HTMLElement && target.matches('web-ui-radio'),\n isItemSelected: (radio, value) => radio.value === value,\n getNextValue: (radio, value) => (radio.checked ? radio.value : value),\n valuesEqual: (a, b) => a === b,\n copyValue: value => value,\n setItemSelected: (radio, selected) => {\n radio.checked = selected\n },\n dispatchValueChange: () => {\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n }).make()\n )\n\n get value(): string {\n return this._value\n }\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 private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => (this.name && this._value ? this._value : null),\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 override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n this._groupController.sync()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n override render() {\n return html`<div class=\"wui-radio-group\"><slot></slot></div>`\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-radio-group': WebUiRadioGroup\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/radio-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupCoordinator, GroupController } from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport type { WebUiRadio } from '../radio'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_DIRECTIONS = ['horizontal', 'vertical'] as const\n\n@customElement('web-ui-radio-group')\nexport class WebUiRadioGroup extends FormAssociated(LitElement) {\n static override styles = unsafeCSS(style)\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 @property({ type: String, reflect: true })\n get direction(): 'horizontal' | 'vertical' {\n return this._direction\n }\n set direction(v: string) {\n const old = this._direction\n this._direction = normalizeLiteral(v, ALLOWED_DIRECTIONS, 'vertical')\n this.requestUpdate('direction', old)\n }\n private _direction: 'horizontal' | 'vertical' = 'vertical'\n\n @state() private _value = ''\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupCoordinator<WebUiRadio, string>({\n host: this,\n getItems: () => [...this.querySelectorAll<WebUiRadio>('web-ui-radio')],\n getValue: () => this._value,\n setValue: value => {\n this.value = value\n },\n getDisabled: () => this._isDisabled,\n isItem: (target): target is WebUiRadio => target instanceof HTMLElement && target.matches('web-ui-radio'),\n isItemSelected: (radio, value) => radio.value === value,\n getNextValue: (radio, value) => (radio.checked ? radio.value : value),\n valuesEqual: (a, b) => a === b,\n copyValue: value => value,\n setItemSelected: (radio, selected) => {\n radio.checked = selected\n },\n dispatchValueChange: () => {\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n }).make()\n )\n\n get value(): string {\n return this._value\n }\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 private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string>({\n host: this,\n initialize: () => {\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n getFormValue: () => (this.name && this._value ? this._value : null),\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 override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n this._groupController.sync()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n override render() {\n return html`<div class=\"wui-radio-group\"><slot></slot></div>`\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-radio-group': WebUiRadioGroup\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/components/radio-group/style.css?inline
|
|
2
|
-
var e = "*,:before,:after{box-sizing:border-box}:host{-webkit-user-select:none;user-select:none;flex-direction:column;
|
|
2
|
+
var e = "*,:before,:after{box-sizing:border-box}:host{-webkit-user-select:none;user-select:none;gap:var(--wui-radio-group-gap,8px);flex-direction:column;display:inline-flex}.wui-radio-group{flex-direction:inherit;gap:inherit;display:flex}:host([direction=horizontal]){flex-direction:row}";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { e as default };
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio-group/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.wui-radio-group {\n display: flex;\n flex-direction:
|
|
1
|
+
{"version":3,"file":"style.js","names":[],"sources":["../../../src/components/radio-group/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n user-select: none;\n display: inline-flex;\n flex-direction: column;\n gap: var(--wui-radio-group-gap, 8px);\n}\n\n.wui-radio-group {\n display: flex;\n flex-direction: inherit;\n gap: inherit;\n}\n\n:host([direction='horizontal']) {\n flex-direction: row;\n}\n"],"mappings":""}
|
|
@@ -364,8 +364,11 @@ declare const WebUiSegmented_base: {
|
|
|
364
364
|
formAssociated: boolean;
|
|
365
365
|
} & typeof LitElement;
|
|
366
366
|
export declare class WebUiSegmented extends WebUiSegmented_base {
|
|
367
|
-
static styles: import('lit').CSSResult;
|
|
367
|
+
static styles: import('lit').CSSResult[];
|
|
368
368
|
name: string;
|
|
369
|
+
get variant(): 'inset' | 'raised';
|
|
370
|
+
set variant(v: string);
|
|
371
|
+
private _variant;
|
|
369
372
|
disabled: boolean;
|
|
370
373
|
required: boolean;
|
|
371
374
|
private _value;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
|
-
import
|
|
3
|
-
import { installPointerFocusSuppression as
|
|
4
|
-
import { GroupController as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
2
|
+
import t from "../../assets/glass.js";
|
|
3
|
+
import { installPointerFocusSuppression as n } from "../../shared/focus/pointer-focus.js";
|
|
4
|
+
import { GroupController as r, defineGroupCoordinator as i } from "../../shared/group-management/index.js";
|
|
5
|
+
import { normalizeLiteral as a } from "../../shared/normalize/index.js";
|
|
6
|
+
import { FormAssociated as o, FormAssociationController as s, defineFormAssociation as c } from "../../shared/form-association/index.js";
|
|
7
|
+
import { attachDragGesture as l } from "../../shared/gesture/drag-gesture.js";
|
|
8
|
+
import { clamp as u, snapToNearest as d } from "../../shared/gesture/physics.js";
|
|
9
|
+
import f from "./style.js";
|
|
10
|
+
import { LitElement as p, html as m, unsafeCSS as h } from "lit";
|
|
11
|
+
import { customElement as g, property as _, state as v } from "lit/decorators.js";
|
|
12
|
+
import { classMap as y } from "lit/directives/class-map.js";
|
|
11
13
|
//#region src/components/segmented/index.ts
|
|
12
|
-
|
|
13
|
-
var
|
|
14
|
+
n();
|
|
15
|
+
var b = ["inset", "raised"], x = class extends o(p) {
|
|
14
16
|
constructor(...e) {
|
|
15
|
-
super(...e), this.name = "", this.disabled = !1, this.required = !1, this._value = "", this._indicatorReady = !1, this._pressed = !1, this._isDragging = !1, this._dragGestureHandle = null, this._groupController = new
|
|
17
|
+
super(...e), this.name = "", this._variant = "inset", this.disabled = !1, this.required = !1, this._value = "", this._indicatorReady = !1, this._pressed = !1, this._isDragging = !1, this._dragGestureHandle = null, this._groupController = new r(this, i({
|
|
16
18
|
host: this,
|
|
17
19
|
getItems: () => [...this.querySelectorAll("web-ui-segmented-trigger")],
|
|
18
20
|
getValue: () => this._value,
|
|
@@ -37,7 +39,7 @@ var v = class extends t(d) {
|
|
|
37
39
|
composed: !0
|
|
38
40
|
}));
|
|
39
41
|
}
|
|
40
|
-
}).make(), { afterSync: () => requestAnimationFrame(() => this._updateIndicator()) }), this._formAssociation =
|
|
42
|
+
}).make(), { afterSync: () => requestAnimationFrame(() => this._updateIndicator()) }), this._formAssociation = c({
|
|
41
43
|
host: this,
|
|
42
44
|
initialize: () => {
|
|
43
45
|
let e = this.getAttribute("value");
|
|
@@ -52,10 +54,17 @@ var v = class extends t(d) {
|
|
|
52
54
|
restoreState: (e) => {
|
|
53
55
|
typeof e == "string" && (this.value = e);
|
|
54
56
|
}
|
|
55
|
-
}).make(), this._formAssociationController = new
|
|
57
|
+
}).make(), this._formAssociationController = new s(this, this._formAssociation);
|
|
56
58
|
}
|
|
57
59
|
static {
|
|
58
|
-
this.styles =
|
|
60
|
+
this.styles = [h(t), h(f)];
|
|
61
|
+
}
|
|
62
|
+
get variant() {
|
|
63
|
+
return this._variant;
|
|
64
|
+
}
|
|
65
|
+
set variant(e) {
|
|
66
|
+
let t = this._variant;
|
|
67
|
+
this._variant = a(e, b, "inset"), this.requestUpdate("variant", t);
|
|
59
68
|
}
|
|
60
69
|
disconnectedCallback() {
|
|
61
70
|
super.disconnectedCallback(), this._dragGestureHandle?.destroy(), this._dragGestureHandle = null;
|
|
@@ -88,22 +97,22 @@ var v = class extends t(d) {
|
|
|
88
97
|
let i = r.getBoundingClientRect();
|
|
89
98
|
if (!(e.clientX >= i.left && e.clientX <= i.right && e.clientY >= i.top && e.clientY <= i.bottom)) return;
|
|
90
99
|
this._pressed = !0;
|
|
91
|
-
let a = this.getBoundingClientRect(), o = r.getBoundingClientRect(),
|
|
100
|
+
let a = this.getBoundingClientRect(), o = r.getBoundingClientRect(), s = o.left - a.left, c = o.width, f = t[0].getBoundingClientRect(), p = t[t.length - 1].getBoundingClientRect(), m = f.left - a.left, h = p.right - a.left - c, g = n.map((e) => {
|
|
92
101
|
let t = e.getBoundingClientRect();
|
|
93
102
|
return t.left - a.left + t.width / 2;
|
|
94
103
|
});
|
|
95
|
-
this._dragGestureHandle?.destroy(), this._dragGestureHandle =
|
|
104
|
+
this._dragGestureHandle?.destroy(), this._dragGestureHandle = l(e, {
|
|
96
105
|
axis: "x",
|
|
97
106
|
threshold: 6,
|
|
98
107
|
onMove: (e) => {
|
|
99
108
|
this._isDragging = !0;
|
|
100
|
-
let t =
|
|
101
|
-
this.style.setProperty("--indicator-left", `${t}px`), this.style.setProperty("--indicator-width", `${
|
|
109
|
+
let t = u(s + e.deltaX, m, h);
|
|
110
|
+
this.style.setProperty("--indicator-left", `${t}px`), this.style.setProperty("--indicator-width", `${c}px`);
|
|
102
111
|
},
|
|
103
112
|
onEnd: (e) => {
|
|
104
113
|
let t = this._isDragging;
|
|
105
114
|
if (this._isDragging = !1, this._pressed = !1, t) {
|
|
106
|
-
let t =
|
|
115
|
+
let t = u(s + e.deltaX, m, h) + c / 2, i = r;
|
|
107
116
|
if (e.velocityX > 300) {
|
|
108
117
|
let e = n.indexOf(r);
|
|
109
118
|
i = e !== -1 && e < n.length - 1 ? n[e + 1] : n[n.length - 1];
|
|
@@ -111,7 +120,7 @@ var v = class extends t(d) {
|
|
|
111
120
|
let e = n.indexOf(r);
|
|
112
121
|
i = e > 0 ? n[e - 1] : n[0];
|
|
113
122
|
} else {
|
|
114
|
-
let e =
|
|
123
|
+
let e = d(t, g);
|
|
115
124
|
e !== -1 && n[e] && (i = n[e]);
|
|
116
125
|
}
|
|
117
126
|
i.value === this._value ? this._updateIndicator() : (this.value = i.value, this._groupController.sync(), this.dispatchEvent(new Event("input", {
|
|
@@ -139,9 +148,10 @@ var v = class extends t(d) {
|
|
|
139
148
|
this._formAssociation.setDisabled(e), this._groupController.sync();
|
|
140
149
|
}
|
|
141
150
|
render() {
|
|
142
|
-
return
|
|
151
|
+
return m`
|
|
143
152
|
<div
|
|
144
|
-
class=${
|
|
153
|
+
class=${y({
|
|
154
|
+
"wui-glass": !0,
|
|
145
155
|
"wui-segmented": !0,
|
|
146
156
|
"is-disabled": this._isDisabled,
|
|
147
157
|
"is-pressed": this._pressed,
|
|
@@ -155,23 +165,26 @@ var v = class extends t(d) {
|
|
|
155
165
|
@pointercancel=${this.handlePointerUp}
|
|
156
166
|
@pointerleave=${this.handlePointerLeave}
|
|
157
167
|
>
|
|
158
|
-
<span class="wui-segmented-indicator"></span>
|
|
168
|
+
<span class="wui-glass wui-segmented-indicator"></span>
|
|
159
169
|
<slot></slot>
|
|
160
170
|
</div>
|
|
161
171
|
`;
|
|
162
172
|
}
|
|
163
173
|
};
|
|
164
|
-
e([
|
|
174
|
+
e([_({
|
|
175
|
+
type: String,
|
|
176
|
+
reflect: !0
|
|
177
|
+
})], x.prototype, "name", void 0), e([_({
|
|
165
178
|
type: String,
|
|
166
179
|
reflect: !0
|
|
167
|
-
})],
|
|
180
|
+
})], x.prototype, "variant", null), e([_({
|
|
168
181
|
type: Boolean,
|
|
169
182
|
reflect: !0
|
|
170
|
-
})],
|
|
183
|
+
})], x.prototype, "disabled", void 0), e([_({
|
|
171
184
|
type: Boolean,
|
|
172
185
|
reflect: !0
|
|
173
|
-
})],
|
|
186
|
+
})], x.prototype, "required", void 0), e([v()], x.prototype, "_value", void 0), e([v()], x.prototype, "_indicatorReady", void 0), e([v()], x.prototype, "_pressed", void 0), e([v()], x.prototype, "_isDragging", void 0), x = e([g("web-ui-segmented")], x);
|
|
174
187
|
//#endregion
|
|
175
|
-
export {
|
|
188
|
+
export { x as WebUiSegmented };
|
|
176
189
|
|
|
177
190
|
//# sourceMappingURL=index.js.map
|