@greypan/web-ui 2.1.7 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.CN.md +95 -41
  2. package/README.md +100 -42
  3. package/dist/assets/glass.js.map +1 -1
  4. package/dist/assets/menu-portal.js +1 -1
  5. package/dist/assets/menu-portal.js.map +1 -1
  6. package/dist/components/autocomplete/index.d.ts +121 -0
  7. package/dist/components/autocomplete/index.js +414 -0
  8. package/dist/components/autocomplete/index.js.map +1 -0
  9. package/dist/components/autocomplete/style.js +6 -0
  10. package/dist/components/autocomplete/style.js.map +1 -0
  11. package/dist/components/avatar/index.d.ts +0 -1
  12. package/dist/components/avatar/index.js +9 -9
  13. package/dist/components/avatar/index.js.map +1 -1
  14. package/dist/components/back-top/index.d.ts +0 -1
  15. package/dist/components/back-top/index.js +1 -1
  16. package/dist/components/back-top/index.js.map +1 -1
  17. package/dist/components/badge/index.d.ts +0 -1
  18. package/dist/components/badge/index.js +5 -5
  19. package/dist/components/badge/index.js.map +1 -1
  20. package/dist/components/button/index.d.ts +6 -2
  21. package/dist/components/button/index.js +40 -19
  22. package/dist/components/button/index.js.map +1 -1
  23. package/dist/components/button/style.js +1 -1
  24. package/dist/components/button/style.js.map +1 -1
  25. package/dist/components/button-group/index.d.ts +0 -1
  26. package/dist/components/button-group/index.js.map +1 -1
  27. package/dist/components/checkbox/index.d.ts +0 -3
  28. package/dist/components/checkbox/index.js +7 -5
  29. package/dist/components/checkbox/index.js.map +1 -1
  30. package/dist/components/checkbox-group/index.js +2 -2
  31. package/dist/components/checkbox-group/index.js.map +1 -1
  32. package/dist/components/context-menu/index.d.ts +4 -3
  33. package/dist/components/context-menu/index.js +47 -50
  34. package/dist/components/context-menu/index.js.map +1 -1
  35. package/dist/components/dialog/index.d.ts +1 -1
  36. package/dist/components/dialog/index.js +20 -19
  37. package/dist/components/dialog/index.js.map +1 -1
  38. package/dist/components/drawer/index.d.ts +2 -3
  39. package/dist/components/drawer/index.js +43 -33
  40. package/dist/components/drawer/index.js.map +1 -1
  41. package/dist/components/drawer/style.js +1 -1
  42. package/dist/components/drawer/style.js.map +1 -1
  43. package/dist/components/dropdown/index.d.ts +2 -9
  44. package/dist/components/dropdown/index.js +58 -53
  45. package/dist/components/dropdown/index.js.map +1 -1
  46. package/dist/components/dropdown-divider/index.d.ts +0 -1
  47. package/dist/components/dropdown-divider/index.js.map +1 -1
  48. package/dist/components/dropdown-header/index.d.ts +0 -1
  49. package/dist/components/dropdown-header/index.js.map +1 -1
  50. package/dist/components/dropdown-item/index.d.ts +0 -2
  51. package/dist/components/dropdown-item/index.js.map +1 -1
  52. package/dist/components/dropdown-item/style.js +1 -1
  53. package/dist/components/dropdown-item/style.js.map +1 -1
  54. package/dist/components/empty/index.d.ts +0 -1
  55. package/dist/components/empty/index.js +6 -6
  56. package/dist/components/empty/index.js.map +1 -1
  57. package/dist/components/icon/index.d.ts +0 -1
  58. package/dist/components/icon/index.js.map +1 -1
  59. package/dist/components/index.d.ts +5 -0
  60. package/dist/components/index.js +36 -35
  61. package/dist/components/input/index.d.ts +3 -0
  62. package/dist/components/input/index.js +48 -24
  63. package/dist/components/input/index.js.map +1 -1
  64. package/dist/components/input/style.js +1 -1
  65. package/dist/components/input/style.js.map +1 -1
  66. package/dist/components/input-number/index.d.ts +2 -0
  67. package/dist/components/input-number/index.js +25 -12
  68. package/dist/components/input-number/index.js.map +1 -1
  69. package/dist/components/input-number/style.js +1 -1
  70. package/dist/components/input-number/style.js.map +1 -1
  71. package/dist/components/layout/index.d.ts +0 -1
  72. package/dist/components/layout/index.js +4 -4
  73. package/dist/components/layout/index.js.map +1 -1
  74. package/dist/components/option/index.d.ts +0 -11
  75. package/dist/components/option/index.js +1 -1
  76. package/dist/components/option/index.js.map +1 -1
  77. package/dist/components/option/style.js +1 -1
  78. package/dist/components/option/style.js.map +1 -1
  79. package/dist/components/popover/index.d.ts +1 -5
  80. package/dist/components/popover/index.js +42 -37
  81. package/dist/components/popover/index.js.map +1 -1
  82. package/dist/components/radio/index.d.ts +0 -3
  83. package/dist/components/radio/index.js +8 -5
  84. package/dist/components/radio/index.js.map +1 -1
  85. package/dist/components/radio-group/index.js +2 -2
  86. package/dist/components/radio-group/index.js.map +1 -1
  87. package/dist/components/segmented/index.js +8 -4
  88. package/dist/components/segmented/index.js.map +1 -1
  89. package/dist/components/segmented-trigger/index.d.ts +1 -0
  90. package/dist/components/segmented-trigger/index.js +12 -3
  91. package/dist/components/segmented-trigger/index.js.map +1 -1
  92. package/dist/components/segmented-trigger/style.js +1 -1
  93. package/dist/components/segmented-trigger/style.js.map +1 -1
  94. package/dist/components/select/index.d.ts +0 -1
  95. package/dist/components/select/index.js +22 -31
  96. package/dist/components/select/index.js.map +1 -1
  97. package/dist/components/select/style.js +1 -1
  98. package/dist/components/select/style.js.map +1 -1
  99. package/dist/components/slider/index.d.ts +0 -2
  100. package/dist/components/slider/index.js +1 -1
  101. package/dist/components/slider/index.js.map +1 -1
  102. package/dist/components/spinner/index.d.ts +0 -3
  103. package/dist/components/spinner/index.js.map +1 -1
  104. package/dist/components/svg-draw-lines/index.d.ts +0 -3
  105. package/dist/components/svg-draw-lines/index.js.map +1 -1
  106. package/dist/components/switch/index.d.ts +0 -1
  107. package/dist/components/switch/index.js +6 -6
  108. package/dist/components/switch/index.js.map +1 -1
  109. package/dist/components/switch/style.js +1 -1
  110. package/dist/components/switch/style.js.map +1 -1
  111. package/dist/components/textarea/index.d.ts +1 -0
  112. package/dist/components/textarea/index.js +51 -34
  113. package/dist/components/textarea/index.js.map +1 -1
  114. package/dist/components/textarea/style.js +1 -1
  115. package/dist/components/textarea/style.js.map +1 -1
  116. package/dist/components/theme/index.d.ts +0 -3
  117. package/dist/components/theme/index.js.map +1 -1
  118. package/dist/components/toast/manager.js.map +1 -1
  119. package/dist/components/toast/style.js +1 -1
  120. package/dist/components/toast/style.js.map +1 -1
  121. package/dist/components/toast/toast.d.ts +0 -4
  122. package/dist/components/toast/toast.js +25 -17
  123. package/dist/components/toast/toast.js.map +1 -1
  124. package/dist/components/toast/types.d.ts +0 -3
  125. package/dist/components/tooltip/index.d.ts +1 -0
  126. package/dist/components/tooltip/index.js +34 -33
  127. package/dist/components/tooltip/index.js.map +1 -1
  128. package/dist/shared/events/user-change.js +17 -0
  129. package/dist/shared/events/user-change.js.map +1 -0
  130. package/dist/shared/menu-portal/menu-portal.js +10 -11
  131. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  132. package/dist/shared/normalize/index.js.map +1 -1
  133. package/dist/shared/overlay/anchored-panel.js +12 -12
  134. package/dist/shared/overlay/native-dialog-presence.js +8 -3
  135. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  136. package/dist/shared/overlay/overlay.js +55 -33
  137. package/dist/shared/overlay/overlay.js.map +1 -1
  138. package/dist/shared/overlay/portal.js +27 -13
  139. package/dist/shared/overlay/portal.js.map +1 -1
  140. package/dist/shared/overlay/presence.js.map +1 -1
  141. package/dist/shared/scroll-lock/scroll-lock.js +13 -12
  142. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  143. package/dist/shared/theme/overlay-root.js +3 -3
  144. package/dist/types/react.d.ts +15 -41
  145. package/dist/types/utils.d.ts +33 -4
  146. package/dist/types/vue.d.ts +17 -49
  147. package/package.json +11 -6
@@ -1,14 +1,15 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
2
2
  import t from "../../assets/glass.js";
3
- import { normalizeLiteral as n, normalizeNumber as r } from "../../shared/normalize/index.js";
4
- import i from "../../assets/overlay-motion.js";
3
+ import n from "../../assets/overlay-motion.js";
4
+ import { normalizeLiteral as r, normalizeNumber as i } from "../../shared/normalize/index.js";
5
5
  import { defineAnchoredPanel as a } from "../../shared/overlay/anchored-panel.js";
6
- import { createOverlayPortal as o } from "../../shared/overlay/portal.js";
7
- import s from "./style.js";
8
- import { LitElement as c, html as l, unsafeCSS as u } from "lit";
9
- import { customElement as d, property as f } from "lit/decorators.js";
6
+ import { defineOverlayPortal as o } from "../../shared/overlay/portal.js";
7
+ import { UserChangeController as s } from "../../shared/events/user-change.js";
8
+ import c from "./style.js";
9
+ import { LitElement as l, html as u, unsafeCSS as d } from "lit";
10
+ import { customElement as f, property as p } from "lit/decorators.js";
10
11
  //#region src/components/popover/index.ts
11
- var p = [
12
+ var m = [
12
13
  "top",
13
14
  "top-start",
14
15
  "top-end",
@@ -21,13 +22,13 @@ var p = [
21
22
  "right",
22
23
  "right-start",
23
24
  "right-end"
24
- ], m = [
25
+ ], h = [
25
26
  "click",
26
27
  "hover",
27
28
  "manual"
28
- ], h = 0, g = class extends c {
29
+ ], g = 0, _ = class extends l {
29
30
  constructor(...e) {
30
- super(...e), this.open = !1, this.disabled = !1, this._placement = "bottom", this._offset = 8, this._trigger = "click", this.portal = !1, this._suppressEvent = !1, this._shouldOpenInstantly = !0, this._panelId = `wui-popover-panel-${++h}`, this._panel = a().make({
31
+ super(...e), this.open = !1, this.disabled = !1, this._placement = "bottom", this._offset = 8, this._trigger = "click", this.portal = !1, this._userOpenChange = new s(), this._shouldOpenInstantly = !0, this._panelId = `wui-popover-panel-${++g}`, this._panel = a().make({
31
32
  getAnchor: () => this.shadowRoot?.querySelector(".popover-trigger") ?? null,
32
33
  getLocalPanel: () => this.shadowRoot?.querySelector(".popover-panel") ?? null,
33
34
  getPositioning: () => ({
@@ -38,32 +39,36 @@ var p = [
38
39
  isPortal: () => this.portal,
39
40
  createPortal: () => this._createPortal()
40
41
  }), this._onTriggerClick = (e) => {
41
- this.disabled || (clearTimeout(this._showTimer), clearTimeout(this._hideTimer), this.trigger !== "hover" && (this.open || (this._shouldOpenInstantly = e.detail === 0), this.toggle()));
42
+ this.disabled || (clearTimeout(this._showTimer), clearTimeout(this._hideTimer), this.trigger !== "hover" && (this.open || (this._shouldOpenInstantly = e.detail === 0), this._userOpenChange.mark(), this.toggle()));
42
43
  }, this._onClickOutside = (e) => {
43
- this.open && this.trigger !== "manual" && this.trigger !== "hover" && (e.target instanceof Node && this.portal && this._panel.getPanel()?.contains(e.target) || this._isInsideShadowRoot(e) || (this.open = !1));
44
+ this.open && this.trigger !== "manual" && this.trigger !== "hover" && (e.target instanceof Node && this.portal && this._panel.getPanel()?.contains(e.target) || this._isInsideShadowRoot(e) || (this._userOpenChange.mark(), this.open = !1));
44
45
  }, this._onFocusOut = () => {
45
46
  this.trigger !== "manual" && this.trigger !== "hover" && requestAnimationFrame(() => {
46
- this.open && !this.matches(":focus-within") && !this._panel.getPanel()?.matches(":focus-within") && (this.open = !1);
47
+ this.open && !this.matches(":focus-within") && !this._panel.getPanel()?.matches(":focus-within") && (this._userOpenChange.mark(), this.open = !1);
47
48
  });
48
49
  }, this._onKeydown = (e) => {
49
- this.open && this.trigger !== "manual" && e.key === "Escape" && (this.open = !1, e.preventDefault());
50
+ this.open && this.trigger !== "manual" && e.key === "Escape" && (this._userOpenChange.mark(), this.open = !1, e.preventDefault());
50
51
  }, this._onPointerEnter = (e) => {
51
52
  e.pointerType !== "touch" && (this.disabled || this.trigger !== "hover" || (clearTimeout(this._hideTimer), this._showTimer = setTimeout(() => {
52
- this._shouldOpenInstantly = !1, this.show();
53
+ this._shouldOpenInstantly = !1, !this.open && (this._userOpenChange.mark(), this.show());
53
54
  }, 100)));
54
55
  }, this._onPointerLeave = (e) => {
55
- e.pointerType !== "touch" && (this.disabled || this.trigger !== "hover" || (clearTimeout(this._showTimer), this._hideTimer = setTimeout(() => this.close(), 100)));
56
+ e.pointerType !== "touch" && (this.disabled || this.trigger !== "hover" || (clearTimeout(this._showTimer), this._hideTimer = setTimeout(() => {
57
+ this.open && (this._userOpenChange.mark(), this.close());
58
+ }, 100)));
56
59
  }, this._onPanelPointerEnter = (e) => {
57
60
  e.pointerType !== "touch" && this.trigger === "hover" && clearTimeout(this._hideTimer);
58
61
  }, this._onPanelPointerLeave = (e) => {
59
- e.pointerType !== "touch" && this.trigger === "hover" && (this._hideTimer = setTimeout(() => this.close(), 100));
62
+ e.pointerType !== "touch" && this.trigger === "hover" && (this._hideTimer = setTimeout(() => {
63
+ this.open && (this._userOpenChange.mark(), this.close());
64
+ }, 100));
60
65
  };
61
66
  }
62
67
  static {
63
68
  this.styles = [
64
- u(t),
65
- u(i),
66
- u(s)
69
+ d(t),
70
+ d(n),
71
+ d(c)
67
72
  ];
68
73
  }
69
74
  get placement() {
@@ -71,21 +76,21 @@ var p = [
71
76
  }
72
77
  set placement(e) {
73
78
  let t = this._placement;
74
- this._placement = n(e, p, "bottom"), this.requestUpdate("placement", t);
79
+ this._placement = r(e, m, "bottom"), this.requestUpdate("placement", t);
75
80
  }
76
81
  get offset() {
77
82
  return this._offset;
78
83
  }
79
84
  set offset(e) {
80
85
  let t = this._offset;
81
- this._offset = r(e, 0, 100, 8), this.requestUpdate("offset", t);
86
+ this._offset = i(e, 0, 100, 8), this.requestUpdate("offset", t);
82
87
  }
83
88
  get trigger() {
84
89
  return this._trigger;
85
90
  }
86
91
  set trigger(e) {
87
92
  let t = this._trigger;
88
- this._trigger = n(e, m, "click"), this.requestUpdate("trigger", t);
93
+ this._trigger = r(e, h, "click"), this.requestUpdate("trigger", t);
89
94
  }
90
95
  get isOpen() {
91
96
  return this.open;
@@ -102,15 +107,15 @@ var p = [
102
107
  updated(e) {
103
108
  if (e.has("portal") || e.has("overlayContainer") ? requestAnimationFrame(() => this._reconfigureOverlay()) : (e.has("placement") || e.has("offset")) && requestAnimationFrame(() => this._panel.updatePosition()), e.has("open")) if (this.open) {
104
109
  let e = this._shouldOpenInstantly;
105
- this._shouldOpenInstantly = !0, requestAnimationFrame(() => this._openOverlay(e)), this._dispatchChange(!0), this._focusPanel();
106
- } else this._returnFocus(), this._closeOverlay(), this._suppressEvent || this._dispatchChange(!1);
110
+ this._shouldOpenInstantly = !0, requestAnimationFrame(() => this._openOverlay(e)), this._userOpenChange.consume() && this._dispatchChange(!0), this._focusPanel();
111
+ } else this._returnFocus(), this._closeOverlay(), this._userOpenChange.consume() && this._dispatchChange(!1);
107
112
  e.has("trigger") && (this.removeEventListener("pointerenter", this._onPointerEnter), this.removeEventListener("pointerleave", this._onPointerLeave), clearTimeout(this._showTimer), clearTimeout(this._hideTimer), this._syncTriggerListeners());
108
113
  }
109
114
  show() {
110
- this.disabled || this.open || (this._suppressEvent = !0, this.open = !0, this._suppressEvent = !1);
115
+ this.disabled || this.open || (this.open = !0);
111
116
  }
112
117
  close() {
113
- this.open && (this._suppressEvent = !0, this.open = !1, this._suppressEvent = !1);
118
+ this.open &&= !1;
114
119
  }
115
120
  toggle() {
116
121
  this.open ? this.close() : this.show();
@@ -126,10 +131,10 @@ var p = [
126
131
  this._panel.open(e);
127
132
  }
128
133
  _createPortal() {
129
- let e = o({
134
+ let e = o().make({
130
135
  container: this.overlayContainer,
131
136
  target: this,
132
- style: `${t}\n${i}\n${s}`,
137
+ style: `${t}\n${n}\n${c}`,
133
138
  className: "popover-panel portal wui-glass wui-floating-panel"
134
139
  });
135
140
  return e.panel.id = this._panelId, e.panel.setAttribute("role", "dialog"), e.panel.tabIndex = -1, e.panel.addEventListener("pointerenter", this._onPanelPointerEnter), e.panel.addEventListener("pointerleave", this._onPanelPointerLeave), e.moveContent(Array.from(this.childNodes).filter((e) => !(e instanceof HTMLElement && e.slot === "trigger"))), e;
@@ -161,7 +166,7 @@ var p = [
161
166
  return e instanceof HTMLElement ? e : null;
162
167
  }
163
168
  render() {
164
- return l`
169
+ return u`
165
170
  <div class="popover-anchor">
166
171
  <div
167
172
  class="popover-trigger"
@@ -186,23 +191,23 @@ var p = [
186
191
  `;
187
192
  }
188
193
  };
189
- e([f({
194
+ e([p({
190
195
  type: Boolean,
191
196
  reflect: !0
192
- })], g.prototype, "open", void 0), e([f({
197
+ })], _.prototype, "open", void 0), e([p({
193
198
  type: Boolean,
194
199
  reflect: !0
195
- })], g.prototype, "disabled", void 0), e([f({
200
+ })], _.prototype, "disabled", void 0), e([p({
196
201
  type: String,
197
202
  reflect: !0
198
- })], g.prototype, "placement", null), e([f({ type: Number })], g.prototype, "offset", null), e([f({
203
+ })], _.prototype, "placement", null), e([p({ type: Number })], _.prototype, "offset", null), e([p({
199
204
  type: String,
200
205
  reflect: !0
201
- })], g.prototype, "trigger", null), e([f({
206
+ })], _.prototype, "trigger", null), e([p({
202
207
  type: Boolean,
203
208
  reflect: !0
204
- })], g.prototype, "portal", void 0), e([f({ attribute: !1 })], g.prototype, "overlayContainer", void 0), g = e([d("web-ui-popover")], g);
209
+ })], _.prototype, "portal", void 0), e([p({ attribute: !1 })], _.prototype, "overlayContainer", void 0), _ = e([f("web-ui-popover")], _);
205
210
  //#endregion
206
- export { g as WebUiPopover };
211
+ export { _ as WebUiPopover };
207
212
 
208
213
  //# sourceMappingURL=index.js.map
@@ -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 { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { createOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = [\n 'top',\n 'top-start',\n 'top-end',\n 'bottom',\n 'bottom-start',\n 'bottom-end',\n 'left',\n 'left-start',\n 'left-end',\n 'right',\n 'right-start',\n 'right-end'\n] as const\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, ALLOWED_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 _suppressEvent = false\n private _shouldOpenInstantly = true\n\n private _panelId = `wui-popover-panel-${++popoverIdCounter}`\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 /** 当前是否打开 */\n get isOpen(): boolean {\n return this.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\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 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 clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._panel.dispose()\n }\n\n override firstUpdated() {\n if (this.open) {\n requestAnimationFrame(() => this._openOverlay(this._shouldOpenInstantly))\n this._shouldOpenInstantly = true\n }\n }\n\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('portal') || changed.has('overlayContainer'))\n requestAnimationFrame(() => 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 requestAnimationFrame(() => this._openOverlay(isInstant))\n this._dispatchChange(true)\n this._focusPanel()\n } else {\n this._returnFocus()\n void this._closeOverlay()\n if (!this._suppressEvent) 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 /** 打开 popover */\n show() {\n if (this.disabled || this.open) return\n this._suppressEvent = true\n this.open = true\n this._suppressEvent = false\n }\n\n /** 关闭 popover */\n close() {\n if (!this.open) return\n this._suppressEvent = true\n this.open = false\n this._suppressEvent = false\n }\n\n /** 切换 popover */\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 }\n\n private _createPortal(): OverlayPortal {\n const portal = createOverlayPortal({\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 })\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(\n Array.from(this.childNodes).filter(node => !(node instanceof HTMLElement && node.slot === 'trigger'))\n )\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n this._panel.reconfigure(this.open)\n }\n\n private _dispatchChange(open: boolean) {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _focusPanel() {\n requestAnimationFrame(() => {\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.toggle()\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this.open) return\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n if (e.target instanceof Node && this.portal && this._panel.getPanel()?.contains(e.target)) return\n if (this._isInsideShadowRoot(e)) return\n this.open = false\n }\n\n private _onFocusOut = () => {\n if (this.trigger === 'manual' || this.trigger === 'hover') return\n\n requestAnimationFrame(() => {\n if (this.open && !this.matches(':focus-within') && !this._panel.getPanel()?.matches(':focus-within')) {\n this.open = false\n }\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.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 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(() => this.close(), 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(() => this.close(), 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-glass wui-floating-panel\"\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 { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { defineOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = [\n 'top',\n 'top-start',\n 'top-end',\n 'bottom',\n 'bottom-start',\n 'bottom-end',\n 'left',\n 'left-start',\n 'left-end',\n 'right',\n 'right-start',\n 'right-end'\n] as const\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, ALLOWED_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 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 // 当前是否打开\n get isOpen(): boolean {\n return this.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\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 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 clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._panel.dispose()\n }\n\n override firstUpdated() {\n if (this.open) {\n requestAnimationFrame(() => this._openOverlay(this._shouldOpenInstantly))\n this._shouldOpenInstantly = true\n }\n }\n\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('portal') || changed.has('overlayContainer'))\n requestAnimationFrame(() => 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 requestAnimationFrame(() => this._openOverlay(isInstant))\n if (this._userOpenChange.consume()) this._dispatchChange(true)\n this._focusPanel()\n } else {\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 // 打开 popover\n show() {\n if (this.disabled || this.open) return\n this.open = true\n }\n\n // 关闭 popover\n close() {\n if (!this.open) return\n this.open = false\n }\n\n // 切换 popover\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 }\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 })\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(\n Array.from(this.childNodes).filter(node => !(node instanceof HTMLElement && node.slot === 'trigger'))\n )\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n this._panel.reconfigure(this.open)\n }\n\n private _dispatchChange(open: boolean) {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _focusPanel() {\n requestAnimationFrame(() => {\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 if (e.target instanceof Node && this.portal && this._panel.getPanel()?.contains(e.target)) 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 requestAnimationFrame(() => {\n if (this.open && !this.matches(':focus-within') && !this._panel.getPanel()?.matches(':focus-within')) {\n this._userOpenChange.mark()\n this.open = false\n }\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-glass wui-floating-panel\"\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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"}
@@ -2,11 +2,9 @@ import { LitElement } from 'lit';
2
2
  export declare class WebUiRadio extends LitElement {
3
3
  static styles: import('lit').CSSResult;
4
4
  static formAssociated: boolean;
5
- /** 内部表单关联实例(connectedCallback 中初始化) */
6
5
  private _internals?;
7
6
  private _formDisabled;
8
7
  private _groupDisabled;
9
- /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */
10
8
  private _checked;
11
9
  get checked(): boolean;
12
10
  set checked(v: boolean);
@@ -23,7 +21,6 @@ export declare class WebUiRadio extends LitElement {
23
21
  updated(): void;
24
22
  private _syncFormValue;
25
23
  private _syncValidity;
26
- /** 用户点击选中(已选中时不重复触发) */
27
24
  private handleClick;
28
25
  private handleKeyDown;
29
26
  render(): import('lit').TemplateResult<1>;
@@ -55,13 +55,16 @@ var l = class extends n {
55
55
  }
56
56
  }
57
57
  handleClick() {
58
- this._isDisabled || this._checked || (this._checked = !0, this._syncFormValue(), this.requestUpdate("checked", !1), this.dispatchEvent(new Event("input", {
58
+ if (this._isDisabled || this._checked) return;
59
+ this._checked = !0, this._syncFormValue(), this.requestUpdate("checked", !1);
60
+ let e = this._isManagedByGroup ? {
61
+ bubbles: !1,
62
+ composed: !1
63
+ } : {
59
64
  bubbles: !0,
60
65
  composed: !0
61
- })), this.dispatchEvent(new Event("change", {
62
- bubbles: !0,
63
- composed: !0
64
- })));
66
+ };
67
+ this.dispatchEvent(new Event("input", e)), this.dispatchEvent(new Event("change", e));
65
68
  }
66
69
  handleKeyDown(e) {
67
70
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.handleClick());
@@ -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 style from './style.css?inline'\n\n@customElement('web-ui-radio')\nexport class WebUiRadio extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n /** 内部表单关联实例(connectedCallback 中初始化) */\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n /** 内部 checked 状态,通过 getter/setter 暴露为公共 API */\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._syncFormValue()\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 this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-radio-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n /** 用户点击选中(已选中时不重复触发) */\n private handleClick() {\n if (this._isDisabled || this._checked) return\n this._checked = true\n this._syncFormValue()\n this.requestUpdate('checked', false)\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\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
+ {"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 style from './style.css?inline'\n\n@customElement('web-ui-radio')\nexport class WebUiRadio extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\n // 内部表单关联实例(connectedCallback 中初始化)\n private _internals?: ElementInternals\n @state() private _formDisabled = false\n @state() private _groupDisabled = false\n\n // 内部 checked 状态,通过 getter/setter 暴露为公共 API\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._syncFormValue()\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 this.disabled || this._formDisabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-radio-group') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (this._internals) return\n this._internals = this.attachInternals()\n if (this.hasAttribute('checked')) {\n this._checked = true\n }\n this._syncFormValue()\n }\n\n formResetCallback() {\n this.checked = this.hasAttribute('checked')\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override updated() {\n this._syncFormValue()\n this._syncValidity()\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(!this._isManagedByGroup && this._checked ? this.value || 'on' : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n this._internals.setValidity({})\n return\n }\n this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n // 用户点击选中(已选中时不重复触发)\n private handleClick() {\n if (this._isDisabled || this._checked) return\n this._checked = true\n this._syncFormValue()\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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"}
@@ -26,10 +26,10 @@ var c = class extends n {
26
26
  connectedCallback() {
27
27
  super.connectedCallback(), this._internals ||= this.attachInternals();
28
28
  let e = this.getAttribute("value");
29
- e !== null && (this.value = e), this._initialValue = this._value, this.addEventListener("change", this._handleChildChange);
29
+ e !== null && (this.value = e), this._initialValue = this._value, this.addEventListener("change", this._handleChildChange, !0);
30
30
  }
31
31
  disconnectedCallback() {
32
- super.disconnectedCallback(), this.removeEventListener("change", this._handleChildChange);
32
+ super.disconnectedCallback(), this.removeEventListener("change", this._handleChildChange, !0);
33
33
  }
34
34
  updated(e) {
35
35
  (e.has("value") || e.has("disabled") || e.has("_formDisabled")) && this._syncValueToChildren(), this._syncFormValue(), this._syncValidity();
@@ -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 type { WebUiRadio } from '../radio'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-radio-group')\nexport class WebUiRadioGroup extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\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 _internals?: ElementInternals\n @state() private _value = ''\n @state() private _formDisabled = false\n private _initialValue = ''\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._syncFormValue()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (!this._internals) this._internals = this.attachInternals()\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue\n this._initialValue = this._value\n this.addEventListener('change', this._handleChildChange)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('change', this._handleChildChange)\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') || changed.has('disabled') || changed.has('_formDisabled')) this._syncValueToChildren()\n this._syncFormValue()\n this._syncValidity()\n }\n\n formResetCallback() {\n this.value = this._initialValue\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(this.name && this._value ? this._value : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value) this._internals.setValidity({})\n else this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n private _syncValueToChildren() {\n this.querySelectorAll<WebUiRadio>('web-ui-radio').forEach(radio => {\n radio.checked = radio.value === this._value\n radio.setGroupDisabled(this._isDisabled)\n })\n }\n\n private _handleChildChange(e: Event) {\n if (this._isDisabled) return\n const target = e.target as HTMLElement\n if (!target.matches?.('web-ui-radio')) return\n\n const radio = target as WebUiRadio\n if (!radio.checked || radio.value === this._value) return\n\n this.value = radio.value\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _handleSlotChange() {\n this._syncValueToChildren()\n }\n\n override render() {\n return html`<div class=\"wui-radio-group\"><slot @slotchange=${this._handleSlotChange}></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
+ {"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 type { WebUiRadio } from '../radio'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-radio-group')\nexport class WebUiRadioGroup extends LitElement {\n static override styles = unsafeCSS(style)\n static formAssociated = true\n\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 _internals?: ElementInternals\n @state() private _value = ''\n @state() private _formDisabled = false\n private _initialValue = ''\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._syncFormValue()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n override connectedCallback() {\n super.connectedCallback()\n if (!this._internals) this._internals = this.attachInternals()\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue\n this._initialValue = this._value\n // group-managed 子项以 bubbles:false 派发 change,须用 capture 相位才能观察到子项事件,\n // 同时该事件不会冒泡到 group 外部的同名监听器\n this.addEventListener('change', this._handleChildChange, true)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('change', this._handleChildChange, true)\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('value') || changed.has('disabled') || changed.has('_formDisabled')) this._syncValueToChildren()\n this._syncFormValue()\n this._syncValidity()\n }\n\n formResetCallback() {\n this.value = this._initialValue\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n private _syncFormValue() {\n this._internals?.setFormValue?.(this.name && this._value ? this._value : null)\n }\n\n private _syncValidity() {\n if (!this._internals || typeof this._internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value) this._internals.setValidity({})\n else this._internals.setValidity({ valueMissing: true }, '请选择一项')\n }\n\n private _syncValueToChildren() {\n this.querySelectorAll<WebUiRadio>('web-ui-radio').forEach(radio => {\n radio.checked = radio.value === this._value\n radio.setGroupDisabled(this._isDisabled)\n })\n }\n\n private _handleChildChange(e: Event) {\n if (this._isDisabled) return\n const target = e.target as HTMLElement\n if (!target.matches?.('web-ui-radio')) return\n\n const radio = target as WebUiRadio\n if (!radio.checked || radio.value === this._value) return\n\n this.value = radio.value\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n private _handleSlotChange() {\n this._syncValueToChildren()\n }\n\n override render() {\n return html`<div class=\"wui-radio-group\"><slot @slotchange=${this._handleSlotChange}></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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"}
@@ -47,13 +47,13 @@ var u = class extends r {
47
47
  connectedCallback() {
48
48
  super.connectedCallback(), this._internals = this.attachInternals();
49
49
  let e = this.getAttribute("value");
50
- e !== null && this._value === "" && (this._value = e), this._initialValue = e ?? "", this._internals?.setFormValue?.(this._value), this.childObserver.observe(this, { childList: !0 }), this.addEventListener("change", this._handleChildChange);
50
+ e !== null && this._value === "" && (this._value = e), this._initialValue = e ?? "", this._internals?.setFormValue?.(this._value), this.childObserver.observe(this, { childList: !0 }), this.addEventListener("change", this._handleChildChange, !0);
51
51
  }
52
52
  firstUpdated() {
53
53
  this._syncPropsToChildren(), requestAnimationFrame(() => this._updateIndicator());
54
54
  }
55
55
  disconnectedCallback() {
56
- super.disconnectedCallback(), this.childObserver.disconnect(), this.removeEventListener("change", this._handleChildChange);
56
+ super.disconnectedCallback(), this.childObserver.disconnect(), this.removeEventListener("change", this._handleChildChange, !0);
57
57
  }
58
58
  _handleChildChange(e) {
59
59
  if (this._isDisabled) return;
@@ -76,10 +76,14 @@ var u = class extends r {
76
76
  }
77
77
  render() {
78
78
  return i`
79
- <div class=${l({
79
+ <div
80
+ class=${l({
80
81
  "wui-segmented": !0,
81
82
  "is-disabled": this._isDisabled
82
- })}>
83
+ })}
84
+ role="listbox"
85
+ aria-orientation="horizontal"
86
+ >
83
87
  <span class="wui-segmented-indicator wui-glass"></span>
84
88
  <slot></slot>
85
89
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport glass from '@/assets/glass.css?inline'\n\nimport type { WebUiSegmentedTrigger } from '../segmented-trigger'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented')\nexport class WebUiSegmented extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n static formAssociated = true\n\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 _internals?: ElementInternals\n @state() private _value = ''\n @state() private _formDisabled = false\n private _initialValue = ''\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._internals?.setFormValue?.(v)\n this.requestUpdate('value', old)\n }\n\n private readonly childObserver = new MutationObserver(() => {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n })\n\n private _syncPropsToChildren() {\n this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger').forEach(trigger => {\n trigger.checked = trigger.value === this._value\n trigger.setGroupDisabled(this._isDisabled)\n })\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n private _updateIndicator() {\n const triggers = this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger')\n let left = 0\n let width = 0\n\n triggers.forEach(trigger => {\n if (trigger.value === this._value) {\n const triggerRect = trigger.getBoundingClientRect()\n const groupRect = this.getBoundingClientRect()\n left = triggerRect.left - groupRect.left\n width = triggerRect.width\n }\n })\n\n this.style.setProperty('--indicator-left', `${left}px`)\n this.style.setProperty('--indicator-width', `${width}px`)\n }\n\n override updated(props: PropertyValues) {\n if (props.has('value') || props.has('disabled') || props.has('_formDisabled')) {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._internals = this.attachInternals()\n\n // 仅当属性在连接前未被 property setter 设值时,才从 attribute 读取初始值\n const attrValue = this.getAttribute('value')\n if (attrValue !== null && this._value === '') {\n this._value = attrValue\n }\n this._initialValue = attrValue ?? ''\n this._internals?.setFormValue?.(this._value)\n\n this.childObserver.observe(this, { childList: true })\n this.addEventListener('change', this._handleChildChange)\n }\n\n override firstUpdated() {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.childObserver.disconnect()\n this.removeEventListener('change', this._handleChildChange)\n }\n\n private _handleChildChange(e: Event) {\n if (this._isDisabled) return\n const target = e.target as HTMLElement\n if (!target.matches?.('web-ui-segmented-trigger')) return\n const trigger = target as WebUiSegmentedTrigger\n if (trigger.value === this._value) return\n\n this.value = trigger.value\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n formResetCallback() {\n this.value = this._initialValue\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override render() {\n return html`\n <div class=${classMap({ 'wui-segmented': true, 'is-disabled': this._isDisabled })}>\n <span class=\"wui-segmented-indicator wui-glass\"></span>\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented': WebUiSegmented\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport glass from '@/assets/glass.css?inline'\n\nimport type { WebUiSegmentedTrigger } from '../segmented-trigger'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-segmented')\nexport class WebUiSegmented extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n static formAssociated = true\n\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 _internals?: ElementInternals\n @state() private _value = ''\n @state() private _formDisabled = false\n private _initialValue = ''\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._internals?.setFormValue?.(v)\n this.requestUpdate('value', old)\n }\n\n private readonly childObserver = new MutationObserver(() => {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n })\n\n private _syncPropsToChildren() {\n this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger').forEach(trigger => {\n trigger.checked = trigger.value === this._value\n trigger.setGroupDisabled(this._isDisabled)\n })\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formDisabled\n }\n\n private _updateIndicator() {\n const triggers = this.querySelectorAll<WebUiSegmentedTrigger>('web-ui-segmented-trigger')\n let left = 0\n let width = 0\n\n triggers.forEach(trigger => {\n if (trigger.value === this._value) {\n const triggerRect = trigger.getBoundingClientRect()\n const groupRect = this.getBoundingClientRect()\n left = triggerRect.left - groupRect.left\n width = triggerRect.width\n }\n })\n\n this.style.setProperty('--indicator-left', `${left}px`)\n this.style.setProperty('--indicator-width', `${width}px`)\n }\n\n override updated(props: PropertyValues) {\n if (props.has('value') || props.has('disabled') || props.has('_formDisabled')) {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._internals = this.attachInternals()\n\n // 仅当属性在连接前未被 property setter 设值时,才从 attribute 读取初始值\n const attrValue = this.getAttribute('value')\n if (attrValue !== null && this._value === '') {\n this._value = attrValue\n }\n this._initialValue = attrValue ?? ''\n this._internals?.setFormValue?.(this._value)\n\n this.childObserver.observe(this, { childList: true })\n // group-managed 子项以 bubbles:false 派发 change,须用 capture 相位才能观察到子项事件,\n // 同时该事件不会冒泡到 segmented 外部的同名监听器\n this.addEventListener('change', this._handleChildChange, true)\n }\n\n override firstUpdated() {\n this._syncPropsToChildren()\n requestAnimationFrame(() => this._updateIndicator())\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.childObserver.disconnect()\n this.removeEventListener('change', this._handleChildChange, true)\n }\n\n private _handleChildChange(e: Event) {\n if (this._isDisabled) return\n const target = e.target as HTMLElement\n if (!target.matches?.('web-ui-segmented-trigger')) return\n const trigger = target as WebUiSegmentedTrigger\n if (trigger.value === this._value) return\n\n this.value = trigger.value\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n\n formResetCallback() {\n this.value = this._initialValue\n }\n\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled\n }\n\n override render() {\n return html`\n <div\n class=${classMap({ 'wui-segmented': true, 'is-disabled': this._isDisabled })}\n role=\"listbox\"\n aria-orientation=\"horizontal\"\n >\n <span class=\"wui-segmented-indicator wui-glass\"></span>\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented': WebUiSegmented\n }\n}\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ export declare class WebUiSegmentedTrigger extends LitElement {
6
6
  disabled: boolean;
7
7
  private _groupDisabled;
8
8
  private get _isDisabled();
9
+ private get _isManagedByGroup();
9
10
  setGroupDisabled(disabled: boolean): void;
10
11
  private handleClick;
11
12
  private handleKeyDown;
@@ -14,14 +14,23 @@ var l = class extends n {
14
14
  get _isDisabled() {
15
15
  return this.disabled || this._groupDisabled;
16
16
  }
17
+ get _isManagedByGroup() {
18
+ return this.closest("web-ui-segmented") !== null;
19
+ }
17
20
  setGroupDisabled(e) {
18
21
  this._groupDisabled = e;
19
22
  }
20
23
  handleClick() {
21
- this._isDisabled || this.checked || (this.checked = !0, this.dispatchEvent(new Event("change", {
24
+ if (this._isDisabled || this.checked) return;
25
+ this.checked = !0;
26
+ let e = this._isManagedByGroup ? {
27
+ bubbles: !1,
28
+ composed: !1
29
+ } : {
22
30
  bubbles: !0,
23
31
  composed: !0
24
- })));
32
+ };
33
+ this.dispatchEvent(new Event("change", e));
25
34
  }
26
35
  handleKeyDown(e) {
27
36
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.handleClick());
@@ -36,7 +45,7 @@ var l = class extends n {
36
45
  })}
37
46
  tabindex=${this._isDisabled ? "-1" : "0"}
38
47
  role="option"
39
- .ariaSelected=${String(this.checked)}
48
+ aria-selected=${String(this.checked)}
40
49
  aria-disabled=${String(this._isDisabled)}
41
50
  @click=${this.handleClick}
42
51
  @keydown=${this.handleKeyDown}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented-trigger/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 style from './style.css?inline'\n\n@customElement('web-ui-segmented-trigger')\nexport class WebUiSegmentedTrigger extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) checked = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @state() private _groupDisabled = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._groupDisabled\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n private handleClick() {\n if (this._isDisabled || this.checked) return\n this.checked = true\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\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-segmented-trigger': true,\n 'is-checked': this.checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <div\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"option\"\n .ariaSelected=${String(this.checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented-trigger': WebUiSegmentedTrigger\n }\n}\n"],"mappings":";;;;;;AAOO,IAAM,IAAN,cAAoC,EAAW;;EAMlB,aAHE,KAAA,QAAA,IACkB,KAAA,UAAA,IACC,KAAA,WAAA,IACrB,KAAA,iBAAA;;;EALT,KAAA,SAAA,EAAU,CAAK;;CAOxC,IAAY,cAAuB;EACjC,OAAO,KAAK,YAAY,KAAK;CAC/B;CAEA,iBAAiB,GAAmB;EAClC,KAAK,iBAAiB;CACxB;CAEA,cAAsB;EAChB,KAAK,eAAe,KAAK,YAC7B,KAAK,UAAU,IACf,KAAK,cAAc,IAAI,MAAM,UAAU;GAAE,SAAS;GAAM,UAAU;EAAK,CAAC,CAAC;CAC3E;CAEA,cAAsB,GAAkB;EACtC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,YAAY;CAErB;CAEA,SAAkB;EAOhB,OAAO,CAAI;;gBAEC,EAAS;GAPnB,yBAAyB;GACzB,cAAc,KAAK;GACnB,eAAe,KAAK;EAKD,CAAG,EAAE;mBACX,KAAK,cAAc,OAAO,IAAI;;wBAEzB,OAAO,KAAK,OAAO,EAAE;wBACrB,OAAO,KAAK,WAAW,EAAE;iBAChC,KAAK,YAAY;mBACf,KAAK,cAAc;;;;;CAKpC;AAKF;AAnDG,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,KAAA,CAAA,GACzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAPR,IAAA,EAAA,CAAA,EAAc,0BAA0B,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/segmented-trigger/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 style from './style.css?inline'\n\n@customElement('web-ui-segmented-trigger')\nexport class WebUiSegmentedTrigger extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: String }) value = ''\n @property({ type: Boolean, reflect: true }) checked = false\n @property({ type: Boolean, reflect: true }) disabled = false\n @state() private _groupDisabled = false\n\n private get _isDisabled(): boolean {\n return this.disabled || this._groupDisabled\n }\n\n private get _isManagedByGroup(): boolean {\n return this.closest('web-ui-segmented') !== null\n }\n\n setGroupDisabled(disabled: boolean) {\n this._groupDisabled = disabled\n }\n\n private handleClick() {\n if (this._isDisabled || this.checked) return\n this.checked = true\n // group-managed 时事件不冒泡/不组合,由 segmented 统一派发一次 host 事件\n const opts: EventInit = this._isManagedByGroup\n ? { bubbles: false, composed: false }\n : { bubbles: true, composed: true }\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-segmented-trigger': true,\n 'is-checked': this.checked,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <div\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"option\"\n aria-selected=${String(this.checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <slot></slot>\n </div>\n `\n }\n\n declare readonly $events: {\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-segmented-trigger': WebUiSegmentedTrigger\n }\n}\n"],"mappings":";;;;;;AAOO,IAAM,IAAN,cAAoC,EAAW;;EAMlB,aAHE,KAAA,QAAA,IACkB,KAAA,UAAA,IACC,KAAA,WAAA,IACrB,KAAA,iBAAA;;;EALT,KAAA,SAAA,EAAU,CAAK;;CAOxC,IAAY,cAAuB;EACjC,OAAO,KAAK,YAAY,KAAK;CAC/B;CAEA,IAAY,oBAA6B;EACvC,OAAO,KAAK,QAAQ,kBAAkB,MAAM;CAC9C;CAEA,iBAAiB,GAAmB;EAClC,KAAK,iBAAiB;CACxB;CAEA,cAAsB;EACpB,IAAI,KAAK,eAAe,KAAK,SAAS;EACtC,KAAK,UAAU;EAEf,IAAM,IAAkB,KAAK,oBACzB;GAAE,SAAS;GAAO,UAAU;EAAM,IAClC;GAAE,SAAS;GAAM,UAAU;EAAK;EACpC,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;CAEA,SAAkB;EAOhB,OAAO,CAAI;;gBAEC,EAAS;GAPnB,yBAAyB;GACzB,cAAc,KAAK;GACnB,eAAe,KAAK;EAKD,CAAG,EAAE;mBACX,KAAK,cAAc,OAAO,IAAI;;wBAEzB,OAAO,KAAK,OAAO,EAAE;wBACrB,OAAO,KAAK,WAAW,EAAE;iBAChC,KAAK,YAAY;mBACf,KAAK,cAAc;;;;;CAKpC;AAKF;AA3DG,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,KAAA,CAAA,GACzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAPR,IAAA,EAAA,CAAA,EAAc,0BAA0B,CAAA,GAAA,CAAA"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/segmented-trigger/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:inline-block}:host([disabled]){cursor:not-allowed}.wui-segmented-trigger{cursor:pointer;-webkit-user-select:none;user-select:none;z-index:1;height:34px;font-size:var(--wui-font-size,14px);color:var(--wui-color-text-muted,#6a6a6a);white-space:nowrap;transition:color var(--wui-duration-focus,.2s) ease;border-radius:2147483647px;justify-content:center;align-items:center;padding:0 16px;line-height:1;display:inline-flex;position:relative}.wui-segmented-trigger:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px}.wui-segmented-trigger.is-checked{color:var(--wui-color-text,#1a1a1a)}.wui-segmented-trigger.is-disabled{cursor:not-allowed;opacity:.4}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{display:inline-block}:host([disabled]){cursor:not-allowed}.wui-segmented-trigger{--wui-segmented-trigger-bg-hover:color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent);--wui-segmented-trigger-bg-active:color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, transparent);cursor:pointer;-webkit-user-select:none;user-select:none;z-index:1;height:34px;font-size:var(--wui-font-size,14px);color:var(--wui-color-text-muted,#6a6a6a);white-space:nowrap;transition:background-color var(--wui-duration-trigger,.16s) ease, color var(--wui-duration-focus,.2s) ease;background-color:#0000;border-radius:2147483647px;justify-content:center;align-items:center;padding:0 16px;line-height:1;display:inline-flex;position:relative}.wui-segmented-trigger:focus-visible{outline:3px solid var(--wui-focus-ring,#08f6);outline-offset:2px}.wui-segmented-trigger.is-checked{color:var(--wui-color-text,#1a1a1a)}@media (hover:hover) and (pointer:fine){.wui-segmented-trigger:hover:not(.is-disabled){background-color:var(--wui-segmented-trigger-bg-hover)}}.wui-segmented-trigger:active:not(.is-disabled){background-color:var(--wui-segmented-trigger-bg-active)}.wui-segmented-trigger.is-disabled{cursor:not-allowed;opacity:.4}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented-trigger/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-segmented-trigger {\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n height: 34px;\n padding: 0 16px;\n border-radius: calc(infinity * 1px);\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text-muted, #6a6a6a);\n white-space: nowrap;\n\n transition: color var(--wui-duration-focus, 200ms) ease;\n\n &:focus-visible {\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n\n &.is-checked {\n color: var(--wui-color-text, #1a1a1a);\n }\n}\n\n.wui-segmented-trigger.is-disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/segmented-trigger/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\n.wui-segmented-trigger {\n --wui-segmented-trigger-bg-hover: color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent);\n --wui-segmented-trigger-bg-active: color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent);\n\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n height: 34px;\n padding: 0 16px;\n border-radius: calc(infinity * 1px);\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-color-text-muted, #6a6a6a);\n white-space: nowrap;\n\n background-color: transparent;\n\n transition:\n background-color var(--wui-duration-trigger, 160ms) ease,\n color var(--wui-duration-focus, 200ms) ease;\n\n &:focus-visible {\n outline: 3px solid var(--wui-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n\n &.is-checked {\n color: var(--wui-color-text, #1a1a1a);\n }\n}\n\n@media (hover: hover) and (pointer: fine) {\n .wui-segmented-trigger:hover:not(.is-disabled) {\n background-color: var(--wui-segmented-trigger-bg-hover);\n }\n}\n\n.wui-segmented-trigger:active:not(.is-disabled) {\n background-color: var(--wui-segmented-trigger-bg-active);\n}\n\n.wui-segmented-trigger.is-disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n"],"mappings":""}
@@ -58,7 +58,6 @@ export declare class WebUiSelect extends LitElement {
58
58
  private _syncScrollLock;
59
59
  private _togglePopup;
60
60
  private _openOverlay;
61
- private _getDesiredWidth;
62
61
  private _createPortal;
63
62
  private _closeOverlay;
64
63
  private _reconfigureOverlay;