@antadesign/anta 0.2.2 → 0.3.1

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 (82) hide show
  1. package/README.md +14 -0
  2. package/dist/anta_helpers.d.ts +39 -1
  3. package/dist/anta_helpers.js +30 -2
  4. package/dist/components/Button.d.ts +7 -4
  5. package/dist/components/Button.js +6 -11
  6. package/dist/components/Checkbox.d.ts +97 -0
  7. package/dist/components/Checkbox.js +77 -0
  8. package/dist/components/Expander.d.ts +74 -0
  9. package/dist/components/Expander.js +53 -0
  10. package/dist/components/Input.d.ts +159 -0
  11. package/dist/components/Input.js +150 -0
  12. package/dist/components/Menu.d.ts +73 -0
  13. package/dist/components/Menu.js +42 -0
  14. package/dist/components/MenuGroup.d.ts +24 -0
  15. package/dist/components/MenuGroup.js +19 -0
  16. package/dist/components/MenuItem.d.ts +61 -0
  17. package/dist/components/MenuItem.js +50 -0
  18. package/dist/components/MenuSeparator.d.ts +14 -0
  19. package/dist/components/MenuSeparator.js +7 -0
  20. package/dist/components/Progress.d.ts +12 -6
  21. package/dist/components/Progress.js +7 -4
  22. package/dist/components/Radio.d.ts +37 -0
  23. package/dist/components/Radio.js +33 -0
  24. package/dist/components/RadioGroup.d.ts +119 -0
  25. package/dist/components/RadioGroup.js +108 -0
  26. package/dist/components/Tag.d.ts +38 -5
  27. package/dist/components/Tag.js +9 -5
  28. package/dist/components/Text.d.ts +27 -12
  29. package/dist/components/Text.js +6 -3
  30. package/dist/components/Title.d.ts +10 -1
  31. package/dist/elements/a-button.css +1 -1
  32. package/dist/elements/a-button.d.ts +56 -0
  33. package/dist/elements/a-button.js +13 -11
  34. package/dist/elements/a-checkbox.css +1 -0
  35. package/dist/elements/a-checkbox.d.ts +52 -0
  36. package/dist/elements/a-checkbox.js +130 -0
  37. package/dist/elements/a-expander.css +1 -0
  38. package/dist/elements/a-expander.d.ts +28 -0
  39. package/dist/elements/a-expander.js +237 -0
  40. package/dist/elements/a-icon.d.ts +14 -0
  41. package/dist/elements/a-icon.shapes.css +1 -1
  42. package/dist/elements/a-icon.shapes.d.ts +10 -1
  43. package/dist/elements/a-icon.shapes.js +11 -1
  44. package/dist/elements/a-input.css +1 -0
  45. package/dist/elements/a-input.d.ts +68 -0
  46. package/dist/elements/a-input.js +511 -0
  47. package/dist/elements/a-menu-group.css +1 -0
  48. package/dist/elements/a-menu-group.d.ts +13 -0
  49. package/dist/elements/a-menu-group.js +15 -0
  50. package/dist/elements/a-menu-item.css +1 -0
  51. package/dist/elements/a-menu-item.d.ts +47 -0
  52. package/dist/elements/a-menu-item.js +30 -0
  53. package/dist/elements/a-menu-separator.css +1 -0
  54. package/dist/elements/a-menu-separator.d.ts +13 -0
  55. package/dist/elements/a-menu-separator.js +15 -0
  56. package/dist/elements/a-menu.css +1 -0
  57. package/dist/elements/a-menu.d.ts +183 -0
  58. package/dist/elements/a-menu.js +763 -0
  59. package/dist/elements/a-progress.css +1 -1
  60. package/dist/elements/a-progress.d.ts +12 -0
  61. package/dist/elements/a-progress.js +1 -0
  62. package/dist/elements/a-radio-group.css +1 -0
  63. package/dist/elements/a-radio-group.d.ts +33 -0
  64. package/dist/elements/a-radio-group.js +160 -0
  65. package/dist/elements/a-radio.css +1 -0
  66. package/dist/elements/a-radio.d.ts +14 -0
  67. package/dist/elements/a-radio.js +46 -0
  68. package/dist/elements/a-tag.css +1 -1
  69. package/dist/elements/a-text.css +1 -1
  70. package/dist/elements/a-text.d.ts +42 -3
  71. package/dist/elements/a-text.js +73 -33
  72. package/dist/elements/a-tooltip.d.ts +43 -11
  73. package/dist/elements/a-tooltip.js +46 -51
  74. package/dist/elements/index.d.ts +9 -0
  75. package/dist/elements/index.js +27 -0
  76. package/dist/general_types.d.ts +468 -15
  77. package/dist/index.d.ts +16 -0
  78. package/dist/index.js +16 -0
  79. package/dist/jsx-runtime.d.ts +42 -7
  80. package/dist/jsx-runtime.js +14 -2
  81. package/dist/tokens.css +1 -1
  82. package/package.json +1 -1
@@ -1 +1 @@
1
- @layer anta{a-progress{--progress-bg: var(--bg-4);--progress-border-color: var(--border-4);--progress-indicator-bg: var(--bg-5);--progress-indicator-edge: linear-gradient( 90deg, var(--progress-indicator-bg) 0%, var(--progress-border-color) 100% );--progress-text-color: var(--text-2);--progress-hint-color: var(--text-3);display:block;container-type:inline-size;padding:4px 8px;min-height:8px;background:var(--progress-bg);border:0px solid var(--progress-border-color);border-radius:0}a-progress[tone=info]{--progress-bg: var(--bg-4-info);--progress-border-color: var(--border-4-info);--progress-indicator-bg: var(--bg-5-info);--progress-text-color: var(--text-2-info);--progress-hint-color: var(--text-3-info)}a-progress-label{display:flex;align-items:flex-start;gap:.5ch;font-variant-numeric:tabular-nums;font-feature-settings:"ss02","ss05";letter-spacing:.03em;font-size:13px;line-height:16px}a-progress-number{flex-shrink:0;color:var(--progress-text-color)}a-progress-text{flex:1 1 auto;min-width:0;color:var(--progress-text-color)}a-progress-hint{flex-shrink:0;margin-left:auto;color:var(--progress-hint-color)}}
1
+ @layer anta{a-progress{--progress-bg: var(--bg-4);--progress-border-color: var(--border-4);--progress-indicator-bg: var(--bg-5);--progress-indicator-edge: linear-gradient( 90deg, var(--progress-indicator-bg) 0%, var(--progress-border-color) 100% );--progress-text-color: var(--text-2);--progress-hint-color: var(--text-3);display:block;container-type:inline-size;padding:4px 8px;min-height:8px;background:var(--progress-bg);border:0px solid var(--progress-border-color);border-radius:0}a-progress[tone=brand]{--progress-bg: var(--bg-4-brand);--progress-border-color: var(--border-4-brand);--progress-indicator-bg: var(--bg-5-brand);--progress-text-color: var(--text-2-brand);--progress-hint-color: var(--text-3-brand)}a-progress[tone=info]{--progress-bg: var(--bg-4-info);--progress-border-color: var(--border-4-info);--progress-indicator-bg: var(--bg-5-info);--progress-text-color: var(--text-2-info);--progress-hint-color: var(--text-3-info)}a-progress[tone=success]{--progress-bg: var(--bg-4-success);--progress-border-color: var(--border-4-success);--progress-indicator-bg: var(--bg-5-success);--progress-text-color: var(--text-2-success);--progress-hint-color: var(--text-3-success)}a-progress[tone=warning]{--progress-bg: var(--bg-4-warning);--progress-border-color: var(--border-4-warning);--progress-indicator-bg: var(--bg-5-warning);--progress-text-color: var(--text-2-warning);--progress-hint-color: var(--text-3-warning)}a-progress[tone=critical]{--progress-bg: var(--bg-4-critical);--progress-border-color: var(--border-4-critical);--progress-indicator-bg: var(--bg-5-critical);--progress-text-color: var(--text-2-critical);--progress-hint-color: var(--text-3-critical)}a-progress[tone]:not([tone=""],[tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--progress-tone-source: attr(tone type(<color>), transparent);--progress-bg: oklch(from var(--progress-tone-source) .95 calc(c*.4) h);--progress-border-color: oklch(from var(--progress-tone-source) .85 calc(c*.6) h);--progress-indicator-bg: oklch(from var(--progress-tone-source) .6 c h);--progress-text-color: oklch(from var(--progress-tone-source) .45 c h);--progress-hint-color: oklch(from var(--progress-tone-source) .55 c h);.dark &{--progress-bg: oklch(from var(--progress-tone-source) .28 calc(c/2) h);--progress-border-color: oklch(from var(--progress-tone-source) .4 calc(c*.6) h);--progress-indicator-bg: oklch(from var(--progress-tone-source) .6 c h);--progress-text-color: oklch(from var(--progress-tone-source) .85 c h);--progress-hint-color: oklch(from var(--progress-tone-source) .75 c h)}}a-progress-label{display:flex;align-items:flex-start;gap:.5ch;font-variant-numeric:tabular-nums;font-feature-settings:"ss02","ss05";letter-spacing:.03em;font-size:13px;line-height:16px}a-progress-number{flex-shrink:0;color:var(--progress-text-color)}a-progress-text{flex:1 1 auto;min-width:0;color:var(--progress-text-color)}a-progress-hint{flex-shrink:0;margin-left:auto;color:var(--progress-hint-color)}}
@@ -1,5 +1,17 @@
1
1
  import { HTMLElementBase } from '../anta_helpers';
2
2
  import './a-progress.css';
3
+ /**
4
+ * `<a-progress>` — progress bar element.
5
+ *
6
+ * Styling notes (`a-progress.css` ships comment-free):
7
+ * - `--progress-indicator-edge` is a right-edge fade from the indicator's
8
+ * own bg to the border color, both opaque; tone variants re-tint it
9
+ * automatically because both endpoint tokens are re-aliased per tone.
10
+ * - `border: 0px solid var(--progress-border-color)` is a per-component
11
+ * reset (same spirit as Tailwind preflight): style and color are declared
12
+ * at a known state so a consumer opts into a themed border by changing
13
+ * only `border-width`.
14
+ */
3
15
  export declare class AProgressElement extends HTMLElementBase {
4
16
  static observedAttributes: string[];
5
17
  indicator: HTMLDivElement;
@@ -39,6 +39,7 @@ class AProgressElement extends HTMLElementBase {
39
39
  `;
40
40
  this.indicator = document.createElement("div");
41
41
  this.indicator.className = "indicator";
42
+ this.indicator.setAttribute("part", "indicator");
42
43
  const slot = document.createElement("slot");
43
44
  shadow.append(style, this.indicator, slot);
44
45
  }
@@ -0,0 +1 @@
1
+ @layer anta{a-radio-group{--radio-group-hint: var(--text-3);display:flex;flex-direction:column}a-radio-list{display:flex;flex-direction:column;gap:8px}a-radio-group[orientation=horizontal] a-radio-list{flex-direction:row;flex-wrap:wrap;gap:16px}a-radio-list:not(:first-child){margin-block-start:10px}a-radio-group-label{display:block;color:var(--text-3);font-family:var(--sans-serif);font-size:15px;line-height:20px;font-weight:500}a-radio-group-hint{display:block;color:var(--radio-group-hint);font-size:14px;line-height:17px;margin-block-start:2px}a-radio-group[status=critical]{--radio-group-hint: var(--text-2-critical)}a-radio-group[status=warning]{--radio-group-hint: var(--text-2-warning)}a-radio-group[status=success]{--radio-group-hint: var(--text-2-success)}a-radio-group[status=info]{--radio-group-hint: var(--text-2-info)}a-radio-group[status=brand]{--radio-group-hint: var(--text-2-brand)}a-radio-group[size=small] a-radio:not([size]){--radio-control-size: 14px;--radio-dot-size: 5px;--radio-gap: 6px;--radio-label-fs: 13px;--radio-label-lh: 16px;--radio-hint-fs: 12px;--radio-hint-lh: 14px}a-radio-group[size=large] a-radio:not([size]){--radio-control-size: 18px;--radio-dot-size: 7px;--radio-label-fs: 17px;--radio-label-lh: 24px;--radio-hint-fs: 16px;--radio-hint-lh: 21px}a-radio-group[disabled]{--radio-group-hint: var(--text-5)}a-radio-group[disabled] a-radio{cursor:not-allowed;pointer-events:none;color:var(--radio-label-color-disabled);--radio-hint-color: var(--radio-label-color-disabled);--radio-bg: var(--radio-bg-disabled);--radio-border: var(--radio-border-disabled);--radio-border-hover: var(--radio-border-disabled);--radio-border-active: var(--radio-border-disabled);--radio-fill: var(--radio-bg-disabled);--radio-fill-hover: var(--radio-bg-disabled);--radio-fill-active: var(--radio-bg-disabled);--radio-dot: var(--radio-dot-disabled)}}
@@ -0,0 +1,33 @@
1
+ import { HTMLElementBase } from "../anta_helpers";
2
+ import "./a-radio-group.css";
3
+ export declare class ARadioGroupElement extends HTMLElementBase {
4
+ static formAssociated: boolean;
5
+ static observedAttributes: string[];
6
+ private internals?;
7
+ private uncontrolledValue;
8
+ private seeded;
9
+ private observer?;
10
+ private alive;
11
+ /** The selected option's value, or `null` when nothing is selected. */
12
+ get value(): string | null;
13
+ constructor();
14
+ connectedCallback(): void;
15
+ disconnectedCallback(): void;
16
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
17
+ formDisabledCallback(disabled: boolean): void;
18
+ formResetCallback(): void;
19
+ formStateRestoreCallback(state: string): void;
20
+ private get currentValue();
21
+ private get isDisabled();
22
+ private get radios();
23
+ private sync;
24
+ private requestSelect;
25
+ private emitChange;
26
+ /** Dispatch the shared `statechange` event. `reason` lets a controller tell a
27
+ * user pick (cancelable) apart from a form `reset` / bfcache `restore` (not).
28
+ * `next` is `null` when nothing is selected (no default / reset-to-none). */
29
+ private emitStateChange;
30
+ private onClick;
31
+ private onKeyDown;
32
+ }
33
+ export declare function register_a_radio_group(): void;
@@ -0,0 +1,160 @@
1
+ import { HTMLElementBase } from "../anta_helpers";
2
+ import "./a-radio-group.css";
3
+ class ARadioGroupElement extends HTMLElementBase {
4
+ static formAssociated = true;
5
+ static observedAttributes = ["state", "disabled"];
6
+ internals;
7
+ uncontrolledValue = null;
8
+ seeded = false;
9
+ observer;
10
+ // True after the first connect — gates the native `change` event so it never
11
+ // fires for the initial seed (only for real, post-connect selection changes).
12
+ alive = false;
13
+ /** The selected option's value, or `null` when nothing is selected. */
14
+ get value() {
15
+ return this.currentValue;
16
+ }
17
+ constructor() {
18
+ super();
19
+ this.internals = this.attachInternals?.();
20
+ }
21
+ connectedCallback() {
22
+ if (!this.seeded) {
23
+ this.uncontrolledValue = this.getAttribute("default-state");
24
+ this.seeded = true;
25
+ }
26
+ this.addEventListener("click", this.onClick);
27
+ this.addEventListener("keydown", this.onKeyDown);
28
+ this.observer ??= new this.view.MutationObserver((records) => {
29
+ const touchedOptions = records.some(
30
+ (rec) => [...rec.addedNodes, ...rec.removedNodes].some(
31
+ (n) => n.nodeName === "A-RADIO" || n.querySelector?.("a-radio") != null
32
+ )
33
+ );
34
+ if (touchedOptions) this.sync();
35
+ });
36
+ this.observer.observe(this, { childList: true, subtree: true });
37
+ this.sync();
38
+ this.alive = true;
39
+ }
40
+ disconnectedCallback() {
41
+ this.observer?.disconnect();
42
+ }
43
+ attributeChangedCallback(name, oldValue, newValue) {
44
+ this.sync();
45
+ if (name === "state" && this.alive && newValue !== oldValue) this.emitChange();
46
+ }
47
+ formDisabledCallback(disabled) {
48
+ if (disabled) this.internals?.states.add("disabled");
49
+ else this.internals?.states.delete("disabled");
50
+ this.sync();
51
+ }
52
+ formResetCallback() {
53
+ const next = this.getAttribute("default-state");
54
+ this.emitStateChange(next, this.currentValue, "reset", false);
55
+ this.uncontrolledValue = next;
56
+ this.sync();
57
+ }
58
+ formStateRestoreCallback(state) {
59
+ this.emitStateChange(state, this.currentValue, "restore", false);
60
+ this.uncontrolledValue = state;
61
+ this.sync();
62
+ }
63
+ // Controlled when `state` is present; otherwise the in-memory uncontrolled value.
64
+ get currentValue() {
65
+ return this.hasAttribute("state") ? this.getAttribute("state") : this.uncontrolledValue;
66
+ }
67
+ get isDisabled() {
68
+ return this.hasAttribute("disabled") || (this.internals?.states.has("disabled") ?? false);
69
+ }
70
+ get radios() {
71
+ return Array.from(this.querySelectorAll("a-radio"));
72
+ }
73
+ sync = () => {
74
+ const value = this.currentValue;
75
+ const radios = this.radios;
76
+ const selectedEl = radios.find((r) => r.value === value && value != null) ?? null;
77
+ const submitted = selectedEl ? selectedEl.value : null;
78
+ this.internals?.setFormValue(submitted, submitted);
79
+ for (const r of radios) r.selected = r === selectedEl;
80
+ if (this.internals && "ariaActiveDescendantElement" in this.internals) {
81
+ this.internals.ariaActiveDescendantElement = selectedEl;
82
+ }
83
+ };
84
+ // The shared state algorithm: fire the cancelable `statechange` *before*
85
+ // applying. Controlled never self-applies; uncontrolled applies unless vetoed.
86
+ requestSelect(next) {
87
+ const prev = this.currentValue;
88
+ if (next === prev) return;
89
+ const ok = this.emitStateChange(next, prev, "user", true);
90
+ if (this.hasAttribute("state")) return;
91
+ if (ok) {
92
+ this.uncontrolledValue = next;
93
+ this.sync();
94
+ this.emitChange();
95
+ }
96
+ }
97
+ // Native `change`, fired *after* a selection applies (user pick or a controlled
98
+ // `state` update) — the post-apply counterpart to the cancelable, pre-apply
99
+ // `statechange`. Bubbles like a native radio group.
100
+ emitChange() {
101
+ this.dispatchEvent(new Event("change", { bubbles: true }));
102
+ }
103
+ /** Dispatch the shared `statechange` event. `reason` lets a controller tell a
104
+ * user pick (cancelable) apart from a form `reset` / bfcache `restore` (not).
105
+ * `next` is `null` when nothing is selected (no default / reset-to-none). */
106
+ emitStateChange(next, prev, reason, cancelable) {
107
+ return this.dispatchEvent(
108
+ new CustomEvent("statechange", {
109
+ cancelable,
110
+ bubbles: true,
111
+ composed: true,
112
+ detail: { next, prev, reason }
113
+ })
114
+ );
115
+ }
116
+ onClick = (e) => {
117
+ if (this.isDisabled) return;
118
+ const radio = e.target?.closest(
119
+ "a-radio"
120
+ );
121
+ if (!radio || radio.hasAttribute("disabled")) return;
122
+ radio.focus();
123
+ this.requestSelect(radio.value);
124
+ };
125
+ onKeyDown = (e) => {
126
+ if (this.isDisabled) return;
127
+ const enabled = this.radios.filter((r) => !r.hasAttribute("disabled"));
128
+ if (enabled.length === 0) return;
129
+ const focused = e.target?.closest(
130
+ "a-radio"
131
+ );
132
+ if (e.key === " " || e.key === "Enter") {
133
+ if (focused && enabled.includes(focused)) {
134
+ e.preventDefault();
135
+ this.requestSelect(focused.value);
136
+ }
137
+ return;
138
+ }
139
+ const forward = e.key === "ArrowDown" || e.key === "ArrowRight";
140
+ const back = e.key === "ArrowUp" || e.key === "ArrowLeft";
141
+ if (!forward && !back) return;
142
+ e.preventDefault();
143
+ let i = focused ? enabled.indexOf(focused) : -1;
144
+ if (i === -1) i = enabled.findIndex((r) => r.value === this.currentValue);
145
+ if (i === -1) i = 0;
146
+ const next = enabled[(i + (forward ? 1 : -1) + enabled.length) % enabled.length];
147
+ next.focus();
148
+ this.requestSelect(next.value);
149
+ };
150
+ }
151
+ function register_a_radio_group() {
152
+ if (typeof customElements === "undefined") return;
153
+ if (!customElements.get("a-radio-group"))
154
+ customElements.define("a-radio-group", ARadioGroupElement);
155
+ }
156
+ register_a_radio_group();
157
+ export {
158
+ ARadioGroupElement,
159
+ register_a_radio_group
160
+ };
@@ -0,0 +1 @@
1
+ @layer anta{a-radio{--radio-control-size: 16px;--radio-border-width: 1.5px;--radio-dot-size: 6px;--_radio-dot-adjust: 0px;--radio-gap: 8px;--radio-bg: var(--bg-1);--radio-fill: #635b65;--radio-fill-hover: #534c57;--radio-fill-active: #49424c;--radio-border-neutral: #d4ced4;--radio-border: var(--radio-border-neutral);--radio-border-hover: #c1b9c1;--radio-border-active: #9f99a1;--radio-dot: #ffffff;--radio-dot-disabled: #c1b9c1;--radio-bg-disabled: color-mix(in oklch, #44374b 10%, transparent);--radio-border-disabled: color-mix(in oklch, #44374b 15%, transparent);--radio-label-color: var(--text-2);--radio-label-color-disabled: var(--text-4);--radio-hint-color: var(--text-3);--radio-label-fs: 15px;--radio-label-lh: 20px;--radio-hint-fs: 14px;--radio-hint-lh: 17px;display:inline-grid;grid-template-columns:auto 1fr;align-items:center;column-gap:var(--radio-gap);cursor:pointer;user-select:none;-webkit-user-drag:none;vertical-align:middle;outline:none;color:var(--radio-label-color);font-family:var(--sans-serif);font-size:var(--radio-label-fs);line-height:var(--radio-label-lh);font-feature-settings:"ss02","ss05";&:before{content:"";grid-column:1;grid-row:1 / -1;align-self:center;box-sizing:border-box;inline-size:var(--radio-control-size);block-size:var(--radio-control-size);border-radius:50%;background:var(--radio-bg);border:var(--radio-border-width) solid var(--radio-border);transition:background-color .15s ease-out,border-color .15s ease-out}&:after{content:"";grid-column:1;grid-row:1 / -1;align-self:center;justify-self:center;inline-size:calc(var(--radio-dot-size) - var(--_radio-dot-adjust));block-size:calc(var(--radio-dot-size) - var(--_radio-dot-adjust));border-radius:50%;background:var(--radio-dot);transform:scale(0);transition:transform .12s ease-out;pointer-events:none}@media(hover:hover)and (pointer:fine){&:not([disabled]):hover:before{border-color:var(--radio-border-hover);transition:background-color 75ms ease-in,border-color 75ms ease-in}&:not([disabled]):hover:state(selected):before{background:var(--radio-fill-hover);border-color:var(--radio-fill-hover)}}&:not([disabled]):active:before{border-color:var(--radio-border-active);transition:background-color 50ms linear,border-color 50ms linear}&:not([disabled]):active:state(selected):before{background:var(--radio-fill-active);border-color:var(--radio-fill-active)}&:state(selected){&:before{background:var(--radio-fill);border-color:var(--radio-fill)}&:after{transform:scale(1)}}&:focus-visible:before{outline:1px solid var(--focus-ring);outline-offset:1px}&[disabled]{cursor:not-allowed;color:var(--radio-label-color-disabled);&:before{background:var(--radio-bg-disabled);border-color:var(--radio-border-disabled);transition:none}&:state(selected):after{background:var(--radio-dot-disabled)}a-radio-hint{color:var(--radio-label-color-disabled)}}&[size=small]{--radio-control-size: 14px;--radio-dot-size: 5px;--radio-gap: 6px;--radio-label-fs: 13px;--radio-label-lh: 16px;--radio-hint-fs: 12px;--radio-hint-lh: 14px}&[size=large]{--radio-control-size: 18px;--radio-dot-size: 7px;--radio-label-fs: 17px;--radio-label-lh: 24px;--radio-hint-fs: 16px;--radio-hint-lh: 21px}}a-radio-label,a-radio-hint{display:block;grid-column:2;min-width:0}a-radio-hint{color:var(--radio-hint-color);font-size:var(--radio-hint-fs);line-height:var(--radio-hint-lh);margin-block-start:2px}a-radio-group:focus-visible a-radio:state(selected):before{outline:1px solid var(--focus-ring);outline-offset:1px}a-radio[priority=secondary],a-radio-group[priority=secondary] a-radio:not([priority]){&:not([disabled]):state(selected){&:before{background:var(--radio-bg);border-color:var(--radio-fill)}&:after{background:var(--radio-fill)}}@media(hover:hover)and (pointer:fine){&:not([disabled]):hover:state(selected){&:before{background:var(--radio-bg);border-color:var(--radio-fill-hover)}&:after{background:var(--radio-fill-hover)}}}&:not([disabled]):active:state(selected){&:before{background:var(--radio-bg);border-color:var(--radio-fill-active)}&:after{background:var(--radio-fill-active)}}}.dark a-radio[priority=secondary],.dark a-radio-group[priority=secondary] a-radio:not([priority]){&:not([disabled]):state(selected){&:before{border-color:var(--radio-fill-active)}&:after{background:var(--radio-fill-active)}}@media(hover:hover)and (pointer:fine){&:not([disabled]):hover:state(selected){&:before{border-color:oklch(from var(--radio-fill-active) calc(l + .07) c h)}&:after{background:oklch(from var(--radio-fill-active) calc(l + .07) c h)}}}&:not([disabled]):active:state(selected){&:before{border-color:oklch(from var(--radio-fill-active) calc(l + .12) c h)}&:after{background:oklch(from var(--radio-fill-active) calc(l + .12) c h)}}}a-radio[tone=brand],a-radio-group[tone=brand] a-radio:not([tone]){--radio-label-color: var(--text-2-brand);--radio-hint-color: var(--text-3-brand);--radio-fill: #5f4bc3;--radio-fill-hover: #503cb4;--radio-fill-active: #483493}a-radio[tone=neutral],a-radio-group[tone=neutral] a-radio:not([tone]){--radio-fill: #635b65;--radio-fill-hover: #534c57;--radio-fill-active: #49424c}a-radio[tone=info],a-radio-group[tone=info] a-radio:not([tone]){--radio-label-color: var(--text-2-info);--radio-hint-color: var(--text-3-info);--radio-fill: #1f6eb2;--radio-fill-hover: #1a5b93;--radio-fill-active: #175082}a-radio[tone=success],a-radio-group[tone=success] a-radio:not([tone]){--radio-label-color: var(--text-2-success);--radio-hint-color: var(--text-3-success);--radio-fill: #2a7e43;--radio-fill-hover: #226737;--radio-fill-active: #1f5c31}a-radio[tone=warning],a-radio-group[tone=warning] a-radio:not([tone]){--radio-label-color: var(--text-2-warning);--radio-hint-color: var(--text-3-warning);--radio-fill: #c37416;--radio-fill-hover: #ae6613;--radio-fill-active: #995200}a-radio[tone=critical],a-radio-group[tone=critical] a-radio:not([tone]){--radio-label-color: var(--text-2-critical);--radio-hint-color: var(--text-3-critical);--radio-fill: #c9302c;--radio-fill-hover: #b02120;--radio-fill-active: #a01c1c}a-radio[tone]:not([tone=""],[tone=neutral]),a-radio-group[tone]:not([tone=""],[tone=neutral]) a-radio:not([tone]){--_radio-border-base: color-mix(in oklch, var(--radio-fill) 70%, var(--radio-border-neutral));--radio-border: oklch(from var(--_radio-border-base) calc(l + .17) c h);--radio-border-hover: oklch(from var(--_radio-border-base) calc(l + .1) c h);--radio-border-active: var(--_radio-border-base);.dark &{--radio-border: var(--_radio-border-base);--radio-border-hover: oklch(from var(--_radio-border-base) calc(l + .1) c h);--radio-border-active: oklch(from var(--_radio-border-base) calc(l + .17) c h)}}a-radio[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]){--radio-tone-source: attr(tone type(<color>), transparent)}a-radio[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]),a-radio-group[tone]:not([tone=""],[tone=brand],[tone=neutral],[tone=info],[tone=success],[tone=warning],[tone=critical]) a-radio:not([tone]){--_tone-l-rest: .5;--_tone-l-hover: .45;--_tone-l-active: .4;--radio-fill: oklch(from var(--radio-tone-source) var(--_tone-l-rest) c h);--radio-fill-hover: oklch(from var(--radio-tone-source) var(--_tone-l-hover) c h);--radio-fill-active: oklch(from var(--radio-tone-source) var(--_tone-l-active) c h);--radio-label-color: oklch(from var(--radio-tone-source) .5 c h);--radio-hint-color: oklch(from var(--radio-tone-source) .5 c h / .8);.dark &{--_tone-l-rest: .45;--_tone-l-hover: .5;--_tone-l-active: .57;--radio-label-color: oklch(from var(--radio-tone-source) .8 c h);--radio-hint-color: oklch(from var(--radio-tone-source) .8 c h / .8)}}.dark a-radio{--_radio-dot-adjust: 1px;&:after{box-shadow:0 0 1px 1px #000}--radio-border-neutral: #49424c;--radio-border-hover: #635b65;--radio-border-active: #776e77;--radio-fill: #534c57;--radio-fill-hover: #635b65;--radio-fill-active: #938d96;--radio-dot-disabled: #635b65;--radio-bg-disabled: color-mix(in oklch, #e4d1ef 10%, transparent);--radio-border-disabled: color-mix(in oklch, #e4d1ef 15%, transparent)}.dark a-radio[tone=brand],.dark a-radio-group[tone=brand] a-radio:not([tone]){--radio-fill: #503cb4;--radio-fill-hover: #5f4bc3;--radio-fill-active: #7460d7}.dark a-radio[tone=neutral],.dark a-radio-group[tone=neutral] a-radio:not([tone]){--radio-fill: #534c57;--radio-fill-hover: #635b65;--radio-fill-active: #938d96}.dark a-radio[tone=info],.dark a-radio-group[tone=info] a-radio:not([tone]){--radio-fill: #1a5b93;--radio-fill-hover: #1f6eb2;--radio-fill-active: #2686d9}.dark a-radio[tone=success],.dark a-radio-group[tone=success] a-radio:not([tone]){--radio-fill: #226737;--radio-fill-hover: #2a7e43;--radio-fill-active: #329550}.dark a-radio[tone=warning],.dark a-radio-group[tone=warning] a-radio:not([tone]){--radio-fill: #7f410b;--radio-fill-hover: #995200;--radio-fill-active: #ae6613}.dark a-radio[tone=critical],.dark a-radio-group[tone=critical] a-radio:not([tone]){--radio-fill: #b02120;--radio-fill-hover: #c9302c;--radio-fill-active: #de4545}}
@@ -0,0 +1,14 @@
1
+ import { HTMLElementBase } from "../anta_helpers";
2
+ import "./a-radio.css";
3
+ export declare class ARadioElement extends HTMLElementBase {
4
+ static observedAttributes: string[];
5
+ private internals?;
6
+ constructor();
7
+ connectedCallback(): void;
8
+ attributeChangedCallback(name: string): void;
9
+ get selected(): boolean;
10
+ set selected(on: boolean);
11
+ get value(): string;
12
+ private applyState;
13
+ }
14
+ export declare function register_a_radio(): void;
@@ -0,0 +1,46 @@
1
+ import { HTMLElementBase } from "../anta_helpers";
2
+ import "./a-radio.css";
3
+ class ARadioElement extends HTMLElementBase {
4
+ static observedAttributes = ["selected"];
5
+ internals;
6
+ constructor() {
7
+ super();
8
+ this.internals = this.attachInternals?.();
9
+ }
10
+ connectedCallback() {
11
+ this.applyState(this.hasAttribute("selected"));
12
+ }
13
+ attributeChangedCallback(name) {
14
+ if (name === "selected") this.applyState(this.hasAttribute("selected"));
15
+ }
16
+ get selected() {
17
+ return this.internals?.states.has("selected") ?? this.hasAttribute("selected");
18
+ }
19
+ set selected(on) {
20
+ this.applyState(!!on);
21
+ }
22
+ get value() {
23
+ return this.getAttribute("value") ?? "";
24
+ }
25
+ // `selected` is the single source: it drives the visual `:state(selected)` and
26
+ // publishes `aria-checked` through ElementInternals (the accessibility tree,
27
+ // not a DOM attribute). The group only sets `r.selected`; the radio owns how it
28
+ // reflects that. role="radio" comes from the wrapper, which gives ariaChecked
29
+ // something to attach to.
30
+ applyState(on) {
31
+ if (!this.internals) return;
32
+ if (on) this.internals.states.add("selected");
33
+ else this.internals.states.delete("selected");
34
+ this.internals.ariaChecked = on ? "true" : "false";
35
+ }
36
+ }
37
+ function register_a_radio() {
38
+ if (typeof customElements === "undefined") return;
39
+ if (!customElements.get("a-radio"))
40
+ customElements.define("a-radio", ARadioElement);
41
+ }
42
+ register_a_radio();
43
+ export {
44
+ ARadioElement,
45
+ register_a_radio
46
+ };
@@ -1 +1 @@
1
- @layer anta{a-tag{--tag-text: var(--text-3);--tag-bg: var(--bg-4);--tag-border: color-mix(in oklch, var(--tag-text) 9%, transparent);--tag-separator: color-mix(in oklch, var(--tag-text) 30%, transparent);--tag-padding-block: 1.5px;--tag-padding-inline: 6.5px;--tag-icon-size: 13px;--tag-label-weight: 600;--tag-gap: .6ch;display:inline-flex;align-items:center;gap:var(--tag-gap);box-sizing:border-box;max-width:100%;vertical-align:middle;overflow:hidden;white-space:nowrap;-webkit-user-drag:none;color:var(--tag-text);background:var(--tag-bg);border:.5px solid var(--tag-border);border-radius:22px;padding-block:var(--tag-padding-block);padding-inline:var(--tag-padding-inline);font-family:var(--sans-serif);font-weight:450;font-size:11px;line-height:16px;text-transform:uppercase;letter-spacing:.08ch;font-feature-settings:"tnum" 1,"ss05" 1,"ss01","case","calt"}a-tag a-icon{--icon-size: var(--tag-icon-size);flex:none}a-tag a-tag-label,a-tag a-tag-value{display:inline-block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a-tag a-tag-value{font-weight:450}a-tag a-tag-label{font-weight:var(--tag-label-weight)}a-tag:has(>a-icon:first-child){padding-inline-start:max(0px,var(--tag-padding-inline) - 2px)}a-tag:has(>a-icon:last-child){padding-inline-end:max(0px,var(--tag-padding-inline) - 2px)}a-tag>:not(a-icon,a-tag-label,a-tag-value)~:not(a-icon,a-tag-label,a-tag-value){padding-left:var(--tag-gap);border-left:.5px solid var(--tag-separator)}a-tag[tone=brand]{--tag-text: var(--text-2-brand);--tag-bg: var(--bg-4-brand)}a-tag[tone=info]{--tag-text: var(--text-2-info);--tag-bg: var(--bg-4-info)}a-tag[tone=success]{--tag-text: var(--text-2-success);--tag-bg: var(--bg-4-success)}a-tag[tone=warning]{--tag-text: var(--text-2-warning);--tag-bg: var(--bg-4-warning)}a-tag[tone=critical]{--tag-text: var(--text-2-critical);--tag-bg: var(--bg-4-critical)}a-tag[tone]:not([tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--tag-tone-source: attr(tone type(<color>), currentColor);--_tag-text-l: .46;--_tag-text-c: .17;--_tag-bg-l: .96;--_tag-bg-c: .04;--tag-text: oklch(from var(--tag-tone-source) var(--_tag-text-l) var(--_tag-text-c) h);--tag-bg: oklch(from var(--tag-tone-source) var(--_tag-bg-l) var(--_tag-bg-c) h)}.dark a-tag[tone]:not([tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--_tag-text-l: .8;--_tag-text-c: .11;--_tag-bg-l: .21;--_tag-bg-c: .05}a-tag[size=small]{--tag-padding-block: .5px;--tag-padding-inline: 4.5px;--tag-icon-size: 11px;font-size:10px;line-height:14px}a-tag[size=large]{--tag-padding-block: 2.5px;--tag-padding-inline: 8.5px;--tag-icon-size: 15px;font-size:12px;line-height:18px}a-tag[nocaps]{font-size:12px;text-transform:none;letter-spacing:.02ch;font-feature-settings:"tnum" 1,"ss05" 1,"lnum","ss01","ss04","case","calt"}a-tag[size=large][nocaps]{font-size:13px}}
1
+ @layer anta{a-tag{--tag-text: var(--text-3);--tag-tint: #44374b;--tag-fill: #776e77;--tag-edge: var(--tag-tint);--_tag-bg-alpha: 7%;--_tag-border-alpha: 15%;--_tag-edge-alpha: 25%;--tag-bg: color-mix(in oklch, var(--tag-tint) var(--_tag-bg-alpha), transparent);--tag-border: color-mix(in oklch, var(--tag-tint) var(--_tag-border-alpha), transparent);--tag-separator: color-mix(in oklch, var(--tag-text) 30%, transparent);--tag-padding-block: 1.5px;--tag-padding-inline: 6.5px;--tag-icon-size: 13px;--tag-label-weight: 600;--tag-gap: .6ch;display:inline-flex;align-items:center;gap:var(--tag-gap);box-sizing:border-box;max-width:100%;vertical-align:middle;overflow:hidden;white-space:nowrap;-webkit-user-drag:none;color:var(--tag-text);background:var(--tag-bg);border:.5px solid var(--tag-border);border-radius:22px;padding-block:var(--tag-padding-block);padding-inline:var(--tag-padding-inline);font-family:var(--sans-serif);font-weight:450;font-size:11px;line-height:16px;text-transform:uppercase;letter-spacing:.08ch;font-feature-settings:"tnum" 1,"ss05" 1,"ss01","case","calt"}a-tag a-icon{--icon-size: var(--tag-icon-size);flex:none}a-tag a-tag-label,a-tag a-tag-value{display:inline-block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a-tag a-tag-value{font-weight:450}a-tag a-tag-label{font-weight:var(--tag-label-weight)}a-tag:has(>a-icon:first-child){padding-inline-start:max(0px,var(--tag-padding-inline) - 2px)}a-tag:has(>a-icon:last-child){padding-inline-end:max(0px,var(--tag-padding-inline) - 2px)}a-tag>:not(a-icon,a-tag-label,a-tag-value)~:not(a-icon,a-tag-label,a-tag-value){padding-left:var(--tag-gap);border-left:.5px solid var(--tag-separator)}a-tag[tone=brand]{--tag-text: var(--text-3-brand);--tag-tint: #7460d7;--tag-fill: #7460d7;--tag-edge: var(--text-2-brand);--_tag-bg-alpha: 10%;--_tag-edge-alpha: 20%}a-tag[tone=info]{--tag-text: var(--text-3-info);--tag-tint: #2686d9;--tag-fill: #2686d9;--tag-edge: var(--text-2-info);--_tag-bg-alpha: 10%;--_tag-edge-alpha: 20%}a-tag[tone=success]{--tag-text: var(--text-3-success);--tag-tint: #329550;--tag-fill: #329550;--tag-edge: var(--text-2-success);--_tag-bg-alpha: 10%;--_tag-edge-alpha: 20%}a-tag[tone=warning]{--tag-text: var(--text-3-warning);--tag-tint: #c37416;--tag-fill: #ae6613;--tag-edge: var(--text-2-warning);--_tag-bg-alpha: 10%;--_tag-edge-alpha: 20%}a-tag[tone=critical]{--tag-text: var(--text-3-critical);--tag-tint: #de4545;--tag-fill: #de4545;--tag-edge: var(--text-2-critical);--_tag-bg-alpha: 10%;--_tag-edge-alpha: 20%}.dark a-tag:not([tone]),.dark a-tag[tone=neutral]{--tag-tint: #e4d1ef;--tag-fill: #635b65;--_tag-bg-alpha: 12%}.dark a-tag[tone=brand],.dark a-tag[tone=info],.dark a-tag[tone=success],.dark a-tag[tone=warning],.dark a-tag[tone=critical]{--_tag-bg-alpha: 20%;--_tag-border-alpha: 25%;--_tag-edge-alpha: 30%}.dark a-tag[tone=brand]{--tag-fill: #5f4bc3}.dark a-tag[tone=info]{--tag-fill: #1f6eb2}.dark a-tag[tone=success]{--tag-fill: #2a7e43}.dark a-tag[tone=warning]{--tag-fill: #995200}.dark a-tag[tone=critical]{--tag-fill: #c9302c}a-tag[tone]:not([tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--tag-tone-source: attr(tone type(<color>), currentColor);--_tag-bg-alpha: 10%;--_tag-border-alpha: 15%;--_tag-edge-alpha: 20%;--_tag-tint-l: .54;--_tag-tint-c: .16;--tag-tint: oklch(from var(--tag-tone-source) var(--_tag-tint-l) var(--_tag-tint-c) h);--_tag-fill-l: .5;--tag-fill: oklch(from var(--tag-tone-source) var(--_tag-fill-l) var(--_tag-tint-c) h);--_tag-text-l: .4;--_tag-text-c: .15;--tag-text: color-mix(in oklch, oklch(from var(--tag-tone-source) var(--_tag-text-l) var(--_tag-text-c) h) 80%, transparent);--tag-edge: oklch(from var(--tag-tone-source) var(--_tag-text-l) var(--_tag-text-c) h)}.dark a-tag[tone]:not([tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--_tag-bg-alpha: 20%;--_tag-border-alpha: 25%;--_tag-edge-alpha: 30%;--_tag-tint-l: .58;--_tag-fill-l: .45;--_tag-text-l: .75;--_tag-text-c: .11}a-tag[priority=primary]{--tag-bg: var(--tag-fill);--tag-text: #fff}a-tag[priority=primary][tone]:not([tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--tag-text: #fff}a-tag[priority=tertiary]{--tag-bg: transparent;--tag-border: color-mix(in oklch, var(--tag-edge) var(--_tag-edge-alpha), transparent)}a-tag[size=small]{--tag-padding-block: .5px;--tag-padding-inline: 4.5px;--tag-icon-size: 11px;font-size:10px;line-height:14px}a-tag[size=large]{--tag-padding-block: 2.5px;--tag-padding-inline: 8.5px;--tag-icon-size: 15px;font-size:12px;line-height:18px}a-tag[nocaps]{font-size:12px;text-transform:none;letter-spacing:.02ch;font-feature-settings:"tnum" 1,"ss05" 1,"lnum","ss01","ss04","case","calt"}a-tag[size=large][nocaps]{font-size:13px}}
@@ -1 +1 @@
1
- @layer anta{a-text{--text-color: var(--text-2);--text-link-color: var(--link-color);--text-link-hover: var(--link-color-hover);display:block;color:var(--text-color);font-size:15px;line-height:20px;font-feature-settings:"ss02","ss05"}a-text[size=small]{font-size:13px;line-height:16px}a-text[size=medium]{font-size:15px;line-height:20px}a-text[size=large]{font-size:17px;line-height:24px}a-text[inline]{display:inline-block}a-text[truncate]{min-width:0}a-text[priority=primary]{--text-color: var(--text-1)}a-text[priority=tertiary]{--text-color: var(--text-3);--text-link-color: currentColor;--text-link-hover: var(--text-2)}a-text[priority=quaternary]{--text-color: var(--text-4);--text-link-color: currentColor;--text-link-hover: var(--text-3)}a-text[priority=quinary]{--text-color: var(--text-5);--text-link-color: currentColor;--text-link-hover: var(--text-4)}a-text[tone=brand]{--text-color: var(--text-2-brand);--text-link-color: currentColor;--text-link-hover: var(--text-1-brand)}a-text[tone=brand][priority=primary]{--text-color: var(--text-1-brand)}a-text[tone=brand][priority=tertiary]{--text-color: var(--text-3-brand);--text-link-hover: var(--text-2-brand)}a-text[tone=brand][priority=quaternary]{--text-color: var(--text-4-brand);--text-link-hover: var(--text-3-brand)}a-text[tone=brand][priority=quinary]{--text-color: var(--text-5-brand);--text-link-hover: var(--text-4-brand)}a-text[tone=success]{--text-color: var(--text-2-success);--text-link-color: currentColor;--text-link-hover: var(--text-1-success)}a-text[tone=success][priority=primary]{--text-color: var(--text-1-success)}a-text[tone=success][priority=tertiary]{--text-color: var(--text-3-success);--text-link-hover: var(--text-2-success)}a-text[tone=success][priority=quaternary]{--text-color: var(--text-4-success);--text-link-hover: var(--text-3-success)}a-text[tone=success][priority=quinary]{--text-color: var(--text-5-success);--text-link-hover: var(--text-4-success)}a-text[tone=critical]{--text-color: var(--text-2-critical);--text-link-color: currentColor;--text-link-hover: var(--text-1-critical)}a-text[tone=critical][priority=primary]{--text-color: var(--text-1-critical)}a-text[tone=critical][priority=tertiary]{--text-color: var(--text-3-critical);--text-link-hover: var(--text-2-critical)}a-text[tone=critical][priority=quaternary]{--text-color: var(--text-4-critical);--text-link-hover: var(--text-3-critical)}a-text[tone=critical][priority=quinary]{--text-color: var(--text-5-critical);--text-link-hover: var(--text-4-critical)}a-text[tone=warning]{--text-color: var(--text-2-warning);--text-link-color: currentColor;--text-link-hover: var(--text-1-warning)}a-text[tone=warning][priority=primary]{--text-color: var(--text-1-warning)}a-text[tone=warning][priority=tertiary]{--text-color: var(--text-3-warning);--text-link-hover: var(--text-2-warning)}a-text[tone=warning][priority=quaternary]{--text-color: var(--text-4-warning);--text-link-hover: var(--text-3-warning)}a-text[tone=warning][priority=quinary]{--text-color: var(--text-5-warning);--text-link-hover: var(--text-4-warning)}a-text[tone=info]{--text-color: var(--text-2-info);--text-link-color: currentColor;--text-link-hover: var(--text-1-info)}a-text[tone=info][priority=primary]{--text-color: var(--text-1-info)}a-text[tone=info][priority=tertiary]{--text-color: var(--text-3-info);--text-link-hover: var(--text-2-info)}a-text[tone=info][priority=quaternary]{--text-color: var(--text-4-info);--text-link-hover: var(--text-3-info)}a-text[tone=info][priority=quinary]{--text-color: var(--text-5-info);--text-link-hover: var(--text-4-info)}a-text a,a-text a:link,a-text a:visited{color:var(--text-link-color)}@media(hover:hover)and (pointer:fine){a-text a:hover{color:var(--text-link-hover);text-decoration-color:var(--text-link-hover)}}}
1
+ @layer anta{a-text{--text-color: var(--text-2);--text-link-color: var(--link-color);--text-link-hover: var(--link-color-hover);display:block;color:var(--text-color);font-size:15px;line-height:20px;text-wrap:pretty;font-feature-settings:"ss02","ss05"}a-text[size=small]{font-size:13px;line-height:16px}a-text[size=medium]{font-size:15px;line-height:20px}a-text[size=large]{font-size:17px;line-height:24px}a-text[inline]{display:inline-block}a-text[truncate]{min-width:0}a-text[priority=primary]{--text-color: var(--text-1)}a-text[priority=tertiary]{--text-color: var(--text-3);--text-link-color: currentColor;--text-link-hover: var(--text-2)}a-text[priority=quaternary]{--text-color: var(--text-4);--text-link-color: currentColor;--text-link-hover: var(--text-3)}a-text[priority=quinary]{--text-color: var(--text-5);--text-link-color: currentColor;--text-link-hover: var(--text-4)}a-text[tone=brand]{--text-color: var(--text-2-brand);--text-link-color: currentColor;--text-link-hover: var(--text-1-brand)}a-text[tone=brand][priority=primary]{--text-color: var(--text-1-brand)}a-text[tone=brand][priority=tertiary]{--text-color: var(--text-3-brand);--text-link-hover: var(--text-2-brand)}a-text[tone=brand][priority=quaternary]{--text-color: var(--text-4-brand);--text-link-hover: var(--text-3-brand)}a-text[tone=brand][priority=quinary]{--text-color: var(--text-5-brand);--text-link-hover: var(--text-4-brand)}a-text[tone=success]{--text-color: var(--text-2-success);--text-link-color: currentColor;--text-link-hover: var(--text-1-success)}a-text[tone=success][priority=primary]{--text-color: var(--text-1-success)}a-text[tone=success][priority=tertiary]{--text-color: var(--text-3-success);--text-link-hover: var(--text-2-success)}a-text[tone=success][priority=quaternary]{--text-color: var(--text-4-success);--text-link-hover: var(--text-3-success)}a-text[tone=success][priority=quinary]{--text-color: var(--text-5-success);--text-link-hover: var(--text-4-success)}a-text[tone=critical]{--text-color: var(--text-2-critical);--text-link-color: currentColor;--text-link-hover: var(--text-1-critical)}a-text[tone=critical][priority=primary]{--text-color: var(--text-1-critical)}a-text[tone=critical][priority=tertiary]{--text-color: var(--text-3-critical);--text-link-hover: var(--text-2-critical)}a-text[tone=critical][priority=quaternary]{--text-color: var(--text-4-critical);--text-link-hover: var(--text-3-critical)}a-text[tone=critical][priority=quinary]{--text-color: var(--text-5-critical);--text-link-hover: var(--text-4-critical)}a-text[tone=warning]{--text-color: var(--text-2-warning);--text-link-color: currentColor;--text-link-hover: var(--text-1-warning)}a-text[tone=warning][priority=primary]{--text-color: var(--text-1-warning)}a-text[tone=warning][priority=tertiary]{--text-color: var(--text-3-warning);--text-link-hover: var(--text-2-warning)}a-text[tone=warning][priority=quaternary]{--text-color: var(--text-4-warning);--text-link-hover: var(--text-3-warning)}a-text[tone=warning][priority=quinary]{--text-color: var(--text-5-warning);--text-link-hover: var(--text-4-warning)}a-text[tone=info]{--text-color: var(--text-2-info);--text-link-color: currentColor;--text-link-hover: var(--text-1-info)}a-text[tone=info][priority=primary]{--text-color: var(--text-1-info)}a-text[tone=info][priority=tertiary]{--text-color: var(--text-3-info);--text-link-hover: var(--text-2-info)}a-text[tone=info][priority=quaternary]{--text-color: var(--text-4-info);--text-link-hover: var(--text-3-info)}a-text[tone=info][priority=quinary]{--text-color: var(--text-5-info);--text-link-hover: var(--text-4-info)}a-text a,a-text a:link,a-text a:visited{color:var(--text-link-color)}@media(hover:hover)and (pointer:fine){a-text a:hover{color:var(--text-link-hover);text-decoration-color:var(--text-link-hover)}}}
@@ -1,11 +1,50 @@
1
1
  import { HTMLElementBase } from '../anta_helpers';
2
2
  import './a-text.css';
3
+ /**
4
+ * `<a-text>` — body text element with truncation / expansion.
5
+ *
6
+ * Styling notes (`a-text.css` ships comment-free):
7
+ * - `a-text[truncate] { min-width: 0 }` is the one external requirement of
8
+ * the shadow clamp: the host must be allowed to shrink inside flex/grid
9
+ * parents so the inner clamp can actually clip content.
10
+ * - The default (no `priority`) is the SECONDARY level — body text reads at
11
+ * `--text-2` on the base rule; `priority="primary"` opts into the
12
+ * strongest `--text-1`.
13
+ * - Priority/tone link colors: levels 1–2 keep the brand link color; levels
14
+ * 3–5 mute the link to `currentColor` and step the hover up one level
15
+ * (3→2, 4→3, 5→4). Tinted variants do the same within their
16
+ * `--text-{N}-{tone}` ramp (level 1 has nothing above it — hover keeps the
17
+ * color and only the underline alpha changes).
18
+ * - The `a-text a` rules layer on anta's global `a` defaults from
19
+ * `reset.css`, overriding only color and the one-step-up hover color
20
+ * (underline thickness/offset/alpha are inherited); the hover repeats the
21
+ * underline color so it tracks the priority color. Hover is gated to
22
+ * `(hover: hover) and (pointer: fine)` to avoid sticky hover after a tap.
23
+ */
3
24
  export declare class ATextElement extends HTMLElementBase {
4
25
  static observedAttributes: string[];
5
26
  private slotEl;
6
- private expandBtn;
27
+ /** The expand/collapse chevron — built lazily, only while the element is
28
+ * expandable (a plain `<a-text>` never creates a button or a listener).
29
+ * Removed when `expandable` is dropped, and when a one-way expand completes. */
30
+ private expandBtn?;
31
+ /** Expanded state lives here, on the element — a stateless wrapper can't hold
32
+ * it and the app DOM may be reconciled off the UI thread. */
33
+ private expanded;
7
34
  constructor();
8
- attributeChangedCallback(): void;
9
- private handleExpand;
35
+ connectedCallback(): void;
36
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
37
+ private get isExpandable();
38
+ private get isCollapsible();
39
+ /** Create or remove the chevron button to match `expandable`, then refresh
40
+ * its label/visibility — the single place the button's lifecycle lives. */
41
+ private syncExpandButton;
42
+ private handleToggle;
43
+ private setExpanded;
44
+ /** Reflect the current state onto the button: label + `aria-expanded` + the
45
+ * `.expanded` class (CSS keeps it visible and rotates the chevron up). A
46
+ * one-way expand (no `collapsible`) removes the button once expanded — there
47
+ * is nothing to collapse back to. */
48
+ private refreshButton;
10
49
  }
11
50
  export declare function register_a_text(): void;
@@ -9,9 +9,6 @@ const SHADOW_STYLE = `
9
9
  display: inline-block;
10
10
  }
11
11
 
12
- /* Default: slot disappears from layout so slotted nodes flow as
13
- direct children of the host. Truncation rules below give the slot
14
- a real display so it becomes the wrapper that holds the clamp. */
15
12
  slot {
16
13
  display: contents;
17
14
  }
@@ -23,27 +20,22 @@ const SHADOW_STYLE = `
23
20
  overflow: hidden;
24
21
  }
25
22
 
26
- /* Expandable \u2014 vertical fade for multi-line. */
27
23
  :host([truncate][expandable]) slot:not(.expanded) {
28
24
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 2em), transparent 97%);
29
25
  mask-image: linear-gradient(to bottom, black calc(100% - 2em), transparent 97%);
30
26
  }
31
27
 
32
- /* Expandable \u2014 horizontal right-edge fade for single-line. */
33
28
  :host([truncate="1"][expandable]) slot:not(.expanded) {
34
29
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 7ch), transparent 97%);
35
30
  mask-image: linear-gradient(to right, black calc(100% - 7ch), transparent 97%);
36
31
  }
37
32
 
38
- /* Expanded \u2014 drop truncation entirely. */
39
33
  :host([truncate]) slot.expanded {
40
34
  display: block;
41
35
  -webkit-line-clamp: unset;
42
36
  overflow: visible;
43
37
  }
44
38
 
45
- /* Expand button. The whole button is the click target; the chevron
46
- icon is positioned absolutely in the button's bottom-right corner. */
47
39
  .expand-btn {
48
40
  appearance: none;
49
41
  background: transparent;
@@ -78,10 +70,10 @@ const SHADOW_STYLE = `
78
70
  mask-repeat: no-repeat;
79
71
  -webkit-mask-size: contain;
80
72
  mask-size: contain;
73
+ transition: transform 150ms ease-out;
81
74
  }
82
75
 
83
- /* Multi-line \u2014 full-width strip pinned to the bottom of the host. */
84
- :host([truncate][expandable]) .expand-btn:not(.hidden) {
76
+ :host([truncate][expandable]) .expand-btn {
85
77
  display: block;
86
78
  left: 0;
87
79
  right: 0;
@@ -89,48 +81,96 @@ const SHADOW_STYLE = `
89
81
  height: 1.5em;
90
82
  }
91
83
 
92
- /* Single-line \u2014 narrow region pinned to the right side. */
93
- :host([truncate="1"][expandable]) .expand-btn:not(.hidden) {
84
+ :host([truncate="1"][expandable]) .expand-btn {
94
85
  left: auto;
95
86
  top: 0;
96
87
  bottom: 0;
97
88
  width: 3em;
98
89
  }
99
90
 
100
- :host([truncate][expandable]:hover) .expand-btn:not(.hidden),
101
- :host([truncate][expandable]:focus-within) .expand-btn:not(.hidden) {
91
+ :host([truncate][expandable]:hover) .expand-btn,
92
+ :host([truncate][expandable]:focus-within) .expand-btn,
93
+ .expand-btn.expanded {
102
94
  opacity: 1;
103
95
  }
96
+
97
+ .expand-btn.expanded::before {
98
+ transform: rotate(180deg);
99
+ }
104
100
  `;
105
101
  class ATextElement extends HTMLElementBase {
106
- static observedAttributes = ["expandable", "truncate"];
102
+ static observedAttributes = ["expandable", "truncate", "collapsible"];
107
103
  slotEl;
104
+ /** The expand/collapse chevron — built lazily, only while the element is
105
+ * expandable (a plain `<a-text>` never creates a button or a listener).
106
+ * Removed when `expandable` is dropped, and when a one-way expand completes. */
108
107
  expandBtn;
108
+ /** Expanded state lives here, on the element — a stateless wrapper can't hold
109
+ * it and the app DOM may be reconciled off the UI thread. */
110
+ expanded = false;
109
111
  constructor() {
110
112
  super();
111
113
  const shadow = this.attachShadow({ mode: "open" });
112
114
  const style = document.createElement("style");
113
115
  style.textContent = SHADOW_STYLE;
114
116
  this.slotEl = document.createElement("slot");
115
- this.expandBtn = document.createElement("button");
116
- this.expandBtn.className = "expand-btn";
117
- this.expandBtn.type = "button";
118
- this.expandBtn.setAttribute("aria-label", "Show more");
119
- this.expandBtn.setAttribute("aria-expanded", "false");
120
- this.expandBtn.addEventListener("click", this.handleExpand);
121
- shadow.append(style, this.slotEl, this.expandBtn);
122
- }
123
- attributeChangedCallback() {
124
- this.slotEl.classList.remove("expanded");
125
- this.expandBtn.classList.remove("hidden");
126
- this.expandBtn.setAttribute("aria-expanded", "false");
127
- }
128
- handleExpand = () => {
129
- if (this.slotEl.classList.contains("expanded")) return;
130
- this.slotEl.classList.add("expanded");
131
- this.expandBtn.classList.add("hidden");
132
- this.expandBtn.setAttribute("aria-expanded", "true");
117
+ shadow.append(style, this.slotEl);
118
+ }
119
+ connectedCallback() {
120
+ this.syncExpandButton();
121
+ }
122
+ attributeChangedCallback(name, oldValue, newValue) {
123
+ if (oldValue === newValue) return;
124
+ if (name === "truncate" || name === "expandable") this.setExpanded(false);
125
+ this.syncExpandButton();
126
+ }
127
+ get isExpandable() {
128
+ return this.hasAttribute("truncate") && this.hasAttribute("expandable");
129
+ }
130
+ get isCollapsible() {
131
+ return this.hasAttribute("collapsible");
132
+ }
133
+ /** Create or remove the chevron button to match `expandable`, then refresh
134
+ * its label/visibility — the single place the button's lifecycle lives. */
135
+ syncExpandButton() {
136
+ if (this.isExpandable && !this.expandBtn) {
137
+ const btn = document.createElement("button");
138
+ btn.className = "expand-btn";
139
+ btn.type = "button";
140
+ btn.addEventListener("click", this.handleToggle);
141
+ this.shadowRoot.append(btn);
142
+ this.expandBtn = btn;
143
+ } else if (!this.isExpandable && this.expandBtn) {
144
+ this.expandBtn.remove();
145
+ this.expandBtn = void 0;
146
+ }
147
+ this.refreshButton();
148
+ }
149
+ handleToggle = () => {
150
+ this.setExpanded(!this.expanded);
133
151
  };
152
+ setExpanded(next) {
153
+ if (next === this.expanded) return;
154
+ this.expanded = next;
155
+ this.slotEl.classList.toggle("expanded", next);
156
+ this.refreshButton();
157
+ }
158
+ /** Reflect the current state onto the button: label + `aria-expanded` + the
159
+ * `.expanded` class (CSS keeps it visible and rotates the chevron up). A
160
+ * one-way expand (no `collapsible`) removes the button once expanded — there
161
+ * is nothing to collapse back to. */
162
+ refreshButton() {
163
+ const btn = this.expandBtn;
164
+ if (!btn) return;
165
+ if (this.expanded && !this.isCollapsible) {
166
+ btn.remove();
167
+ this.expandBtn = void 0;
168
+ return;
169
+ }
170
+ btn.setAttribute("aria-expanded", this.expanded ? "true" : "false");
171
+ btn.setAttribute("aria-label", this.expanded ? "Show less" : "Show more");
172
+ btn.classList.toggle("expanded", this.expanded);
173
+ }
134
174
  }
135
175
  function register_a_text() {
136
176
  if (typeof customElements === "undefined") return;