@greypan/web-ui 9.1.0 → 10.1.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 +67 -28
- package/README.md +69 -28
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/avatar/index.js +5 -5
- package/dist/components/avatar/index.js.map +1 -1
- package/dist/components/back-top/index.js.map +1 -1
- package/dist/components/badge/index.js +5 -5
- package/dist/components/button/index.js +5 -5
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/context-menu/index.js +65 -65
- package/dist/components/dialog/index.d.ts +29 -4
- package/dist/components/dialog/index.js +26 -13
- 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.js.map +1 -1
- package/dist/components/dropdown-item/index.js.map +1 -1
- package/dist/components/editable-text/index.js +4 -4
- package/dist/components/empty/index.js.map +1 -1
- package/dist/components/image-preview/index.js.map +1 -1
- package/dist/components/input/index.js +5 -5
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input-number/index.js.map +1 -1
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/option/index.js.map +1 -1
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/textarea/index.js +8 -8
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/scrollbars/index.js.map +1 -1
- package/dist/shared/overlay/overlay.js +33 -33
- package/dist/vite/index.d.ts +28 -0
- package/dist/vite/index.js +16 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +5 -1
- package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js +0 -246
- package/dist/node_modules/.pnpm/@floating-ui_core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.js.map +0 -1
- package/dist/node_modules/.pnpm/@floating-ui_dom@1.8.0/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +0 -324
- package/dist/node_modules/.pnpm/@floating-ui_dom@1.8.0/node_modules/@floating-ui/dom/dist/floating-ui.dom.js.map +0 -1
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +0 -100
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +0 -1
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +0 -102
- package/dist/node_modules/.pnpm/@floating-ui_utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.js.map +0 -1
|
@@ -6,8 +6,8 @@ import { normalizeLiteral as r } from "../../shared/normalize/index.js";
|
|
|
6
6
|
import i from "./style.js";
|
|
7
7
|
import { LitElement as a, html as o, unsafeCSS as s } from "lit";
|
|
8
8
|
import { customElement as c, property as l, state as u } from "lit/decorators.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { classMap as d } from "lit/directives/class-map.js";
|
|
10
|
+
import { ifDefined as f } from "lit/directives/if-defined.js";
|
|
11
11
|
//#region src/components/avatar/index.ts
|
|
12
12
|
var p = ["circle", "square"], m = class extends a {
|
|
13
13
|
constructor(...e) {
|
|
@@ -61,19 +61,19 @@ var p = ["circle", "square"], m = class extends a {
|
|
|
61
61
|
let e = !this._ariaLabel;
|
|
62
62
|
return o`
|
|
63
63
|
<div
|
|
64
|
-
class=${
|
|
64
|
+
class=${d({
|
|
65
65
|
"avatar-inner": !0,
|
|
66
66
|
"wui-glass": this._showFallback
|
|
67
67
|
})}
|
|
68
68
|
role=${e ? "presentation" : "img"}
|
|
69
|
-
aria-label=${
|
|
69
|
+
aria-label=${f(this._ariaLabel)}
|
|
70
70
|
aria-hidden=${e ? "true" : void 0}
|
|
71
71
|
style="width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px"
|
|
72
72
|
>
|
|
73
73
|
${this._showImage ? o`<img
|
|
74
74
|
class="avatar-img"
|
|
75
75
|
src=${this.src}
|
|
76
|
-
alt=${
|
|
76
|
+
alt=${f(this.alt || void 0)}
|
|
77
77
|
@error=${this._onImgError}
|
|
78
78
|
/>` : ""}
|
|
79
79
|
<slot @slotchange=${this._checkSlot}></slot>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/avatar/index.ts"],"sourcesContent":["// 注册 web-ui-icon:本组件模板直接渲染该标签,消费者模板里不会出现它,\n// 因此没有别处会引入。产物保留模块(build.rollupOptions.output.preserveModules)\n// 并由 package.json 的 sideEffects 保证这段副作用 import 不被 tree-shake 掉。\nimport '@/components/icon'\n\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport { lucideUser } from '@/icons'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_SHAPES = ['circle', 'square'] as const\n\n@customElement('web-ui-avatar')\nexport class WebUiAvatar extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n set src(value: string) {\n const old = this._src\n this._src = value\n if (old !== value) {\n this._imgError = false\n this.requestUpdate('src', old)\n }\n }\n\n get src(): string {\n return this._src\n }\n\n private _src = ''\n\n @property({ type: String, reflect: true }) alt = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Number, reflect: true }) size = 40\n\n @property({ type: String, reflect: true })\n set shape(value: string) {\n const normalized = normalizeLiteral(value, ALLOWED_SHAPES, 'circle')\n if (this._shape !== normalized) {\n const old = this._shape\n this._shape = normalized\n this.requestUpdate('shape', old)\n }\n // 外部 setAttribute 非法值后,宿主 attribute 与规范化后的值不同步,立即修正\n if (this.getAttribute('shape') !== normalized) {\n this.setAttribute('shape', normalized)\n }\n }\n\n get shape(): 'circle' | 'square' {\n return this._shape\n }\n\n private _shape: 'circle' | 'square' = 'circle'\n\n @state() private _imgError = false\n @state() private _hasDefaultSlot = false\n\n private _checkSlot() {\n const slot = this.shadowRoot?.querySelector('slot:not([name])')\n const has = slot instanceof HTMLSlotElement && slot.assignedElements().length > 0\n if (this._hasDefaultSlot !== has) {\n this._hasDefaultSlot = has\n }\n }\n\n private get _initials(): string {\n const words = this.name.trim().split(/\\s+/)\n return words\n .slice(0, 2)\n .map(w => Array.from(w)[0])\n .join('')\n .toUpperCase()\n }\n\n private get _iconSize(): number {\n return Math.round(this.size * 0.4)\n }\n\n private get _showImage(): boolean {\n return !!this.src && !this._imgError\n }\n\n private get _showFallback(): boolean {\n return !this._showImage && !this._hasDefaultSlot\n }\n\n private _onImgError() {\n this._imgError = true\n }\n\n private get _ariaLabel(): string | undefined {\n if (this.alt) return this.alt\n if (this.name) return this.name\n return undefined\n }\n\n override render() {\n const isDecorative = !this._ariaLabel\n\n return html`\n <div\n class=${classMap({ 'avatar-inner': true, 'wui-glass': this._showFallback })}\n role=${isDecorative ? 'presentation' : 'img'}\n aria-label=${ifDefined(this._ariaLabel)}\n aria-hidden=${isDecorative ? 'true' : undefined}\n style=\"width:${this.size}px;height:${this.size}px;--wui-avatar-size:${this.size}px\"\n >\n ${\n this._showImage\n ? html`<img\n class=\"avatar-img\"\n src=${this.src}\n alt=${ifDefined(this.alt || undefined)}\n @error=${this._onImgError}\n />`\n : ''\n }\n <slot @slotchange=${this._checkSlot}></slot>\n ${\n this._showFallback && this._initials\n ? html`<span class=\"avatar-fallback avatar-initials\">${this._initials}</span>`\n : ''\n }\n ${\n this._showFallback && !this._initials\n ? html`<span class=\"avatar-fallback\"\n ><web-ui-icon .icon=${lucideUser} .size=${this._iconSize}></web-ui-icon\n ></span>`\n : ''\n }\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-avatar': WebUiAvatar\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/back-top/index.ts"],"sourcesContent":["import { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/back-top/index.ts"],"sourcesContent":["import '@/components/button'\nimport '@/components/icon'\n\nimport { getRootScrollTop } from '@greypan/browser-kit'\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { lucideArrowUpToLine } from '@/icons'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-back-top')\nexport class WebUiBackTop extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ reflect: true, attribute: 'scroll-behavior', useDefault: true })\n get scrollBehavior(): 'smooth' | 'auto' {\n return this._scrollBehavior\n }\n set scrollBehavior(value: string) {\n const old = this._scrollBehavior\n this._scrollBehavior = normalizeLiteral(value, ['smooth', 'auto'] as const, 'smooth')\n this.requestUpdate('scrollBehavior', old)\n }\n private _scrollBehavior: 'smooth' | 'auto' = 'smooth'\n @property({ type: Boolean, reflect: true }) visible = false\n @property({ attribute: false }) scrollTarget: HTMLElement | Window = window\n\n @property({ type: Number, reflect: true })\n get threshold(): number {\n return this._threshold\n }\n set threshold(v: number) {\n const old = this._threshold\n this._threshold = normalizeNumber(v, 0, 10000, 200)\n this.requestUpdate('threshold', old)\n }\n private _threshold = 200\n\n @state() private eventController?: AbortController\n\n override connectedCallback() {\n super.connectedCallback()\n this.computeVisible()\n this.onScrollTarget()\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.eventController?.abort()\n }\n\n protected override willUpdate(props: PropertyValues) {\n super.willUpdate(props)\n\n if (props.has('threshold') || props.has('scrollTarget')) {\n this.computeVisible()\n }\n // 不设 hasUpdated 门控:scrollTarget 可能在首次更新完成前赋值(如框架 onMounted 中),\n // 此时 connectedCallback 已按 window 绑定,必须重绑到新容器;onScrollTarget 幂等,重复调用安全\n if (props.has('scrollTarget')) {\n // 容器模式:scrollTarget 为元素时按钮通过 sticky 悬浮于容器底部,而非固定视口角落\n this.toggleAttribute('container-mode', this.target !== window)\n this.onScrollTarget()\n }\n }\n\n private get target() {\n if (!this.scrollTarget) return window\n const isRoot =\n this.scrollTarget === window ||\n this.scrollTarget === document.documentElement ||\n this.scrollTarget === document.body\n return isRoot ? window : this.scrollTarget\n }\n\n private onScrollTarget() {\n this.eventController?.abort()\n this.eventController = new AbortController()\n\n this.target.addEventListener(\n 'scroll',\n () => {\n this.computeVisible()\n },\n { signal: this.eventController.signal, passive: true }\n )\n }\n\n private computeVisible() {\n const target = this.target\n if (target === window) {\n this.visible = getRootScrollTop() >= this.threshold\n } else if (target instanceof HTMLElement) {\n this.visible = target.scrollTop >= this.threshold\n } else {\n throw new Error('Prop scrollTarget must be HTMLElement or Window.')\n }\n }\n\n toTop() {\n this.target.scrollTo({\n top: 0,\n behavior: this.scrollBehavior\n })\n }\n\n // ARIA button 契约要求 Enter 与 Space 均能激活\n private onEnter(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.toTop()\n }\n }\n\n override render() {\n return html`\n <div class=\"back-top-inner\" role=\"button\" tabindex=\"0\" @click=${this.toTop} @keydown=${this.onEnter}>\n <slot>\n <web-ui-button variant=\"glass\" tabindex=\"-1\" icon>\n <web-ui-icon .icon=${lucideArrowUpToLine}></web-ui-icon>\n </web-ui-button>\n </slot>\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-back-top': WebUiBackTop\n }\n}\n"],"mappings":";;;;;;;;;;AAaO,IAAM,IAAN,cAA2B,EAAW;;EAyBtB,aAbwB,KAAA,kBAAA,UACS,KAAA,UAAA,IACe,KAAA,eAAA,QAWhD,KAAA,aAAA;;;EAxBI,KAAA,SAAA,EAAU,CAAK;;CAExC,IACI,iBAAoC;EACtC,OAAO,KAAK;CACd;CACA,IAAI,eAAe,GAAe;EAChC,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,kBAAkB,EAAiB,GAAO,CAAC,UAAU,MAAM,GAAY,QAAQ,GACpF,KAAK,cAAc,kBAAkB,CAAG;CAC1C;CAKA,IACI,YAAoB;EACtB,OAAO,KAAK;CACd;CACA,IAAI,UAAU,GAAW;EACvB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,aAAa,EAAgB,GAAG,GAAG,KAAO,GAAG,GAClD,KAAK,cAAc,aAAa,CAAG;CACrC;CAKA,oBAA6B;EAG3B,AAFA,MAAM,kBAAkB,GACxB,KAAK,eAAe,GACpB,KAAK,eAAe;CACtB;CAEA,uBAAgC;EAE9B,AADA,MAAM,qBAAqB,GAC3B,KAAK,iBAAiB,MAAM;CAC9B;CAEA,WAA8B,GAAuB;EAQnD,AAPA,MAAM,WAAW,CAAK,IAElB,EAAM,IAAI,WAAW,KAAK,EAAM,IAAI,cAAc,MACpD,KAAK,eAAe,GAIlB,EAAM,IAAI,cAAc,MAE1B,KAAK,gBAAgB,kBAAkB,KAAK,WAAW,MAAM,GAC7D,KAAK,eAAe;CAExB;CAEA,IAAY,SAAS;EAMnB,OALK,KAAK,eAER,KAAK,iBAAiB,UACtB,KAAK,iBAAiB,SAAS,mBAC/B,KAAK,iBAAiB,SAAS,OACjB,SAAS,KAAK,eALC;CAMjC;CAEA,iBAAyB;EAIvB,AAHA,KAAK,iBAAiB,MAAM,GAC5B,KAAK,kBAAkB,IAAI,gBAAgB,GAE3C,KAAK,OAAO,iBACV,gBACM;GACJ,KAAK,eAAe;EACtB,GACA;GAAE,QAAQ,KAAK,gBAAgB;GAAQ,SAAS;EAAK,CACvD;CACF;CAEA,iBAAyB;EACvB,IAAM,IAAS,KAAK;EACpB,IAAI,MAAW,QACb,KAAK,UAAU,EAAiB,KAAK,KAAK;OACrC,IAAI,aAAkB,aAC3B,KAAK,UAAU,EAAO,aAAa,KAAK;OAExC,MAAU,MAAM,kDAAkD;CAEtE;CAEA,QAAQ;EACN,KAAK,OAAO,SAAS;GACnB,KAAK;GACL,UAAU,KAAK;EACjB,CAAC;CACH;CAGA,QAAgB,GAAkB;EAChC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,MAAM;CAEf;CAEA,SAAkB;EAChB,OAAO,CAAI;sEACuD,KAAK,MAAM,YAAY,KAAK,QAAQ;;;iCAGzE,EAAoB;;;;;CAKnD;AACF;AA/GG,EAAA,CAAA,EAAS;CAAE,SAAS;CAAM,WAAW;CAAmB,YAAY;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,kBAAA,IAAA,GAU1E,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS,EAAE,WAAW,GAAM,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GAE7B,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,IAAA,GAWxC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GA5BR,IAAA,EAAA,CAAA,EAAc,iBAAiB,CAAA,GAAA,CAAA"}
|
|
@@ -4,8 +4,8 @@ import { normalizeLiteral as n, normalizeNumber as r } from "../../shared/normal
|
|
|
4
4
|
import i from "./style.js";
|
|
5
5
|
import { LitElement as a, html as o, unsafeCSS as s } from "lit";
|
|
6
6
|
import { customElement as c, property as l, state as u } from "lit/decorators.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { classMap as d } from "lit/directives/class-map.js";
|
|
8
|
+
import { ifDefined as f } from "lit/directives/if-defined.js";
|
|
9
9
|
import { styleMap as p } from "lit/directives/style-map.js";
|
|
10
10
|
//#region src/components/badge/index.ts
|
|
11
11
|
var m = [
|
|
@@ -71,13 +71,13 @@ var m = [
|
|
|
71
71
|
"--badge-offset-y": `${this.offsetY}px`
|
|
72
72
|
};
|
|
73
73
|
return o`
|
|
74
|
-
<div class=${
|
|
74
|
+
<div class=${d(r)}>
|
|
75
75
|
<slot @slotchange=${this._handleSlotChange}></slot>
|
|
76
76
|
${e ? o`<span
|
|
77
|
-
class=${
|
|
77
|
+
class=${d(i)}
|
|
78
78
|
style=${p(a)}
|
|
79
79
|
role="status"
|
|
80
|
-
aria-label=${
|
|
80
|
+
aria-label=${f(n)}
|
|
81
81
|
>${t}</span
|
|
82
82
|
>` : ""}
|
|
83
83
|
</div>
|
|
@@ -9,8 +9,8 @@ import { normalizeLiteral as l } from "../../shared/normalize/index.js";
|
|
|
9
9
|
import u from "./style.js";
|
|
10
10
|
import { LitElement as d, html as f, nothing as p, unsafeCSS as m } from "lit";
|
|
11
11
|
import { customElement as h, property as g } from "lit/decorators.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { classMap as _ } from "lit/directives/class-map.js";
|
|
13
|
+
import { ifDefined as v } from "lit/directives/if-defined.js";
|
|
14
14
|
import { styleMap as y } from "lit/directives/style-map.js";
|
|
15
15
|
//#region src/components/button/index.ts
|
|
16
16
|
var b = [
|
|
@@ -90,8 +90,8 @@ var S = class extends i(d) {
|
|
|
90
90
|
return f`
|
|
91
91
|
<button
|
|
92
92
|
type=${this.type}
|
|
93
|
-
aria-label=${
|
|
94
|
-
class=${
|
|
93
|
+
aria-label=${v(this.ariaLabel)}
|
|
94
|
+
class=${_(t)}
|
|
95
95
|
part="button"
|
|
96
96
|
style=${Object.keys(this._sizeStyle).length > 0 ? y(this._sizeStyle) : p}
|
|
97
97
|
?disabled=${this._isDisabled}
|
|
@@ -104,7 +104,7 @@ var S = class extends i(d) {
|
|
|
104
104
|
<slot name="suffix"></slot>
|
|
105
105
|
`}
|
|
106
106
|
</button>
|
|
107
|
-
${e && !e.isLast ? f`<span class=${
|
|
107
|
+
${e && !e.isLast ? f`<span class=${_(r)} aria-hidden="true"></span>` : ""}
|
|
108
108
|
`;
|
|
109
109
|
}
|
|
110
110
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/button/index.ts"],"sourcesContent":["import { html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/button/index.ts"],"sourcesContent":["import '@/components/icon'\n\nimport { html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { styleMap } from 'lit/directives/style-map.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport { lucideLoaderCircle } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { buttonGroupContextKey, defineGroupManaged, type ButtonGroupContext } from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_VARIANTS = ['primary', 'secondary', 'ghost', 'danger', 'glass'] as const\nconst ALLOWED_TYPES = ['button', 'submit', 'reset'] as const\n\ninstallPointerFocusSuppression()\n\n@customElement('web-ui-button')\nexport class WebUiButton extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n get variant(): 'primary' | 'secondary' | 'ghost' | 'danger' | 'glass' {\n return this._variant\n }\n set variant(v: string) {\n const old = this._variant\n this._variant = normalizeLiteral(v, ALLOWED_VARIANTS, 'glass')\n this.requestUpdate('variant', old)\n }\n private _variant: 'primary' | 'secondary' | 'ghost' | 'danger' | 'glass' = 'glass'\n\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) loading = false\n @property({ type: Boolean, reflect: true }) full = false\n @property({ type: Boolean, reflect: true }) icon = false\n @property({ type: String, reflect: true }) size = ''\n\n @property({ type: String, reflect: true })\n get type(): (typeof ALLOWED_TYPES)[number] {\n return this._type\n }\n set type(value: unknown) {\n const old = this._type\n this._type = normalizeLiteral(value, ALLOWED_TYPES, 'button')\n this.requestUpdate('type', old)\n }\n private _type: (typeof ALLOWED_TYPES)[number] = 'button'\n\n // Explicitly delegated accessible naming attributes.\n @property({ type: String, attribute: 'aria-label' }) override ariaLabel: string | null = null\n\n private readonly _groupManagement = defineGroupManaged<ButtonGroupContext>(this, {\n context: buttonGroupContextKey,\n requestUpdate: () => this.requestUpdate(),\n equals: (a, b) => a?.direction === b?.direction && a?.isLast === b?.isLast\n }).make()\n\n private get _groupContext(): ButtonGroupContext | undefined {\n return this._groupManagement.getContext()\n }\n\n /*\n * 按钮不贡献表单值,接 shared form-association 只为拿 ElementInternals 与原生禁用回调:\n * 禁用态由浏览器在宿主 disabled 反射时同步回报,自己镜像一份会漏掉更新时机。\n */\n private readonly _formAssociation = defineFormAssociation<null>({\n host: this,\n getState: () => null,\n setState: () => {},\n getFormValue: () => null,\n getFormState: () => null,\n restoreState: () => {}\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private get _isDisabled(): boolean {\n return this.disabled || this.loading || this._formAssociation.isFormDisabled()\n }\n\n private get _sizeStyle(): Record<string, string> {\n // size 仅控制按钮高度;icon 模式下 min-width 同步为相同值,天然保持正方形。\n const size = this._groupContext ? '30' : this.size\n return size ? { '--wui-control-size': `${size}px` } : {}\n }\n\n private handleClick(e: Event) {\n if (this._isDisabled) {\n e.preventDefault()\n e.stopPropagation()\n return\n }\n\n const action = this.type\n if (action === 'button') return\n\n /*\n * Shadow 内按钮没有 form owner;等 composed click 的同步监听器全部完成后,\n * 再读取宿主的 live form owner 并转发,调用方仍可用 preventDefault 取消这次原生 activation。\n */\n setTimeout(() => {\n if (e.defaultPrevented) return\n const form = this._formAssociation.getInternals()?.form\n if (!form) return\n if (action === 'submit') form.requestSubmit()\n else form.reset()\n })\n }\n\n override render() {\n const groupContext = this._groupContext\n const btnClass = {\n 'wui-glass': this.variant === 'glass' && !groupContext,\n 'is-grouped': Boolean(groupContext)\n }\n const dividerClass = {\n 'group-divider': true,\n vertical: groupContext?.direction === 'vertical'\n }\n\n return html`\n <button\n type=${this.type}\n aria-label=${ifDefined(this.ariaLabel)}\n class=${classMap(btnClass)}\n part=\"button\"\n style=${Object.keys(this._sizeStyle).length > 0 ? styleMap(this._sizeStyle) : nothing}\n ?disabled=${this._isDisabled}\n @click=${this.handleClick}\n >\n ${\n this.icon\n ? // loading 优先于 icon 内容:icon 模式下只展示 spinner,不投影默认 slot,避免双图标叠加\n this.loading\n ? html`<web-ui-icon .icon=${lucideLoaderCircle} spin></web-ui-icon>`\n : html`<slot></slot>`\n : html`\n ${this.loading ? html`<web-ui-icon .icon=${lucideLoaderCircle} spin></web-ui-icon>` : ''}\n <slot name=\"prefix\"></slot>\n <span class=\"label\"><slot></slot></span>\n <slot name=\"suffix\"></slot>\n `\n }\n </button>\n ${\n groupContext && !groupContext.isLast\n ? html`<span class=${classMap(dividerClass)} aria-hidden=\"true\"></span>`\n : ''\n }\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-button': WebUiButton\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
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 '@/components/icon'\nimport selectionControl from '@/assets/selection-control.css?inline'\nimport { WebUiSvgDrawLines } from '@/components/svg-draw-lines'\nimport { akarIconsCheck } from '@/icons'\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 { LabelEmptinessController } from '@/shared/label-emptiness'\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 /** 标签没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */\n @state() private _labelEmpty = 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 readonly _labelEmptiness = new LabelEmptinessController(this, '.wui-checkbox-label', empty => {\n this._labelEmpty = empty\n })\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-label-empty': this._labelEmpty,\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 ><web-ui-icon .icon=${akarIconsCheck}></web-ui-icon></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
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/index.ts"],"sourcesContent":["import '@/components/icon'\n\nimport { 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 { akarIconsCheck } from '@/icons'\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 { LabelEmptinessController } from '@/shared/label-emptiness'\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 /** 标签没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */\n @state() private _labelEmpty = 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 readonly _labelEmptiness = new LabelEmptinessController(this, '.wui-checkbox-label', empty => {\n this._labelEmpty = empty\n })\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-label-empty': this._labelEmpty,\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 ><web-ui-icon .icon=${akarIconsCheck}></web-ui-icon></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":";;;;;;;;;;;;;;;;AAkBA,EAA+B;AAM/B,SAAS,EAAgB,GAAyB;CAChD,IAAM,IAAS,EAAc,iBAAiB,CAAE,CAAC,CAAC,iBAAiB,wBAAwB,CAAC;CAC5F,OAAO,MAAW,OAAO,MAAM,KAAK,IAAI,GAAG,CAAM;AACnD;AAGO,IAAM,IAAN,cAA4B,EAAe,CAAU,CAAC,CAAC;;EAoElC,aAlEU,KAAA,mBAAA,EAA0C,MAAM;GAClF,SAAS;GACT,qBAAqB,KAAK,cAAc;EAC1C,CAAC,CAAC,CAAC,KAAK,GAEoB,KAAA,WAAA,IAGG,KAAA,cAAA,IAGA,KAAA,cAAA,IAaK,KAAA,QAAA,IACc,KAAA,OAAA,IACK,KAAA,WAAA,IACA,KAAA,WAAA,IAYnB,KAAA,mBAAA,EAA+B;GACjE,MAAM;GACN,kBAAkB;IAChB,AAAI,KAAK,aAAa,SAAS,MAAG,KAAK,WAAW;GACpD;GACA,gBAAgB,KAAK;GACrB,WAAU,MAAW;IACnB,KAAK,UAAU;GACjB;GACA,oBAAqB,CAAC,KAAK,qBAAqB,KAAK,WAAW,KAAK,SAAS,OAAO;GACrF,oBAAoB,OAAO,KAAK,QAAQ;GACxC,eAAc,MAAS;IACrB,AAAI,OAAO,KAAU,aAAU,KAAK,UAAU,MAAU;GAC1D;GACA,sBAAsB,KAAK;GAC3B,oBAAoB,KAAK,cAAc;EACzC,CAAC,CAAC,CAAC,KAAK,GAEsC,KAAA,6BAAA,IAAI,EAA0B,MAAM,KAAK,gBAAgB,GAEpE,KAAA,kBAAA,IAAI,EAAyB,MAAM,wBAAuB,MAAS;GACpG,KAAK,cAAc;EACrB,CAAC,GAKyB,KAAA,kBAAA;;;EAnED,KAAA,SAAA,CAAC,EAAU,CAAgB,GAAG,EAAU,CAAK,CAAC;;CAcvE,IAAI,UAAmB;EACrB,OAAO,KAAK;CACd;CAEA,IAAI,QAAQ,GAAY;EACtB,IAAM,IAAM,KAAK;EAGjB,AAFA,KAAK,WAAW,GAChB,KAAK,iBAAiB,KAAK,GAC3B,KAAK,cAAc,WAAW,CAAG;CACnC;CAOA,IAAY,cAAuB;EACjC,OACE,KAAK,YAAY,KAAK,iBAAiB,eAAe,KAAK,KAAK,iBAAiB,WAAW,CAAC,EAAE,aAAa;CAEhH;CAEA,IAAY,oBAA6B;EACvC,OAAO,KAAK,iBAAiB,WAAW,MAAM,KAAA;CAChD;CA+BA,gBAAwB;EACtB,IAAM,IAAY,KAAK,iBAAiB,aAAa;EACjD,IAAC,KAAa,OAAO,EAAU,eAAgB,YACnD;OAAI,KAAK,eAAe,KAAK,qBAAqB,CAAC,KAAK,YAAY,KAAK,UAAU;IACjF,EAAU,YAAY,CAAC,CAAC;IACxB;GACF;GACA,EAAU,YAAY,EAAE,cAAc,GAAK,GAAG,OAAO;EADrD;CAEF;CAEA,cAAsB;EACpB,IAAI,KAAK,aAAa;EACtB,IAAM,IAAM,KAAK;EAGjB,AAFA,KAAK,WAAW,CAAC,GACjB,KAAK,iBAAiB,KAAK,GAC3B,KAAK,cAAc,WAAW,CAAG;EAEjC,IAAM,IAAkB,KAAK,oBACzB;GAAE,SAAS;GAAO,UAAU;EAAM,IAClC;GAAE,SAAS;GAAM,UAAU;EAAK;EAEpC,AADA,KAAK,cAAc,IAAI,MAAM,SAAS,CAAI,CAAC,GAC3C,KAAK,cAAc,IAAI,MAAM,UAAU,CAAI,CAAC;CAC9C;CAEA,cAAsB,GAAkB;EACtC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,YAAY;CAErB;CAQA,WAAoB,GAAyB;EAE3C,AADA,MAAM,WAAW,CAAO,GACxB,KAAK,kBAAkB,EAAgB,IAAI;EAC3C,IAAM,IAAa,EAAQ,IAAI,UAAU;EACzC,AAAI,OAAO,KAAe,cACxB,KAAK,cAAc,KAAc,CAAC,EAAqB,IAAI;CAE/D;CAOA,QAAiB,GAAyB;EACxC,MAAM,QAAQ,CAAO;EACrB,IAAM,IAAa,EAAQ,IAAI,UAAU;EACrC,OAAO,KAAe,cAEtB,IAAY,KAAU,YAAY,OAAO,EAAE,SAAS,GAAK,CAAC,IACzD,KAAU,YAAY,OAAO;CACpC;CAEA,SAAkB;EAChB,IAAM,IAAM;GACV,gBAAgB;GAChB,cAAc,KAAK;GACnB,iBAAiB,KAAK;GACtB,kBAAkB,KAAK;GACvB,eAAe,KAAK;EACtB;EAEA,OAAO,CAAI;;gBAEC,EAAS,CAAG,EAAE;mBACX,KAAK,cAAc,OAAO,IAAI;;uBAE1B,OAAO,KAAK,QAAQ,EAAE;wBACrB,OAAO,KAAK,WAAW,EAAE;iBAChC,KAAK,YAAY;mBACf,KAAK,cAAc;;;;+CAIS,KAAK,gBAAgB;oCAChC,EAAe;;;;;;CAMjD;AAMF;AA7JG,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAGN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GAGN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GAaN,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,KAAA,CAAA,GACzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAoCzC,EAAA,CAAA,EAAM,uBAAuB,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GAlE/B,IAAA,EAAA,CAAA,EAAc,iBAAiB,CAAA,GAAA,CAAA"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
|
|
2
2
|
import { normalizeNumber as t } from "../../shared/normalize/index.js";
|
|
3
3
|
import { dispatchOpenChangeEvent as n } from "../../shared/open-state/index.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import M from "
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
4
|
+
import { defineOverlayPositioningGeneration as r } from "../../shared/overlay/positioning-generation.js";
|
|
5
|
+
import { hideOverlayPresence as i, showOverlayPresence as a } from "../../shared/overlay/presence.js";
|
|
6
|
+
import { defineOpenOverlay as o } from "../../shared/overlay/open-overlay.js";
|
|
7
|
+
import { findNearestTheme as s } from "../../shared/overlay/theme-overlay-scope.js";
|
|
8
|
+
import { defineScrollLockLease as c } from "../../shared/scroll-lock/scroll-lock.js";
|
|
9
|
+
import { UserChangeController as l } from "../../shared/events/user-change.js";
|
|
10
|
+
import { captureFrameworkAnchors as u, findFocusedMenuItem as d, focusMenuItem as f, getMenuChildren as p, getMenuItemFromEvent as m, hideNestedMenuChildren as h, moveMenuChildren as g, orderManagedMenuItems as _, reconcileManagedMenuItems as v, restoreFrameworkAnchors as y, returnManagedMenuItemsToSlot as b } from "../../shared/menu-portal/menu-tree.js";
|
|
11
|
+
import { createClosingSubmenuStack as x, createMenuHoverBinder as S, createMenuOutsideClickGuard as C, getEnabledMenuLevelItems as w, getFocusedMenuItemFromPanels as T, handleMenuKeyboard as E } from "../../shared/menu-behavior/index.js";
|
|
12
|
+
import { createMenuPortalOverlay as D } from "../../shared/menu-portal/menu-portal.js";
|
|
13
|
+
import O from "./scrim.js";
|
|
14
|
+
import k from "./style.js";
|
|
15
|
+
import { LitElement as A, html as j, unsafeCSS as M } from "lit";
|
|
16
|
+
import { customElement as N, property as P, state as F } from "lit/decorators.js";
|
|
17
|
+
import { computePosition as I, flip as L, shift as R } from "@floating-ui/dom";
|
|
18
18
|
//#region src/components/context-menu/index.ts
|
|
19
|
-
var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wui-menu-scrim", G = 5, K = 8, q = class extends
|
|
19
|
+
var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wui-menu-scrim", G = 5, K = 8, q = class extends A {
|
|
20
20
|
constructor(...e) {
|
|
21
|
-
super(...e), this.disabled = !1, this.noScrollLock = !1, this.longPress = !1, this._longPressDelay = B, this._isOpen = !1, this._x = 0, this._y = 0, this._activeSubmenus = [], this._activeSubmenuItems = [], this._longPressOpenedAt = null, this._submenuPositionEpochs = /* @__PURE__ */ new WeakMap(), this._centerOnPressPoint = !1, this._closeSource = "default", this._menuHandle = null, this._submenuHandles = /* @__PURE__ */ new Map(), this._outsideClickGuard =
|
|
21
|
+
super(...e), this.disabled = !1, this.noScrollLock = !1, this.longPress = !1, this._longPressDelay = B, this._isOpen = !1, this._x = 0, this._y = 0, this._activeSubmenus = [], this._activeSubmenuItems = [], this._longPressOpenedAt = null, this._submenuPositionEpochs = /* @__PURE__ */ new WeakMap(), this._centerOnPressPoint = !1, this._closeSource = "default", this._menuHandle = null, this._submenuHandles = /* @__PURE__ */ new Map(), this._outsideClickGuard = C(this, (e) => this._menuHandle?.contains(e) ?? !1), this._closingSubmenus = x({
|
|
22
22
|
getPanel: (e) => e.panel,
|
|
23
23
|
restoreItems: (e, t) => this._restoreSubmenuItems(e, t),
|
|
24
24
|
dispose: (e) => {
|
|
@@ -33,13 +33,13 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
33
33
|
closeFrom: (e) => {
|
|
34
34
|
this._closeSubmenusFrom(e), this._hoverBinder.bind();
|
|
35
35
|
}
|
|
36
|
-
}, this._hoverBinder =
|
|
37
|
-
getFocusedItem: (e) =>
|
|
36
|
+
}, this._hoverBinder = S(this._hoverDelegate, "web-ui-dropdown-item"), this._keyboardDelegate = {
|
|
37
|
+
getFocusedItem: (e) => T(e, [this._menu?.content, ...this._activeSubmenus.map((e) => e.content)], "web-ui-dropdown-item"),
|
|
38
38
|
getLevelOf: (e) => {
|
|
39
39
|
let t = this._getItemLevel(e);
|
|
40
40
|
return t === -1 ? void 0 : t;
|
|
41
41
|
},
|
|
42
|
-
getEnabledItems: (e) =>
|
|
42
|
+
getEnabledItems: (e) => w(this._getLevelContainer(e)?.content),
|
|
43
43
|
isSubmenuItem: (e) => e.hasAttribute("submenu"),
|
|
44
44
|
openSubmenuInstant: (e) => this._openSubmenu(e, !0),
|
|
45
45
|
closeToParent: (e) => {
|
|
@@ -47,10 +47,10 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
47
47
|
return this._closeSubmenusFrom(e - 1), this._hoverBinder.bind(), t;
|
|
48
48
|
},
|
|
49
49
|
closeDeepestOrAll: () => this._closeLastSubmenuOrMenu()
|
|
50
|
-
}, this._overlay =
|
|
50
|
+
}, this._overlay = o().make({
|
|
51
51
|
requestClose: () => this._keyboardDelegate.closeDeepestOrAll(),
|
|
52
52
|
isConnected: () => this.isConnected
|
|
53
|
-
}), this._menuItemAnchors = /* @__PURE__ */ new Map(), this._scrollLock =
|
|
53
|
+
}), this._menuItemAnchors = /* @__PURE__ */ new Map(), this._scrollLock = c().make(), this._userOpenChange = new l(), this._shouldOpenInstantly = !0, this._suppressInitialFocusVisible = !0, this._refreshScheduled = !1, this._menuPositionGeneration = r().make(), this._contentObserver = new MutationObserver(() => {
|
|
54
54
|
this._isOpen && this._scheduleRefresh();
|
|
55
55
|
}), this._closeFromUser = (e = "default") => {
|
|
56
56
|
this._isOpen && (this._userOpenChange.mark(), this._closeSource = e, this.close());
|
|
@@ -96,7 +96,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
}, this._onMenuClick = (e) => {
|
|
99
|
-
let t =
|
|
99
|
+
let t = m(e);
|
|
100
100
|
if (t && !t.hasAttribute("disabled")) {
|
|
101
101
|
if (t.hasAttribute("submenu")) {
|
|
102
102
|
this._openSubmenu(t);
|
|
@@ -109,11 +109,11 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
109
109
|
}, this._onTouchMove = (e) => {
|
|
110
110
|
this._preventBackgroundScroll(e);
|
|
111
111
|
}, this._onDocumentKeydown = (e) => {
|
|
112
|
-
this._isOpen &&
|
|
112
|
+
this._isOpen && E(this._keyboardDelegate, e);
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
static {
|
|
116
|
-
this.styles =
|
|
116
|
+
this.styles = M(k);
|
|
117
117
|
}
|
|
118
118
|
get longPressDelay() {
|
|
119
119
|
return this._longPressDelay;
|
|
@@ -146,7 +146,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
146
146
|
if (this._isOpen) {
|
|
147
147
|
if (this._syncScrollLock(), !this._menu) {
|
|
148
148
|
let e = this._openScrim();
|
|
149
|
-
this._menu =
|
|
149
|
+
this._menu = D("context-menu", this, e), this._menu.panel.setAttribute("role", "menu"), this._menu.panel.setAttribute("aria-label", "上下文菜单"), this._menu.panel.addEventListener("click", this._onMenuClick);
|
|
150
150
|
}
|
|
151
151
|
if (!this._menuHandle) {
|
|
152
152
|
this._menuHandle = this._overlay.claim(this._menu.panel);
|
|
@@ -157,7 +157,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
157
157
|
childList: !0,
|
|
158
158
|
subtree: !0
|
|
159
159
|
}), requestAnimationFrame(() => {
|
|
160
|
-
this._isOpen && this._menu && (this._refreshMenu(),
|
|
160
|
+
this._isOpen && this._menu && (this._refreshMenu(), a(this._menu.panel, { isInstant: this._shouldOpenInstantly }), this._shouldOpenInstantly = !0, requestAnimationFrame(() => {
|
|
161
161
|
this._isOpen && this._menu && this._focusFirstItem();
|
|
162
162
|
}));
|
|
163
163
|
});
|
|
@@ -188,20 +188,20 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
188
188
|
if (!e) return;
|
|
189
189
|
let t = this._safeAreaBottom();
|
|
190
190
|
e.style.visibility = "hidden", e.style.display = "";
|
|
191
|
-
let n = this._menuPositionGeneration.next(),
|
|
191
|
+
let n = this._menuPositionGeneration.next(), r = {
|
|
192
192
|
top: K,
|
|
193
193
|
bottom: K + t,
|
|
194
194
|
left: K,
|
|
195
195
|
right: K
|
|
196
|
-
},
|
|
197
|
-
|
|
196
|
+
}, i = this._centerOnPressPoint ? ["bottom", "top"] : ["bottom-start", "top-start"];
|
|
197
|
+
I({ getBoundingClientRect: () => new DOMRect(this._x, this._y, 0, 0) }, e, {
|
|
198
198
|
strategy: "fixed",
|
|
199
|
-
placement:
|
|
200
|
-
middleware: [
|
|
201
|
-
fallbackPlacements: [...
|
|
202
|
-
padding:
|
|
203
|
-
}),
|
|
204
|
-
padding:
|
|
199
|
+
placement: i[0],
|
|
200
|
+
middleware: [L({
|
|
201
|
+
fallbackPlacements: [...i],
|
|
202
|
+
padding: r
|
|
203
|
+
}), R({
|
|
204
|
+
padding: r,
|
|
205
205
|
crossAxis: !0
|
|
206
206
|
})]
|
|
207
207
|
}).then(({ x: t, y: r, placement: i, middlewareData: a }) => {
|
|
@@ -219,7 +219,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
219
219
|
}
|
|
220
220
|
_focusFirstItem(e = 0) {
|
|
221
221
|
let t = this._menu?.content.querySelectorAll("web-ui-dropdown-item:not([disabled])")?.[0];
|
|
222
|
-
t && (
|
|
222
|
+
t && (f(t, { suppressFocusVisible: this._suppressInitialFocusVisible }), !(e + 1 >= G) && (d([this._menu?.panel]) || requestAnimationFrame(() => {
|
|
223
223
|
this._isOpen && this._menu && this._focusFirstItem(e + 1);
|
|
224
224
|
})));
|
|
225
225
|
}
|
|
@@ -227,22 +227,22 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
227
227
|
let e = this._menu;
|
|
228
228
|
if (!e) return;
|
|
229
229
|
let t = e.content;
|
|
230
|
-
|
|
231
|
-
let n =
|
|
232
|
-
|
|
230
|
+
v(this, t, this._menuItemAnchors, z), this._hideMenuItems(), h(t, "context-menu-hidden");
|
|
231
|
+
let n = u(t, z);
|
|
232
|
+
_(this, t, this._menuItemAnchors, z), y(t, n);
|
|
233
233
|
}
|
|
234
234
|
_returnItemsToSlot() {
|
|
235
235
|
let e = this._menu;
|
|
236
|
-
e && (this._closeSubmenusFrom(0, !0), this._closingSubmenus.restoreAll(),
|
|
236
|
+
e && (this._closeSubmenusFrom(0, !0), this._closingSubmenus.restoreAll(), b(this, e.content, this._menuItemAnchors));
|
|
237
237
|
}
|
|
238
238
|
_openScrim() {
|
|
239
239
|
let e = document.createElement("dialog");
|
|
240
240
|
e.className = "wui-context-menu-scrim";
|
|
241
241
|
let t = document.createElement("style");
|
|
242
|
-
return t.textContent =
|
|
242
|
+
return t.textContent = O, e.append(t), e.setAttribute(W, ""), e.addEventListener("click", this._onScrimClick), e.addEventListener("cancel", this._onScrimCancel), this._scrimParent().append(e), e.showModal(), this._scrim = e, e;
|
|
243
243
|
}
|
|
244
244
|
_scrimParent() {
|
|
245
|
-
return
|
|
245
|
+
return s(this)?.getOverlayRoot() ?? document.body;
|
|
246
246
|
}
|
|
247
247
|
_closeScrim() {
|
|
248
248
|
let e = this._scrim;
|
|
@@ -254,10 +254,10 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
254
254
|
}
|
|
255
255
|
async _closeMenuAfterPresence() {
|
|
256
256
|
let e = this._menu;
|
|
257
|
-
(!e || await
|
|
257
|
+
(!e || await i(e.panel)) && !this._isOpen && this.isConnected && this._menu === e && (this._closeScrim(), this._returnItemsToSlot(), e?.panel.remove(), this._menu = void 0);
|
|
258
258
|
}
|
|
259
259
|
_hideMenuItems() {
|
|
260
|
-
|
|
260
|
+
p(this).forEach((e) => e.setAttribute("slot", "context-menu-hidden")), h(this, "context-menu-hidden");
|
|
261
261
|
}
|
|
262
262
|
_openSubmenu(e, t = !1) {
|
|
263
263
|
if (!this._isOpen || !e.hasAttribute("submenu") || e.hasAttribute("disabled")) return;
|
|
@@ -266,12 +266,12 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
266
266
|
this._closeSubmenusFrom(n);
|
|
267
267
|
let r = this._closingSubmenus.take(e);
|
|
268
268
|
if (r) {
|
|
269
|
-
this._activeSubmenus[n] = r, this._activeSubmenuItems[n] = e, this._menuHandle && this._submenuHandles.set(r.panel, this._menuHandle.adopt(r.panel)), e.setAttribute("active", ""), this._positionSubmenu(e, r),
|
|
269
|
+
this._activeSubmenus[n] = r, this._activeSubmenuItems[n] = e, this._menuHandle && this._submenuHandles.set(r.panel, this._menuHandle.adopt(r.panel)), e.setAttribute("active", ""), this._positionSubmenu(e, r), a(r.panel, { isInstant: t }), this._hoverBinder.bind();
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
|
-
if (
|
|
273
|
-
let i =
|
|
274
|
-
i.panel.dataset.level = String(n), i.panel.setAttribute("role", "menu"), i.panel.setAttribute("aria-label", "子菜单"), i.panel.style.visibility = "hidden", i.panel.addEventListener("click", this._onMenuClick),
|
|
272
|
+
if (p(e).length === 0) return;
|
|
273
|
+
let i = D("context-submenu", this, this._scrim);
|
|
274
|
+
i.panel.dataset.level = String(n), i.panel.setAttribute("role", "menu"), i.panel.setAttribute("aria-label", "子菜单"), i.panel.style.visibility = "hidden", i.panel.addEventListener("click", this._onMenuClick), g(e, i.content), this._activeSubmenus[n] = i, this._activeSubmenuItems[n] = e, this._menuHandle && this._submenuHandles.set(i.panel, this._menuHandle.adopt(i.panel)), e.setAttribute("active", ""), this._positionSubmenu(e, i), a(i.panel, { isInstant: t }), this._hoverBinder.bind();
|
|
275
275
|
}
|
|
276
276
|
_closeSubmenusFrom(e, t = !1) {
|
|
277
277
|
for (let n = this._activeSubmenus.length - 1; n >= e; n--) {
|
|
@@ -281,7 +281,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
281
281
|
this._activeSubmenus.length = e, this._activeSubmenuItems.length = e;
|
|
282
282
|
}
|
|
283
283
|
_restoreSubmenuItems(e, t) {
|
|
284
|
-
t && (
|
|
284
|
+
t && (g(e.content, t), h(t, "context-menu-hidden"));
|
|
285
285
|
}
|
|
286
286
|
_getItemLevel(e) {
|
|
287
287
|
if (this._menu?.panel.contains(e)) return 0;
|
|
@@ -290,23 +290,23 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
290
290
|
}
|
|
291
291
|
_positionSubmenu(e, t) {
|
|
292
292
|
if (t.panel.parentElement instanceof HTMLDialogElement && t.panel.parentElement.open) {
|
|
293
|
-
let n = e.getBoundingClientRect().right + t.panel.getBoundingClientRect().width + 8 <= window.innerWidth,
|
|
294
|
-
this._submenuPositionEpochs.set(t.panel,
|
|
293
|
+
let n = e.getBoundingClientRect().right + t.panel.getBoundingClientRect().width + 8 <= window.innerWidth, r = (this._submenuPositionEpochs.get(t.panel) ?? 0) + 1;
|
|
294
|
+
this._submenuPositionEpochs.set(t.panel, r), I(e, t.panel, {
|
|
295
295
|
strategy: "fixed",
|
|
296
296
|
placement: n ? "right-start" : "left-start",
|
|
297
|
-
middleware: [
|
|
297
|
+
middleware: [R({
|
|
298
298
|
padding: 8,
|
|
299
299
|
crossAxis: !0
|
|
300
300
|
})]
|
|
301
|
-
}).then(({ x: e, y: n, middlewareData:
|
|
302
|
-
if (!this._activeSubmenus.includes(t) ||
|
|
303
|
-
let a =
|
|
301
|
+
}).then(({ x: e, y: n, middlewareData: i }) => {
|
|
302
|
+
if (!this._activeSubmenus.includes(t) || r !== this._submenuPositionEpochs.get(t.panel)) return;
|
|
303
|
+
let a = i.shift?.x ?? 0, o = i.shift?.y ?? 0, s = a < 0 ? "right" : "left", c = o < 0 ? "bottom" : "top";
|
|
304
304
|
t.panel.style.left = `${e}px`, t.panel.style.top = `${n}px`, t.panel.style.setProperty("--wui-internal-overlay-transform-origin", `${c} ${s}`), t.panel.style.visibility = "";
|
|
305
305
|
});
|
|
306
306
|
return;
|
|
307
307
|
}
|
|
308
|
-
let n = e.getBoundingClientRect(),
|
|
309
|
-
t.panel.style.left = `${
|
|
308
|
+
let n = e.getBoundingClientRect(), r = t.panel.getBoundingClientRect(), i = n.right + r.width + 8 <= window.innerWidth, a = i ? n.right : Math.max(8, n.left - r.width), o = Math.min(Math.max(8, n.top), window.innerHeight - r.height - 8);
|
|
309
|
+
t.panel.style.left = `${a}px`, t.panel.style.top = `${o}px`, t.panel.style.setProperty("--wui-internal-overlay-transform-origin", i ? "top left" : "top right"), t.panel.style.visibility = "";
|
|
310
310
|
}
|
|
311
311
|
_dispatchChange(e) {
|
|
312
312
|
n(this, e);
|
|
@@ -323,12 +323,12 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
323
323
|
}
|
|
324
324
|
_getLevelItems(e) {
|
|
325
325
|
let t = this._getLevelContainer(e);
|
|
326
|
-
return t ?
|
|
326
|
+
return t ? p(t.content) : [];
|
|
327
327
|
}
|
|
328
328
|
_closeLastSubmenuOrMenu() {
|
|
329
329
|
if (this._activeSubmenus.length > 0) {
|
|
330
330
|
let e = this._activeSubmenus.length - 1, t = this._activeSubmenuItems[e];
|
|
331
|
-
this._closeSubmenusFrom(e),
|
|
331
|
+
this._closeSubmenusFrom(e), f(t), this._hoverBinder.bind();
|
|
332
332
|
} else this._closeFromUser();
|
|
333
333
|
}
|
|
334
334
|
_preventBackgroundScroll(e) {
|
|
@@ -344,7 +344,7 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
344
344
|
return this._menuHandle?.containsEvent(e) ?? !1;
|
|
345
345
|
}
|
|
346
346
|
render() {
|
|
347
|
-
return
|
|
347
|
+
return j`
|
|
348
348
|
<div class="context-menu-anchor">
|
|
349
349
|
<slot @slotchange=${this._onSlotChange}></slot>
|
|
350
350
|
</div>
|
|
@@ -354,21 +354,21 @@ var z = "wui-context-menu-item", B = 500, V = 5e3, H = 10, U = 1e3, W = "data-wu
|
|
|
354
354
|
this._hideMenuItems(), this._isOpen && this._scheduleRefresh();
|
|
355
355
|
}
|
|
356
356
|
};
|
|
357
|
-
e([
|
|
357
|
+
e([P({
|
|
358
358
|
type: Boolean,
|
|
359
359
|
reflect: !0
|
|
360
|
-
})], q.prototype, "disabled", void 0), e([
|
|
360
|
+
})], q.prototype, "disabled", void 0), e([P({
|
|
361
361
|
type: Boolean,
|
|
362
362
|
reflect: !0,
|
|
363
363
|
attribute: "no-scroll-lock"
|
|
364
|
-
})], q.prototype, "noScrollLock", void 0), e([
|
|
364
|
+
})], q.prototype, "noScrollLock", void 0), e([P({
|
|
365
365
|
type: Boolean,
|
|
366
366
|
reflect: !0,
|
|
367
367
|
attribute: "long-press"
|
|
368
|
-
})], q.prototype, "longPress", void 0), e([
|
|
368
|
+
})], q.prototype, "longPress", void 0), e([P({
|
|
369
369
|
type: Number,
|
|
370
370
|
attribute: "long-press-delay"
|
|
371
|
-
})], q.prototype, "longPressDelay", null), e([
|
|
371
|
+
})], q.prototype, "longPressDelay", null), e([F()], q.prototype, "_isOpen", void 0), e([F()], q.prototype, "_x", void 0), e([F()], q.prototype, "_y", void 0), q = e([N("web-ui-context-menu")], q);
|
|
372
372
|
//#endregion
|
|
373
373
|
export { q as WebUiContextMenu };
|
|
374
374
|
|