@relements/core 0.1.2 → 0.1.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.
@@ -4,19 +4,42 @@ import { enhanceTabs } from '../chunk-GMICGIQW.js';
4
4
  var ReTabsElement = class extends HTMLElement {
5
5
  /** @type {{ destroy: () => void } | null} */
6
6
  #controller = null;
7
+ /** @type {MutationObserver | null} */
8
+ #observer = null;
7
9
  static get observedAttributes() {
8
10
  return ["value"];
9
11
  }
10
12
  connectedCallback() {
11
13
  this.setAttribute("data-re-tabs", "");
12
- this.#controller = enhanceTabs(this);
13
- const initial = this.getAttribute("value");
14
- if (initial) this.#selectById(initial);
14
+ if (this.#hasTabs()) {
15
+ this.#enhance();
16
+ } else {
17
+ this.#observer = new MutationObserver(() => {
18
+ if (this.#hasTabs()) {
19
+ this.#observer?.disconnect();
20
+ this.#observer = null;
21
+ this.#enhance();
22
+ }
23
+ });
24
+ this.#observer.observe(this, { childList: true, subtree: true });
25
+ }
15
26
  }
16
27
  disconnectedCallback() {
28
+ this.#observer?.disconnect();
29
+ this.#observer = null;
17
30
  this.#controller?.destroy();
18
31
  this.#controller = null;
19
32
  }
33
+ /** @returns {boolean} */
34
+ #hasTabs() {
35
+ return !!this.querySelector('[role="tablist"] [role="tab"]');
36
+ }
37
+ #enhance() {
38
+ this.#controller?.destroy();
39
+ this.#controller = enhanceTabs(this);
40
+ const initial = this.getAttribute("value");
41
+ if (initial) this.#selectById(initial);
42
+ }
20
43
  /**
21
44
  * @param {string} name
22
45
  * @param {string | null} _oldValue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relements/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "HTML-first design system core: tokens, styles, and progressive enhancement.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,9 @@
25
25
  "type": "module",
26
26
  "sideEffects": [
27
27
  "**/*.css",
28
- "dist/**/*.css"
28
+ "dist/**/*.css",
29
+ "dist/elements/*.js",
30
+ "src/elements/*.js"
29
31
  ],
30
32
  "files": [
31
33
  "dist",
@@ -25,6 +25,8 @@ import { enhanceTabs } from "../behaviors/tabs.js";
25
25
  export class ReTabsElement extends HTMLElement {
26
26
  /** @type {{ destroy: () => void } | null} */
27
27
  #controller = null;
28
+ /** @type {MutationObserver | null} */
29
+ #observer = null;
28
30
 
29
31
  static get observedAttributes() {
30
32
  return ["value"];
@@ -33,17 +35,44 @@ export class ReTabsElement extends HTMLElement {
33
35
  connectedCallback() {
34
36
  // Mark the host so enhanceTabs picks it up.
35
37
  this.setAttribute("data-re-tabs", "");
36
- this.#controller = enhanceTabs(this);
37
- // Honor a value attribute if present and different from initial state.
38
- const initial = this.getAttribute("value");
39
- if (initial) this.#selectById(initial);
38
+ if (this.#hasTabs()) {
39
+ this.#enhance();
40
+ } else {
41
+ // Some frameworks (e.g. Angular) connect the host before projecting its
42
+ // children. Enhance once the tabs appear, then stop observing.
43
+ this.#observer = new MutationObserver(() => {
44
+ if (this.#hasTabs()) {
45
+ this.#observer?.disconnect();
46
+ this.#observer = null;
47
+ this.#enhance();
48
+ }
49
+ });
50
+ this.#observer.observe(this, { childList: true, subtree: true });
51
+ }
40
52
  }
41
53
 
42
54
  disconnectedCallback() {
55
+ this.#observer?.disconnect();
56
+ this.#observer = null;
43
57
  this.#controller?.destroy();
44
58
  this.#controller = null;
45
59
  }
46
60
 
61
+ /** @returns {boolean} */
62
+ #hasTabs() {
63
+ return !!this.querySelector('[role="tablist"] [role="tab"]');
64
+ }
65
+
66
+ #enhance() {
67
+ // Idempotent: tear down any prior controller first so a reconnected or
68
+ // moved host (with children already present) does not double-wire listeners.
69
+ this.#controller?.destroy();
70
+ this.#controller = enhanceTabs(this);
71
+ // Honor a value attribute if present and different from initial state.
72
+ const initial = this.getAttribute("value");
73
+ if (initial) this.#selectById(initial);
74
+ }
75
+
47
76
  /**
48
77
  * @param {string} name
49
78
  * @param {string | null} _oldValue