@y14e/tabs 1.3.3 → 1.3.5

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.
package/dist/index.cjs CHANGED
@@ -1,5 +1,43 @@
1
1
  'use strict';
2
2
 
3
+ // node_modules/@y14e/attributes-utils/dist/index.js
4
+ function addTokenToAttribute(element, attribute, token) {
5
+ const tokens = new Set(
6
+ element.getAttribute(attribute)?.trim().split(/\s+/) ?? []
7
+ );
8
+ tokens.add(token);
9
+ element.setAttribute(attribute, [...tokens].join(" "));
10
+ }
11
+ var snapshots = /* @__PURE__ */ new WeakMap();
12
+ function restoreAttributes(elements) {
13
+ elements.forEach((element) => {
14
+ const snapshot = snapshots.get(element);
15
+ if (!snapshot) {
16
+ return;
17
+ }
18
+ for (const [attribute, value] of snapshot.entries()) {
19
+ if (value === null) {
20
+ element.removeAttribute(attribute);
21
+ } else {
22
+ element.setAttribute(attribute, value);
23
+ }
24
+ }
25
+ snapshots.delete(element);
26
+ });
27
+ }
28
+ function saveAttributes(elements, attributes) {
29
+ elements.forEach((element) => {
30
+ let snapshot = snapshots.get(element);
31
+ if (!snapshot) {
32
+ snapshot = /* @__PURE__ */ new Map();
33
+ snapshots.set(element, snapshot);
34
+ }
35
+ attributes.forEach((attribute) => {
36
+ snapshot.set(attribute, element.getAttribute(attribute));
37
+ });
38
+ });
39
+ }
40
+
3
41
  // src/index.ts
4
42
  var Tabs = class _Tabs {
5
43
  static defaults = {};
@@ -116,7 +154,7 @@ var Tabs = class _Tabs {
116
154
  });
117
155
  this.#initialize();
118
156
  }
119
- async activate(tab, isMatch = false) {
157
+ activate(tab, isMatch = false) {
120
158
  if (this.#isDestroyed) {
121
159
  return;
122
160
  }
@@ -274,6 +312,11 @@ var Tabs = class _Tabs {
274
312
  this.#onAnimationFinish();
275
313
  this.#animationController?.abort();
276
314
  this.#animationController = null;
315
+ restoreAttributes([
316
+ ...this.#listElements,
317
+ ...this.#tabElements,
318
+ ...this.#panelElements
319
+ ]);
277
320
  this.#listElements.length = 0;
278
321
  this.#tabElements.length = 0;
279
322
  this.#contentElement = null;
@@ -282,6 +325,11 @@ var Tabs = class _Tabs {
282
325
  }
283
326
  #initialize() {
284
327
  const { signal } = this.#eventController ?? new AbortController();
328
+ saveAttributes(this.#listElements, [
329
+ "aria-hidden",
330
+ "aria-orientation",
331
+ "role"
332
+ ]);
285
333
  this.#listElements.forEach((list, i) => {
286
334
  if (this.#settings.avoidDuplicates && i) {
287
335
  list.setAttribute("aria-hidden", "true");
@@ -291,12 +339,24 @@ var Tabs = class _Tabs {
291
339
  }
292
340
  list.setAttribute("role", "tablist");
293
341
  });
342
+ saveAttributes(this.#tabElements, [
343
+ "aria-controls",
344
+ "id",
345
+ "role",
346
+ "tabindex"
347
+ ]);
294
348
  this.#tabElements.forEach((tab, i) => {
295
349
  const id = Math.random().toString(36).slice(-8);
296
350
  const panel = this.#panelElements[i % this.#panelElements.length];
297
351
  if (!panel) {
298
352
  return;
299
353
  }
354
+ if (i < this.#panelElements.length) {
355
+ saveAttributes(
356
+ [panel],
357
+ ["aria-controls", "aria-labelledby", "id", "role", "tabindex"]
358
+ );
359
+ }
300
360
  panel.id ||= `tabs-panel-${id}`;
301
361
  addTokenToAttribute(tab, "aria-controls", panel.id);
302
362
  if (!tab.hasAttribute("aria-selected")) {
@@ -338,7 +398,6 @@ var Tabs = class _Tabs {
338
398
  }
339
399
  #onTabClick = (event) => {
340
400
  event.preventDefault();
341
- event.stopPropagation();
342
401
  const tab = event.currentTarget;
343
402
  if (!(tab instanceof HTMLElement)) {
344
403
  return;
@@ -346,6 +405,10 @@ var Tabs = class _Tabs {
346
405
  this.activate(tab);
347
406
  };
348
407
  #onTabKeyDown = (event) => {
408
+ const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
409
+ if (altKey || ctrlKey || metaKey || shiftKey) {
410
+ return;
411
+ }
349
412
  const currentTab = event.currentTarget;
350
413
  if (!(currentTab instanceof HTMLElement)) {
351
414
  return;
@@ -356,7 +419,6 @@ var Tabs = class _Tabs {
356
419
  }
357
420
  const isBoth = list.ariaOrientation === "undefined";
358
421
  const isHorizontal = list.ariaOrientation !== "vertical";
359
- const { key } = event;
360
422
  if (![
361
423
  "Enter",
362
424
  " ",
@@ -367,8 +429,6 @@ var Tabs = class _Tabs {
367
429
  ].includes(key)) {
368
430
  return;
369
431
  }
370
- event.preventDefault();
371
- event.stopPropagation();
372
432
  const focusables = [
373
433
  ...list.querySelectorAll(this.#settings.selector.tab)
374
434
  ].filter(isFocusable);
@@ -376,6 +436,7 @@ var Tabs = class _Tabs {
376
436
  if (!(active instanceof HTMLElement)) {
377
437
  return;
378
438
  }
439
+ event.preventDefault();
379
440
  const currentIndex = focusables.indexOf(active);
380
441
  let newIndex = currentIndex;
381
442
  switch (key) {
@@ -532,13 +593,6 @@ var TabsIndicator = class {
532
593
  this.#listElement = null;
533
594
  }
534
595
  };
535
- function addTokenToAttribute(element, attribute, token) {
536
- const tokens = new Set(
537
- element.getAttribute(attribute)?.trim().split(/\s+/) ?? []
538
- );
539
- tokens.add(token);
540
- element.setAttribute(attribute, [...tokens].join(" "));
541
- }
542
596
  function createBinding(tabs, panel) {
543
597
  return { tabs, panel, animation: null };
544
598
  }
@@ -563,11 +617,24 @@ function isFocusable(element) {
563
617
  * Tabs
564
618
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
565
619
  *
566
- * @version 1.3.3
620
+ * @version 1.3.5
567
621
  * @author Yusuke Kamiyamane
568
622
  * @license MIT
569
623
  * @copyright Copyright (c) Yusuke Kamiyamane
570
624
  * @see {@link https://github.com/y14e/tabs}
571
625
  */
626
+ /*! Bundled license information:
627
+
628
+ @y14e/attributes-utils/dist/index.js:
629
+ (**
630
+ * Attributes Utils
631
+ *
632
+ * @version 1.0.0
633
+ * @author Yusuke Kamiyamane
634
+ * @license MIT
635
+ * @copyright Copyright (c) Yusuke Kamiyamane
636
+ * @see {@link https://github.com/y14e/attributes-utils}
637
+ *)
638
+ */
572
639
 
573
640
  module.exports = Tabs;
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 1.3.3
5
+ * @version 1.3.5
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -36,7 +36,7 @@ declare class Tabs {
36
36
  #private;
37
37
  static defaults: TabsOptions;
38
38
  constructor(root: HTMLElement, options?: TabsOptions);
39
- activate(tab: HTMLElement, isMatch?: boolean): Promise<void>;
39
+ activate(tab: HTMLElement, isMatch?: boolean): void;
40
40
  destroy(force?: boolean): Promise<void>;
41
41
  }
42
42
 
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 1.3.3
5
+ * @version 1.3.5
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -36,7 +36,7 @@ declare class Tabs {
36
36
  #private;
37
37
  static defaults: TabsOptions;
38
38
  constructor(root: HTMLElement, options?: TabsOptions);
39
- activate(tab: HTMLElement, isMatch?: boolean): Promise<void>;
39
+ activate(tab: HTMLElement, isMatch?: boolean): void;
40
40
  destroy(force?: boolean): Promise<void>;
41
41
  }
42
42
 
package/dist/index.js CHANGED
@@ -1,3 +1,41 @@
1
+ // node_modules/@y14e/attributes-utils/dist/index.js
2
+ function addTokenToAttribute(element, attribute, token) {
3
+ const tokens = new Set(
4
+ element.getAttribute(attribute)?.trim().split(/\s+/) ?? []
5
+ );
6
+ tokens.add(token);
7
+ element.setAttribute(attribute, [...tokens].join(" "));
8
+ }
9
+ var snapshots = /* @__PURE__ */ new WeakMap();
10
+ function restoreAttributes(elements) {
11
+ elements.forEach((element) => {
12
+ const snapshot = snapshots.get(element);
13
+ if (!snapshot) {
14
+ return;
15
+ }
16
+ for (const [attribute, value] of snapshot.entries()) {
17
+ if (value === null) {
18
+ element.removeAttribute(attribute);
19
+ } else {
20
+ element.setAttribute(attribute, value);
21
+ }
22
+ }
23
+ snapshots.delete(element);
24
+ });
25
+ }
26
+ function saveAttributes(elements, attributes) {
27
+ elements.forEach((element) => {
28
+ let snapshot = snapshots.get(element);
29
+ if (!snapshot) {
30
+ snapshot = /* @__PURE__ */ new Map();
31
+ snapshots.set(element, snapshot);
32
+ }
33
+ attributes.forEach((attribute) => {
34
+ snapshot.set(attribute, element.getAttribute(attribute));
35
+ });
36
+ });
37
+ }
38
+
1
39
  // src/index.ts
2
40
  var Tabs = class _Tabs {
3
41
  static defaults = {};
@@ -114,7 +152,7 @@ var Tabs = class _Tabs {
114
152
  });
115
153
  this.#initialize();
116
154
  }
117
- async activate(tab, isMatch = false) {
155
+ activate(tab, isMatch = false) {
118
156
  if (this.#isDestroyed) {
119
157
  return;
120
158
  }
@@ -272,6 +310,11 @@ var Tabs = class _Tabs {
272
310
  this.#onAnimationFinish();
273
311
  this.#animationController?.abort();
274
312
  this.#animationController = null;
313
+ restoreAttributes([
314
+ ...this.#listElements,
315
+ ...this.#tabElements,
316
+ ...this.#panelElements
317
+ ]);
275
318
  this.#listElements.length = 0;
276
319
  this.#tabElements.length = 0;
277
320
  this.#contentElement = null;
@@ -280,6 +323,11 @@ var Tabs = class _Tabs {
280
323
  }
281
324
  #initialize() {
282
325
  const { signal } = this.#eventController ?? new AbortController();
326
+ saveAttributes(this.#listElements, [
327
+ "aria-hidden",
328
+ "aria-orientation",
329
+ "role"
330
+ ]);
283
331
  this.#listElements.forEach((list, i) => {
284
332
  if (this.#settings.avoidDuplicates && i) {
285
333
  list.setAttribute("aria-hidden", "true");
@@ -289,12 +337,24 @@ var Tabs = class _Tabs {
289
337
  }
290
338
  list.setAttribute("role", "tablist");
291
339
  });
340
+ saveAttributes(this.#tabElements, [
341
+ "aria-controls",
342
+ "id",
343
+ "role",
344
+ "tabindex"
345
+ ]);
292
346
  this.#tabElements.forEach((tab, i) => {
293
347
  const id = Math.random().toString(36).slice(-8);
294
348
  const panel = this.#panelElements[i % this.#panelElements.length];
295
349
  if (!panel) {
296
350
  return;
297
351
  }
352
+ if (i < this.#panelElements.length) {
353
+ saveAttributes(
354
+ [panel],
355
+ ["aria-controls", "aria-labelledby", "id", "role", "tabindex"]
356
+ );
357
+ }
298
358
  panel.id ||= `tabs-panel-${id}`;
299
359
  addTokenToAttribute(tab, "aria-controls", panel.id);
300
360
  if (!tab.hasAttribute("aria-selected")) {
@@ -336,7 +396,6 @@ var Tabs = class _Tabs {
336
396
  }
337
397
  #onTabClick = (event) => {
338
398
  event.preventDefault();
339
- event.stopPropagation();
340
399
  const tab = event.currentTarget;
341
400
  if (!(tab instanceof HTMLElement)) {
342
401
  return;
@@ -344,6 +403,10 @@ var Tabs = class _Tabs {
344
403
  this.activate(tab);
345
404
  };
346
405
  #onTabKeyDown = (event) => {
406
+ const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
407
+ if (altKey || ctrlKey || metaKey || shiftKey) {
408
+ return;
409
+ }
347
410
  const currentTab = event.currentTarget;
348
411
  if (!(currentTab instanceof HTMLElement)) {
349
412
  return;
@@ -354,7 +417,6 @@ var Tabs = class _Tabs {
354
417
  }
355
418
  const isBoth = list.ariaOrientation === "undefined";
356
419
  const isHorizontal = list.ariaOrientation !== "vertical";
357
- const { key } = event;
358
420
  if (![
359
421
  "Enter",
360
422
  " ",
@@ -365,8 +427,6 @@ var Tabs = class _Tabs {
365
427
  ].includes(key)) {
366
428
  return;
367
429
  }
368
- event.preventDefault();
369
- event.stopPropagation();
370
430
  const focusables = [
371
431
  ...list.querySelectorAll(this.#settings.selector.tab)
372
432
  ].filter(isFocusable);
@@ -374,6 +434,7 @@ var Tabs = class _Tabs {
374
434
  if (!(active instanceof HTMLElement)) {
375
435
  return;
376
436
  }
437
+ event.preventDefault();
377
438
  const currentIndex = focusables.indexOf(active);
378
439
  let newIndex = currentIndex;
379
440
  switch (key) {
@@ -530,13 +591,6 @@ var TabsIndicator = class {
530
591
  this.#listElement = null;
531
592
  }
532
593
  };
533
- function addTokenToAttribute(element, attribute, token) {
534
- const tokens = new Set(
535
- element.getAttribute(attribute)?.trim().split(/\s+/) ?? []
536
- );
537
- tokens.add(token);
538
- element.setAttribute(attribute, [...tokens].join(" "));
539
- }
540
594
  function createBinding(tabs, panel) {
541
595
  return { tabs, panel, animation: null };
542
596
  }
@@ -561,11 +615,24 @@ function isFocusable(element) {
561
615
  * Tabs
562
616
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
563
617
  *
564
- * @version 1.3.3
618
+ * @version 1.3.5
565
619
  * @author Yusuke Kamiyamane
566
620
  * @license MIT
567
621
  * @copyright Copyright (c) Yusuke Kamiyamane
568
622
  * @see {@link https://github.com/y14e/tabs}
569
623
  */
624
+ /*! Bundled license information:
625
+
626
+ @y14e/attributes-utils/dist/index.js:
627
+ (**
628
+ * Attributes Utils
629
+ *
630
+ * @version 1.0.0
631
+ * @author Yusuke Kamiyamane
632
+ * @license MIT
633
+ * @copyright Copyright (c) Yusuke Kamiyamane
634
+ * @see {@link https://github.com/y14e/attributes-utils}
635
+ *)
636
+ */
570
637
 
571
638
  export { Tabs as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/tabs",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -42,9 +42,11 @@
42
42
  },
43
43
  "homepage": "https://github.com/y14e/tabs#readme",
44
44
  "devDependencies": {
45
+ "@y14e/attributes-utils": "^1.0.0",
45
46
  "bun-types": "latest",
46
47
  "tsup": "^8.0.0",
47
- "typescript": "^5.6.0"
48
+ "typescript": "^5.6.0",
49
+ "utility-types": "^3.11.0"
48
50
  },
49
51
  "engines": {
50
52
  "node": ">=18"