@greypan/web-ui 8.0.0 → 8.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.
Files changed (83) hide show
  1. package/README.CN.md +36 -18
  2. package/README.md +82 -63
  3. package/dist/assets/menu-portal.js +1 -1
  4. package/dist/assets/menu-portal.js.map +1 -1
  5. package/dist/assets/selection-control.js +1 -1
  6. package/dist/assets/selection-control.js.map +1 -1
  7. package/dist/components/autocomplete/index.js +6 -6
  8. package/dist/components/autocomplete/style.js +1 -1
  9. package/dist/components/autocomplete/style.js.map +1 -1
  10. package/dist/components/badge/style.js.map +1 -1
  11. package/dist/components/button/index.d.ts +368 -1
  12. package/dist/components/button/index.js +56 -36
  13. package/dist/components/button/index.js.map +1 -1
  14. package/dist/components/button/style.js +1 -1
  15. package/dist/components/button/style.js.map +1 -1
  16. package/dist/components/checkbox/index.d.ts +3 -0
  17. package/dist/components/checkbox/index.js +33 -35
  18. package/dist/components/checkbox/index.js.map +1 -1
  19. package/dist/components/checkbox/style.js +1 -1
  20. package/dist/components/checkbox/style.js.map +1 -1
  21. package/dist/components/checkbox-group/index.js +8 -8
  22. package/dist/components/dropdown-item/style.js +1 -1
  23. package/dist/components/dropdown-item/style.js.map +1 -1
  24. package/dist/components/editable-text/index.d.ts +2 -0
  25. package/dist/components/editable-text/index.js +50 -30
  26. package/dist/components/editable-text/index.js.map +1 -1
  27. package/dist/components/icon/index.js +7 -7
  28. package/dist/components/icon/index.js.map +1 -1
  29. package/dist/components/input/index.d.ts +7 -0
  30. package/dist/components/input/index.js +34 -29
  31. package/dist/components/input/index.js.map +1 -1
  32. package/dist/components/input-number/index.d.ts +1 -0
  33. package/dist/components/input-number/index.js +28 -26
  34. package/dist/components/input-number/index.js.map +1 -1
  35. package/dist/components/layout/index.js +1 -1
  36. package/dist/components/layout/index.js.map +1 -1
  37. package/dist/components/layout/style.js +1 -1
  38. package/dist/components/layout/style.js.map +1 -1
  39. package/dist/components/option/style.js +1 -1
  40. package/dist/components/option/style.js.map +1 -1
  41. package/dist/components/popover/style.js +1 -1
  42. package/dist/components/popover/style.js.map +1 -1
  43. package/dist/components/radio/index.d.ts +3 -0
  44. package/dist/components/radio/index.js +23 -19
  45. package/dist/components/radio/index.js.map +1 -1
  46. package/dist/components/radio-group/index.js +8 -8
  47. package/dist/components/segmented/index.js +8 -8
  48. package/dist/components/select/style.js +1 -1
  49. package/dist/components/select/style.js.map +1 -1
  50. package/dist/components/slider/index.js +9 -9
  51. package/dist/components/switch/index.d.ts +1 -0
  52. package/dist/components/switch/index.js +26 -24
  53. package/dist/components/switch/index.js.map +1 -1
  54. package/dist/components/textarea/index.d.ts +7 -1
  55. package/dist/components/textarea/index.js +44 -42
  56. package/dist/components/textarea/index.js.map +1 -1
  57. package/dist/components/textarea/style.js.map +1 -1
  58. package/dist/components/theme/index.d.ts +9 -0
  59. package/dist/components/theme/index.js +128 -85
  60. package/dist/components/theme/index.js.map +1 -1
  61. package/dist/components/theme/style.js +1 -1
  62. package/dist/components/theme/style.js.map +1 -1
  63. package/dist/components/toast/toast.js +8 -8
  64. package/dist/components/toast/toast.js.map +1 -1
  65. package/dist/components/tooltip/style.js +1 -1
  66. package/dist/components/tooltip/style.js.map +1 -1
  67. package/dist/icons/generated/akar-icons-check.d.ts +6 -0
  68. package/dist/icons/generated/akar-icons-check.js +10 -0
  69. package/dist/icons/generated/akar-icons-check.js.map +1 -0
  70. package/dist/icons/generated/bi-check.d.ts +6 -0
  71. package/dist/icons/generated/bi-check.js +10 -0
  72. package/dist/icons/generated/bi-check.js.map +1 -0
  73. package/dist/icons/index.d.ts +2 -0
  74. package/dist/icons/index.js +3 -1
  75. package/dist/shared/form-association/field-id.js +9 -0
  76. package/dist/shared/form-association/field-id.js.map +1 -0
  77. package/dist/shared/form-association/index.js +9 -1
  78. package/dist/shared/form-association/index.js.map +1 -1
  79. package/dist/shared/label-emptiness/index.js +45 -0
  80. package/dist/shared/label-emptiness/index.js.map +1 -0
  81. package/dist/shared/theme/root-sync.js +24 -18
  82. package/dist/shared/theme/root-sync.js.map +1 -1
  83. package/package.json +3 -1
@@ -3,61 +3,81 @@ import "../icon/index.js";
3
3
  import t from "../../assets/glass.js";
4
4
  import n from "../../icons/generated/lucide-loader-circle.js";
5
5
  import { installPointerFocusSuppression as r } from "../../shared/focus/pointer-focus.js";
6
- import { buttonGroupContextKey as i, defineGroupManaged as a } from "../../shared/group-management/index.js";
7
- import { normalizeLiteral as o } from "../../shared/normalize/index.js";
8
- import s from "./style.js";
9
- import { LitElement as c, html as l, nothing as u, unsafeCSS as d } from "lit";
10
- import { customElement as f, property as p } from "lit/decorators.js";
11
- import { ifDefined as m } from "lit/directives/if-defined.js";
12
- import { classMap as h } from "lit/directives/class-map.js";
13
- import { styleMap as g } from "lit/directives/style-map.js";
6
+ import { FormAssociated as i, FormAssociationController as a, defineFormAssociation as o } from "../../shared/form-association/index.js";
7
+ import { buttonGroupContextKey as s, defineGroupManaged as c } from "../../shared/group-management/index.js";
8
+ import { normalizeLiteral as l } from "../../shared/normalize/index.js";
9
+ import u from "./style.js";
10
+ import { LitElement as d, html as f, nothing as p, unsafeCSS as m } from "lit";
11
+ import { customElement as h, property as g } from "lit/decorators.js";
12
+ import { ifDefined as _ } from "lit/directives/if-defined.js";
13
+ import { classMap as v } from "lit/directives/class-map.js";
14
+ import { styleMap as y } from "lit/directives/style-map.js";
14
15
  //#region src/components/button/index.ts
15
- var _ = [
16
+ var b = [
16
17
  "primary",
17
18
  "secondary",
18
19
  "ghost",
19
20
  "danger",
20
21
  "glass"
21
- ], v = [
22
+ ], x = [
22
23
  "button",
23
24
  "submit",
24
25
  "reset"
25
26
  ];
26
27
  r();
27
- var y = class extends c {
28
+ var S = class extends i(d) {
28
29
  constructor(...e) {
29
- super(...e), this._variant = "glass", this.disabled = !1, this.loading = !1, this.full = !1, this.icon = !1, this.size = "", this._type = "button", this.ariaLabel = null, this._groupManagement = a(this, {
30
- context: i,
30
+ super(...e), this._variant = "glass", this.disabled = !1, this.loading = !1, this.full = !1, this.icon = !1, this.size = "", this._type = "button", this.ariaLabel = null, this._groupManagement = c(this, {
31
+ context: s,
31
32
  requestUpdate: () => this.requestUpdate(),
32
33
  equals: (e, t) => e?.direction === t?.direction && e?.isLast === t?.isLast
33
- }).make();
34
+ }).make(), this._formAssociation = o({
35
+ host: this,
36
+ getState: () => null,
37
+ setState: () => {},
38
+ getFormValue: () => null,
39
+ getFormState: () => null,
40
+ restoreState: () => {}
41
+ }).make(), this._formAssociationController = new a(this, this._formAssociation);
34
42
  }
35
43
  static {
36
- this.styles = [d(t), d(s)];
44
+ this.styles = [m(t), m(u)];
37
45
  }
38
46
  get variant() {
39
47
  return this._variant;
40
48
  }
41
49
  set variant(e) {
42
50
  let t = this._variant;
43
- this._variant = o(e, _, "glass"), this.requestUpdate("variant", t);
51
+ this._variant = l(e, b, "glass"), this.requestUpdate("variant", t);
44
52
  }
45
53
  get type() {
46
54
  return this._type;
47
55
  }
48
56
  set type(e) {
49
57
  let t = this._type;
50
- this._type = o(e, v, "button"), this.requestUpdate("type", t);
58
+ this._type = l(e, x, "button"), this.requestUpdate("type", t);
51
59
  }
52
60
  get _groupContext() {
53
61
  return this._groupManagement.getContext();
54
62
  }
63
+ get _isDisabled() {
64
+ return this.disabled || this.loading || this._formAssociation.isFormDisabled();
65
+ }
55
66
  get _sizeStyle() {
56
67
  let e = this._groupContext ? "30" : this.size;
57
68
  return e ? { "--wui-control-size": `${e}px` } : {};
58
69
  }
59
70
  handleClick(e) {
60
- (this.disabled || this.loading) && (e.preventDefault(), e.stopPropagation());
71
+ if (this._isDisabled) {
72
+ e.preventDefault(), e.stopPropagation();
73
+ return;
74
+ }
75
+ let t = this.type;
76
+ t !== "button" && setTimeout(() => {
77
+ if (e.defaultPrevented) return;
78
+ let n = this._formAssociation.getInternals()?.form;
79
+ n && (t === "submit" ? n.requestSubmit() : n.reset());
80
+ });
61
81
  }
62
82
  render() {
63
83
  let e = this._groupContext, t = {
@@ -67,53 +87,53 @@ var y = class extends c {
67
87
  "group-divider": !0,
68
88
  vertical: e?.direction === "vertical"
69
89
  };
70
- return l`
90
+ return f`
71
91
  <button
72
92
  type=${this.type}
73
- aria-label=${m(this.ariaLabel)}
74
- class=${h(t)}
93
+ aria-label=${_(this.ariaLabel)}
94
+ class=${v(t)}
75
95
  part="button"
76
- style=${Object.keys(this._sizeStyle).length > 0 ? g(this._sizeStyle) : u}
77
- ?disabled=${this.disabled || this.loading}
96
+ style=${Object.keys(this._sizeStyle).length > 0 ? y(this._sizeStyle) : p}
97
+ ?disabled=${this._isDisabled}
78
98
  @click=${this.handleClick}
79
99
  >
80
- ${this.icon ? this.loading ? l`<web-ui-icon .icon=${n} spin></web-ui-icon>` : l`<slot></slot>` : l`
81
- ${this.loading ? l`<web-ui-icon .icon=${n} spin></web-ui-icon>` : ""}
100
+ ${this.icon ? this.loading ? f`<web-ui-icon .icon=${n} spin></web-ui-icon>` : f`<slot></slot>` : f`
101
+ ${this.loading ? f`<web-ui-icon .icon=${n} spin></web-ui-icon>` : ""}
82
102
  <slot name="prefix"></slot>
83
103
  <span class="label"><slot></slot></span>
84
104
  <slot name="suffix"></slot>
85
105
  `}
86
106
  </button>
87
- ${e && !e.isLast ? l`<span class=${h(r)} aria-hidden="true"></span>` : ""}
107
+ ${e && !e.isLast ? f`<span class=${v(r)} aria-hidden="true"></span>` : ""}
88
108
  `;
89
109
  }
90
110
  };
91
- e([p({
111
+ e([g({
92
112
  type: String,
93
113
  reflect: !0
94
- })], y.prototype, "variant", null), e([p({
114
+ })], S.prototype, "variant", null), e([g({
95
115
  type: Boolean,
96
116
  reflect: !0
97
- })], y.prototype, "disabled", void 0), e([p({
117
+ })], S.prototype, "disabled", void 0), e([g({
98
118
  type: Boolean,
99
119
  reflect: !0
100
- })], y.prototype, "loading", void 0), e([p({
120
+ })], S.prototype, "loading", void 0), e([g({
101
121
  type: Boolean,
102
122
  reflect: !0
103
- })], y.prototype, "full", void 0), e([p({
123
+ })], S.prototype, "full", void 0), e([g({
104
124
  type: Boolean,
105
125
  reflect: !0
106
- })], y.prototype, "icon", void 0), e([p({
126
+ })], S.prototype, "icon", void 0), e([g({
107
127
  type: String,
108
128
  reflect: !0
109
- })], y.prototype, "size", void 0), e([p({
129
+ })], S.prototype, "size", void 0), e([g({
110
130
  type: String,
111
131
  reflect: !0
112
- })], y.prototype, "type", null), e([p({
132
+ })], S.prototype, "type", null), e([g({
113
133
  type: String,
114
134
  attribute: "aria-label"
115
- })], y.prototype, "ariaLabel", void 0), y = e([f("web-ui-button")], y);
135
+ })], S.prototype, "ariaLabel", void 0), S = e([h("web-ui-button")], S);
116
136
  //#endregion
117
- export { y as WebUiButton };
137
+ export { S as WebUiButton };
118
138
 
119
139
  //# sourceMappingURL=index.js.map
@@ -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 '@/components/icon'\nimport glass from '@/assets/glass.css?inline'\nimport { lucideLoaderCircle } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\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 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 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.disabled || this.loading) {\n e.preventDefault()\n e.stopPropagation()\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.disabled || this.loading}\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
+ {"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 '@/components/icon'\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,5 +1,5 @@
1
1
  //#region src/components/button/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{justify-content:center;align-items:center;display:inline-flex;position:relative}:host([full]){width:100%;display:block}:host([disabled]){cursor:not-allowed}button{--wui-glass-corner-radius:calc(var(--wui-control-size,36px) / 2);cursor:default;-webkit-user-select:none;user-select:none;gap:var(--wui-button-gap,8px);box-sizing:border-box;width:var(--wui-button-width,max-content);min-width:var(--wui-control-size,36px);height:var(--wui-control-size,36px);padding:0 var(--wui-button-px,12px);border-radius:var(--wui-radius-control,calc(infinity * 1px));font:inherit;font-size:var(--wui-font-size,14px);color:var(--wui-button-color);white-space:nowrap;background-color:var(--wui-button-bg);border:none;justify-content:center;align-items:center;line-height:1;display:inline-flex;position:relative;overflow:clip}button:disabled{cursor:not-allowed;opacity:.4}button:focus-visible{outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,#08f6);outline-offset:2px}@media (hover:hover) and (pointer:fine){button:hover:not(:disabled){background-color:var(--wui-button-bg-hover)}}button:active:not(:disabled){background-color:var(--wui-button-bg-active)}:host([full]) button{width:100%;display:flex}:host([icon]) button{padding:0}:host([data-wui-pointer-focus]) button:focus-visible{outline-color:#0000}:host([variant=primary]){--wui-button-color:var(--wui-color-on-accent,#fff);--wui-button-bg:var(--wui-color-accent,#08f);--wui-button-bg-hover:color-mix(in srgb, var(--wui-button-bg,#08f) 88%, black);--wui-button-bg-active:color-mix(in srgb, var(--wui-button-bg,#08f) 76%, black)}:host([variant=secondary]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:var(--wui-color-surface-control,#dfdfdf);--wui-button-bg-hover:color-mix(in srgb, var(--wui-button-bg,#dfdfdf) 92%, black);--wui-button-bg-active:color-mix(in srgb, var(--wui-button-bg,#dfdfdf) 82%, black)}:host([variant=ghost]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-state-layer-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent));--wui-button-bg-active:var(--wui-color-state-layer-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, transparent))}:host([variant=danger]){--wui-button-color:var(--wui-color-danger,#dc2626);--wui-button-bg:color-mix(in srgb, var(--wui-color-danger,#dc2626) 18%, var(--wui-color-surface,#fff));--wui-button-bg-hover:color-mix(in srgb, var(--wui-color-danger,#dc2626) 26%, var(--wui-color-surface,#fff));--wui-button-bg-active:color-mix(in srgb, var(--wui-color-danger,#dc2626) 45%, var(--wui-color-surface,#fff))}:host([variant=glass]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-surface-glass-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, var(--wui-color-surface-glass,#fafafa57)));--wui-button-bg-active:var(--wui-color-surface-glass-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, var(--wui-color-surface-glass,#fafafa57)))}button.is-grouped{--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-state-layer-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent));--wui-button-bg-active:var(--wui-color-state-layer-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, transparent))}.group-divider{z-index:1;background-color:var(--wui-color-border,#0000001a);width:1px;height:24px;position:absolute;top:50%;right:-2px;transform:translateY(-50%)}.group-divider.vertical{width:24px;height:1px;inset:auto auto -2px 50%;transform:translate(-50%)}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{justify-content:center;align-items:center;display:inline-flex;position:relative}:host([full]){width:100%;display:block}:host([disabled]){cursor:not-allowed}button{--wui-glass-corner-radius:calc(var(--wui-control-size,36px) / 2);cursor:default;-webkit-user-select:none;user-select:none;gap:var(--wui-button-gap,8px);box-sizing:border-box;width:var(--wui-button-width,max-content);min-width:var(--wui-control-size,36px);height:var(--wui-control-size,36px);padding:0 var(--wui-button-px,12px);border-radius:var(--wui-radius-control,calc(infinity * 1px));font:inherit;font-size:var(--wui-font-size,14px);color:var(--wui-button-color);white-space:nowrap;background-color:var(--wui-button-bg);border:none;justify-content:center;align-items:center;line-height:1;display:inline-flex;position:relative;overflow:clip}button:disabled{cursor:not-allowed;opacity:.4}button:focus-visible{outline:var(--wui-focus-ring-width,3px) solid var(--wui-color-focus-ring,#08f6);outline-offset:2px}@media (hover:hover) and (pointer:fine){button:hover:not(:disabled){background-color:var(--wui-button-bg-hover)}}button:active:not(:disabled){background-color:var(--wui-button-bg-active)}:host([full]) button{width:100%;display:flex}:host([icon]) button{padding:0}:host([data-wui-pointer-focus]) button:focus-visible{outline-color:#0000}:host([variant=primary]){--wui-button-color:var(--wui-color-on-accent,#fff);--wui-button-bg:var(--wui-color-accent,#08f);--wui-button-bg-hover:color-mix(in srgb, var(--wui-button-bg,#08f) 88%, black);--wui-button-bg-active:color-mix(in srgb, var(--wui-button-bg,#08f) 76%, black)}:host([variant=secondary]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:var(--wui-color-surface-control,#dfdfdf);--wui-button-bg-hover:color-mix(in srgb, var(--wui-button-bg,#dfdfdf) 92%, black);--wui-button-bg-active:color-mix(in srgb, var(--wui-button-bg,#dfdfdf) 82%, black)}:host([variant=ghost]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-state-layer-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent));--wui-button-bg-active:var(--wui-color-state-layer-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, transparent))}:host([variant=danger]){--wui-button-color:var(--wui-color-danger,#dc2626);--wui-button-bg:color-mix(in srgb, var(--wui-color-danger,#dc2626) 18%, var(--wui-color-surface,#fff));--wui-button-bg-hover:color-mix(in srgb, var(--wui-color-danger,#dc2626) 26%, var(--wui-color-surface,#fff));--wui-button-bg-active:color-mix(in srgb, var(--wui-color-danger,#dc2626) 45%, var(--wui-color-surface,#fff))}:host([variant=glass]){--wui-button-color:var(--wui-color-text,#1b1b1b);--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-surface-glass-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, var(--wui-color-surface-glass,#fafafa57)));--wui-button-bg-active:var(--wui-color-surface-glass-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, var(--wui-color-surface-glass,#fafafa57)))}button.is-grouped{--wui-button-bg:transparent;--wui-button-bg-hover:var(--wui-color-state-layer-hover,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 6%, transparent));--wui-button-bg-active:var(--wui-color-state-layer-active,color-mix(in srgb, var(--wui-color-text,#1b1b1b) 15%, transparent))}.group-divider{z-index:1;width:1px;height:var(--wui-button-group-divider-length,20px);background-color:var(--wui-color-border,#0000001a);position:absolute;top:50%;right:-2px;transform:translateY(-50%)}.group-divider.vertical{width:var(--wui-button-group-divider-length,20px);height:1px;inset:auto auto -2px 50%;transform:translate(-50%)}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n position: relative;\n\n /* inline-flex 让内层按钮在宿主内完全居中,避免继承的行高撑高宿主、导致图标偏移 */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n:host([full]) {\n display: block;\n width: 100%;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\nbutton {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n cursor: default;\n user-select: none;\n\n position: relative;\n\n overflow: clip;\n display: inline-flex;\n gap: var(--wui-button-gap, 8px);\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n width: var(--wui-button-width, max-content);\n min-width: var(--wui-control-size, 36px);\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-button-px, 12px);\n border: none;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n /* 原生 button 不继承字体;显式继承以对齐宿主排版,避免 UA 默认 Arial 差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-button-color);\n white-space: nowrap;\n\n background-color: var(--wui-button-bg);\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n\n &:focus-visible {\n outline: var(--wui-focus-ring-width, 3px) solid var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n@media (hover: hover) and (pointer: fine) {\n button:hover:not(:disabled) {\n background-color: var(--wui-button-bg-hover);\n }\n}\n\nbutton:active:not(:disabled) {\n background-color: var(--wui-button-bg-active);\n}\n\n:host([full]) button {\n display: flex;\n width: 100%;\n}\n\n:host([icon]) button {\n padding: 0;\n}\n\n/* pointer-focus helper 把标记写到 shadow host 上;这里抑制 Shadow DOM 内按钮的 focus ring。 */\n:host([data-wui-pointer-focus]) button:focus-visible {\n outline-color: transparent;\n}\n\n/* ===== Variant: primary (默认) ===== */\n\n:host([variant='primary']) {\n --wui-button-color: var(--wui-color-on-accent, #fff);\n --wui-button-bg: var(--wui-color-accent, #08f);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #08f) 88%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #08f) 76%, black);\n}\n\n:host([variant='secondary']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: var(--wui-color-surface-control, #dfdfdf);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 92%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 82%, black);\n}\n\n:host([variant='ghost']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n:host([variant='danger']) {\n --wui-button-color: var(--wui-color-danger, #dc2626);\n --wui-button-bg: color-mix(in srgb, var(--wui-color-danger, #dc2626) 18%, var(--wui-color-surface, #fff));\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-color-danger, #dc2626) 26%, var(--wui-color-surface, #fff));\n --wui-button-bg-active: color-mix(in srgb, var(--wui-color-danger, #dc2626) 45%, var(--wui-color-surface, #fff));\n}\n\n/* .wui-glass 样式由 @/assets/glass.css 提供 */\n:host([variant='glass']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n\n /* standalone glass 底色由 .wui-glass 提供;hover/active 需要还原玻璃底,避免被按钮状态色整块替换 */\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-surface-glass-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n --wui-button-bg-active: var(\n --wui-color-surface-glass-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n}\n\nbutton.is-grouped {\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n.group-divider {\n position: absolute;\n z-index: 1;\n top: 50%;\n right: -2px;\n transform: translateY(-50%);\n\n width: 1px;\n height: 24px;\n\n background-color: var(--wui-color-border, rgb(0 0 0 / 0.1));\n}\n\n.group-divider.vertical {\n top: auto;\n right: auto;\n bottom: -2px;\n left: 50%;\n transform: translateX(-50%);\n\n width: 24px;\n height: 1px;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n position: relative;\n\n /* inline-flex 让内层按钮在宿主内完全居中,避免继承的行高撑高宿主、导致图标偏移 */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n:host([full]) {\n display: block;\n width: 100%;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n}\n\nbutton {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n cursor: default;\n user-select: none;\n\n position: relative;\n\n overflow: clip;\n display: inline-flex;\n gap: var(--wui-button-gap, 8px);\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n width: var(--wui-button-width, max-content);\n min-width: var(--wui-control-size, 36px);\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-button-px, 12px);\n border: none;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n /* 原生 button 不继承字体;显式继承以对齐宿主排版,避免 UA 默认 Arial 差异 */\n font: inherit;\n font-size: var(--wui-font-size, 14px);\n line-height: 1;\n color: var(--wui-button-color);\n white-space: nowrap;\n\n background-color: var(--wui-button-bg);\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n\n &:focus-visible {\n outline: var(--wui-focus-ring-width, 3px) solid var(--wui-color-focus-ring, rgb(0 136 255 / 0.4));\n outline-offset: 2px;\n }\n}\n\n@media (hover: hover) and (pointer: fine) {\n button:hover:not(:disabled) {\n background-color: var(--wui-button-bg-hover);\n }\n}\n\nbutton:active:not(:disabled) {\n background-color: var(--wui-button-bg-active);\n}\n\n:host([full]) button {\n display: flex;\n width: 100%;\n}\n\n:host([icon]) button {\n padding: 0;\n}\n\n/* pointer-focus helper 把标记写到 shadow host 上;这里抑制 Shadow DOM 内按钮的 focus ring。 */\n:host([data-wui-pointer-focus]) button:focus-visible {\n outline-color: transparent;\n}\n\n:host([variant='primary']) {\n --wui-button-color: var(--wui-color-on-accent, #fff);\n --wui-button-bg: var(--wui-color-accent, #08f);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #08f) 88%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #08f) 76%, black);\n}\n\n:host([variant='secondary']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: var(--wui-color-surface-control, #dfdfdf);\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 92%, black);\n --wui-button-bg-active: color-mix(in srgb, var(--wui-button-bg, #dfdfdf) 82%, black);\n}\n\n:host([variant='ghost']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n:host([variant='danger']) {\n --wui-button-color: var(--wui-color-danger, #dc2626);\n --wui-button-bg: color-mix(in srgb, var(--wui-color-danger, #dc2626) 18%, var(--wui-color-surface, #fff));\n --wui-button-bg-hover: color-mix(in srgb, var(--wui-color-danger, #dc2626) 26%, var(--wui-color-surface, #fff));\n --wui-button-bg-active: color-mix(in srgb, var(--wui-color-danger, #dc2626) 45%, var(--wui-color-surface, #fff));\n}\n\n/* .wui-glass 样式由 @/assets/glass.css 提供 */\n:host([variant='glass']) {\n --wui-button-color: var(--wui-color-text, #1b1b1b);\n\n /* standalone glass 底色由 .wui-glass 提供;hover/active 需要还原玻璃底,避免被按钮状态色整块替换 */\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-surface-glass-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n --wui-button-bg-active: var(\n --wui-color-surface-glass-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, var(--wui-color-surface-glass, rgb(250 250 250 / 0.34)))\n );\n}\n\nbutton.is-grouped {\n --wui-button-bg: transparent;\n --wui-button-bg-hover: var(\n --wui-color-state-layer-hover,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 6%, transparent)\n );\n --wui-button-bg-active: var(\n --wui-color-state-layer-active,\n color-mix(in srgb, var(--wui-color-text, #1b1b1b) 15%, transparent)\n );\n}\n\n.group-divider {\n position: absolute;\n z-index: 1;\n top: 50%;\n right: -2px;\n transform: translateY(-50%);\n\n width: 1px;\n height: var(--wui-button-group-divider-length, 20px);\n\n background-color: var(--wui-color-border, rgb(0 0 0 / 0.1));\n}\n\n.group-divider.vertical {\n top: auto;\n right: auto;\n bottom: -2px;\n left: 50%;\n transform: translateX(-50%);\n\n width: var(--wui-button-group-divider-length, 20px);\n height: 1px;\n}\n"],"mappings":""}
@@ -369,6 +369,8 @@ export declare class WebUiCheckbox extends WebUiCheckbox_base {
369
369
  private _checked;
370
370
  /** 描边收回期间把勾按在可见档,见 willUpdate。 */
371
371
  private _retracting;
372
+ /** 标签没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */
373
+ private _labelEmpty;
372
374
  get checked(): boolean;
373
375
  set checked(v: boolean);
374
376
  value: string;
@@ -379,6 +381,7 @@ export declare class WebUiCheckbox extends WebUiCheckbox_base {
379
381
  private get _isManagedByGroup();
380
382
  private readonly _formAssociation;
381
383
  private readonly _formAssociationController;
384
+ private readonly _labelEmptiness;
382
385
  private readonly _drawLines?;
383
386
  /** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */
384
387
  private _drawDurationMs;
@@ -1,27 +1,30 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
2
- import { installPointerFocusSuppression as t } from "../../shared/focus/pointer-focus.js";
3
- import { defineGroupManaged as n, selectionGroupContextKey as r } from "../../shared/group-management/index.js";
4
- import { FormAssociated as i, FormAssociationController as a, defineFormAssociation as o } from "../../shared/form-association/index.js";
5
- import { parseDuration as s } from "../../shared/theme/duration.js";
6
- import c from "../../assets/selection-control.js";
2
+ import "../icon/index.js";
3
+ import t from "../../icons/generated/akar-icons-check.js";
4
+ import { installPointerFocusSuppression as n } from "../../shared/focus/pointer-focus.js";
5
+ import { FormAssociated as r, FormAssociationController as i, defineFormAssociation as a } from "../../shared/form-association/index.js";
6
+ import { defineGroupManaged as o, selectionGroupContextKey as s } from "../../shared/group-management/index.js";
7
+ import { parseDuration as c } from "../../shared/theme/duration.js";
7
8
  import { prefersReducedMotion as l } from "../../shared/theme/reduced-motion.js";
8
9
  import "../svg-draw-lines/index.js";
9
- import u from "./style.js";
10
- import { LitElement as d, html as f, unsafeCSS as p } from "lit";
11
- import { customElement as m, property as h, query as g, state as _ } from "lit/decorators.js";
12
- import { classMap as v } from "lit/directives/class-map.js";
10
+ import u from "../../assets/selection-control.js";
11
+ import { LabelEmptinessController as d } from "../../shared/label-emptiness/index.js";
12
+ import f from "./style.js";
13
+ import { LitElement as p, html as m, unsafeCSS as h } from "lit";
14
+ import { customElement as g, property as _, query as v, state as y } from "lit/decorators.js";
15
+ import { classMap as b } from "lit/directives/class-map.js";
13
16
  //#region src/components/checkbox/index.ts
14
- t();
15
- function y(e) {
16
- let t = s(getComputedStyle(e).getPropertyValue("--wui-duration-trigger"));
17
+ n();
18
+ function x(e) {
19
+ let t = c(getComputedStyle(e).getPropertyValue("--wui-duration-trigger"));
17
20
  return t === null ? 160 : Math.max(0, t);
18
21
  }
19
- var b = class extends i(d) {
22
+ var S = class extends r(p) {
20
23
  constructor(...e) {
21
- super(...e), this._groupManagement = n(this, {
22
- context: r,
24
+ super(...e), this._groupManagement = o(this, {
25
+ context: s,
23
26
  requestUpdate: () => this.requestUpdate()
24
- }).make(), this._checked = !1, this._retracting = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation = o({
27
+ }).make(), this._checked = !1, this._retracting = !1, this._labelEmpty = !1, this.value = "", this.name = "", this.disabled = !1, this.required = !1, this._formAssociation = a({
25
28
  host: this,
26
29
  initialize: () => {
27
30
  this.hasAttribute("checked") && (this._checked = !0);
@@ -37,10 +40,12 @@ var b = class extends i(d) {
37
40
  },
38
41
  isStateManaged: () => this._isManagedByGroup,
39
42
  syncValidity: () => this._syncValidity()
40
- }).make(), this._formAssociationController = new a(this, this._formAssociation), this._drawDurationMs = 160;
43
+ }).make(), this._formAssociationController = new i(this, this._formAssociation), this._labelEmptiness = new d(this, ".wui-checkbox-label", (e) => {
44
+ this._labelEmpty = e;
45
+ }), this._drawDurationMs = 160;
41
46
  }
42
47
  static {
43
- this.styles = [p(c), p(u)];
48
+ this.styles = [h(u), h(f)];
44
49
  }
45
50
  get checked() {
46
51
  return this._checked;
@@ -82,7 +87,7 @@ var b = class extends i(d) {
82
87
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), this.handleClick());
83
88
  }
84
89
  willUpdate(e) {
85
- super.willUpdate(e), this._drawDurationMs = y(this);
90
+ super.willUpdate(e), this._drawDurationMs = x(this);
86
91
  let t = e.get("_checked");
87
92
  typeof t == "boolean" && (this._retracting = t && !l(this));
88
93
  }
@@ -96,11 +101,12 @@ var b = class extends i(d) {
96
101
  "wui-checkbox": !0,
97
102
  "is-checked": this._checked,
98
103
  "is-retracting": this._retracting,
104
+ "is-label-empty": this._labelEmpty,
99
105
  "is-disabled": this._isDisabled
100
106
  };
101
- return f`
107
+ return m`
102
108
  <label
103
- class=${v(e)}
109
+ class=${b(e)}
104
110
  tabindex=${this._isDisabled ? "-1" : "0"}
105
111
  role="checkbox"
106
112
  aria-checked=${String(this._checked)}
@@ -111,15 +117,7 @@ var b = class extends i(d) {
111
117
  <span class="wui-checkbox-box">
112
118
  <span class="wui-checkbox-icon"
113
119
  ><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay
114
- ><svg class="wui-checkbox-check" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
115
- <path
116
- d="M5 12.5l4.5 4.5L19 7"
117
- fill="none"
118
- stroke="currentColor"
119
- stroke-width="3"
120
- stroke-linecap="round"
121
- stroke-linejoin="round"
122
- /></svg></web-ui-svg-draw-lines
120
+ ><web-ui-icon .icon=${t}></web-ui-icon></web-ui-svg-draw-lines
123
121
  ></span>
124
122
  </span>
125
123
  <span class="wui-checkbox-label"><slot></slot></span>
@@ -127,17 +125,17 @@ var b = class extends i(d) {
127
125
  `;
128
126
  }
129
127
  };
130
- e([_()], b.prototype, "_checked", void 0), e([_()], b.prototype, "_retracting", void 0), e([h({ type: String })], b.prototype, "value", void 0), e([h({
128
+ e([y()], S.prototype, "_checked", void 0), e([y()], S.prototype, "_retracting", void 0), e([y()], S.prototype, "_labelEmpty", void 0), e([_({ type: String })], S.prototype, "value", void 0), e([_({
131
129
  type: String,
132
130
  reflect: !0
133
- })], b.prototype, "name", void 0), e([h({
131
+ })], S.prototype, "name", void 0), e([_({
134
132
  type: Boolean,
135
133
  reflect: !0
136
- })], b.prototype, "disabled", void 0), e([h({
134
+ })], S.prototype, "disabled", void 0), e([_({
137
135
  type: Boolean,
138
136
  reflect: !0
139
- })], b.prototype, "required", void 0), e([g("web-ui-svg-draw-lines")], b.prototype, "_drawLines", void 0), b = e([m("web-ui-checkbox")], b);
137
+ })], S.prototype, "required", void 0), e([v("web-ui-svg-draw-lines")], S.prototype, "_drawLines", void 0), S = e([g("web-ui-checkbox")], S);
140
138
  //#endregion
141
- export { b as WebUiCheckbox };
139
+ export { S as WebUiCheckbox };
142
140
 
143
141
  //# sourceMappingURL=index.js.map
@@ -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 selectionControl from '@/assets/selection-control.css?inline'\nimport { WebUiSvgDrawLines } from '@/components/svg-draw-lines'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\nimport { parseDuration } from '@/shared/theme/duration'\nimport { prefersReducedMotion } from '@/shared/theme/reduced-motion'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n/*\n * 描边时长取 `--wui-duration-trigger`,让勾和指示器底色那条 transition 落在同一拍。\n * 读不到 token 或格式不符时兜底 160,负值钳到 0。\n */\nfunction triggerDuration(el: HTMLElement): number {\n const parsed = parseDuration(getComputedStyle(el).getPropertyValue('--wui-duration-trigger'))\n return parsed === null ? 160 : Math.max(0, parsed)\n}\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(selectionControl), unsafeCSS(style)]\n private readonly _groupManagement = defineGroupManaged<SelectionGroupContext>(this, {\n context: selectionGroupContextKey,\n requestUpdate: () => this.requestUpdate()\n }).make()\n\n @state() private _checked = false\n\n /** 描边收回期间把勾按在可见档,见 willUpdate。 */\n @state() private _retracting = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return (\n this.disabled || this._formAssociation.isFormDisabled() || this._groupManagement.getContext()?.disabled === true\n )\n }\n\n private get _isManagedByGroup(): boolean {\n return this._groupManagement.getContext() !== undefined\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (!this._isManagedByGroup && this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n isStateManaged: () => this._isManagedByGroup,\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n @query('web-ui-svg-draw-lines') private readonly _drawLines?: WebUiSvgDrawLines\n\n /** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */\n private _drawDurationMs = 160\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请选择此项')\n }\n\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n // group-managed 时事件不冒泡/不组合,由 group 统一派发一次 host 事件,避免同名事件外泄\n const opts: EventInit = this._isManagedByGroup\n ? { bubbles: false, composed: false }\n : { bubbles: true, composed: true }\n this.dispatchEvent(new Event('input', opts))\n this.dispatchEvent(new Event('change', opts))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n /*\n * 收回期间勾要留在可见档,否则 160ms 淡出抢在描边收回之前把它藏掉。翻转放在 willUpdate:\n * 与 checked 同一次 update 落地,渲染后不再改状态。收回的终点是留在内联样式上的空白,所以这一位\n * 不需要在动画结束后复位,下一次勾选会清掉;reduced motion 下收回根本不跑,按住可见位就是把勾\n * 永久留在未勾选的框里,所以那里必须让位给淡出。\n */\n override willUpdate(changed: PropertyValues) {\n super.willUpdate(changed)\n this._drawDurationMs = triggerDuration(this)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked === 'boolean') {\n this._retracting = wasChecked && !prefersReducedMotion(this)\n }\n }\n\n /*\n * 挂载时就勾选是初始状态而非用户勾选,不画线:_checked 的字段初始化器在构造阶段写过一次,\n * Lit 对同一轮里已记录过旧值的键不再覆盖,所以首帧拿到的是 undefined,之后的每次真实切换才带\n * boolean 旧值——包括 group 在子项首帧前把选中态写回去那一种。\n */\n override updated(changed: PropertyValues) {\n super.updated(changed)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked !== 'boolean') return\n\n if (wasChecked) void this._drawLines?.replay({ reverse: true })\n else void this._drawLines?.replay()\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-retracting': this._retracting,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"checkbox\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-checkbox-box\">\n <span class=\"wui-checkbox-icon\"\n ><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay\n ><svg class=\"wui-checkbox-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n d=\"M5 12.5l4.5 4.5L19 7\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n /></svg></web-ui-svg-draw-lines\n ></span>\n </span>\n <span class=\"wui-checkbox-label\"><slot></slot></span>\n </label>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox': WebUiCheckbox\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,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;;EA6DlC,aA3DU,KAAA,mBAAA,EAA0C,MAAM;GAClF,SAAS;GACT,qBAAqB,KAAK,cAAc;EAC1C,CAAC,CAAC,CAAC,KAAK,GAEoB,KAAA,WAAA,IAGG,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,GAK7E,KAAA,kBAAA;;;EA5DD,KAAA,SAAA,CAAC,EAAU,CAAgB,GAAG,EAAU,CAAK,CAAC;;CAWvE,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;CA2BA,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,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;;;;;;;;;;;;;;;CAelE;AAMF;AA7JG,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,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,GAgCzC,EAAA,CAAA,EAAM,uBAAuB,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GA3D/B,IAAA,EAAA,CAAA,EAAc,iBAAiB,CAAA,GAAA,CAAA"}
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 '@/components/svg-draw-lines'\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,5 +1,5 @@
1
1
  //#region src/components/checkbox/style.css?inline
2
- var e = ".wui-checkbox-box{border-radius:var(--wui-internal-checkbox-radius,6px)}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#08f);background-color:var(--wui-color-accent,#08f)}.wui-checkbox-icon{opacity:0;transition:opacity var(--wui-duration-trigger,.16s) ease;font-size:0;line-height:0;display:block;overflow:hidden}.is-checked .wui-checkbox-icon,.is-retracting .wui-checkbox-icon{opacity:1}.wui-checkbox-check{width:var(--wui-selection-control-size,18px);height:var(--wui-selection-control-size,18px);color:var(--wui-color-on-control,#fff);display:block}";
2
+ var e = ".wui-checkbox-box{border-radius:var(--wui-internal-checkbox-radius,6px)}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#08f);background-color:var(--wui-color-accent,#08f)}.wui-checkbox-icon{--wui-icon-color:var(--wui-color-on-control,#fff);opacity:0;transition:opacity var(--wui-duration-trigger,.16s) ease;font-size:0;line-height:0;display:block;overflow:hidden}.is-checked .wui-checkbox-icon,.is-retracting .wui-checkbox-icon{opacity:1}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":[".wui-checkbox-box {\n border-radius: var(--wui-internal-checkbox-radius, 6px);\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #08f);\n background-color: var(--wui-color-accent, #08f);\n}\n\n.wui-checkbox-icon {\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition: opacity var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * is-retracting 是描边收回的那一段:勾得留在可见档,否则这条 160ms 的淡出会抢在收回结束之前\n * 把它藏掉,收回根本看不见。收回的终点是留在内联样式上的「整条路径落在 dash 间隙里」,动画自己\n * 收尾就撤销了,所以停在这里就是看不见的勾,不必再等一次淡出;复位由下一次勾选负责(见 index.ts 的 willUpdate)。\n */\n.is-checked .wui-checkbox-icon,\n.is-retracting .wui-checkbox-icon {\n opacity: 1;\n}\n\n/*\n * 勾是控件自持的指示几何,和 radio 圆点同级,不走 @/icons 资产:画线从路径起点开始揭示,\n * 起笔方向由 d 决定,图标资产把 d 和 stroke-width 都定死在上游,两者都无法在这里调。\n * 尺寸跟随指示器 token,放大 --wui-selection-control-size 时勾按比例变大。\n */\n.wui-checkbox-check {\n display: block;\n width: var(--wui-selection-control-size, 18px);\n height: var(--wui-selection-control-size, 18px);\n color: var(--wui-color-on-control, #fff);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":[".wui-checkbox-box {\n border-radius: var(--wui-internal-checkbox-radius, 6px);\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #08f);\n background-color: var(--wui-color-accent, #08f);\n}\n\n/*\n * 勾是 @/icons 的描边资产,颜色经 web-ui-icon 的 --wui-icon-color 传入并取 on-control 档:勾选后\n * 指示器底是 accent,勾留在继承的文字色就是深灰压深蓝。资产必须是 fill:none + stroke:currentColor,\n * 换成实心图标那条 dash 动画照跑但什么都看不见(判据见 checkbox.motion.browser.spec.ts)。\n * 尺寸是 web-ui-icon 自己的默认 18,宿主够不到嵌套 shadow root 里的 svg,因此不随\n * --wui-selection-control-size 按比例放大。\n */\n.wui-checkbox-icon {\n --wui-icon-color: var(--wui-color-on-control, #fff);\n\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition: opacity var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * is-retracting 是描边收回的那一段:勾得留在可见档,否则这条 160ms 的淡出会抢在收回结束之前\n * 把它藏掉,收回根本看不见。收回的终点是留在内联样式上的「整条路径落在 dash 间隙里」,动画自己\n * 收尾就撤销了,所以停在这里就是看不见的勾,不必再等一次淡出;复位由下一次勾选负责(见 index.ts 的 willUpdate)。\n */\n.is-checked .wui-checkbox-icon,\n.is-retracting .wui-checkbox-icon {\n opacity: 1;\n}\n"],"mappings":""}
@@ -1,14 +1,14 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
2
- import { GroupController as t, defineGroupCoordinator as n } from "../../shared/group-management/index.js";
3
- import { normalizeLiteral as r } from "../../shared/normalize/index.js";
4
- import { FormAssociated as i, FormAssociationController as a, defineFormAssociation as o } from "../../shared/form-association/index.js";
2
+ import { FormAssociated as t, FormAssociationController as n, defineFormAssociation as r } from "../../shared/form-association/index.js";
3
+ import { GroupController as i, defineGroupCoordinator as a } from "../../shared/group-management/index.js";
4
+ import { normalizeLiteral as o } from "../../shared/normalize/index.js";
5
5
  import s from "./style.js";
6
6
  import { LitElement as c, html as l, unsafeCSS as u } from "lit";
7
7
  import { customElement as d, property as f, state as p } from "lit/decorators.js";
8
8
  //#region src/components/checkbox-group/index.ts
9
- var m = ["horizontal", "vertical"], h = class extends i(c) {
9
+ var m = ["horizontal", "vertical"], h = class extends t(c) {
10
10
  constructor(...e) {
11
- super(...e), this.name = "", this.disabled = !1, this.required = !1, this._direction = "vertical", this._value = [], this._groupController = new t(this, n({
11
+ super(...e), this.name = "", this.disabled = !1, this.required = !1, this._direction = "vertical", this._value = [], this._groupController = new i(this, a({
12
12
  host: this,
13
13
  getItems: () => [...this.querySelectorAll("web-ui-checkbox")],
14
14
  getValue: () => this._value,
@@ -33,7 +33,7 @@ var m = ["horizontal", "vertical"], h = class extends i(c) {
33
33
  composed: !0
34
34
  }));
35
35
  }
36
- }).make()), this._formAssociation = o({
36
+ }).make()), this._formAssociation = r({
37
37
  host: this,
38
38
  initialize: () => {
39
39
  let e = this.getAttribute("value");
@@ -57,7 +57,7 @@ var m = ["horizontal", "vertical"], h = class extends i(c) {
57
57
  } catch {}
58
58
  },
59
59
  syncValidity: () => this._syncValidity()
60
- }).make(), this._formAssociationController = new a(this, this._formAssociation);
60
+ }).make(), this._formAssociationController = new n(this, this._formAssociation);
61
61
  }
62
62
  static {
63
63
  this.styles = u(s);
@@ -67,7 +67,7 @@ var m = ["horizontal", "vertical"], h = class extends i(c) {
67
67
  }
68
68
  set direction(e) {
69
69
  let t = this._direction;
70
- this._direction = r(e, m, "vertical"), this.requestUpdate("direction", t);
70
+ this._direction = o(e, m, "vertical"), this.requestUpdate("direction", t);
71
71
  }
72
72
  get value() {
73
73
  return this._value;
@@ -1,5 +1,5 @@
1
1
  //#region src/components/dropdown-item/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:block}:host([disabled]){cursor:not-allowed;opacity:.4}.item-inner{-webkit-user-select:none;user-select:none;border-radius:var(--wui-radius-control,calc(infinity * 1px));height:32px;font-size:var(--wui-font-size,14px);color:inherit;white-space:nowrap;outline:none;align-items:center;gap:8px;padding:0 8px;display:flex}.item-inner:focus-visible{color:var(--wui-color-on-accent,#fff);background:var(--wui-color-accent,#08f)}:host([active]) .item-inner{color:inherit;background:var(--wui-color-border,#0000001a)}@media (hover:hover) and (pointer:fine){:host(:hover) .item-inner{color:var(--wui-color-on-accent,#fff);background:var(--wui-color-accent,#08f)}}.item-label{min-width:0;color:inherit;text-overflow:ellipsis;flex:1;overflow:hidden}.item-suffix{opacity:.4;flex:none}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{display:block}:host([disabled]){cursor:not-allowed;opacity:.4}.item-inner{-webkit-user-select:none;user-select:none;border-radius:var(--wui-radius-control,calc(infinity * 1px));height:32px;font-size:var(--wui-font-size,14px);color:inherit;white-space:nowrap;outline:none;align-items:center;gap:8px;padding:0 8px;display:flex}.item-inner:focus-visible{color:var(--wui-color-on-accent,#fff);background:var(--wui-color-accent,#08f)}:host([active]) .item-inner{color:inherit;background:var(--wui-color-border,#0000001a)}@media (hover:hover) and (pointer:fine){:host(:not([active])) .item-inner:hover:not(:focus-visible){color:inherit;background:var(--wui-color-border,#0000001a)}}.item-label{min-width:0;color:inherit;text-overflow:ellipsis;flex:1;overflow:hidden}.item-suffix{opacity:.4;flex:none}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/dropdown-item/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.item-inner {\n user-select: none;\n\n display: flex;\n gap: 8px;\n align-items: center;\n\n height: 32px;\n padding: 0 8px;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n font-size: var(--wui-font-size, 14px);\n color: inherit;\n white-space: nowrap;\n\n outline: none;\n}\n\n.item-inner:focus-visible {\n color: var(--wui-color-on-accent, #fff);\n background: var(--wui-color-accent, #08f);\n}\n\n:host([active]) .item-inner {\n color: inherit;\n background: var(--wui-color-border, rgb(0 0 0 / 0.1));\n}\n\n@media (hover: hover) and (pointer: fine) {\n :host(:hover) .item-inner {\n color: var(--wui-color-on-accent, #fff);\n background: var(--wui-color-accent, #08f);\n }\n}\n\n.item-label {\n overflow: hidden;\n flex: 1;\n\n min-width: 0;\n\n color: inherit;\n text-overflow: ellipsis;\n}\n\n.item-suffix {\n flex: none;\n opacity: 0.4;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/dropdown-item/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n}\n\n:host([disabled]) {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.item-inner {\n user-select: none;\n\n display: flex;\n gap: 8px;\n align-items: center;\n\n height: 32px;\n padding: 0 8px;\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n\n font-size: var(--wui-font-size, 14px);\n color: inherit;\n white-space: nowrap;\n\n outline: none;\n}\n\n.item-inner:focus-visible {\n color: var(--wui-color-on-accent, #fff);\n background: var(--wui-color-accent, #08f);\n}\n\n:host([active]) .item-inner {\n color: inherit;\n background: var(--wui-color-border, rgb(0 0 0 / 0.1));\n}\n\n@media (hover: hover) and (pointer: fine) {\n :host(:not([active])) .item-inner:hover:not(:focus-visible) {\n color: inherit;\n background: var(--wui-color-border, rgb(0 0 0 / 0.1));\n }\n}\n\n.item-label {\n overflow: hidden;\n flex: 1;\n\n min-width: 0;\n\n color: inherit;\n text-overflow: ellipsis;\n}\n\n.item-suffix {\n flex: none;\n opacity: 0.4;\n}\n"],"mappings":""}
@@ -368,6 +368,7 @@ export declare class WebUiEditableText extends WebUiEditableText_base {
368
368
  name: string;
369
369
  placeholder: string;
370
370
  disabled: boolean;
371
+ readonly: boolean;
371
372
  ariaLabel: string | null;
372
373
  private _value;
373
374
  /**
@@ -383,6 +384,7 @@ export declare class WebUiEditableText extends WebUiEditableText_base {
383
384
  private _pendingCaret;
384
385
  private _refocusing;
385
386
  private _resizeObserver;
387
+ private readonly _fieldId;
386
388
  private get _isDisabled();
387
389
  private readonly _formAssociation;
388
390
  private readonly _formAssociationController;