@antadesign/anta 0.3.33 → 0.3.35

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 (205) hide show
  1. package/LICENSE.md +14 -1
  2. package/README.md +9 -0
  3. package/dist/anta_helpers.d.ts +46 -30
  4. package/dist/anta_helpers.js +66 -25
  5. package/dist/bundle.css +1 -1
  6. package/dist/bundle.js +2 -1353
  7. package/dist/components/Banner.d.ts +25 -40
  8. package/dist/components/Banner.js +15 -17
  9. package/dist/components/Breadcrumbs.d.ts +0 -1
  10. package/dist/components/Breadcrumbs.js +0 -1
  11. package/dist/components/Button.d.ts +2 -3
  12. package/dist/components/Button.js +1 -0
  13. package/dist/components/ButtonCopy.js +3 -2
  14. package/dist/components/Calendar.js +13 -13
  15. package/dist/components/Card.d.ts +9 -17
  16. package/dist/components/Card.js +50 -46
  17. package/dist/components/Dialog.d.ts +1 -0
  18. package/dist/components/Dialog.js +16 -10
  19. package/dist/components/Expander.d.ts +6 -21
  20. package/dist/components/Expander.js +24 -23
  21. package/dist/components/Icon.d.ts +8 -14
  22. package/dist/components/Input.d.ts +77 -96
  23. package/dist/components/Input.js +23 -27
  24. package/dist/components/InputAutocomplete.d.ts +29 -10
  25. package/dist/components/InputAutocomplete.js +25 -8
  26. package/dist/components/InputDate.d.ts +0 -1
  27. package/dist/components/InputDate.js +2 -3
  28. package/dist/components/InputTime.d.ts +10 -4
  29. package/dist/components/InputTime.js +20 -16
  30. package/dist/components/Loader.d.ts +2 -2
  31. package/dist/components/Menu.d.ts +5 -4
  32. package/dist/components/Menu.js +13 -8
  33. package/dist/components/MenuItem.js +1 -14
  34. package/dist/components/MenuItemCopy.js +2 -2
  35. package/dist/components/Panel.d.ts +3 -1
  36. package/dist/components/Panel.js +17 -11
  37. package/dist/components/Progress.d.ts +21 -23
  38. package/dist/components/Progress.js +13 -9
  39. package/dist/components/RadioGroup.js +6 -8
  40. package/dist/components/{select-parts.css → Select.css} +1 -1
  41. package/dist/components/Select.d.ts +53 -36
  42. package/dist/components/Select.js +53 -98
  43. package/dist/components/SelectFaceted.d.ts +7 -4
  44. package/dist/components/SelectFaceted.js +21 -10
  45. package/dist/components/Slider.d.ts +28 -11
  46. package/dist/components/Slider.js +20 -20
  47. package/dist/components/Steps.css +1 -1
  48. package/dist/components/Steps.d.ts +0 -1
  49. package/dist/components/Steps.js +1 -12
  50. package/dist/components/Tabs.d.ts +17 -20
  51. package/dist/components/Tabs.js +7 -9
  52. package/dist/components/Text.d.ts +55 -36
  53. package/dist/components/Text.js +35 -22
  54. package/dist/components/Title.d.ts +19 -27
  55. package/dist/components/Title.js +2 -1
  56. package/dist/components/Toaster.js +9 -2
  57. package/dist/components/Tooltip.d.ts +10 -15
  58. package/dist/components/copy-props.d.ts +14 -3
  59. package/dist/components/copy-props.js +14 -3
  60. package/dist/components/select-tree.d.ts +24 -0
  61. package/dist/components/select-tree.js +35 -0
  62. package/dist/element-base.d.ts +10 -0
  63. package/dist/element-base.js +15 -0
  64. package/dist/elements/a-avatar.css +1 -1
  65. package/dist/elements/a-avatar.js +2 -28
  66. package/dist/elements/a-banner.css +1 -1
  67. package/dist/elements/a-banner.d.ts +4 -1
  68. package/dist/elements/a-banner.js +22 -112
  69. package/dist/elements/a-breadcrumbs.d.ts +1 -0
  70. package/dist/elements/a-breadcrumbs.js +1 -0
  71. package/dist/elements/a-button.css +1 -1
  72. package/dist/elements/a-button.d.ts +10 -7
  73. package/dist/elements/a-button.js +18 -1
  74. package/dist/elements/a-calendar.d.ts +14 -13
  75. package/dist/elements/a-calendar.js +29 -24
  76. package/dist/elements/a-card.css +1 -1
  77. package/dist/elements/a-card.d.ts +0 -9
  78. package/dist/elements/a-card.js +0 -184
  79. package/dist/elements/a-checkbox.css +1 -1
  80. package/dist/elements/a-copy.css +1 -1
  81. package/dist/elements/a-copy.d.ts +1 -5
  82. package/dist/elements/a-copy.js +129 -108
  83. package/dist/elements/a-dialog.css +1 -1
  84. package/dist/elements/a-dialog.d.ts +1 -1
  85. package/dist/elements/a-dialog.js +68 -194
  86. package/dist/elements/a-expander.css +1 -1
  87. package/dist/elements/a-expander.d.ts +4 -30
  88. package/dist/elements/a-expander.js +85 -344
  89. package/dist/elements/a-icon.d.ts +5 -23
  90. package/dist/elements/a-icon.js +1 -2
  91. package/dist/elements/a-input-date.d.ts +1 -0
  92. package/dist/elements/a-input-date.js +1 -0
  93. package/dist/elements/a-input-time.css +1 -1
  94. package/dist/elements/a-input-time.d.ts +2 -1
  95. package/dist/elements/a-input-time.js +101 -168
  96. package/dist/elements/a-input.css +1 -1
  97. package/dist/elements/a-input.d.ts +10 -8
  98. package/dist/elements/a-input.js +155 -230
  99. package/dist/elements/a-loader.d.ts +5 -8
  100. package/dist/elements/a-loader.js +1 -2
  101. package/dist/elements/a-menu-item.css +1 -1
  102. package/dist/elements/a-menu-item.d.ts +5 -3
  103. package/dist/elements/a-menu-item.js +5 -1
  104. package/dist/elements/a-menu.css +1 -1
  105. package/dist/elements/a-menu.d.ts +5 -7
  106. package/dist/elements/a-menu.js +383 -299
  107. package/dist/elements/a-panel.css +1 -1
  108. package/dist/elements/a-panel.js +19 -37
  109. package/dist/elements/a-progress.css +1 -1
  110. package/dist/elements/a-progress.d.ts +0 -22
  111. package/dist/elements/a-progress.js +0 -100
  112. package/dist/elements/a-radio-group.d.ts +1 -1
  113. package/dist/elements/a-radio-group.js +6 -4
  114. package/dist/elements/a-select-faceted.d.ts +1 -0
  115. package/dist/elements/a-select-faceted.js +1 -0
  116. package/dist/elements/a-select.d.ts +1 -0
  117. package/dist/elements/a-select.js +1 -0
  118. package/dist/elements/a-slider.css +1 -1
  119. package/dist/elements/a-slider.d.ts +11 -3
  120. package/dist/elements/a-slider.js +244 -242
  121. package/dist/elements/a-steps.d.ts +1 -0
  122. package/dist/elements/a-steps.js +1 -0
  123. package/dist/elements/a-switch.css +1 -1
  124. package/dist/elements/a-tab.css +1 -1
  125. package/dist/elements/a-tabpanel.d.ts +2 -2
  126. package/dist/elements/a-tabpanel.js +13 -3
  127. package/dist/elements/a-tabs.css +1 -1
  128. package/dist/elements/a-tabs.d.ts +1 -1
  129. package/dist/elements/a-tabs.js +6 -4
  130. package/dist/elements/a-tag.css +1 -1
  131. package/dist/elements/a-tag.d.ts +1 -0
  132. package/dist/elements/a-tag.js +1 -0
  133. package/dist/elements/a-text.css +1 -1
  134. package/dist/elements/a-text.d.ts +6 -43
  135. package/dist/elements/a-text.js +110 -193
  136. package/dist/elements/a-title.css +1 -1
  137. package/dist/elements/a-title.d.ts +1 -0
  138. package/dist/elements/a-title.js +1 -0
  139. package/dist/elements/a-toast.css +1 -1
  140. package/dist/elements/a-toast.d.ts +10 -45
  141. package/dist/elements/a-toast.js +80 -66
  142. package/dist/elements/a-toaster.css +1 -1
  143. package/dist/elements/a-toaster.js +9 -44
  144. package/dist/elements/a-tooltip.css +1 -1
  145. package/dist/elements/a-tooltip.d.ts +1 -1
  146. package/dist/elements/a-tooltip.js +142 -136
  147. package/dist/elements/copy-behavior.d.ts +1 -1
  148. package/dist/elements/copy-behavior.js +21 -21
  149. package/dist/elements/index.d.ts +9 -3
  150. package/dist/elements/index.js +6 -6
  151. package/dist/elements/input-focus-modality.d.ts +15 -0
  152. package/dist/elements/input-focus-modality.js +44 -0
  153. package/dist/elements/input-trailing-actions.d.ts +5 -0
  154. package/dist/elements/input-trailing-actions.js +38 -0
  155. package/dist/elements/shadow-aria.d.ts +2 -0
  156. package/dist/elements/shadow-aria.js +2 -1
  157. package/dist/elements/value-input.d.ts +3 -0
  158. package/dist/elements/value-input.js +12 -0
  159. package/dist/general_types.d.ts +103 -96
  160. package/dist/index.d.ts +1 -1
  161. package/dist/input-events.d.ts +4 -0
  162. package/dist/input-events.js +15 -0
  163. package/dist/jsx-runtime.d.ts +70 -23
  164. package/dist/jsx-runtime.js +26 -19
  165. package/dist/native-event-props.d.ts +2 -0
  166. package/dist/native-event-props.js +10 -0
  167. package/dist/reset.css +1 -1
  168. package/dist/theme-antithesis.css +10 -1
  169. package/dist/theme-antune.css +1 -1
  170. package/docs/accessibility.md +17 -3
  171. package/docs/changelog.md +384 -2
  172. package/docs/comparison.md +2 -2
  173. package/docs/components/avatar.md +5 -0
  174. package/docs/components/banner.md +117 -187
  175. package/docs/components/breadcrumbs.md +9 -6
  176. package/docs/components/button.md +22 -0
  177. package/docs/components/card.md +74 -28
  178. package/docs/components/checkbox.md +9 -10
  179. package/docs/components/dialog.md +83 -32
  180. package/docs/components/expander.md +198 -435
  181. package/docs/components/icon.md +11 -17
  182. package/docs/components/input-autocomplete.md +152 -52
  183. package/docs/components/input-date.md +175 -148
  184. package/docs/components/input-time.md +81 -38
  185. package/docs/components/input.md +343 -349
  186. package/docs/components/loader.md +2 -1
  187. package/docs/components/menu.md +35 -6
  188. package/docs/components/panel.md +18 -0
  189. package/docs/components/progress.md +83 -49
  190. package/docs/components/radio.md +39 -43
  191. package/docs/components/select-faceted.md +54 -7
  192. package/docs/components/select.md +390 -386
  193. package/docs/components/slider.md +136 -19
  194. package/docs/components/steps.md +6 -3
  195. package/docs/components/switch.md +8 -9
  196. package/docs/components/tabs.md +110 -104
  197. package/docs/components/text.md +110 -86
  198. package/docs/components/title.md +47 -33
  199. package/docs/components/toaster.md +242 -84
  200. package/docs/components/tooltip.md +204 -113
  201. package/docs/install-config.md +461 -96
  202. package/docs/packages/plot.md +228 -143
  203. package/docs/theming.md +29 -13
  204. package/package.json +43 -4
  205. package/theme-antithesis-license.md +66 -0
@@ -1,3 +1,6 @@
1
+ import { CLEAR_TRIGGER, CLEAR_CLICK_EVENT, CLEAR_INPUT_EVENT, ownsInputClearRequest } from "../input-events";
2
+ import { inputTrailingActions } from "./input-trailing-actions";
3
+ import { MODALITY, trackFocusModality } from "./input-focus-modality";
1
4
  import { HTMLElementBase, SYNC_POPUP_ARIA } from "../anta_helpers";
2
5
  import {
3
6
  applyShadowAria,
@@ -23,170 +26,12 @@ const FORWARDED = [
23
26
  "step"
24
27
  ];
25
28
  const BOOL_FORWARDED = /* @__PURE__ */ new Set(["readonly", "required"]);
26
- let focusFromKeyboard = false;
27
- const modalityDocs = /* @__PURE__ */ new WeakSet();
28
- function trackFocusModality(doc) {
29
- if (modalityDocs.has(doc)) return;
30
- modalityDocs.add(doc);
31
- doc.addEventListener("keydown", () => {
32
- focusFromKeyboard = true;
33
- }, true);
34
- doc.addEventListener("pointerdown", () => {
35
- focusFromKeyboard = false;
36
- }, true);
37
- }
38
- const CLEAR_TRIGGER = "clearrequest";
39
- const CLEAR_CLICK_EVENT = "clearclick";
40
- const CLEAR_INPUT_EVENT = "clearinput";
41
- const SUPPORTS_FIELD_SIZING = typeof CSS !== "undefined" && !!CSS.supports?.("field-sizing", "content");
42
- const SHADOW_STYLE = `
43
- :host {
44
- --_fs: 15px;
45
- --_lh: 20px;
46
-
47
- display: grid;
48
- grid-template-columns: minmax(0, 1fr);
49
- row-gap: 4px;
50
- outline: none;
51
- }
52
-
53
- .label {
54
- display: none;
55
- color: var(--input-label);
56
- font-family: var(--sans-serif);
57
- font-size: var(--_fs);
58
- line-height: var(--_lh);
59
- font-weight: 500;
60
- }
61
-
62
- .field {
63
- --_bc: var(--input-rest-border);
64
- --_bw: var(--input-border-width);
65
- --_pad-block: 4px;
66
-
67
- display: flex;
68
- align-items: center;
69
- box-sizing: border-box;
70
- min-height: 28px;
71
- background: var(--input-bg);
72
- border-radius: 4px;
73
- box-shadow: inset 0 0 0 var(--_bw) var(--_bc);
74
- transition: box-shadow 120ms ease;
75
- }
76
- :host([multiline]) .field { align-items: stretch; }
77
- :host([size="small"]) { --_fs: 13px; --_lh: 16px; }
78
- :host([size="large"]) { --_fs: 17px; --_lh: 22px; }
79
- :host([size="small"]) .field { min-height: 24px; }
80
- :host([size="large"]) .field { min-height: 32px; }
81
- :host([round]) .field { border-radius: var(--input-round, 999px); }
82
-
83
- @media (hover: hover) and (pointer: fine) {
84
- :host(:not(:disabled)) .field:hover { --_bw: 1px; --_bc: var(--input-border); }
85
- }
86
- :host(:not([readonly])) .field:has(input:focus, textarea:focus, button:focus-visible),
87
- :host([readonly]:state(kb-focus)) .field {
88
- --_bw: 1px;
89
- --_bc: var(--input-border);
90
- outline: 1px solid var(--focus-ring);
91
- outline-offset: 1px;
92
- }
93
- @media (forced-colors: active) { .field { border: 1px solid ButtonBorder; } }
94
-
95
- input, textarea, button {
96
- flex: 1 1 auto;
97
- min-width: 0;
98
- width: 100%;
99
- box-sizing: border-box;
100
- border: 0;
101
- margin: 0;
102
- padding-block: 0;
103
- padding-inline: 7px;
104
- background: transparent;
105
- outline: none;
106
- color: var(--input-text);
107
- font-family: var(--sans-serif);
108
- font-stretch: normal;
109
- font-style: normal;
110
- font-variation-settings: inherit;
111
- font-size: var(--_fs);
112
- line-height: var(--_lh);
113
- font-weight: 400;
114
- -webkit-appearance: none;
115
- appearance: none;
116
- }
117
- textarea {
118
- resize: none;
119
- padding-block: var(--_pad-block);
120
- overflow-y: auto;
121
- }
122
- button { text-align: start; white-space: nowrap; overflow: hidden; cursor: pointer; }
123
- button.placeholder { color: var(--input-placeholder); }
124
- :host([maxrows]:not([rows])) textarea {
125
- max-height: calc(var(--_lh) * var(--_maxrows) + var(--_pad-block) * 2);
126
- }
127
- input::placeholder, textarea::placeholder { color: var(--input-placeholder); opacity: 1; }
128
- input:disabled, textarea:disabled, button:disabled { cursor: not-allowed; }
129
- :host([readonly]:not([disabled])) .field,
130
- :host([readonly]:not([disabled])) input,
131
- :host([readonly]:not([disabled])) textarea { cursor: pointer; }
132
- :host([readonly]:not([disabled])) input { text-overflow: ellipsis; }
133
- input::-webkit-search-cancel-button,
134
- input::-webkit-search-decoration,
135
- input::-webkit-search-results-button,
136
- input::-webkit-search-results-decoration,
137
- input::-webkit-inner-spin-button,
138
- input::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; display: none; }
139
- input::-ms-clear, input::-ms-reveal { display: none; }
140
-
141
- slot[name="leading"], slot[name="trailing"] {
142
- display: none;
143
- color: var(--input-adornment);
144
- font-size: var(--_fs);
145
- line-height: var(--_lh);
146
- font-stretch: var(--_input-adornment-font-stretch, normal);
147
- }
148
- :host([dim-actions]) slot[name="leading"],
149
- :host([dim-actions]) slot[name="trailing"],
150
- :host([dim-actions]) slot[name="clear"] {
151
- opacity: 0.6;
152
- transition: opacity 120ms ease;
153
- }
154
- :host([dim-actions]:not(:disabled)) .field:hover slot[name="leading"],
155
- :host([dim-actions]:not(:disabled)) .field:hover slot[name="trailing"],
156
- :host([dim-actions]:not(:disabled)) .field:hover slot[name="clear"],
157
- :host([dim-actions]:not(:disabled)) .field:focus-within slot[name="leading"],
158
- :host([dim-actions]:not(:disabled)) .field:focus-within slot[name="trailing"],
159
- :host([dim-actions]:not(:disabled)) .field:focus-within slot[name="clear"] {
160
- opacity: 1;
161
- }
162
-
163
- :host(:disabled) slot[name="leading"],
164
- :host(:disabled) slot[name="trailing"] { opacity: 0.5; pointer-events: none; }
165
-
166
- slot[name="clear"] {
167
- display: flex;
168
- align-items: center;
169
- flex-shrink: 0;
170
- visibility: hidden;
171
- }
172
- :host(:state(filled):not(:disabled):not([readonly])) slot[name="clear"] { visibility: visible; }
173
-
174
- :host([multiline]:state(filled)) slot[name="clear"] {
175
- align-self: flex-start;
176
- height: calc(var(--_lh) + var(--_pad-block) * 2);
177
- }
178
-
179
- .hint {
180
- display: none;
181
- gap: 4px;
182
- align-items: flex-start;
183
- padding-inline-start: 1px;
184
- color: var(--input-hint);
185
- font-family: var(--sans-serif);
186
- font-size: calc(var(--_fs) - 1px);
187
- line-height: calc(var(--_lh) - 2px);
188
- }
189
- `;
29
+ const USER_AGENT = typeof navigator !== "undefined" ? navigator.userAgent : "";
30
+ const IS_WEBKIT = /AppleWebKit\//.test(USER_AGENT) && !/Chrom(?:e|ium)\//.test(USER_AGENT);
31
+ const USE_NATIVE_FIELD_SIZING = !IS_WEBKIT && typeof CSS !== "undefined" && !!CSS.supports?.("field-sizing", "content");
32
+ const isInput = (control) => control?.localName === "input";
33
+ const isTextarea = (control) => control?.localName === "textarea";
34
+ const isButton = (control) => control?.localName === "button";
190
35
  const READ_DELEGATED_ARIA = /* @__PURE__ */ Symbol("readDelegatedAria");
191
36
  const WRITE_DELEGATED_ARIA = /* @__PURE__ */ Symbol("writeDelegatedAria");
192
37
  class AInputElement extends HTMLElementBase {
@@ -208,11 +53,15 @@ class AInputElement extends HTMLElementBase {
208
53
  labelSlot;
209
54
  hintSlot;
210
55
  leadingSlot;
56
+ #trailingSlot;
57
+ #trailingActions;
211
58
  control;
59
+ #buttonText;
212
60
  // The intended value, captured even before the control exists (a framework
213
61
  // may set the `value` property before the element connects), so the initial
214
62
  // value isn't lost when the control is built.
215
63
  pendingValue;
64
+ #releaseModality;
216
65
  // True between connect and the first control build, so attribute changes for
217
66
  // forwarded props don't try to touch a control that doesn't exist yet.
218
67
  ready = false;
@@ -231,6 +80,8 @@ class AInputElement extends HTMLElementBase {
231
80
  popupAriaSource;
232
81
  popupControls = null;
233
82
  popupActiveDescendant = null;
83
+ #labelObserver;
84
+ #labelHasText = false;
234
85
  constructor() {
235
86
  super();
236
87
  try {
@@ -239,40 +90,43 @@ class AInputElement extends HTMLElementBase {
239
90
  console.warn("a-input: ElementInternals unavailable \u2014 form association disabled.", err);
240
91
  }
241
92
  const shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
242
- const style = document.createElement("style");
243
- style.textContent = SHADOW_STYLE;
244
- this.labelSlot = document.createElement("slot");
93
+ this.labelSlot = this.doc.createElement("slot");
245
94
  this.labelSlot.className = "label";
246
95
  this.labelSlot.setAttribute("part", "label");
247
96
  this.labelSlot.name = "label";
248
97
  this.labelSlot.addEventListener("click", () => this.control?.focus());
249
98
  this.labelSlot.addEventListener("slotchange", this.onLabelSlotChange);
250
- this.field = document.createElement("div");
99
+ this.field = this.doc.createElement("div");
251
100
  this.field.className = "field";
252
101
  this.field.setAttribute("part", "field");
253
- this.leadingSlot = document.createElement("slot");
102
+ this.leadingSlot = this.doc.createElement("slot");
254
103
  this.leadingSlot.name = "leading";
255
104
  this.leadingSlot.setAttribute("part", "leading");
256
- const trailingSlot = document.createElement("slot");
257
- trailingSlot.name = "trailing";
258
- trailingSlot.setAttribute("part", "trailing");
259
- const clearSlot = document.createElement("slot");
105
+ this.#trailingSlot = this.doc.createElement("slot");
106
+ this.#trailingSlot.name = "trailing";
107
+ this.#trailingSlot.setAttribute("part", "trailing");
108
+ this.#trailingActions = inputTrailingActions(this, this.#trailingSlot, "a-input-trailing", (actions) => {
109
+ this.internals?.states?.[actions ? "add" : "delete"]("trailing-actions");
110
+ });
111
+ this.#trailingSlot.addEventListener("slotchange", this.#trailingActions.sync);
112
+ const clearSlot = this.doc.createElement("slot");
260
113
  clearSlot.name = "clear";
261
114
  clearSlot.setAttribute("part", "clear");
262
- this.field.append(this.leadingSlot, clearSlot, trailingSlot);
263
- this.addEventListener(CLEAR_TRIGGER, () => {
115
+ this.field.append(this.leadingSlot, clearSlot, this.#trailingSlot);
116
+ this.addEventListener(CLEAR_TRIGGER, (event) => {
117
+ if (!ownsInputClearRequest(this, event) || this.control?.disabled || this.hasAttribute("readonly")) return;
264
118
  const proceed = this.dispatchEvent(
265
119
  new CustomEvent(CLEAR_CLICK_EVENT, { bubbles: true, cancelable: true })
266
120
  );
267
121
  if (proceed) this.clear();
268
122
  });
269
- this.hintSlot = document.createElement("slot");
123
+ this.hintSlot = this.doc.createElement("slot");
270
124
  this.hintSlot.className = "hint";
271
125
  this.hintSlot.setAttribute("part", "hint");
272
126
  this.hintSlot.name = "hint";
273
127
  this.hintSlot.addEventListener("slotchange", this.onHintSlotChange);
274
- const extrasSlot = document.createElement("slot");
275
- shadow.append(style, this.labelSlot, this.field, extrasSlot, this.hintSlot);
128
+ const extrasSlot = this.doc.createElement("slot");
129
+ shadow.append(this.labelSlot, this.field, extrasSlot, this.hintSlot);
276
130
  }
277
131
  /** Floating-element anchor protocol (see `anchorRect` in anta_helpers): point
278
132
  * a menu / tooltip anchored to this input at the `.field` box, not the host —
@@ -282,14 +136,31 @@ class AInputElement extends HTMLElementBase {
282
136
  return this.field.getBoundingClientRect();
283
137
  }
284
138
  connectedCallback() {
285
- trackFocusModality(this.doc);
139
+ this.#releaseModality?.();
140
+ this.#releaseModality = trackFocusModality(this.doc, this.syncButtonFocus);
286
141
  if (Object.prototype.hasOwnProperty.call(this, "value")) {
287
142
  const v = this.value;
288
143
  delete this.value;
289
144
  this.value = v;
290
145
  }
146
+ if (Object.prototype.hasOwnProperty.call(this, "name")) {
147
+ const name = this.name;
148
+ delete this.name;
149
+ this.name = name;
150
+ }
291
151
  if (!this.control) this.buildControl();
152
+ else this.syncAutoHeight();
292
153
  this.ready = true;
154
+ this.#trailingActions.sync();
155
+ this.applyLabelAria();
156
+ this.applyDescriptionAria();
157
+ }
158
+ disconnectedCallback() {
159
+ this.#labelObserver?.disconnect();
160
+ this.#trailingActions.disconnect();
161
+ this.#releaseModality?.();
162
+ this.#releaseModality = void 0;
163
+ this.onBlur();
293
164
  }
294
165
  [SYNC_POPUP_ARIA](relations) {
295
166
  if (relations.clear) {
@@ -315,11 +186,11 @@ class AInputElement extends HTMLElementBase {
315
186
  if (name === "multiline" || name === "button" || name === "rows" || name === "maxrows") {
316
187
  if (!this.control) return;
317
188
  const needTextarea = this.hasAttribute("multiline") || this.hasAttribute("rows");
318
- const isTextarea = this.control instanceof HTMLTextAreaElement;
189
+ const hasTextarea = isTextarea(this.control);
319
190
  const needButton = !needTextarea && this.hasAttribute("button");
320
- const isButton = this.control instanceof HTMLButtonElement;
321
- if (needTextarea !== isTextarea || needButton !== isButton) this.buildControl(this.value);
322
- else if (this.control instanceof HTMLTextAreaElement) this.configureTextarea(this.control);
191
+ const hasButton = isButton(this.control);
192
+ if (needTextarea !== hasTextarea || needButton !== hasButton) this.buildControl(this.value);
193
+ else if (isTextarea(this.control)) this.configureTextarea(this.control);
323
194
  return;
324
195
  }
325
196
  if (name === "status") {
@@ -338,6 +209,7 @@ class AInputElement extends HTMLElementBase {
338
209
  if (name === "defaultvalue") return;
339
210
  if (this.control) {
340
211
  this.forward(name, value);
212
+ if (name === "readonly" || name === "type") this.syncButtonFocus();
341
213
  this.syncButtonPresentation();
342
214
  this.updateValidity();
343
215
  }
@@ -388,7 +260,10 @@ class AInputElement extends HTMLElementBase {
388
260
  const control = this.control;
389
261
  if (!control) return;
390
262
  applyShadowAria(this, control, name, this.delegatedAria.get(name) ?? null);
391
- if (name === "aria-label" || name === "aria-labelledby") this.applyLabelAria();
263
+ if (name === "aria-label" || name === "aria-labelledby") {
264
+ this.applyLabelAria();
265
+ this.applyDescriptionAria();
266
+ }
392
267
  if (name === "aria-description" || name === "aria-describedby") this.applyDescriptionAria();
393
268
  if (name === "aria-invalid" && !this.delegatedAria.has(name)) this.syncStatus();
394
269
  if (name === "aria-controls" || name === "aria-activedescendant") this.applyPopupAria();
@@ -401,6 +276,7 @@ class AInputElement extends HTMLElementBase {
401
276
  const control = this.control;
402
277
  if (!control) return;
403
278
  for (const [name, value] of this.delegatedAria) applyShadowAria(this, control, name, value);
279
+ this.applyDescriptionAria();
404
280
  });
405
281
  }
406
282
  /** (Re)build the shadow control from the current attributes. */
@@ -409,24 +285,34 @@ class AInputElement extends HTMLElementBase {
409
285
  const refocus = prev != null && this.shadowRoot?.activeElement === prev;
410
286
  let selStart = null;
411
287
  let selEnd = null;
412
- if (prev instanceof HTMLInputElement || prev instanceof HTMLTextAreaElement) {
288
+ let selDirection = null;
289
+ if (isInput(prev) || isTextarea(prev)) {
413
290
  try {
414
291
  selStart = prev.selectionStart;
415
292
  selEnd = prev.selectionEnd;
293
+ selDirection = prev.selectionDirection;
416
294
  } catch {
417
295
  }
418
296
  }
419
297
  const multiline = this.hasAttribute("multiline") || this.hasAttribute("rows");
420
298
  const button = !multiline && this.hasAttribute("button");
421
- const next = document.createElement(button ? "button" : multiline ? "textarea" : "input");
422
- if (next instanceof HTMLButtonElement) next.type = "button";
299
+ const next = this.doc.createElement(button ? "button" : multiline ? "textarea" : "input");
300
+ this.#buttonText = void 0;
301
+ if (isButton(next)) {
302
+ next.type = "button";
303
+ this.#buttonText = this.doc.createElement("span");
304
+ this.#buttonText.setAttribute("part", "input-label");
305
+ next.append(this.#buttonText);
306
+ }
423
307
  next.setAttribute("part", "input");
424
308
  if (this.control) this.control.replaceWith(next);
425
309
  else this.leadingSlot.after(next);
426
310
  this.control = next;
311
+ this.internals?.states?.[multiline ? "add" : "delete"]("multiline");
312
+ this.internals?.states?.[button ? "add" : "delete"]("button");
427
313
  for (const attr of FORWARDED) {
428
- if (next instanceof HTMLTextAreaElement && attr === "type") continue;
429
- this.forward(attr, this.getAttribute(attr));
314
+ if (isTextarea(next) && attr === "type") continue;
315
+ this.forward(attr, attr === "name" ? this.name : this.getAttribute(attr));
430
316
  }
431
317
  this.syncDisabled();
432
318
  this.syncStatus();
@@ -445,9 +331,9 @@ class AInputElement extends HTMLElementBase {
445
331
  next.addEventListener("blur", this.onBlur);
446
332
  if (refocus) {
447
333
  next.focus();
448
- if (selStart != null && (next instanceof HTMLInputElement || next instanceof HTMLTextAreaElement)) {
334
+ if (selStart != null && (isInput(next) || isTextarea(next))) {
449
335
  try {
450
- next.setSelectionRange(selStart, selEnd ?? selStart);
336
+ next.setSelectionRange(selStart, selEnd ?? selStart, selDirection ?? void 0);
451
337
  } catch {
452
338
  }
453
339
  }
@@ -457,8 +343,8 @@ class AInputElement extends HTMLElementBase {
457
343
  this.updateFilled();
458
344
  this.syncAutoHeight();
459
345
  }
460
- /** Autogrow (no `rows`) via `field-sizing: content` — or the JS fallback where
461
- * that's unsupported — capped by `maxrows`; a fixed `rows` count switches it
346
+ /** Autogrow (no `rows`) via `field-sizing: content` or the JS fallback,
347
+ * capped by `maxrows`; a fixed `rows` count switches it
462
348
  * off for a constant-height box. */
463
349
  configureTextarea(ta) {
464
350
  const rows = this.getAttribute("rows");
@@ -470,30 +356,35 @@ class AInputElement extends HTMLElementBase {
470
356
  ta.style.removeProperty("height");
471
357
  } else {
472
358
  ta.rows = 1;
473
- if (SUPPORTS_FIELD_SIZING) ta.style.setProperty("field-sizing", "content");
474
- else ta.style.removeProperty("field-sizing");
359
+ ta.style.setProperty("field-sizing", USE_NATIVE_FIELD_SIZING ? "content" : "fixed");
475
360
  if (maxrows != null) ta.style.setProperty("--_maxrows", String(parseInt(maxrows, 10) || 1));
476
361
  else ta.style.removeProperty("--_maxrows");
477
362
  this.syncAutoHeight();
478
363
  }
479
364
  }
480
- /** Autogrow fallback for browsers without `field-sizing: content` (Firefox,
481
- * Safari < 26.2). Grows the shadow textarea to fit its content; the CSS
365
+ /** Autogrow fallback for WebKit and browsers without `field-sizing: content`.
366
+ * Grows the shadow textarea to fit its content; the CSS
482
367
  * `max-height` cap (when `maxrows` is set) still clamps it and scrolls past.
483
- * A no-op where `field-sizing` is supported, or when the field isn't
368
+ * A no-op on the native sizing path, or when the field isn't
484
369
  * autogrowing (fixed `rows`, or not a textarea) — those size via CSS. */
485
370
  syncAutoHeight = () => {
486
- if (SUPPORTS_FIELD_SIZING) return;
371
+ if (USE_NATIVE_FIELD_SIZING) return;
487
372
  const ta = this.control;
488
- if (!(ta instanceof HTMLTextAreaElement) || this.getAttribute("rows") != null) return;
489
- ta.style.height = "auto";
373
+ if (!isTextarea(ta) || this.getAttribute("rows") != null) return;
374
+ const minHeight = this.field.style.getPropertyValue("--_input-measured-min-height");
375
+ const scrollTop = ta.scrollTop;
376
+ this.field.style.setProperty("--_input-measured-min-height", this.view.getComputedStyle(this.field).height);
377
+ ta.style.height = "0px";
490
378
  ta.style.height = `${ta.scrollHeight}px`;
379
+ if (minHeight) this.field.style.setProperty("--_input-measured-min-height", minHeight);
380
+ else this.field.style.removeProperty("--_input-measured-min-height");
381
+ ta.scrollTop = scrollTop;
491
382
  };
492
383
  forward(name, value) {
493
384
  const c = this.control;
494
385
  if (!c) return;
495
- if (c instanceof HTMLButtonElement) return;
496
- if (c instanceof HTMLTextAreaElement && name === "type") return;
386
+ if (isButton(c)) return;
387
+ if (isTextarea(c) && name === "type") return;
497
388
  if (BOOL_FORWARDED.has(name)) c.toggleAttribute(name, value != null);
498
389
  else if (value == null) c.removeAttribute(name);
499
390
  else c.setAttribute(name, value);
@@ -503,13 +394,17 @@ class AInputElement extends HTMLElementBase {
503
394
  }
504
395
  syncButtonPresentation() {
505
396
  const button = this.control;
506
- if (!(button instanceof HTMLButtonElement)) return;
397
+ if (!isButton(button)) return;
507
398
  const value = button.value;
508
- button.textContent = value || this.getAttribute("placeholder") || "";
509
- button.classList.toggle("placeholder", !value);
399
+ if (this.#buttonText) this.#buttonText.textContent = value || this.getAttribute("placeholder") || "";
400
+ this.applyDescriptionAria();
510
401
  }
511
402
  syncFormValue(value) {
512
- this.internals?.setFormValue(this.control instanceof HTMLButtonElement ? null : value);
403
+ if (isButton(this.control)) {
404
+ this.internals?.setFormValue(null);
405
+ return;
406
+ }
407
+ this.internals?.setFormValue(value);
513
408
  }
514
409
  /** Reflect `status` into the control's `aria-invalid` and the `:state(invalid)`
515
410
  * custom state. Called on `status` change AND from buildControl — so a field
@@ -537,18 +432,28 @@ class AInputElement extends HTMLElementBase {
537
432
  onChange = () => {
538
433
  this.dispatchEvent(new Event("change", { bubbles: true }));
539
434
  };
540
- // Stamp the off-DOM `:state(kb-focus)` when this focus arrived via the keyboard
541
- // (see `trackFocusModality`), so the read-only field's ring can draw for keyboard
542
- // focus but not a mouse click — the one distinction Chromium's `:focus-visible`
543
- // won't make for an <input>. Editable fields ignore the state (ring on `:focus`).
435
+ syncButtonFocus = () => {
436
+ if (!isButton(this.control)) return;
437
+ const show = this.shadowRoot?.activeElement === this.control && this.control.matches(":focus-visible");
438
+ this.internals?.states?.[show ? "add" : "delete"]("button-focus");
439
+ };
544
440
  onFocus = () => {
441
+ if (isButton(this.control)) this.syncButtonFocus();
442
+ const modality = this.doc[MODALITY];
443
+ if (modality) {
444
+ modality.active = isButton(this.control) ? this.syncButtonFocus : void 0;
445
+ if (isButton(this.control)) modality.refresh();
446
+ }
545
447
  try {
546
- if (focusFromKeyboard) this.internals?.states?.add("kb-focus");
448
+ if (this.doc[MODALITY]?.keyboard) this.internals?.states?.add("kb-focus");
547
449
  else this.internals?.states?.delete("kb-focus");
548
450
  } catch {
549
451
  }
550
452
  };
551
453
  onBlur = () => {
454
+ const modality = this.doc[MODALITY];
455
+ if (modality?.active === this.syncButtonFocus) modality.active = void 0;
456
+ if (isButton(this.control)) this.internals?.states?.delete("button-focus");
552
457
  try {
553
458
  this.internals?.states?.delete("kb-focus");
554
459
  } catch {
@@ -556,14 +461,28 @@ class AInputElement extends HTMLElementBase {
556
461
  };
557
462
  onLabelSlotChange = () => {
558
463
  this.applyLabelAria();
464
+ this.applyDescriptionAria();
559
465
  };
560
466
  applyLabelAria() {
561
467
  const c = this.control;
562
468
  if (!c) return;
563
- if (this.delegatedAria.has("aria-label") || this.delegatedAria.has("aria-labelledby")) return;
564
- const text = this.labelSlot.assignedNodes().map((n) => n.textContent ?? "").join(" ").trim();
565
- if (text) c.setAttribute("aria-label", text);
566
- else c.removeAttribute("aria-label");
469
+ this.#labelObserver?.disconnect();
470
+ if (this.delegatedAria.has("aria-labelledby")) return;
471
+ if (this.delegatedAria.has("aria-label")) {
472
+ c.ariaLabelledByElements = [];
473
+ return;
474
+ }
475
+ const labels = this.labelSlot.assignedElements();
476
+ c.ariaLabelledByElements = labels;
477
+ this.#labelHasText = labels.some((label) => !!label.textContent?.trim());
478
+ if (!isButton(c) || !this.isConnected || !labels.length) return;
479
+ this.#labelObserver ??= new this.view.MutationObserver(() => {
480
+ const hasText = this.labelSlot.assignedElements().some((label) => !!label.textContent?.trim());
481
+ if (hasText === this.#labelHasText) return;
482
+ this.#labelHasText = hasText;
483
+ this.applyDescriptionAria();
484
+ });
485
+ for (const label of labels) this.#labelObserver.observe(label, { childList: true, characterData: true, subtree: true });
567
486
  }
568
487
  onHintSlotChange = () => {
569
488
  this.applyDescriptionAria();
@@ -571,21 +490,22 @@ class AInputElement extends HTMLElementBase {
571
490
  applyDescriptionAria() {
572
491
  const c = this.control;
573
492
  if (!c) return;
574
- if (this.delegatedAria.has("aria-description") || this.delegatedAria.has("aria-describedby")) return;
575
- const text = this.hintSlot.assignedNodes().map((n) => n.textContent ?? "").join(" ").trim();
576
- if (text) c.setAttribute("aria-description", text);
577
- else c.removeAttribute("aria-description");
493
+ if (this.delegatedAria.has("aria-describedby")) return;
494
+ if (this.delegatedAria.has("aria-description")) {
495
+ c.ariaDescribedByElements = [];
496
+ return;
497
+ }
498
+ const named = c.getAttribute("aria-label")?.trim() || (this.delegatedAria.has("aria-labelledby") ? c.ariaLabelledByElements?.length : !this.delegatedAria.has("aria-label") && this.#labelHasText);
499
+ const value = isButton(c) && named && c.value.trim() ? this.#buttonText : null;
500
+ c.ariaDescribedByElements = [...value ? [value] : [], ...this.hintSlot.assignedElements()];
578
501
  }
579
502
  applyPopupAria() {
580
503
  const control = this.control;
581
504
  if (!control) return;
582
- try {
583
- if (!this.delegatedAria.has("aria-controls") && "ariaControlsElements" in control)
584
- control.ariaControlsElements = this.popupControls ? [this.popupControls] : null;
585
- if (!this.delegatedAria.has("aria-activedescendant") && "ariaActiveDescendantElement" in control)
586
- control.ariaActiveDescendantElement = this.popupActiveDescendant;
587
- } catch {
588
- }
505
+ if (!this.delegatedAria.has("aria-controls"))
506
+ control.ariaControlsElements = this.popupControls ? [this.popupControls] : null;
507
+ if (!this.delegatedAria.has("aria-activedescendant"))
508
+ control.ariaActiveDescendantElement = this.popupActiveDescendant;
589
509
  }
590
510
  updateFilled() {
591
511
  if (this.value) this.internals?.states?.add("filled");
@@ -594,6 +514,10 @@ class AInputElement extends HTMLElementBase {
594
514
  updateValidity() {
595
515
  const c = this.control;
596
516
  if (!this.internals || !c) return;
517
+ if (isButton(c)) {
518
+ this.internals.setValidity({});
519
+ return;
520
+ }
597
521
  if (this.getAttribute("status") === "critical" && c.validity.valid) {
598
522
  this.internals.setValidity({ customError: true }, "Invalid value.", c);
599
523
  } else {
@@ -653,16 +577,17 @@ class AInputElement extends HTMLElementBase {
653
577
  reportValidity() {
654
578
  return this.internals?.reportValidity() ?? true;
655
579
  }
656
- /** Form field name — mirrors the `name` attribute, like native `<input>.name`,
657
- * so `el.name` works (e.g. keying validation messages by field in a form loop). */
580
+ /** Form field name, reflected to the host attribute for native form lookup. */
658
581
  get name() {
659
582
  return this.getAttribute("name") ?? "";
660
583
  }
661
584
  set name(v) {
662
- this.setAttribute("name", v);
585
+ if (v == null) this.removeAttribute("name");
586
+ else if (this.getAttribute("name") !== String(v)) this.setAttribute("name", String(v));
663
587
  }
664
588
  // --- Form-associated callbacks ---
665
589
  formResetCallback() {
590
+ if (isButton(this.control)) return;
666
591
  this.value = this.getAttribute("defaultvalue") ?? "";
667
592
  this.dispatchEvent(new Event("input", { bubbles: true }));
668
593
  this.dispatchEvent(new Event("change", { bubbles: true }));
@@ -1,12 +1,9 @@
1
- import { HTMLElementBase } from '../anta_helpers';
1
+ import { HTMLElementBase } from '../element-base';
2
2
  import './a-loader.css';
3
- /**
4
- * `<a-loader>` — a declarative, icon-sized loading indicator.
5
- *
6
- * Its visual treatment is entirely external CSS. The wrapper supplies
7
- * `--loader-value` for a determinate ring; no shadow DOM or element state is
8
- * needed.
9
- */
3
+ /** Compatibility class for applications that explicitly register `<a-loader>`.
4
+ * Loader renders through CSS and does not require registration. */
10
5
  export declare class ALoaderElement extends HTMLElementBase {
11
6
  }
7
+ /** Register the compatibility class when an integration requires a defined tag.
8
+ * Ordinary Loader usage needs only its stylesheet. */
12
9
  export declare function register_a_loader(): void;
@@ -1,4 +1,4 @@
1
- import { HTMLElementBase } from "../anta_helpers";
1
+ import { HTMLElementBase } from "../element-base";
2
2
  import "./a-loader.css";
3
3
  class ALoaderElement extends HTMLElementBase {
4
4
  }
@@ -8,7 +8,6 @@ function register_a_loader() {
8
8
  customElements.define("a-loader", ALoaderElement);
9
9
  }
10
10
  }
11
- register_a_loader();
12
11
  export {
13
12
  ALoaderElement,
14
13
  register_a_loader
@@ -1 +1 @@
1
- @layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu-item:not(:defined){display:none}a[data-anta-menu-item]{text-decoration:none}a-menu-item,a[data-anta-menu-item]{--menu-item-color: var(--text-2);--menu-item-icon-color: var(--text-3);--menu-item-hint-color: var(--text-3);--menu-item-hover-bg: light-dark( color-mix(in oklch, currentColor 5%, transparent), color-mix(in oklch, currentColor 10%, transparent) );--menu-item-active-bg: light-dark( color-mix(in oklch, currentColor 8%, transparent), color-mix(in oklch, currentColor 14%, transparent) );--menu-item-selected-bg: var(--menu-item-active-bg);--menu-item-timing-in: 60ms ease-in-out;--menu-item-timing-out: .28s ease-out;--menu-item-padding-x: 8px;--menu-item-padding-y: 6px;display:flex;flex-shrink:0;align-items:center;gap:.6ch;box-sizing:border-box;width:100%;min-height:28px;padding-block:var(--menu-item-padding-y);padding-inline:var(--menu-item-padding-x);border-radius:var(--radius-sm, 4px);color:var(--menu-item-color);background:transparent;transition:background-color var(--menu-item-timing-out);font:inherit;font-variation-settings:inherit;font-size:14px;line-height:16px;text-align:left;white-space:nowrap;cursor:pointer;user-select:none;outline:none}a-menu[round] a-menu-item,a-menu[round] a[data-anta-menu-item]{border-radius:999px}a-menu-item:hover,a-menu-item:focus-visible,a[data-anta-menu-item]:hover,a[data-anta-menu-item]:focus-visible,a-menu-item:has(>a-menu:state(open)),a-menu-item:state(active){background:var(--menu-item-hover-bg);transition:background-color var(--menu-item-timing-in)}a-menu-item:active,a[data-anta-menu-item]:active{background:var(--menu-item-active-bg);transition:none}a-menu-item[selected],a[data-anta-menu-item][aria-current=true]{background:var(--menu-item-selected-bg)}a-menu-item:focus-visible,a[data-anta-menu-item]:focus-visible{outline:1px solid var(--focus-ring);outline-offset:1px}a-menu-item>a-menu-item-label,a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-label,a[data-anta-menu-item]>a-menu-item-text{flex:1 1 auto;min-width:0}a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-text{display:flex;flex-direction:column}a-menu-item:has(>a-menu-item-text),a[data-anta-menu-item]:has(>a-menu-item-text){align-items:flex-start}a-menu-item-label{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis}a-menu-item-hint{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;margin-block-start:1px;color:var(--menu-item-hint-color);font-size:12px;line-height:15px}a-menu-item>a-icon,a[data-anta-menu-item]>a-icon{flex:none;--icon-size: 16px;color:var(--menu-item-icon-color)}a-menu-item>a-checkbox,a-menu-item>a-radio{flex:none;--checkbox-gap: 0;--radio-gap: 0;pointer-events:none}a-menu-item>a-switch[data-menu-item-switch]{flex:none;margin-inline-start:auto;--switch-gap: 0;pointer-events:none}a-menu-item>kbd+a-switch[data-menu-item-switch]{margin-inline-start:0}a-menu-item>a-checkbox:before,a-menu-item>a-checkbox:after,a-menu-item>a-radio:before{margin-block-start:0}a-menu-item>a-radio:after{margin-block-start:calc((var(--radio-control-size) - (var(--radio-dot-size) - var(--_radio-dot-adjust))) / 2)}a-menu-item:has(>:is(a-icon,a-checkbox,a-radio,[data-indicator]):first-child:not(:only-child)),a[data-anta-menu-item]:has(>:is(a-icon,[data-indicator]):first-child:not(:only-child)){padding-inline-start:var(--menu-item-padding-y)}a-menu-item:not([submenu]):has(>a-icon:last-child:not(:only-child)),a[data-anta-menu-item]:has(>a-icon:last-child:not(:only-child)){padding-inline-end:max(0px,var(--menu-item-padding-x) - 2px)}a-menu-item>kbd,a[data-anta-menu-item]>kbd{flex:none;margin-left:auto;padding-left:12px;color:var(--text-5);font:inherit;font-variation-settings:inherit;font-size:1em;letter-spacing:.1ch;white-space:nowrap}a-menu-item[submenu]>a-icon:last-of-type{margin-left:auto}a-menu-item[submenu]>a-icon:last-of-type,a-menu-item>a-icon:last-child:not(:only-child),a[data-anta-menu-item]>a-icon:last-child:not(:only-child){position:relative;inset-inline-end:-2px}a-menu-item[tone=brand],a-menu-item[tone=info],a-menu-item[tone=success],a-menu-item[tone=warning],a-menu-item[tone=critical],a[data-anta-menu-item][tone=brand],a[data-anta-menu-item][tone=info],a[data-anta-menu-item][tone=success],a[data-anta-menu-item][tone=warning],a[data-anta-menu-item][tone=critical]{--menu-item-icon-color: var(--menu-item-color)}a-menu-item[tone=brand],a[data-anta-menu-item][tone=brand]{--menu-item-color: var(--text-2-brand);--menu-item-hint-color: var(--text-3-brand)}a-menu-item[tone=info],a[data-anta-menu-item][tone=info]{--menu-item-color: var(--text-2-info);--menu-item-hint-color: var(--text-3-info)}a-menu-item[tone=success],a[data-anta-menu-item][tone=success]{--menu-item-color: var(--text-2-success);--menu-item-hint-color: var(--text-3-success)}a-menu-item[tone=warning],a[data-anta-menu-item][tone=warning]{--menu-item-color: var(--text-2-warning);--menu-item-hint-color: var(--text-3-warning)}a-menu-item[tone=critical],a[data-anta-menu-item][tone=critical]{--menu-item-color: var(--text-2-critical);--menu-item-hint-color: var(--text-3-critical)}a-menu-item[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]),a[data-anta-menu-item][tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]){--menu-item-tone-source: var(--text-2);--menu-item-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h), oklch(from var(--menu-item-tone-source) .78 c h) );--menu-item-icon-color: var(--menu-item-color);--menu-item-hint-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h / .8), oklch(from var(--menu-item-tone-source) .78 c h / .8) );@supports (color: attr(probe type(<color>),red)){--menu-item-tone-source: attr(tone type(<color>), var(--text-2))}}a-menu-item[disabled],a[data-anta-menu-item][aria-disabled=true]{--menu-item-color: var(--text-5);--menu-item-icon-color: var(--text-5);--menu-item-hint-color: var(--text-5);cursor:default;pointer-events:none}}
1
+ @layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-menu-item:not(:defined){display:none}a[data-anta-menu-item]{text-decoration:none}a-menu-item,a[data-anta-menu-item]{--menu-item-color: var(--text-2);--menu-item-icon-color: var(--text-3);--menu-item-hint-color: var(--text-3);--menu-item-hover-bg: light-dark( color-mix(in oklch, currentColor 5%, transparent), color-mix(in oklch, currentColor 10%, transparent) );--menu-item-active-bg: light-dark( color-mix(in oklch, currentColor 8%, transparent), color-mix(in oklch, currentColor 14%, transparent) );--menu-item-selected-bg: var(--menu-item-active-bg);--menu-item-timing-in: 60ms ease-in-out;--menu-item-timing-out: .28s ease-out;--menu-item-padding-x: 8px;--menu-item-padding-y: 6px;display:flex;flex-shrink:0;align-items:center;gap:.6ch;box-sizing:border-box;width:100%;min-height:28px;padding-block:var(--menu-item-padding-y);padding-inline:var(--menu-item-padding-x);border-radius:var(--menu-item-radius, var(--radius-sm, 4px));color:var(--menu-item-color);background:transparent;transition:background-color var(--menu-item-timing-out);font:inherit;font-variation-settings:inherit;font-size:14px;line-height:16px;text-align:left;white-space:nowrap;cursor:pointer;user-select:none;outline:none}a-menu-item:hover,a-menu-item:focus-visible,a[data-anta-menu-item]:hover,a[data-anta-menu-item]:focus-visible,a-menu-item:has(>a-menu:state(open)),a-menu-item:state(active){background:var(--menu-item-hover-bg);transition:background-color var(--menu-item-timing-in)}a-menu-item:active,a[data-anta-menu-item]:active{background:var(--menu-item-active-bg);transition:none}a-menu-item[selected],a[data-anta-menu-item][aria-current=true]{background:var(--menu-item-selected-bg)}a-menu-item:focus-visible,a[data-anta-menu-item]:focus-visible{outline:1px solid var(--focus-ring);outline-offset:1px}a-menu-item>a-menu-item-label,a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-label,a[data-anta-menu-item]>a-menu-item-text{flex:1 1 auto;min-width:0}a-menu-item>a-menu-item-text,a[data-anta-menu-item]>a-menu-item-text{display:flex;flex-direction:column}a-menu-item:has(>a-menu-item-text),a[data-anta-menu-item]:has(>a-menu-item-text){align-items:flex-start}a-menu-item-label{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis}a-menu-item-hint{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;margin-block-start:1px;color:var(--menu-item-hint-color);font-size:12px;line-height:15px}a-menu-item>a-icon,a[data-anta-menu-item]>a-icon{flex:none;--icon-size: 16px;color:var(--menu-item-icon-color)}a-menu-item>[data-indicator]{flex:none;display:inline-flex;align-items:center;min-height:1lh;pointer-events:none}a-menu-item>a-checkbox,a-menu-item>a-radio{flex:none;--checkbox-gap: 0;--radio-gap: 0;pointer-events:none}a-menu-item>a-switch[data-menu-item-switch]{flex:none;margin-inline-start:auto;--switch-gap: 0;pointer-events:none}a-menu-item>kbd+a-switch[data-menu-item-switch]{margin-inline-start:0}a-menu-item>a-checkbox:before,a-menu-item>a-checkbox:after,a-menu-item>a-radio:before{margin-block-start:0}a-menu-item>a-radio:after{margin-block-start:calc((var(--radio-control-size) - (var(--radio-dot-size) - var(--_radio-dot-adjust))) / 2)}a-menu-item:has(>:is(a-icon,a-checkbox,a-radio,[data-indicator]):first-child:not(:only-child)),a[data-anta-menu-item]:has(>:is(a-icon,[data-indicator]):first-child:not(:only-child)){padding-inline-start:var(--menu-item-padding-y)}a-menu-item:not([submenu]):has(>a-icon:last-child:not(:only-child)),a[data-anta-menu-item]:has(>a-icon:last-child:not(:only-child)){padding-inline-end:max(0px,var(--menu-item-padding-x) - 2px)}a-menu-item>kbd,a[data-anta-menu-item]>kbd{flex:none;margin-left:auto;padding-left:12px;color:var(--text-5);font:inherit;font-variation-settings:inherit;font-size:1em;letter-spacing:.1ch;white-space:nowrap}a-menu-item[submenu]>a-icon:last-of-type{margin-left:auto}a-menu-item[submenu]>a-icon:last-of-type,a-menu-item>a-icon:last-child:not(:only-child),a[data-anta-menu-item]>a-icon:last-child:not(:only-child){position:relative;inset-inline-end:-2px}a-menu-item[tone=brand],a-menu-item[tone=info],a-menu-item[tone=success],a-menu-item[tone=warning],a-menu-item[tone=critical],a[data-anta-menu-item][tone=brand],a[data-anta-menu-item][tone=info],a[data-anta-menu-item][tone=success],a[data-anta-menu-item][tone=warning],a[data-anta-menu-item][tone=critical]{--menu-item-icon-color: var(--menu-item-color)}a-menu-item[tone=brand],a[data-anta-menu-item][tone=brand]{--menu-item-color: var(--text-2-brand);--menu-item-hint-color: var(--text-3-brand)}a-menu-item[tone=info],a[data-anta-menu-item][tone=info]{--menu-item-color: var(--text-2-info);--menu-item-hint-color: var(--text-3-info)}a-menu-item[tone=success],a[data-anta-menu-item][tone=success]{--menu-item-color: var(--text-2-success);--menu-item-hint-color: var(--text-3-success)}a-menu-item[tone=warning],a[data-anta-menu-item][tone=warning]{--menu-item-color: var(--text-2-warning);--menu-item-hint-color: var(--text-3-warning)}a-menu-item[tone=critical],a[data-anta-menu-item][tone=critical]{--menu-item-color: var(--text-2-critical);--menu-item-hint-color: var(--text-3-critical)}a-menu-item[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]),a[data-anta-menu-item][tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]){--menu-item-tone-source: var(--text-2);--menu-item-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h), oklch(from var(--menu-item-tone-source) .78 c h) );--menu-item-icon-color: var(--menu-item-color);--menu-item-hint-color: light-dark( oklch(from var(--menu-item-tone-source) .45 c h / .8), oklch(from var(--menu-item-tone-source) .78 c h / .8) );@supports (color: attr(probe type(<color>),red)){--menu-item-tone-source: attr(tone type(<color>), var(--text-2))}}a-menu-item[disabled],a[data-anta-menu-item][aria-disabled=true]{--menu-item-color: var(--text-5);--menu-item-icon-color: var(--text-5);--menu-item-hint-color: var(--text-5);cursor:default;pointer-events:none}}