tyrell-components 1.0.0-TC51 → 1.0.0-TC53

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 (108) hide show
  1. package/css/tyrell-theme.css +25 -2
  2. package/css/tyrell.css +4 -0
  3. package/dist/tyrell-colors-static.css +1 -316
  4. package/dist/tyrell-theme.css +1 -1443
  5. package/dist/tyrell.css +1 -1390
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.js +196 -196
  8. package/lib/components/button.d.ts +1 -1
  9. package/lib/components/button.js +260 -259
  10. package/lib/components/calendar-month.d.ts +2 -2
  11. package/lib/components/calendar-month.js +426 -416
  12. package/lib/components/calendar-navigation.js +238 -238
  13. package/lib/components/calendar.js +605 -602
  14. package/lib/components/checkbox.d.ts +1 -1
  15. package/lib/components/checkbox.js +273 -272
  16. package/lib/components/copy.d.ts +1 -1
  17. package/lib/components/copy.js +279 -278
  18. package/lib/components/date-picker.d.ts +1 -1
  19. package/lib/components/date-picker.js +1103 -1108
  20. package/lib/components/file-upload.js +404 -404
  21. package/lib/components/icon.js +141 -141
  22. package/lib/components/input.d.ts +1 -1
  23. package/lib/components/input.js +593 -596
  24. package/lib/components/modal.js +319 -319
  25. package/lib/components/option.js +167 -167
  26. package/lib/components/popup.js +233 -233
  27. package/lib/components/radio.d.ts +2 -2
  28. package/lib/components/radio.js +407 -406
  29. package/lib/components/resize-observer.js +67 -67
  30. package/lib/components/scroll-container.js +294 -294
  31. package/lib/components/select.d.ts +1 -1
  32. package/lib/components/select.js +1524 -1532
  33. package/lib/components/selected-tags.js +184 -184
  34. package/lib/components/step.js +62 -62
  35. package/lib/components/switch.d.ts +1 -1
  36. package/lib/components/switch.js +214 -213
  37. package/lib/components/tab.js +62 -62
  38. package/lib/components/tabs.d.ts +1 -0
  39. package/lib/components/tabs.js +507 -479
  40. package/lib/components/tag.d.ts +1 -1
  41. package/lib/components/tag.js +236 -235
  42. package/lib/components/textarea.d.ts +1 -1
  43. package/lib/components/textarea.js +457 -456
  44. package/lib/components/tooltip.js +283 -283
  45. package/lib/components/wizard.js +384 -384
  46. package/lib/icons/heroicons/micro.js +392 -392
  47. package/lib/icons/heroicons/mini.js +382 -382
  48. package/lib/icons/heroicons/outline.js +337 -337
  49. package/lib/icons/heroicons/solid.js +407 -407
  50. package/lib/icons/lucide.js +22843 -22843
  51. package/lib/icons/material/filled.js +9653 -9653
  52. package/lib/icons/material/outlined.js +10271 -10271
  53. package/lib/icons/material/round.js +10495 -10495
  54. package/lib/icons/material/sharp.js +9905 -9905
  55. package/lib/icons/material/two-tone.js +12792 -12792
  56. package/lib/index.js +21 -21
  57. package/lib/styles/button.js +176 -288
  58. package/lib/styles/calendar-month.js +123 -183
  59. package/lib/styles/calendar-navigation.js +60 -79
  60. package/lib/styles/calendar.js +8 -9
  61. package/lib/styles/checkbox.js +45 -72
  62. package/lib/styles/copy.js +67 -91
  63. package/lib/styles/custom-scrollbar.js +80 -100
  64. package/lib/styles/date-picker.js +261 -331
  65. package/lib/styles/field-size.d.ts +6 -0
  66. package/lib/styles/field-size.js +91 -0
  67. package/lib/styles/file-upload.js +139 -169
  68. package/lib/styles/icon.js +92 -156
  69. package/lib/styles/input.js +125 -241
  70. package/lib/styles/modal.js +67 -102
  71. package/lib/styles/option.d.ts +1 -1
  72. package/lib/styles/option.js +47 -67
  73. package/lib/styles/popup.js +34 -65
  74. package/lib/styles/radio.js +69 -96
  75. package/lib/styles/resize-observer.js +2 -5
  76. package/lib/styles/scroll-container.js +100 -130
  77. package/lib/styles/select-base.js +525 -778
  78. package/lib/styles/select.js +140 -228
  79. package/lib/styles/step.js +22 -29
  80. package/lib/styles/switch.js +34 -55
  81. package/lib/styles/tab.d.ts +1 -1
  82. package/lib/styles/tab.js +22 -29
  83. package/lib/styles/tabs.d.ts +1 -1
  84. package/lib/styles/tabs.js +175 -237
  85. package/lib/styles/tag.js +135 -188
  86. package/lib/styles/textarea.d.ts +1 -1
  87. package/lib/styles/textarea.js +205 -271
  88. package/lib/styles/tooltip.js +3 -3
  89. package/lib/styles/wizard.js +170 -226
  90. package/lib/types/common.d.ts +2 -0
  91. package/lib/types/common.js +6 -5
  92. package/lib/utils/calendar-utils.js +100 -100
  93. package/lib/utils/custom-scrollbar.js +272 -272
  94. package/lib/utils/flavor-sheet.js +14 -14
  95. package/lib/utils/icon-registry.js +127 -127
  96. package/lib/utils/loader-registry.js +3 -3
  97. package/lib/utils/locale.js +34 -34
  98. package/lib/utils/mobile.js +1 -1
  99. package/lib/utils/number-format.js +54 -54
  100. package/lib/utils/positioning.js +212 -212
  101. package/lib/utils/property-capture.js +36 -36
  102. package/lib/utils/property-manager.js +125 -125
  103. package/lib/utils/resize-observer.js +23 -23
  104. package/lib/utils/scroll-lock.js +57 -57
  105. package/lib/utils/styles.js +17 -17
  106. package/lib/version.d.ts +1 -1
  107. package/lib/version.js +1 -1
  108. package/package.json +4 -4
@@ -1,424 +1,425 @@
1
+ import { DEFAULT_SIZE } from "../types/common.js";
1
2
  import { TyComponent } from "../base/ty-component.js";
2
3
  import { ensureStyles } from "../utils/styles.js";
3
4
  import { syncCustomFlavorSheet } from "../utils/flavor-sheet.js";
4
5
  import { radioStyles, radioCustomFlavorCss } from "../styles/radio.js";
5
6
  import { REQUIRED_ICON_SVG } from "../utils/icons.js";
6
7
  export class TyRadio extends TyComponent {
7
- constructor() {
8
- super();
9
- this._customFlavorSheet = null;
10
- this._listenersSetup = false;
11
- this._clickHandler = null;
12
- this._focusHandler = null;
13
- this._blurHandler = null;
14
- const shadow = this.shadowRoot;
15
- ensureStyles(shadow, { css: radioStyles, id: "ty-radio" });
16
- }
17
- onConnect() {
18
- this.setupEventListeners();
19
- this.dispatchEvent(new CustomEvent("ty-radio-connected", { bubbles: true }));
20
- this._syncCustomFlavor();
21
- }
22
- onDisconnect() {
23
- this.removeEventListeners();
24
- }
25
- onPropertiesChanged(changes) {
26
- if (changes.some((c) => c.name === "flavor")) {
27
- this._syncCustomFlavor();
28
- }
29
- }
30
- _syncCustomFlavor() {
31
- this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.flavor, ({ base }) => radioCustomFlavorCss(base));
32
- }
33
- buildClassList() {
34
- const classes = [this.size];
35
- if (this.disabled)
36
- classes.push("disabled");
37
- return classes.join(" ");
38
- }
39
- handleClick(e) {
40
- if (this.disabled)
41
- return;
42
- e.stopPropagation();
43
- this.dispatchEvent(new CustomEvent("ty-radio-select", {
44
- detail: { value: this.value },
45
- bubbles: true,
46
- composed: true,
47
- }));
48
- }
49
- removeEventListeners() {
50
- if (!this._listenersSetup)
51
- return;
52
- if (this._clickHandler) {
53
- this.removeEventListener("click", this._clickHandler);
54
- this._clickHandler = null;
55
- }
56
- const el = this.shadowRoot?.querySelector(".radio-container");
57
- if (!el) {
58
- this._listenersSetup = false;
59
- return;
60
- }
61
- if (this._focusHandler) {
62
- el.removeEventListener("focus", this._focusHandler);
63
- this._focusHandler = null;
64
- }
65
- if (this._blurHandler) {
66
- el.removeEventListener("blur", this._blurHandler);
67
- this._blurHandler = null;
68
- }
69
- this._listenersSetup = false;
70
- }
71
- setupEventListeners() {
72
- if (this._listenersSetup)
73
- return;
74
- const el = this.shadowRoot.querySelector(".radio-container");
75
- if (!el)
76
- return;
77
- this._clickHandler = (e) => this.handleClick(e);
78
- this._focusHandler = () => el.classList.add("focused");
79
- this._blurHandler = () => el.classList.remove("focused");
80
- this.addEventListener("click", this._clickHandler);
81
- el.addEventListener("focus", this._focusHandler);
82
- el.addEventListener("blur", this._blurHandler);
83
- this._listenersSetup = true;
84
- }
85
- render() {
86
- const shadow = this.shadowRoot;
87
- let radioEl = shadow.querySelector(".radio-container");
88
- const classes = this.buildClassList();
89
- if (!radioEl) {
90
- radioEl = document.createElement("div");
91
- radioEl.className = "radio-container " + classes;
92
- radioEl.tabIndex = this.disabled ? -1 : 0;
93
- radioEl.setAttribute("role", "radio");
94
- radioEl.setAttribute("aria-checked", String(this.checked));
95
- radioEl.setAttribute("aria-disabled", String(this.disabled));
96
- const circle = document.createElement("div");
97
- circle.className = "radio-circle";
98
- radioEl.appendChild(circle);
99
- shadow.appendChild(radioEl);
100
- }
101
- else {
102
- radioEl.className = "radio-container " + classes;
103
- radioEl.tabIndex = this.disabled ? -1 : 0;
104
- radioEl.setAttribute("aria-checked", String(this.checked));
105
- radioEl.setAttribute("aria-disabled", String(this.disabled));
106
- }
107
- this.setupEventListeners();
108
- this.applyLabelName(radioEl);
109
- }
110
- get value() { return this.getProperty("value"); }
111
- set value(v) { this.setProperty("value", v); }
112
- get checked() { return this.getProperty("checked"); }
113
- set checked(v) { this.setProperty("checked", v); }
114
- get disabled() { return this.getProperty("disabled"); }
115
- set disabled(v) { this.setProperty("disabled", v); }
116
- get size() { return this.getProperty("size"); }
117
- set size(v) { this.setProperty("size", v); }
118
- get flavor() { return this.getProperty("flavor"); }
119
- set flavor(v) { this.setProperty("flavor", v); }
8
+ constructor() {
9
+ super();
10
+ this._customFlavorSheet = null;
11
+ this._listenersSetup = false;
12
+ this._clickHandler = null;
13
+ this._focusHandler = null;
14
+ this._blurHandler = null;
15
+ const shadow = this.shadowRoot;
16
+ ensureStyles(shadow, { css: radioStyles, id: "ty-radio" });
17
+ }
18
+ onConnect() {
19
+ this.setupEventListeners();
20
+ this.dispatchEvent(new CustomEvent("ty-radio-connected", { bubbles: true }));
21
+ this._syncCustomFlavor();
22
+ }
23
+ onDisconnect() {
24
+ this.removeEventListeners();
25
+ }
26
+ onPropertiesChanged(changes) {
27
+ if (changes.some((c) => c.name === "flavor")) {
28
+ this._syncCustomFlavor();
29
+ }
30
+ }
31
+ _syncCustomFlavor() {
32
+ this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.flavor, ({ base }) => radioCustomFlavorCss(base));
33
+ }
34
+ buildClassList() {
35
+ const classes = [this.size];
36
+ if (this.disabled)
37
+ classes.push("disabled");
38
+ return classes.join(" ");
39
+ }
40
+ handleClick(e) {
41
+ if (this.disabled)
42
+ return;
43
+ e.stopPropagation();
44
+ this.dispatchEvent(new CustomEvent("ty-radio-select", {
45
+ detail: { value: this.value },
46
+ bubbles: true,
47
+ composed: true,
48
+ }));
49
+ }
50
+ removeEventListeners() {
51
+ if (!this._listenersSetup)
52
+ return;
53
+ if (this._clickHandler) {
54
+ this.removeEventListener("click", this._clickHandler);
55
+ this._clickHandler = null;
56
+ }
57
+ const el = this.shadowRoot?.querySelector(".radio-container");
58
+ if (!el) {
59
+ this._listenersSetup = false;
60
+ return;
61
+ }
62
+ if (this._focusHandler) {
63
+ el.removeEventListener("focus", this._focusHandler);
64
+ this._focusHandler = null;
65
+ }
66
+ if (this._blurHandler) {
67
+ el.removeEventListener("blur", this._blurHandler);
68
+ this._blurHandler = null;
69
+ }
70
+ this._listenersSetup = false;
71
+ }
72
+ setupEventListeners() {
73
+ if (this._listenersSetup)
74
+ return;
75
+ const el = this.shadowRoot.querySelector(".radio-container");
76
+ if (!el)
77
+ return;
78
+ this._clickHandler = (e) => this.handleClick(e);
79
+ this._focusHandler = () => el.classList.add("focused");
80
+ this._blurHandler = () => el.classList.remove("focused");
81
+ this.addEventListener("click", this._clickHandler);
82
+ el.addEventListener("focus", this._focusHandler);
83
+ el.addEventListener("blur", this._blurHandler);
84
+ this._listenersSetup = true;
85
+ }
86
+ render() {
87
+ const shadow = this.shadowRoot;
88
+ let radioEl = shadow.querySelector(".radio-container");
89
+ const classes = this.buildClassList();
90
+ if (!radioEl) {
91
+ radioEl = document.createElement("div");
92
+ radioEl.className = "radio-container " + classes;
93
+ radioEl.tabIndex = this.disabled ? -1 : 0;
94
+ radioEl.setAttribute("role", "radio");
95
+ radioEl.setAttribute("aria-checked", String(this.checked));
96
+ radioEl.setAttribute("aria-disabled", String(this.disabled));
97
+ const circle = document.createElement("div");
98
+ circle.className = "radio-circle";
99
+ radioEl.appendChild(circle);
100
+ shadow.appendChild(radioEl);
101
+ }
102
+ else {
103
+ radioEl.className = "radio-container " + classes;
104
+ radioEl.tabIndex = this.disabled ? -1 : 0;
105
+ radioEl.setAttribute("aria-checked", String(this.checked));
106
+ radioEl.setAttribute("aria-disabled", String(this.disabled));
107
+ }
108
+ this.setupEventListeners();
109
+ this.applyLabelName(radioEl);
110
+ }
111
+ get value() { return this.getProperty("value"); }
112
+ set value(v) { this.setProperty("value", v); }
113
+ get checked() { return this.getProperty("checked"); }
114
+ set checked(v) { this.setProperty("checked", v); }
115
+ get disabled() { return this.getProperty("disabled"); }
116
+ set disabled(v) { this.setProperty("disabled", v); }
117
+ get size() { return this.getProperty("size"); }
118
+ set size(v) { this.setProperty("size", v); }
119
+ get flavor() { return this.getProperty("flavor"); }
120
+ set flavor(v) { this.setProperty("flavor", v); }
120
121
  }
121
122
  TyRadio.properties = {
122
- value: { type: "string", default: "" },
123
- checked: {
124
- type: "boolean",
125
- visual: true,
126
- default: false,
127
- },
128
- disabled: {
129
- type: "boolean",
130
- visual: true,
131
- default: false,
132
- },
133
- size: {
134
- type: "string",
135
- visual: true,
136
- default: "md",
137
- },
138
- flavor: {
139
- type: "string",
140
- visual: true,
141
- default: "primary",
142
- },
123
+ value: { type: "string", default: "" },
124
+ checked: {
125
+ type: "boolean",
126
+ visual: true,
127
+ default: false,
128
+ },
129
+ disabled: {
130
+ type: "boolean",
131
+ visual: true,
132
+ default: false,
133
+ },
134
+ size: {
135
+ type: "string",
136
+ visual: true,
137
+ default: DEFAULT_SIZE,
138
+ },
139
+ flavor: {
140
+ type: "string",
141
+ visual: true,
142
+ default: "primary",
143
+ },
143
144
  };
144
145
  if (!customElements.get("ty-radio")) {
145
- customElements.define("ty-radio", TyRadio);
146
+ customElements.define("ty-radio", TyRadio);
146
147
  }
147
148
  export class TyRadioGroup extends TyComponent {
148
- constructor() {
149
- super();
150
- this._listenersSetup = false;
151
- this._selectHandler = null;
152
- this._keydownHandler = null;
153
- this._connectedHandler = null;
154
- const shadow = this.shadowRoot;
155
- ensureStyles(shadow, { css: radioStyles, id: "ty-radio-group" });
156
- }
157
- onConnect() {
158
- this.setupEventListeners();
159
- queueMicrotask(() => this.syncChildren());
160
- }
161
- onDisconnect() {
162
- this.removeEventListeners();
163
- }
164
- onPropertiesChanged(changes) {
165
- if (changes.some((c) => c.name === "value" || c.name === "size" || c.name === "flavor" || c.name === "disabled")) {
166
- this.syncChildren();
167
- }
168
- }
169
- getFormValue() {
170
- return this.value || null;
171
- }
172
- getRadios() {
173
- return Array.from(this.querySelectorAll("ty-radio"));
174
- }
175
- syncChildren() {
176
- const radios = this.getRadios();
177
- for (const radio of radios) {
178
- radio.checked = radio.value === this.value;
179
- if (this.disabled) {
180
- if (!radio.disabled) {
181
- radio.disabled = true;
182
- radio.dataset.tyGroupDisabled = "";
183
- }
184
- }
185
- else if ("tyGroupDisabled" in radio.dataset) {
186
- radio.disabled = false;
187
- delete radio.dataset.tyGroupDisabled;
188
- }
189
- radio.size = this.size;
190
- radio.flavor = this.flavor;
191
- }
192
- }
193
- handleRadioSelect(e) {
194
- if (this.disabled)
195
- return;
196
- const detail = e.detail;
197
- const newValue = detail?.value;
198
- if (typeof newValue !== "string" || newValue === this.value)
199
- return;
200
- this.value = newValue;
201
- this.syncChildren();
202
- setTimeout(() => {
203
- const eventDetail = {
204
- value: newValue,
205
- formValue: newValue,
206
- originalEvent: e,
207
- };
208
- this.dispatchEvent(new CustomEvent("input", { detail: eventDetail, bubbles: true, composed: true }));
209
- this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
210
- }, 0);
211
- }
212
- handleKeydown(e) {
213
- if (this.disabled)
214
- return;
215
- const radios = this.getRadios().filter((r) => !r.disabled);
216
- if (radios.length === 0)
217
- return;
218
- const active = document.activeElement;
219
- const current = radios.find((r) => r === active || r.contains(active));
220
- let nextIndex = -1;
221
- if (["ArrowDown", "ArrowRight"].includes(e.key)) {
222
- e.preventDefault();
223
- nextIndex = current ? (radios.indexOf(current) + 1) % radios.length : 0;
224
- }
225
- else if (["ArrowUp", "ArrowLeft"].includes(e.key)) {
226
- e.preventDefault();
227
- nextIndex = current
228
- ? (radios.indexOf(current) - 1 + radios.length) % radios.length
229
- : radios.length - 1;
230
- }
231
- else if (["Space", " ", "Enter"].includes(e.key)) {
232
- if (current) {
233
- e.preventDefault();
234
- this.value = current.value;
235
- this.syncChildren();
236
- const eventDetail = {
237
- value: current.value,
238
- formValue: current.value,
239
- originalEvent: e,
240
- };
241
- setTimeout(() => {
242
- this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
243
- }, 0);
244
- }
245
- return;
246
- }
247
- else {
248
- return;
249
- }
250
- const next = radios[nextIndex];
251
- if (next) {
252
- next.focus();
253
- this.value = next.value;
254
- this.syncChildren();
255
- const eventDetail = {
256
- value: next.value,
257
- formValue: next.value,
258
- originalEvent: e,
259
- };
260
- setTimeout(() => {
261
- this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
262
- }, 0);
263
- }
264
- }
265
- removeEventListeners() {
266
- if (!this._listenersSetup)
267
- return;
268
- if (this._selectHandler) {
269
- this.removeEventListener("ty-radio-select", this._selectHandler);
270
- this._selectHandler = null;
271
- }
272
- if (this._keydownHandler) {
273
- this.removeEventListener("keydown", this._keydownHandler);
274
- this._keydownHandler = null;
275
- }
276
- if (this._connectedHandler) {
277
- this.removeEventListener("ty-radio-connected", this._connectedHandler);
278
- this._connectedHandler = null;
279
- }
280
- this._listenersSetup = false;
281
- }
282
- setupEventListeners() {
283
- if (this._listenersSetup)
284
- return;
285
- this._selectHandler = (e) => this.handleRadioSelect(e);
286
- this._keydownHandler = (e) => this.handleKeydown(e);
287
- this._connectedHandler = () => this.syncChildren();
288
- this.addEventListener("ty-radio-select", this._selectHandler);
289
- this.addEventListener("keydown", this._keydownHandler);
290
- this.addEventListener("ty-radio-connected", this._connectedHandler);
291
- this._listenersSetup = true;
292
- }
293
- render() {
294
- const shadow = this.shadowRoot;
295
- let container = shadow.querySelector(".radio-group-container");
296
- if (!container) {
297
- container = document.createElement("div");
298
- container.className = "radio-group-container";
299
- container.setAttribute("role", "radiogroup");
300
- container.setAttribute("aria-disabled", String(this.disabled));
301
- if (this.label) {
302
- const labelEl = document.createElement("div");
303
- labelEl.className = "radio-group-label";
304
- labelEl.textContent = this.label;
305
- if (this.required) {
306
- const req = document.createElement("span");
307
- req.className = "required-icon";
308
- req.innerHTML = REQUIRED_ICON_SVG;
309
- labelEl.appendChild(req);
310
- }
311
- container.appendChild(labelEl);
312
- }
313
- const list = document.createElement("div");
314
- list.className = "radio-group-list " + this.orientation;
315
- const slot = document.createElement("slot");
316
- list.appendChild(slot);
317
- container.appendChild(list);
318
- if (this.error) {
319
- const errorEl = document.createElement("div");
320
- errorEl.className = "radio-group-error";
321
- errorEl.textContent = this.error;
322
- container.appendChild(errorEl);
323
- }
324
- shadow.appendChild(container);
325
- this.setupEventListeners();
326
- }
327
- else {
328
- let labelEl = container.querySelector(".radio-group-label");
329
- if (this.label) {
330
- if (!labelEl) {
331
- labelEl = document.createElement("div");
332
- labelEl.className = "radio-group-label";
333
- container.insertBefore(labelEl, container.firstChild);
334
- }
335
- labelEl.textContent = this.label;
336
- if (this.required && !labelEl.querySelector(".required-icon")) {
337
- const req = document.createElement("span");
338
- req.className = "required-icon";
339
- req.innerHTML = REQUIRED_ICON_SVG;
340
- labelEl.appendChild(req);
341
- }
342
- else if (!this.required) {
343
- labelEl.querySelector(".required-icon")?.remove();
344
- }
345
- }
346
- else if (labelEl) {
347
- labelEl.remove();
348
- }
349
- const list = container.querySelector(".radio-group-list");
350
- if (list)
351
- list.className = "radio-group-list " + this.orientation;
352
- let errorEl = container.querySelector(".radio-group-error");
353
- if (this.error) {
354
- if (!errorEl) {
355
- errorEl = document.createElement("div");
356
- errorEl.className = "radio-group-error";
357
- container.appendChild(errorEl);
358
- }
359
- errorEl.textContent = this.error;
360
- }
361
- else if (errorEl) {
362
- errorEl.remove();
363
- }
364
- container.setAttribute("aria-disabled", String(this.disabled));
365
- }
366
- this.syncChildren();
367
- }
368
- get value() { return this.getProperty("value"); }
369
- set value(v) { this.setProperty("value", v); }
370
- get name() { return this.getProperty("name"); }
371
- set name(v) { this.setProperty("name", v); }
372
- get label() { return this.getProperty("label"); }
373
- set label(v) { this.setProperty("label", v); }
374
- get disabled() { return this.getProperty("disabled"); }
375
- set disabled(v) { this.setProperty("disabled", v); }
376
- get required() { return this.getProperty("required"); }
377
- set required(v) { this.setProperty("required", v); }
378
- get error() { return this.getProperty("error"); }
379
- set error(v) { this.setProperty("error", v); }
380
- get orientation() {
381
- return this.getProperty("orientation");
382
- }
383
- set orientation(v) {
384
- this.setProperty("orientation", v);
385
- }
386
- get size() { return this.getProperty("size"); }
387
- set size(v) { this.setProperty("size", v); }
388
- get flavor() { return this.getProperty("flavor"); }
389
- set flavor(v) { this.setProperty("flavor", v); }
390
- get form() { return this._internals.form; }
149
+ constructor() {
150
+ super();
151
+ this._listenersSetup = false;
152
+ this._selectHandler = null;
153
+ this._keydownHandler = null;
154
+ this._connectedHandler = null;
155
+ const shadow = this.shadowRoot;
156
+ ensureStyles(shadow, { css: radioStyles, id: "ty-radio-group" });
157
+ }
158
+ onConnect() {
159
+ this.setupEventListeners();
160
+ queueMicrotask(() => this.syncChildren());
161
+ }
162
+ onDisconnect() {
163
+ this.removeEventListeners();
164
+ }
165
+ onPropertiesChanged(changes) {
166
+ if (changes.some((c) => c.name === "value" || c.name === "size" || c.name === "flavor" || c.name === "disabled")) {
167
+ this.syncChildren();
168
+ }
169
+ }
170
+ getFormValue() {
171
+ return this.value || null;
172
+ }
173
+ getRadios() {
174
+ return Array.from(this.querySelectorAll("ty-radio"));
175
+ }
176
+ syncChildren() {
177
+ const radios = this.getRadios();
178
+ for (const radio of radios) {
179
+ radio.checked = radio.value === this.value;
180
+ if (this.disabled) {
181
+ if (!radio.disabled) {
182
+ radio.disabled = true;
183
+ radio.dataset.tyGroupDisabled = "";
184
+ }
185
+ }
186
+ else if ("tyGroupDisabled" in radio.dataset) {
187
+ radio.disabled = false;
188
+ delete radio.dataset.tyGroupDisabled;
189
+ }
190
+ radio.size = this.size;
191
+ radio.flavor = this.flavor;
192
+ }
193
+ }
194
+ handleRadioSelect(e) {
195
+ if (this.disabled)
196
+ return;
197
+ const detail = e.detail;
198
+ const newValue = detail?.value;
199
+ if (typeof newValue !== "string" || newValue === this.value)
200
+ return;
201
+ this.value = newValue;
202
+ this.syncChildren();
203
+ setTimeout(() => {
204
+ const eventDetail = {
205
+ value: newValue,
206
+ formValue: newValue,
207
+ originalEvent: e,
208
+ };
209
+ this.dispatchEvent(new CustomEvent("input", { detail: eventDetail, bubbles: true, composed: true }));
210
+ this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
211
+ }, 0);
212
+ }
213
+ handleKeydown(e) {
214
+ if (this.disabled)
215
+ return;
216
+ const radios = this.getRadios().filter((r) => !r.disabled);
217
+ if (radios.length === 0)
218
+ return;
219
+ const active = document.activeElement;
220
+ const current = radios.find((r) => r === active || r.contains(active));
221
+ let nextIndex = -1;
222
+ if (["ArrowDown", "ArrowRight"].includes(e.key)) {
223
+ e.preventDefault();
224
+ nextIndex = current ? (radios.indexOf(current) + 1) % radios.length : 0;
225
+ }
226
+ else if (["ArrowUp", "ArrowLeft"].includes(e.key)) {
227
+ e.preventDefault();
228
+ nextIndex = current
229
+ ? (radios.indexOf(current) - 1 + radios.length) % radios.length
230
+ : radios.length - 1;
231
+ }
232
+ else if (["Space", " ", "Enter"].includes(e.key)) {
233
+ if (current) {
234
+ e.preventDefault();
235
+ this.value = current.value;
236
+ this.syncChildren();
237
+ const eventDetail = {
238
+ value: current.value,
239
+ formValue: current.value,
240
+ originalEvent: e,
241
+ };
242
+ setTimeout(() => {
243
+ this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
244
+ }, 0);
245
+ }
246
+ return;
247
+ }
248
+ else {
249
+ return;
250
+ }
251
+ const next = radios[nextIndex];
252
+ if (next) {
253
+ next.focus();
254
+ this.value = next.value;
255
+ this.syncChildren();
256
+ const eventDetail = {
257
+ value: next.value,
258
+ formValue: next.value,
259
+ originalEvent: e,
260
+ };
261
+ setTimeout(() => {
262
+ this.dispatchEvent(new CustomEvent("change", { detail: eventDetail, bubbles: true, composed: true }));
263
+ }, 0);
264
+ }
265
+ }
266
+ removeEventListeners() {
267
+ if (!this._listenersSetup)
268
+ return;
269
+ if (this._selectHandler) {
270
+ this.removeEventListener("ty-radio-select", this._selectHandler);
271
+ this._selectHandler = null;
272
+ }
273
+ if (this._keydownHandler) {
274
+ this.removeEventListener("keydown", this._keydownHandler);
275
+ this._keydownHandler = null;
276
+ }
277
+ if (this._connectedHandler) {
278
+ this.removeEventListener("ty-radio-connected", this._connectedHandler);
279
+ this._connectedHandler = null;
280
+ }
281
+ this._listenersSetup = false;
282
+ }
283
+ setupEventListeners() {
284
+ if (this._listenersSetup)
285
+ return;
286
+ this._selectHandler = (e) => this.handleRadioSelect(e);
287
+ this._keydownHandler = (e) => this.handleKeydown(e);
288
+ this._connectedHandler = () => this.syncChildren();
289
+ this.addEventListener("ty-radio-select", this._selectHandler);
290
+ this.addEventListener("keydown", this._keydownHandler);
291
+ this.addEventListener("ty-radio-connected", this._connectedHandler);
292
+ this._listenersSetup = true;
293
+ }
294
+ render() {
295
+ const shadow = this.shadowRoot;
296
+ let container = shadow.querySelector(".radio-group-container");
297
+ if (!container) {
298
+ container = document.createElement("div");
299
+ container.className = "radio-group-container";
300
+ container.setAttribute("role", "radiogroup");
301
+ container.setAttribute("aria-disabled", String(this.disabled));
302
+ if (this.label) {
303
+ const labelEl = document.createElement("div");
304
+ labelEl.className = "radio-group-label";
305
+ labelEl.textContent = this.label;
306
+ if (this.required) {
307
+ const req = document.createElement("span");
308
+ req.className = "required-icon";
309
+ req.innerHTML = REQUIRED_ICON_SVG;
310
+ labelEl.appendChild(req);
311
+ }
312
+ container.appendChild(labelEl);
313
+ }
314
+ const list = document.createElement("div");
315
+ list.className = "radio-group-list " + this.orientation;
316
+ const slot = document.createElement("slot");
317
+ list.appendChild(slot);
318
+ container.appendChild(list);
319
+ if (this.error) {
320
+ const errorEl = document.createElement("div");
321
+ errorEl.className = "radio-group-error";
322
+ errorEl.textContent = this.error;
323
+ container.appendChild(errorEl);
324
+ }
325
+ shadow.appendChild(container);
326
+ this.setupEventListeners();
327
+ }
328
+ else {
329
+ let labelEl = container.querySelector(".radio-group-label");
330
+ if (this.label) {
331
+ if (!labelEl) {
332
+ labelEl = document.createElement("div");
333
+ labelEl.className = "radio-group-label";
334
+ container.insertBefore(labelEl, container.firstChild);
335
+ }
336
+ labelEl.textContent = this.label;
337
+ if (this.required && !labelEl.querySelector(".required-icon")) {
338
+ const req = document.createElement("span");
339
+ req.className = "required-icon";
340
+ req.innerHTML = REQUIRED_ICON_SVG;
341
+ labelEl.appendChild(req);
342
+ }
343
+ else if (!this.required) {
344
+ labelEl.querySelector(".required-icon")?.remove();
345
+ }
346
+ }
347
+ else if (labelEl) {
348
+ labelEl.remove();
349
+ }
350
+ const list = container.querySelector(".radio-group-list");
351
+ if (list)
352
+ list.className = "radio-group-list " + this.orientation;
353
+ let errorEl = container.querySelector(".radio-group-error");
354
+ if (this.error) {
355
+ if (!errorEl) {
356
+ errorEl = document.createElement("div");
357
+ errorEl.className = "radio-group-error";
358
+ container.appendChild(errorEl);
359
+ }
360
+ errorEl.textContent = this.error;
361
+ }
362
+ else if (errorEl) {
363
+ errorEl.remove();
364
+ }
365
+ container.setAttribute("aria-disabled", String(this.disabled));
366
+ }
367
+ this.syncChildren();
368
+ }
369
+ get value() { return this.getProperty("value"); }
370
+ set value(v) { this.setProperty("value", v); }
371
+ get name() { return this.getProperty("name"); }
372
+ set name(v) { this.setProperty("name", v); }
373
+ get label() { return this.getProperty("label"); }
374
+ set label(v) { this.setProperty("label", v); }
375
+ get disabled() { return this.getProperty("disabled"); }
376
+ set disabled(v) { this.setProperty("disabled", v); }
377
+ get required() { return this.getProperty("required"); }
378
+ set required(v) { this.setProperty("required", v); }
379
+ get error() { return this.getProperty("error"); }
380
+ set error(v) { this.setProperty("error", v); }
381
+ get orientation() {
382
+ return this.getProperty("orientation");
383
+ }
384
+ set orientation(v) {
385
+ this.setProperty("orientation", v);
386
+ }
387
+ get size() { return this.getProperty("size"); }
388
+ set size(v) { this.setProperty("size", v); }
389
+ get flavor() { return this.getProperty("flavor"); }
390
+ set flavor(v) { this.setProperty("flavor", v); }
391
+ get form() { return this._internals.form; }
391
392
  }
392
393
  TyRadioGroup.formAssociated = true;
393
394
  TyRadioGroup.properties = {
394
- value: {
395
- type: "string",
396
- visual: true,
397
- formValue: true,
398
- emitChange: true,
399
- default: "",
400
- },
401
- name: { type: "string", default: "" },
402
- label: { type: "string", visual: true, default: "" },
403
- disabled: { type: "boolean", visual: true, default: false },
404
- required: { type: "boolean", visual: true, default: false },
405
- error: { type: "string", visual: true, default: "" },
406
- orientation: {
407
- type: "string",
408
- visual: true,
409
- default: "vertical",
410
- },
411
- size: {
412
- type: "string",
413
- visual: true,
414
- default: "md",
415
- },
416
- flavor: {
417
- type: "string",
418
- visual: true,
419
- default: "primary",
420
- },
395
+ value: {
396
+ type: "string",
397
+ visual: true,
398
+ formValue: true,
399
+ emitChange: true,
400
+ default: "",
401
+ },
402
+ name: { type: "string", default: "" },
403
+ label: { type: "string", visual: true, default: "" },
404
+ disabled: { type: "boolean", visual: true, default: false },
405
+ required: { type: "boolean", visual: true, default: false },
406
+ error: { type: "string", visual: true, default: "" },
407
+ orientation: {
408
+ type: "string",
409
+ visual: true,
410
+ default: "vertical",
411
+ },
412
+ size: {
413
+ type: "string",
414
+ visual: true,
415
+ default: DEFAULT_SIZE,
416
+ },
417
+ flavor: {
418
+ type: "string",
419
+ visual: true,
420
+ default: "primary",
421
+ },
421
422
  };
422
423
  if (!customElements.get("ty-radio-group")) {
423
- customElements.define("ty-radio-group", TyRadioGroup);
424
+ customElements.define("ty-radio-group", TyRadioGroup);
424
425
  }