@schalkneethling/miyagi-core 4.4.2 → 4.4.3

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 (115) hide show
  1. package/README.md +7 -2
  2. package/api/app.js +16 -16
  3. package/api/index.js +263 -262
  4. package/bin/miyagi.js +1 -1
  5. package/dist/css/iframe.css +6 -30
  6. package/frontend/assets/css/iframe/accordion-tabs.css +39 -39
  7. package/frontend/assets/css/iframe/jsontree.js.css +149 -149
  8. package/frontend/assets/css/iframe/prism.css +45 -45
  9. package/frontend/assets/css/iframe/styleguide/colors.css +27 -27
  10. package/frontend/assets/css/iframe/styleguide/fonts.css +23 -23
  11. package/frontend/assets/css/iframe/styleguide/index.css +58 -58
  12. package/frontend/assets/css/iframe/styleguide/spacings.css +10 -10
  13. package/frontend/assets/css/iframe.css +191 -191
  14. package/frontend/assets/css/main/menu/config-switcher.css +21 -21
  15. package/frontend/assets/css/main/menu/config-switchers.css +34 -34
  16. package/frontend/assets/css/main/menu/goto.css +16 -16
  17. package/frontend/assets/css/main/menu/nav.css +49 -49
  18. package/frontend/assets/css/main/menu/search.css +34 -34
  19. package/frontend/assets/css/main/menu/title.css +18 -18
  20. package/frontend/assets/css/main/menu.css +89 -89
  21. package/frontend/assets/css/main/reset.css +47 -47
  22. package/frontend/assets/css/main.css +41 -41
  23. package/frontend/assets/css/shared.css +16 -16
  24. package/frontend/assets/css/tokens.css +108 -107
  25. package/frontend/assets/js/_accordion-tabs.js +392 -392
  26. package/frontend/assets/js/_goto.js +59 -59
  27. package/frontend/assets/js/_iframe-links.js +14 -14
  28. package/frontend/assets/js/_is-triggered.js +3 -3
  29. package/frontend/assets/js/_main.js +369 -369
  30. package/frontend/assets/js/_mock-data.js +8 -8
  31. package/frontend/assets/js/_prism.js +1082 -1081
  32. package/frontend/assets/js/_search.js +186 -186
  33. package/frontend/assets/js/_socket.js +44 -44
  34. package/frontend/assets/js/config-switcher/development-mode.js +38 -38
  35. package/frontend/assets/js/config-switcher/index.js +55 -55
  36. package/frontend/assets/js/config-switcher/text-direction.js +22 -22
  37. package/frontend/assets/js/config-switcher/theme.js +68 -68
  38. package/frontend/assets/js/iframe.build.js +25 -25
  39. package/frontend/assets/js/iframe.js +38 -38
  40. package/frontend/assets/js/jsontree.js +979 -976
  41. package/frontend/assets/js/main.build.js +29 -29
  42. package/frontend/assets/js/main.js +31 -31
  43. package/frontend/assets/js/styleguide/color-converter.js +652 -652
  44. package/frontend/assets/js/styleguide/index.js +100 -100
  45. package/lib/build/index.js +1014 -1020
  46. package/lib/cli/app.js +16 -16
  47. package/lib/cli/component.js +50 -50
  48. package/lib/cli/doctor.js +130 -121
  49. package/lib/cli/drupal-assets.js +163 -157
  50. package/lib/cli/lint.js +196 -196
  51. package/lib/cli/run.js +150 -146
  52. package/lib/config.js +86 -86
  53. package/lib/constants/lint-log-levels.js +6 -6
  54. package/lib/drupal/load-assets-config.js +59 -60
  55. package/lib/drupal/resolve-library-assets.js +132 -141
  56. package/lib/errors.js +20 -20
  57. package/lib/generator/component.js +124 -124
  58. package/lib/generator/mocks.js +156 -156
  59. package/lib/helpers.js +68 -68
  60. package/lib/i18n/en.js +93 -93
  61. package/lib/i18n/index.js +8 -8
  62. package/lib/index.js +13 -13
  63. package/lib/init/args.js +153 -153
  64. package/lib/init/config.js +452 -438
  65. package/lib/init/engines.js +41 -41
  66. package/lib/init/index.js +83 -83
  67. package/lib/init/rendering.js +3 -3
  68. package/lib/init/static.js +90 -90
  69. package/lib/init/twing/cache.js +27 -27
  70. package/lib/init/twing/functions.js +37 -37
  71. package/lib/init/views.js +5 -5
  72. package/lib/logger.js +72 -72
  73. package/lib/mocks/get.js +88 -88
  74. package/lib/mocks/index.js +2 -2
  75. package/lib/mocks/resolve/ref.js +447 -447
  76. package/lib/mocks/resolve/tpl.js +218 -218
  77. package/lib/mocks/resolve.js +154 -154
  78. package/lib/render/helpers/resolve-assets.js +29 -39
  79. package/lib/render/helpers.js +27 -27
  80. package/lib/render/index.js +18 -18
  81. package/lib/render/views/iframe/component.docs.js +50 -50
  82. package/lib/render/views/iframe/component.js +249 -248
  83. package/lib/render/views/iframe/design-tokens/colors.js +38 -38
  84. package/lib/render/views/iframe/design-tokens/index.js +3 -3
  85. package/lib/render/views/iframe/design-tokens/sizes.js +35 -35
  86. package/lib/render/views/iframe/design-tokens/typography.js +37 -37
  87. package/lib/render/views/iframe/docs.js +42 -42
  88. package/lib/render/views/iframe/index.js +28 -28
  89. package/lib/render/views/iframe/variation.js +89 -89
  90. package/lib/render/views/iframe/variation.standalone.js +69 -68
  91. package/lib/render/views/main/component.docs.js +38 -38
  92. package/lib/render/views/main/component.js +55 -55
  93. package/lib/render/views/main/design-tokens.js +38 -38
  94. package/lib/render/views/main/docs.js +33 -33
  95. package/lib/render/views/main/index.js +33 -33
  96. package/lib/state/components.js +99 -99
  97. package/lib/state/css.js +33 -33
  98. package/lib/state/docs.js +72 -72
  99. package/lib/state/file-contents.js +154 -154
  100. package/lib/state/helpers.js +53 -53
  101. package/lib/state/index.js +39 -39
  102. package/lib/state/menu/index.js +202 -202
  103. package/lib/state/menu/structure.js +84 -84
  104. package/lib/state/partials.js +12 -12
  105. package/lib/state/source-tree.js +51 -51
  106. package/lib/styleguide/color-names.js +148 -148
  107. package/lib/styleguide/colors.js +113 -113
  108. package/lib/styleguide/helpers.js +33 -33
  109. package/lib/styleguide/index.js +4 -4
  110. package/lib/styleguide/media-queries.js +18 -18
  111. package/lib/styleguide/spacings.js +22 -22
  112. package/lib/styleguide/typography.js +46 -46
  113. package/lib/validator/mocks.js +110 -83
  114. package/lib/validator/schemas.js +236 -227
  115. package/package.json +118 -117
@@ -1,403 +1,403 @@
1
1
  customElements.define(
2
- "accordion-tabs",
3
- class AccordionTabs extends HTMLElement {
4
- #accordion;
5
- #breakpoint;
6
- #prevMode;
7
- #resizeObserver;
8
- #tabs;
9
-
10
- static get observedAttributes() {
11
- return ["breakpoint", "current"];
12
- }
13
-
14
- constructor() {
15
- super();
16
- }
17
-
18
- connectedCallback() {
19
- if (this.closest("code")) return;
20
-
21
- this.content = [];
22
-
23
- if (this.hasAttribute("breakpoint")) {
24
- const breakpoint = this.getAttribute("breakpoint");
25
- const bpParsed = parseInt(breakpoint, 10);
26
- let result;
27
-
28
- if (breakpoint.endsWith("rem")) {
29
- result =
30
- bpParsed *
31
- parseInt(
32
- window.getComputedStyle(document.documentElement).fontSize,
33
- 10,
34
- );
35
- } else if (breakpoint.endsWith("em")) {
36
- result =
37
- bpParsed * parseInt(window.getComputedStyle(this).fontSize, 10);
38
- } else {
39
- result = bpParsed;
40
- }
41
-
42
- this.#breakpoint = result;
43
- }
44
-
45
- window.requestAnimationFrame(() => {
46
- this.details = Array.from(this.children);
47
-
48
- this.details.forEach((child, i) => {
49
- const title = child.querySelector("summary");
50
-
51
- if (child.open) {
52
- this.index = i;
53
- }
54
-
55
- this.content.push({
56
- title: title.textContent,
57
- content: [...title.parentElement.children].filter(
58
- (el) => el.nodeType === 1 && el !== title,
59
- ),
60
- });
61
- });
62
-
63
- let initialized = false;
64
-
65
- this.#resizeObserver = new ResizeObserver((entries) => {
66
- if (initialized) {
67
- for (const entry of entries) {
68
- this.#render(entry.borderBoxSize[0].inlineSize);
69
- }
70
- }
71
-
72
- initialized = true;
73
- });
74
-
75
- this.#render(this.clientWidth, () => {
76
- this.#resizeObserver.observe(this);
77
- });
78
- });
79
- }
80
-
81
- attributeChangedCallback(attr, oldValue, newValue) {
82
- if (attr === "current") {
83
- this.index = parseInt(newValue, 10);
84
- this.#render(this.clientWidth);
85
- }
86
- }
87
-
88
- disconnectedCallback() {
89
- if (this.#resizeObserver) {
90
- this.#resizeObserver.disconnect();
91
- }
92
- }
93
-
94
- async #render(width, cb) {
95
- if (!this.#breakpoint || width < this.#breakpoint) {
96
- await this.#renderAccordion();
97
- this.#prevMode = "accordion";
98
- } else {
99
- await this.#renderTabs();
100
- this.#prevMode = "tabs";
101
- }
102
-
103
- if (cb) {
104
- cb();
105
- }
106
- }
107
-
108
- #renderAccordion() {
109
- if (!this.#accordion) {
110
- this.#accordion = new AccordionTabsAccordion(this);
111
- }
112
-
113
- if (this.#prevMode === "tabs") {
114
- this.#clear();
115
-
116
- this.#accordion.setElements();
117
-
118
- this.#accordion.elements.forEach((detail) => this.appendChild(detail));
119
- } else {
120
- this.#accordion.render();
121
- }
122
-
123
- return true;
124
- }
125
-
126
- async #renderTabs() {
127
- this.#clear();
128
-
129
- if (this.#tabs) {
130
- this.#tabs.index = typeof this.index === "number" ? this.index : 0;
131
- this.#tabs.setElements();
132
- } else {
133
- this.#tabs = new AccordionTabsTabs(this);
134
- }
135
-
136
- const [ol, content] = this.#tabs.elements;
137
-
138
- this.appendChild(ol);
139
-
140
- content.forEach((item) => {
141
- this.appendChild(item);
142
- });
143
-
144
- return await this.#tabs.render(false);
145
- }
146
-
147
- #clear() {
148
- Array.from(this.children).forEach((child) => this.removeChild(child));
149
- }
150
- },
2
+ "accordion-tabs",
3
+ class AccordionTabs extends HTMLElement {
4
+ #accordion;
5
+ #breakpoint;
6
+ #prevMode;
7
+ #resizeObserver;
8
+ #tabs;
9
+
10
+ static get observedAttributes() {
11
+ return ["breakpoint", "current"];
12
+ }
13
+
14
+ constructor() {
15
+ super();
16
+ }
17
+
18
+ connectedCallback() {
19
+ if (this.closest("code")) return;
20
+
21
+ this.content = [];
22
+
23
+ if (this.hasAttribute("breakpoint")) {
24
+ const breakpoint = this.getAttribute("breakpoint");
25
+ const bpParsed = parseInt(breakpoint, 10);
26
+ let result;
27
+
28
+ if (breakpoint.endsWith("rem")) {
29
+ result =
30
+ bpParsed *
31
+ parseInt(
32
+ window.getComputedStyle(document.documentElement).fontSize,
33
+ 10,
34
+ );
35
+ } else if (breakpoint.endsWith("em")) {
36
+ result =
37
+ bpParsed * parseInt(window.getComputedStyle(this).fontSize, 10);
38
+ } else {
39
+ result = bpParsed;
40
+ }
41
+
42
+ this.#breakpoint = result;
43
+ }
44
+
45
+ window.requestAnimationFrame(() => {
46
+ this.details = Array.from(this.children);
47
+
48
+ this.details.forEach((child, i) => {
49
+ const title = child.querySelector("summary");
50
+
51
+ if (child.open) {
52
+ this.index = i;
53
+ }
54
+
55
+ this.content.push({
56
+ title: title.textContent,
57
+ content: [...title.parentElement.children].filter(
58
+ (el) => el.nodeType === 1 && el !== title,
59
+ ),
60
+ });
61
+ });
62
+
63
+ let initialized = false;
64
+
65
+ this.#resizeObserver = new ResizeObserver((entries) => {
66
+ if (initialized) {
67
+ for (const entry of entries) {
68
+ this.#render(entry.borderBoxSize[0].inlineSize);
69
+ }
70
+ }
71
+
72
+ initialized = true;
73
+ });
74
+
75
+ this.#render(this.clientWidth, () => {
76
+ this.#resizeObserver.observe(this);
77
+ });
78
+ });
79
+ }
80
+
81
+ attributeChangedCallback(attr, oldValue, newValue) {
82
+ if (attr === "current") {
83
+ this.index = parseInt(newValue, 10);
84
+ this.#render(this.clientWidth);
85
+ }
86
+ }
87
+
88
+ disconnectedCallback() {
89
+ if (this.#resizeObserver) {
90
+ this.#resizeObserver.disconnect();
91
+ }
92
+ }
93
+
94
+ async #render(width, cb) {
95
+ if (!this.#breakpoint || width < this.#breakpoint) {
96
+ await this.#renderAccordion();
97
+ this.#prevMode = "accordion";
98
+ } else {
99
+ await this.#renderTabs();
100
+ this.#prevMode = "tabs";
101
+ }
102
+
103
+ if (cb) {
104
+ cb();
105
+ }
106
+ }
107
+
108
+ #renderAccordion() {
109
+ if (!this.#accordion) {
110
+ this.#accordion = new AccordionTabsAccordion(this);
111
+ }
112
+
113
+ if (this.#prevMode === "tabs") {
114
+ this.#clear();
115
+
116
+ this.#accordion.setElements();
117
+
118
+ this.#accordion.elements.forEach((detail) => this.appendChild(detail));
119
+ } else {
120
+ this.#accordion.render();
121
+ }
122
+
123
+ return true;
124
+ }
125
+
126
+ async #renderTabs() {
127
+ this.#clear();
128
+
129
+ if (this.#tabs) {
130
+ this.#tabs.index = typeof this.index === "number" ? this.index : 0;
131
+ this.#tabs.setElements();
132
+ } else {
133
+ this.#tabs = new AccordionTabsTabs(this);
134
+ }
135
+
136
+ const [ol, content] = this.#tabs.elements;
137
+
138
+ this.appendChild(ol);
139
+
140
+ content.forEach((item) => {
141
+ this.appendChild(item);
142
+ });
143
+
144
+ return await this.#tabs.render(false);
145
+ }
146
+
147
+ #clear() {
148
+ Array.from(this.children).forEach((child) => this.removeChild(child));
149
+ }
150
+ },
151
151
  );
152
152
 
153
153
  class AccordionTabsAccordion {
154
- constructor(AccordionTabs) {
155
- this.AccordionTabs = AccordionTabs;
156
- this.elements = this.AccordionTabs.details;
157
-
158
- this.elements.forEach((detail, i) => {
159
- detail
160
- .querySelector("summary")
161
- .addEventListener("click", ({ target }) => {
162
- requestAnimationFrame(() => {
163
- this.#onToggle(target.closest("details"), i);
164
- });
165
- });
166
- });
167
-
168
- this.render();
169
- }
170
-
171
- setElements() {
172
- this.elements.forEach((detail, i) => {
173
- this.AccordionTabs.content[i].content.forEach((item) =>
174
- detail.appendChild(item),
175
- );
176
-
177
- detail.open = i === this.AccordionTabs.index;
178
- });
179
- }
180
-
181
- render() {
182
- this.elements.forEach((el, i) => {
183
- el.open = i === this.AccordionTabs.index;
184
- });
185
- }
186
-
187
- #onToggle(element, i) {
188
- if (element.open) {
189
- this.elements.forEach((el) => {
190
- if (element !== el) {
191
- el.open = false;
192
- }
193
- });
194
- this.AccordionTabs.index = i;
195
- } else {
196
- this.AccordionTabs.index = null;
197
- }
198
- }
154
+ constructor(AccordionTabs) {
155
+ this.AccordionTabs = AccordionTabs;
156
+ this.elements = this.AccordionTabs.details;
157
+
158
+ this.elements.forEach((detail, i) => {
159
+ detail
160
+ .querySelector("summary")
161
+ .addEventListener("click", ({ target }) => {
162
+ requestAnimationFrame(() => {
163
+ this.#onToggle(target.closest("details"), i);
164
+ });
165
+ });
166
+ });
167
+
168
+ this.render();
169
+ }
170
+
171
+ setElements() {
172
+ this.elements.forEach((detail, i) => {
173
+ this.AccordionTabs.content[i].content.forEach((item) =>
174
+ detail.appendChild(item),
175
+ );
176
+
177
+ detail.open = i === this.AccordionTabs.index;
178
+ });
179
+ }
180
+
181
+ render() {
182
+ this.elements.forEach((el, i) => {
183
+ el.open = i === this.AccordionTabs.index;
184
+ });
185
+ }
186
+
187
+ #onToggle(element, i) {
188
+ if (element.open) {
189
+ this.elements.forEach((el) => {
190
+ if (element !== el) {
191
+ el.open = false;
192
+ }
193
+ });
194
+ this.AccordionTabs.index = i;
195
+ } else {
196
+ this.AccordionTabs.index = null;
197
+ }
198
+ }
199
199
  }
200
200
 
201
201
  class AccordionTabsTabs {
202
- #AccordionTabs;
203
- #buttons = [];
204
- #divs = [];
205
- #TabsList;
206
-
207
- constructor(AccordionTabs) {
208
- this.#AccordionTabs = AccordionTabs;
209
- this.elements = this.getElements();
210
- this.index =
211
- typeof this.#AccordionTabs.index === "number"
212
- ? this.#AccordionTabs.index
213
- : 0;
214
-
215
- this.#TabsList = new AccordionTabsList(this);
216
- }
217
-
218
- getElements() {
219
- const ol = document.createElement("ol");
220
- const arr = [];
221
-
222
- this.#AccordionTabs.content.forEach(({ title, content }, i) => {
223
- const button = document.createElement("button");
224
- const li = document.createElement("li");
225
- const div = document.createElement("div");
226
-
227
- const id = crypto.randomUUID();
228
- const idTab = `tab-${id}`;
229
- const idPanel = `panel-${id}`;
230
-
231
- ol.setAttribute("role", "tablist");
232
- li.setAttribute("role", "presentation");
233
-
234
- button.textContent = title;
235
- button.type = "button";
236
- button.id = idTab;
237
- button.setAttribute("aria-selected", i === this.index ? "true" : "false");
238
- button.setAttribute("tabindex", i === this.index ? 0 : -1);
239
- button.setAttribute("aria-controls", idPanel);
240
- button.setAttribute("role", "tab");
241
- this.#buttons.push(button);
242
-
243
- li.appendChild(button);
244
- ol.appendChild(li);
245
-
246
- content.forEach((item) => {
247
- div.appendChild(item);
248
- });
249
-
250
- div.id = idPanel;
251
- div.hidden = this.index !== i;
252
- div.setAttribute("role", "tabpanel");
253
- div.setAttribute("tabindex", "0");
254
- div.setAttribute("aria-labelledby", idTab);
255
-
256
- arr.push(div);
257
- this.#divs.push(div);
258
- });
259
-
260
- return [ol, arr];
261
- }
262
-
263
- setElements() {
264
- this.elements[1].forEach((div, i) => {
265
- this.#AccordionTabs.content[i].content.forEach((item) =>
266
- div.appendChild(item),
267
- );
268
- });
269
- }
270
-
271
- /**
272
- * @param {number} activeTab
273
- */
274
- setActiveTab(activeTab) {
275
- this.#AccordionTabs.index = this.index = activeTab;
276
-
277
- this.render();
278
- }
279
-
280
- /**
281
- * @returns {void}
282
- */
283
- async render(focus = true) {
284
- this.elements[1].forEach((tabpanel, i) => {
285
- tabpanel.hidden = i !== this.index;
286
- });
287
-
288
- return await this.#TabsList.render(focus);
289
- }
202
+ #AccordionTabs;
203
+ #buttons = [];
204
+ #divs = [];
205
+ #TabsList;
206
+
207
+ constructor(AccordionTabs) {
208
+ this.#AccordionTabs = AccordionTabs;
209
+ this.elements = this.getElements();
210
+ this.index =
211
+ typeof this.#AccordionTabs.index === "number"
212
+ ? this.#AccordionTabs.index
213
+ : 0;
214
+
215
+ this.#TabsList = new AccordionTabsList(this);
216
+ }
217
+
218
+ getElements() {
219
+ const ol = document.createElement("ol");
220
+ const arr = [];
221
+
222
+ this.#AccordionTabs.content.forEach(({ title, content }, i) => {
223
+ const button = document.createElement("button");
224
+ const li = document.createElement("li");
225
+ const div = document.createElement("div");
226
+
227
+ const id = crypto.randomUUID();
228
+ const idTab = `tab-${id}`;
229
+ const idPanel = `panel-${id}`;
230
+
231
+ ol.setAttribute("role", "tablist");
232
+ li.setAttribute("role", "presentation");
233
+
234
+ button.textContent = title;
235
+ button.type = "button";
236
+ button.id = idTab;
237
+ button.setAttribute("aria-selected", i === this.index ? "true" : "false");
238
+ button.setAttribute("tabindex", i === this.index ? 0 : -1);
239
+ button.setAttribute("aria-controls", idPanel);
240
+ button.setAttribute("role", "tab");
241
+ this.#buttons.push(button);
242
+
243
+ li.appendChild(button);
244
+ ol.appendChild(li);
245
+
246
+ content.forEach((item) => {
247
+ div.appendChild(item);
248
+ });
249
+
250
+ div.id = idPanel;
251
+ div.hidden = this.index !== i;
252
+ div.setAttribute("role", "tabpanel");
253
+ div.setAttribute("tabindex", "0");
254
+ div.setAttribute("aria-labelledby", idTab);
255
+
256
+ arr.push(div);
257
+ this.#divs.push(div);
258
+ });
259
+
260
+ return [ol, arr];
261
+ }
262
+
263
+ setElements() {
264
+ this.elements[1].forEach((div, i) => {
265
+ this.#AccordionTabs.content[i].content.forEach((item) =>
266
+ div.appendChild(item),
267
+ );
268
+ });
269
+ }
270
+
271
+ /**
272
+ * @param {number} activeTab
273
+ */
274
+ setActiveTab(activeTab) {
275
+ this.#AccordionTabs.index = this.index = activeTab;
276
+
277
+ this.render();
278
+ }
279
+
280
+ /**
281
+ * @returns {void}
282
+ */
283
+ async render(focus = true) {
284
+ this.elements[1].forEach((tabpanel, i) => {
285
+ tabpanel.hidden = i !== this.index;
286
+ });
287
+
288
+ return await this.#TabsList.render(focus);
289
+ }
290
290
  }
291
291
 
292
292
  class AccordionTabsList {
293
- #Tabs;
294
- #elements;
295
-
296
- /**
297
- * @param {object} Tabs
298
- */
299
- constructor(Tabs) {
300
- this.#Tabs = Tabs;
301
-
302
- this.#elements = Array.from(
303
- this.#Tabs.elements[0].querySelectorAll("button"),
304
- );
305
-
306
- this.#elements.forEach((button) => {
307
- button.addEventListener("click", this.#onClick.bind(this));
308
- button.addEventListener("keydown", this.#onKeydown.bind(this));
309
- });
310
- }
311
-
312
- /**
313
- * @param {Event} object
314
- * @param {HTMLButtonElement} object.currentTarget
315
- */
316
- #onClick({ currentTarget }) {
317
- this.#Tabs.setActiveTab(this.#elements.indexOf(currentTarget));
318
- }
319
-
320
- /**
321
- * @param {Event} event
322
- */
323
- #onKeydown(event) {
324
- const { dir } = event.target.closest("[dir]") || document.documentElement;
325
- let flag = false;
326
-
327
- switch (event.key) {
328
- case "ArrowLeft":
329
- if (dir === "rtl") {
330
- this.#setNextTab();
331
- } else {
332
- this.#setPreviousTab();
333
- }
334
- flag = true;
335
- break;
336
-
337
- case "ArrowRight":
338
- if (dir === "rtl") {
339
- this.#setPreviousTab();
340
- } else {
341
- this.#setNextTab();
342
- }
343
- flag = true;
344
- break;
345
-
346
- case "Home":
347
- this.#Tabs.setActiveTab(0);
348
- flag = true;
349
- break;
350
-
351
- case "End":
352
- this.#Tabs.setActiveTab(this.#elements.length - 1);
353
- flag = true;
354
- break;
355
-
356
- default:
357
- break;
358
- }
359
-
360
- if (flag) {
361
- event.stopPropagation();
362
- event.preventDefault();
363
- }
364
- }
365
-
366
- /**
367
- * @returns {void}
368
- */
369
- #setNextTab() {
370
- this.#Tabs.setActiveTab(
371
- this.#Tabs.index === this.#elements.length - 1 ? 0 : this.#Tabs.index + 1,
372
- );
373
- }
374
-
375
- /**
376
- * @returns {void}
377
- */
378
- #setPreviousTab() {
379
- this.#Tabs.setActiveTab(
380
- this.#Tabs.index === 0 ? this.#elements.length - 1 : this.#Tabs.index - 1,
381
- );
382
- }
383
-
384
- /**
385
- * @returns {void}
386
- */
387
- render(focus = true) {
388
- this.#elements.forEach((button, i) => {
389
- if (i === this.#Tabs.index) {
390
- button.setAttribute("aria-selected", "true");
391
- button.removeAttribute("tabindex");
392
- if (focus) {
393
- button.focus();
394
- }
395
- } else {
396
- button.setAttribute("aria-selected", "false");
397
- button.setAttribute("tabindex", -1);
398
- }
399
- });
400
-
401
- return new Promise((resolve) => setTimeout(resolve, 1000));
402
- }
293
+ #Tabs;
294
+ #elements;
295
+
296
+ /**
297
+ * @param {object} Tabs
298
+ */
299
+ constructor(Tabs) {
300
+ this.#Tabs = Tabs;
301
+
302
+ this.#elements = Array.from(
303
+ this.#Tabs.elements[0].querySelectorAll("button"),
304
+ );
305
+
306
+ this.#elements.forEach((button) => {
307
+ button.addEventListener("click", this.#onClick.bind(this));
308
+ button.addEventListener("keydown", this.#onKeydown.bind(this));
309
+ });
310
+ }
311
+
312
+ /**
313
+ * @param {Event} object
314
+ * @param {HTMLButtonElement} object.currentTarget
315
+ */
316
+ #onClick({ currentTarget }) {
317
+ this.#Tabs.setActiveTab(this.#elements.indexOf(currentTarget));
318
+ }
319
+
320
+ /**
321
+ * @param {Event} event
322
+ */
323
+ #onKeydown(event) {
324
+ const { dir } = event.target.closest("[dir]") || document.documentElement;
325
+ let flag = false;
326
+
327
+ switch (event.key) {
328
+ case "ArrowLeft":
329
+ if (dir === "rtl") {
330
+ this.#setNextTab();
331
+ } else {
332
+ this.#setPreviousTab();
333
+ }
334
+ flag = true;
335
+ break;
336
+
337
+ case "ArrowRight":
338
+ if (dir === "rtl") {
339
+ this.#setPreviousTab();
340
+ } else {
341
+ this.#setNextTab();
342
+ }
343
+ flag = true;
344
+ break;
345
+
346
+ case "Home":
347
+ this.#Tabs.setActiveTab(0);
348
+ flag = true;
349
+ break;
350
+
351
+ case "End":
352
+ this.#Tabs.setActiveTab(this.#elements.length - 1);
353
+ flag = true;
354
+ break;
355
+
356
+ default:
357
+ break;
358
+ }
359
+
360
+ if (flag) {
361
+ event.stopPropagation();
362
+ event.preventDefault();
363
+ }
364
+ }
365
+
366
+ /**
367
+ * @returns {void}
368
+ */
369
+ #setNextTab() {
370
+ this.#Tabs.setActiveTab(
371
+ this.#Tabs.index === this.#elements.length - 1 ? 0 : this.#Tabs.index + 1,
372
+ );
373
+ }
374
+
375
+ /**
376
+ * @returns {void}
377
+ */
378
+ #setPreviousTab() {
379
+ this.#Tabs.setActiveTab(
380
+ this.#Tabs.index === 0 ? this.#elements.length - 1 : this.#Tabs.index - 1,
381
+ );
382
+ }
383
+
384
+ /**
385
+ * @returns {void}
386
+ */
387
+ render(focus = true) {
388
+ this.#elements.forEach((button, i) => {
389
+ if (i === this.#Tabs.index) {
390
+ button.setAttribute("aria-selected", "true");
391
+ button.removeAttribute("tabindex");
392
+ if (focus) {
393
+ button.focus();
394
+ }
395
+ } else {
396
+ button.setAttribute("aria-selected", "false");
397
+ button.setAttribute("tabindex", -1);
398
+ }
399
+ });
400
+
401
+ return new Promise((resolve) => setTimeout(resolve, 1000));
402
+ }
403
403
  }