@dogsbay/elements 0.2.0-beta.0

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 (42) hide show
  1. package/dist/base-BtvRtAsC.d.ts +20 -0
  2. package/dist/chunk-5T4OXQA2.js +24 -0
  3. package/dist/chunk-5T4OXQA2.js.map +1 -0
  4. package/dist/chunk-7BIVQSGP.js +52 -0
  5. package/dist/chunk-7BIVQSGP.js.map +1 -0
  6. package/dist/chunk-7M7SFLKN.js +95 -0
  7. package/dist/chunk-7M7SFLKN.js.map +1 -0
  8. package/dist/chunk-FWAAU5UY.js +89 -0
  9. package/dist/chunk-FWAAU5UY.js.map +1 -0
  10. package/dist/chunk-LFXZQ4YV.js +37 -0
  11. package/dist/chunk-LFXZQ4YV.js.map +1 -0
  12. package/dist/chunk-LVXR7KTB.js +161 -0
  13. package/dist/chunk-LVXR7KTB.js.map +1 -0
  14. package/dist/chunk-TTNTPXBA.js +46 -0
  15. package/dist/chunk-TTNTPXBA.js.map +1 -0
  16. package/dist/chunk-XBMLE4N3.js +28 -0
  17. package/dist/chunk-XBMLE4N3.js.map +1 -0
  18. package/dist/db-accordion.d.ts +28 -0
  19. package/dist/db-accordion.js +8 -0
  20. package/dist/db-accordion.js.map +1 -0
  21. package/dist/db-card.d.ts +30 -0
  22. package/dist/db-card.js +8 -0
  23. package/dist/db-card.js.map +1 -0
  24. package/dist/db-code-block.d.ts +35 -0
  25. package/dist/db-code-block.js +8 -0
  26. package/dist/db-code-block.js.map +1 -0
  27. package/dist/db-collapsible.d.ts +22 -0
  28. package/dist/db-collapsible.js +8 -0
  29. package/dist/db-collapsible.js.map +1 -0
  30. package/dist/db-link-button.d.ts +24 -0
  31. package/dist/db-link-button.js +8 -0
  32. package/dist/db-link-button.js.map +1 -0
  33. package/dist/db-steps.d.ts +19 -0
  34. package/dist/db-steps.js +8 -0
  35. package/dist/db-steps.js.map +1 -0
  36. package/dist/db-tabs.d.ts +36 -0
  37. package/dist/db-tabs.js +8 -0
  38. package/dist/db-tabs.js.map +1 -0
  39. package/dist/index.d.ts +8 -0
  40. package/dist/index.js +35 -0
  41. package/dist/index.js.map +1 -0
  42. package/package.json +70 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Base class for Dogsbay custom elements.
3
+ *
4
+ * Handles the connect/disconnect lifecycle and ensures one-time setup
5
+ * runs only once even when Obsidian's virtual scrolling removes and
6
+ * re-adds elements to the DOM.
7
+ */
8
+ declare abstract class DogsbayElement extends HTMLElement {
9
+ private _initialized;
10
+ connectedCallback(): void;
11
+ disconnectedCallback(): void;
12
+ /** One-time setup: query children, generate IDs, set ARIA. */
13
+ protected setup(): void;
14
+ /** Called on every connect: attach event listeners. */
15
+ protected connect(): void;
16
+ /** Called on every disconnect: remove event listeners. */
17
+ protected disconnect(): void;
18
+ }
19
+
20
+ export { DogsbayElement as D };
@@ -0,0 +1,24 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-steps.ts
6
+ var DbSteps = class extends DogsbayElement {
7
+ setup() {
8
+ this.setAttribute("role", "list");
9
+ const items = this.querySelectorAll(
10
+ ":scope > [data-part='item']"
11
+ );
12
+ for (const item of items) {
13
+ item.setAttribute("role", "listitem");
14
+ }
15
+ }
16
+ };
17
+ if (!customElements.get("db-steps")) {
18
+ customElements.define("db-steps", DbSteps);
19
+ }
20
+
21
+ export {
22
+ DbSteps
23
+ };
24
+ //# sourceMappingURL=chunk-5T4OXQA2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-steps.ts"],"sourcesContent":["import { DogsbayElement } from \"./base.js\";\n\n/**\n * `<db-steps>` — Accessible step-by-step list.\n *\n * A read-only component that renders numbered steps with ARIA semantics.\n * Visual styling (numbered circles, connector lines) is handled by CSS\n * using counter(step), matching the Astro Steps component.\n *\n * Children:\n * [data-part=\"item\"] — step items\n * [data-part=\"title\"] — step title (inside item, optional)\n * [data-part=\"content\"] — step content (inside item, optional)\n */\nexport class DbSteps extends DogsbayElement {\n protected setup() {\n this.setAttribute(\"role\", \"list\");\n\n const items = this.querySelectorAll(\n \":scope > [data-part='item']\",\n ) as NodeListOf<HTMLElement>;\n\n for (const item of items) {\n item.setAttribute(\"role\", \"listitem\");\n }\n }\n}\n\nif (!customElements.get(\"db-steps\")) {\n customElements.define(\"db-steps\", DbSteps);\n}\n"],"mappings":";;;;;AAcO,IAAM,UAAN,cAAsB,eAAe;AAAA,EAChC,QAAQ;AAChB,SAAK,aAAa,QAAQ,MAAM;AAEhC,UAAM,QAAQ,KAAK;AAAA,MACjB;AAAA,IACF;AAEA,eAAW,QAAQ,OAAO;AACxB,WAAK,aAAa,QAAQ,UAAU;AAAA,IACtC;AAAA,EACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,UAAU,GAAG;AACnC,iBAAe,OAAO,YAAY,OAAO;AAC3C;","names":[]}
@@ -0,0 +1,52 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-card.ts
6
+ var DbCard = class extends DogsbayElement {
7
+ href = null;
8
+ handleClick = () => {
9
+ if (this.href) this.navigate();
10
+ };
11
+ handleKeydown = (e) => {
12
+ if (!this.href) return;
13
+ if (e.key === "Enter" || e.key === " ") {
14
+ e.preventDefault();
15
+ this.navigate();
16
+ }
17
+ };
18
+ setup() {
19
+ this.href = this.getAttribute("href");
20
+ if (this.href) {
21
+ this.setAttribute("role", "link");
22
+ this.setAttribute("tabindex", "0");
23
+ this.setAttribute("data-interactive", "");
24
+ }
25
+ }
26
+ connect() {
27
+ if (this.href) {
28
+ this.addEventListener("click", this.handleClick);
29
+ this.addEventListener("keydown", this.handleKeydown);
30
+ }
31
+ }
32
+ disconnect() {
33
+ this.removeEventListener("click", this.handleClick);
34
+ this.removeEventListener("keydown", this.handleKeydown);
35
+ }
36
+ navigate() {
37
+ this.dispatchEvent(
38
+ new CustomEvent("db-card:navigate", {
39
+ detail: { href: this.href },
40
+ bubbles: true
41
+ })
42
+ );
43
+ }
44
+ };
45
+ if (!customElements.get("db-card")) {
46
+ customElements.define("db-card", DbCard);
47
+ }
48
+
49
+ export {
50
+ DbCard
51
+ };
52
+ //# sourceMappingURL=chunk-7BIVQSGP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-card.ts"],"sourcesContent":["import { DogsbayElement } from \"./base.js\";\n\n/**\n * `<db-card>` — Accessible content card with optional link behavior.\n *\n * Attributes:\n * href — if present, the card is clickable and navigates on click/Enter/Space\n *\n * Children:\n * [data-part=\"icon\"] — icon (optional)\n * [data-part=\"title\"] — card title (optional)\n * [data-part=\"description\"] — card description (optional)\n * [data-part=\"content\"] — card body content (optional)\n *\n * Events:\n * db-card:navigate — fired when a linked card is activated, detail: { href }\n * The host environment (Obsidian plugin or Astro) handles\n * actual navigation by listening for this event.\n */\nexport class DbCard extends DogsbayElement {\n private href: string | null = null;\n\n private handleClick = () => {\n if (this.href) this.navigate();\n };\n\n private handleKeydown = (e: KeyboardEvent) => {\n if (!this.href) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n this.navigate();\n }\n };\n\n protected setup() {\n this.href = this.getAttribute(\"href\");\n\n if (this.href) {\n this.setAttribute(\"role\", \"link\");\n this.setAttribute(\"tabindex\", \"0\");\n this.setAttribute(\"data-interactive\", \"\");\n }\n }\n\n protected connect() {\n if (this.href) {\n this.addEventListener(\"click\", this.handleClick);\n this.addEventListener(\"keydown\", this.handleKeydown as EventListener);\n }\n }\n\n protected disconnect() {\n this.removeEventListener(\"click\", this.handleClick);\n this.removeEventListener(\"keydown\", this.handleKeydown as EventListener);\n }\n\n private navigate() {\n this.dispatchEvent(\n new CustomEvent(\"db-card:navigate\", {\n detail: { href: this.href },\n bubbles: true,\n }),\n );\n }\n}\n\nif (!customElements.get(\"db-card\")) {\n customElements.define(\"db-card\", DbCard);\n}\n"],"mappings":";;;;;AAmBO,IAAM,SAAN,cAAqB,eAAe;AAAA,EACjC,OAAsB;AAAA,EAEtB,cAAc,MAAM;AAC1B,QAAI,KAAK,KAAM,MAAK,SAAS;AAAA,EAC/B;AAAA,EAEQ,gBAAgB,CAAC,MAAqB;AAC5C,QAAI,CAAC,KAAK,KAAM;AAChB,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,QAAE,eAAe;AACjB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEU,QAAQ;AAChB,SAAK,OAAO,KAAK,aAAa,MAAM;AAEpC,QAAI,KAAK,MAAM;AACb,WAAK,aAAa,QAAQ,MAAM;AAChC,WAAK,aAAa,YAAY,GAAG;AACjC,WAAK,aAAa,oBAAoB,EAAE;AAAA,IAC1C;AAAA,EACF;AAAA,EAEU,UAAU;AAClB,QAAI,KAAK,MAAM;AACb,WAAK,iBAAiB,SAAS,KAAK,WAAW;AAC/C,WAAK,iBAAiB,WAAW,KAAK,aAA8B;AAAA,IACtE;AAAA,EACF;AAAA,EAEU,aAAa;AACrB,SAAK,oBAAoB,SAAS,KAAK,WAAW;AAClD,SAAK,oBAAoB,WAAW,KAAK,aAA8B;AAAA,EACzE;AAAA,EAEQ,WAAW;AACjB,SAAK;AAAA,MACH,IAAI,YAAY,oBAAoB;AAAA,QAClC,QAAQ,EAAE,MAAM,KAAK,KAAK;AAAA,QAC1B,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,SAAS,GAAG;AAClC,iBAAe,OAAO,WAAW,MAAM;AACzC;","names":[]}
@@ -0,0 +1,95 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-accordion.ts
6
+ import { CompositeNavigation } from "@dogsbay/primitives/composite";
7
+ import { Collapsible } from "@dogsbay/primitives/collapsible";
8
+ var DbAccordion = class extends DogsbayElement {
9
+ items = [];
10
+ nav = null;
11
+ openValues = /* @__PURE__ */ new Set();
12
+ type = "single";
13
+ setup() {
14
+ this.type = this.getAttribute("type") || "single";
15
+ const defaultStr = this.getAttribute("default-value") || "";
16
+ const defaultValues = defaultStr ? defaultStr.split(",") : [];
17
+ const itemEls = Array.from(
18
+ this.querySelectorAll("[data-part='item']")
19
+ );
20
+ this.items = itemEls.map((el) => {
21
+ const trigger = el.querySelector("[data-part='trigger']");
22
+ const content = el.querySelector("[data-part='content']");
23
+ if (!trigger || !content) return null;
24
+ const value = el.dataset.value || "";
25
+ const disabled = el.hasAttribute("data-disabled");
26
+ if (disabled) {
27
+ trigger.setAttribute("disabled", "");
28
+ trigger.setAttribute("aria-disabled", "true");
29
+ }
30
+ const collapsible = new Collapsible(trigger, content, {
31
+ onToggle: (open) => {
32
+ if (open) {
33
+ this.onItemExpanded(value);
34
+ } else {
35
+ this.onItemCollapsed(value);
36
+ }
37
+ }
38
+ });
39
+ return { el, value, collapsible, disabled };
40
+ }).filter(Boolean);
41
+ this.nav = new CompositeNavigation(this, "[data-part='trigger']", {
42
+ orientation: "vertical",
43
+ loop: true,
44
+ homeEnd: true
45
+ });
46
+ this.nav.activate();
47
+ this.items.forEach((item, i) => {
48
+ item.collapsible.trigger.setAttribute("tabindex", i === 0 ? "0" : "-1");
49
+ });
50
+ defaultValues.forEach((value) => {
51
+ const item = this.items.find((i) => i.value === value && !i.disabled);
52
+ if (item) {
53
+ item.collapsible.expand();
54
+ }
55
+ });
56
+ }
57
+ onItemExpanded(value) {
58
+ if (this.type === "single") {
59
+ for (const openValue of this.openValues) {
60
+ if (openValue !== value) {
61
+ const other = this.items.find((i) => i.value === openValue);
62
+ if (other) other.collapsible.collapse();
63
+ }
64
+ }
65
+ }
66
+ this.openValues.add(value);
67
+ const item = this.items.find((i) => i.value === value);
68
+ if (item) item.el.setAttribute("data-state", "open");
69
+ this.dispatchEvent(
70
+ new CustomEvent("db-accordion:change", {
71
+ detail: { value, open: true, openValues: [...this.openValues] },
72
+ bubbles: true
73
+ })
74
+ );
75
+ }
76
+ onItemCollapsed(value) {
77
+ this.openValues.delete(value);
78
+ const item = this.items.find((i) => i.value === value);
79
+ if (item) item.el.removeAttribute("data-state");
80
+ this.dispatchEvent(
81
+ new CustomEvent("db-accordion:change", {
82
+ detail: { value, open: false, openValues: [...this.openValues] },
83
+ bubbles: true
84
+ })
85
+ );
86
+ }
87
+ };
88
+ if (!customElements.get("db-accordion")) {
89
+ customElements.define("db-accordion", DbAccordion);
90
+ }
91
+
92
+ export {
93
+ DbAccordion
94
+ };
95
+ //# sourceMappingURL=chunk-7M7SFLKN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-accordion.ts"],"sourcesContent":["import { CompositeNavigation } from \"@dogsbay/primitives/composite\";\nimport { Collapsible } from \"@dogsbay/primitives/collapsible\";\nimport { DogsbayElement } from \"./base.js\";\n\ninterface AccordionItem {\n el: HTMLElement;\n value: string;\n collapsible: Collapsible;\n disabled: boolean;\n}\n\n/**\n * `<db-accordion>` — Accessible accordion with single/multiple mode.\n *\n * Attributes:\n * type — \"single\" (default) or \"multiple\"\n * default-value — comma-separated values to open initially\n *\n * Children:\n * [data-part=\"item\"] with data-value — accordion items\n * [data-part=\"trigger\"] — toggle button (inside item)\n * [data-part=\"content\"] — collapsible panel (inside item)\n *\n * Events:\n * db-accordion:change — detail: { value, open, openValues }\n */\nexport class DbAccordion extends DogsbayElement {\n private items: AccordionItem[] = [];\n private nav: CompositeNavigation | null = null;\n private openValues = new Set<string>();\n private type: \"single\" | \"multiple\" = \"single\";\n\n protected setup() {\n this.type =\n (this.getAttribute(\"type\") as \"single\" | \"multiple\") || \"single\";\n const defaultStr = this.getAttribute(\"default-value\") || \"\";\n const defaultValues = defaultStr ? defaultStr.split(\",\") : [];\n\n const itemEls = Array.from(\n this.querySelectorAll(\"[data-part='item']\"),\n ) as HTMLElement[];\n\n this.items = itemEls\n .map((el) => {\n const trigger = el.querySelector<HTMLElement>(\"[data-part='trigger']\");\n const content = el.querySelector<HTMLElement>(\"[data-part='content']\");\n if (!trigger || !content) return null;\n\n const value = el.dataset.value || \"\";\n const disabled = el.hasAttribute(\"data-disabled\");\n\n if (disabled) {\n trigger.setAttribute(\"disabled\", \"\");\n trigger.setAttribute(\"aria-disabled\", \"true\");\n }\n\n const collapsible = new Collapsible(trigger, content, {\n onToggle: (open) => {\n if (open) {\n this.onItemExpanded(value);\n } else {\n this.onItemCollapsed(value);\n }\n },\n });\n\n return { el, value, collapsible, disabled };\n })\n .filter(Boolean) as AccordionItem[];\n\n // Keyboard navigation on triggers\n this.nav = new CompositeNavigation(this, \"[data-part='trigger']\", {\n orientation: \"vertical\",\n loop: true,\n homeEnd: true,\n });\n\n this.nav.activate();\n\n // Set initial tabindex for roving\n this.items.forEach((item, i) => {\n item.collapsible.trigger.setAttribute(\"tabindex\", i === 0 ? \"0\" : \"-1\");\n });\n\n // Set initial open state\n defaultValues.forEach((value) => {\n const item = this.items.find((i) => i.value === value && !i.disabled);\n if (item) {\n item.collapsible.expand();\n }\n });\n }\n\n private onItemExpanded(value: string) {\n // In single mode, collapse all others\n if (this.type === \"single\") {\n for (const openValue of this.openValues) {\n if (openValue !== value) {\n const other = this.items.find((i) => i.value === openValue);\n if (other) other.collapsible.collapse();\n }\n }\n }\n\n this.openValues.add(value);\n const item = this.items.find((i) => i.value === value);\n if (item) item.el.setAttribute(\"data-state\", \"open\");\n\n this.dispatchEvent(\n new CustomEvent(\"db-accordion:change\", {\n detail: { value, open: true, openValues: [...this.openValues] },\n bubbles: true,\n }),\n );\n }\n\n private onItemCollapsed(value: string) {\n this.openValues.delete(value);\n const item = this.items.find((i) => i.value === value);\n if (item) item.el.removeAttribute(\"data-state\");\n\n this.dispatchEvent(\n new CustomEvent(\"db-accordion:change\", {\n detail: { value, open: false, openValues: [...this.openValues] },\n bubbles: true,\n }),\n );\n }\n}\n\nif (!customElements.get(\"db-accordion\")) {\n customElements.define(\"db-accordion\", DbAccordion);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,89 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-code-block.ts
6
+ var DbCodeBlock = class extends DogsbayElement {
7
+ copyBtn = null;
8
+ copyIcon = null;
9
+ checkIcon = null;
10
+ liveRegion = null;
11
+ resetTimeout = null;
12
+ handleCopy = async () => {
13
+ const text = this.getCopyText();
14
+ if (!text) return;
15
+ try {
16
+ await navigator.clipboard.writeText(text);
17
+ this.showCopiedFeedback();
18
+ this.dispatchEvent(
19
+ new CustomEvent("db-code-block:copied", {
20
+ detail: { text },
21
+ bubbles: true
22
+ })
23
+ );
24
+ } catch {
25
+ }
26
+ };
27
+ setup() {
28
+ this.copyBtn = this.querySelector("[data-part='copy']");
29
+ this.copyIcon = this.querySelector("[data-part='copy-icon']");
30
+ this.checkIcon = this.querySelector("[data-part='check-icon']");
31
+ if (this.copyBtn && !this.copyBtn.hasAttribute("aria-label")) {
32
+ this.copyBtn.setAttribute("aria-label", "Copy code");
33
+ }
34
+ this.liveRegion = document.createElement("span");
35
+ this.liveRegion.setAttribute("aria-live", "polite");
36
+ this.liveRegion.setAttribute("role", "status");
37
+ this.liveRegion.className = "sr-only";
38
+ this.liveRegion.style.position = "absolute";
39
+ this.liveRegion.style.width = "1px";
40
+ this.liveRegion.style.height = "1px";
41
+ this.liveRegion.style.overflow = "hidden";
42
+ this.liveRegion.style.clip = "rect(0, 0, 0, 0)";
43
+ this.liveRegion.style.whiteSpace = "nowrap";
44
+ this.appendChild(this.liveRegion);
45
+ }
46
+ connect() {
47
+ this.copyBtn?.addEventListener("click", this.handleCopy);
48
+ }
49
+ disconnect() {
50
+ this.copyBtn?.removeEventListener("click", this.handleCopy);
51
+ this.clearResetTimeout();
52
+ }
53
+ getCopyText() {
54
+ const attrText = this.getAttribute("data-copy-text");
55
+ if (attrText) return attrText;
56
+ const codeEl = this.querySelector("[data-part='code'] code");
57
+ if (codeEl) return codeEl.textContent ?? "";
58
+ const codeContainer = this.querySelector("[data-part='code']");
59
+ return codeContainer?.textContent ?? "";
60
+ }
61
+ showCopiedFeedback() {
62
+ this.clearResetTimeout();
63
+ if (this.copyIcon) this.copyIcon.hidden = true;
64
+ if (this.checkIcon) this.checkIcon.hidden = false;
65
+ this.setAttribute("data-state", "copied");
66
+ if (this.liveRegion) this.liveRegion.textContent = "Copied!";
67
+ this.resetTimeout = setTimeout(() => {
68
+ if (this.copyIcon) this.copyIcon.hidden = false;
69
+ if (this.checkIcon) this.checkIcon.hidden = true;
70
+ this.removeAttribute("data-state");
71
+ if (this.liveRegion) this.liveRegion.textContent = "";
72
+ this.resetTimeout = null;
73
+ }, 2e3);
74
+ }
75
+ clearResetTimeout() {
76
+ if (this.resetTimeout !== null) {
77
+ clearTimeout(this.resetTimeout);
78
+ this.resetTimeout = null;
79
+ }
80
+ }
81
+ };
82
+ if (!customElements.get("db-code-block")) {
83
+ customElements.define("db-code-block", DbCodeBlock);
84
+ }
85
+
86
+ export {
87
+ DbCodeBlock
88
+ };
89
+ //# sourceMappingURL=chunk-FWAAU5UY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-code-block.ts"],"sourcesContent":["import { DogsbayElement } from \"./base.js\";\n\n/**\n * `<db-code-block>` — Code block with copy-to-clipboard.\n *\n * Attributes:\n * data-copy-text — raw code text to copy (preferred over parsing DOM)\n *\n * Children:\n * [data-part=\"header\"] — header bar (optional)\n * [data-part=\"label\"] — title/language label (inside header, optional)\n * [data-part=\"copy\"] — copy button\n * [data-part=\"copy-icon\"] — copy icon SVG (inside copy button)\n * [data-part=\"check-icon\"] — check icon SVG (inside copy button, starts hidden)\n * [data-part=\"code\"] — code content container\n *\n * Events:\n * db-code-block:copied — fired after successful copy, detail: { text }\n */\nexport class DbCodeBlock extends DogsbayElement {\n private copyBtn: HTMLElement | null = null;\n private copyIcon: HTMLElement | null = null;\n private checkIcon: HTMLElement | null = null;\n private liveRegion: HTMLElement | null = null;\n private resetTimeout: ReturnType<typeof setTimeout> | null = null;\n\n private handleCopy = async () => {\n const text = this.getCopyText();\n if (!text) return;\n\n try {\n await navigator.clipboard.writeText(text);\n this.showCopiedFeedback();\n\n this.dispatchEvent(\n new CustomEvent(\"db-code-block:copied\", {\n detail: { text },\n bubbles: true,\n }),\n );\n } catch {\n // Clipboard API unavailable or denied — fail silently\n }\n };\n\n protected setup() {\n this.copyBtn = this.querySelector(\"[data-part='copy']\");\n this.copyIcon = this.querySelector(\"[data-part='copy-icon']\");\n this.checkIcon = this.querySelector(\"[data-part='check-icon']\");\n\n // Ensure copy button has accessible label\n if (this.copyBtn && !this.copyBtn.hasAttribute(\"aria-label\")) {\n this.copyBtn.setAttribute(\"aria-label\", \"Copy code\");\n }\n\n // Create aria-live region for screen reader announcements\n this.liveRegion = document.createElement(\"span\");\n this.liveRegion.setAttribute(\"aria-live\", \"polite\");\n this.liveRegion.setAttribute(\"role\", \"status\");\n this.liveRegion.className = \"sr-only\";\n this.liveRegion.style.position = \"absolute\";\n this.liveRegion.style.width = \"1px\";\n this.liveRegion.style.height = \"1px\";\n this.liveRegion.style.overflow = \"hidden\";\n this.liveRegion.style.clip = \"rect(0, 0, 0, 0)\";\n this.liveRegion.style.whiteSpace = \"nowrap\";\n this.appendChild(this.liveRegion);\n }\n\n protected connect() {\n this.copyBtn?.addEventListener(\"click\", this.handleCopy);\n }\n\n protected disconnect() {\n this.copyBtn?.removeEventListener(\"click\", this.handleCopy);\n this.clearResetTimeout();\n }\n\n private getCopyText(): string {\n // Prefer explicit attribute (set by the processor with raw code)\n const attrText = this.getAttribute(\"data-copy-text\");\n if (attrText) return attrText;\n\n // Fallback: extract text from the code container\n const codeEl = this.querySelector(\"[data-part='code'] code\") as HTMLElement | null;\n if (codeEl) return codeEl.textContent ?? \"\";\n\n const codeContainer = this.querySelector(\"[data-part='code']\") as HTMLElement | null;\n return codeContainer?.textContent ?? \"\";\n }\n\n private showCopiedFeedback() {\n this.clearResetTimeout();\n\n // Swap icons\n if (this.copyIcon) this.copyIcon.hidden = true;\n if (this.checkIcon) this.checkIcon.hidden = false;\n\n // Visual state\n this.setAttribute(\"data-state\", \"copied\");\n\n // Screen reader announcement\n if (this.liveRegion) this.liveRegion.textContent = \"Copied!\";\n\n // Revert after 2 seconds\n this.resetTimeout = setTimeout(() => {\n if (this.copyIcon) this.copyIcon.hidden = false;\n if (this.checkIcon) this.checkIcon.hidden = true;\n this.removeAttribute(\"data-state\");\n if (this.liveRegion) this.liveRegion.textContent = \"\";\n this.resetTimeout = null;\n }, 2000);\n }\n\n private clearResetTimeout() {\n if (this.resetTimeout !== null) {\n clearTimeout(this.resetTimeout);\n this.resetTimeout = null;\n }\n }\n}\n\nif (!customElements.get(\"db-code-block\")) {\n customElements.define(\"db-code-block\", DbCodeBlock);\n}\n"],"mappings":";;;;;AAmBO,IAAM,cAAN,cAA0B,eAAe;AAAA,EACtC,UAA8B;AAAA,EAC9B,WAA+B;AAAA,EAC/B,YAAgC;AAAA,EAChC,aAAiC;AAAA,EACjC,eAAqD;AAAA,EAErD,aAAa,YAAY;AAC/B,UAAM,OAAO,KAAK,YAAY;AAC9B,QAAI,CAAC,KAAM;AAEX,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,IAAI;AACxC,WAAK,mBAAmB;AAExB,WAAK;AAAA,QACH,IAAI,YAAY,wBAAwB;AAAA,UACtC,QAAQ,EAAE,KAAK;AAAA,UACf,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEU,QAAQ;AAChB,SAAK,UAAU,KAAK,cAAc,oBAAoB;AACtD,SAAK,WAAW,KAAK,cAAc,yBAAyB;AAC5D,SAAK,YAAY,KAAK,cAAc,0BAA0B;AAG9D,QAAI,KAAK,WAAW,CAAC,KAAK,QAAQ,aAAa,YAAY,GAAG;AAC5D,WAAK,QAAQ,aAAa,cAAc,WAAW;AAAA,IACrD;AAGA,SAAK,aAAa,SAAS,cAAc,MAAM;AAC/C,SAAK,WAAW,aAAa,aAAa,QAAQ;AAClD,SAAK,WAAW,aAAa,QAAQ,QAAQ;AAC7C,SAAK,WAAW,YAAY;AAC5B,SAAK,WAAW,MAAM,WAAW;AACjC,SAAK,WAAW,MAAM,QAAQ;AAC9B,SAAK,WAAW,MAAM,SAAS;AAC/B,SAAK,WAAW,MAAM,WAAW;AACjC,SAAK,WAAW,MAAM,OAAO;AAC7B,SAAK,WAAW,MAAM,aAAa;AACnC,SAAK,YAAY,KAAK,UAAU;AAAA,EAClC;AAAA,EAEU,UAAU;AAClB,SAAK,SAAS,iBAAiB,SAAS,KAAK,UAAU;AAAA,EACzD;AAAA,EAEU,aAAa;AACrB,SAAK,SAAS,oBAAoB,SAAS,KAAK,UAAU;AAC1D,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEQ,cAAsB;AAE5B,UAAM,WAAW,KAAK,aAAa,gBAAgB;AACnD,QAAI,SAAU,QAAO;AAGrB,UAAM,SAAS,KAAK,cAAc,yBAAyB;AAC3D,QAAI,OAAQ,QAAO,OAAO,eAAe;AAEzC,UAAM,gBAAgB,KAAK,cAAc,oBAAoB;AAC7D,WAAO,eAAe,eAAe;AAAA,EACvC;AAAA,EAEQ,qBAAqB;AAC3B,SAAK,kBAAkB;AAGvB,QAAI,KAAK,SAAU,MAAK,SAAS,SAAS;AAC1C,QAAI,KAAK,UAAW,MAAK,UAAU,SAAS;AAG5C,SAAK,aAAa,cAAc,QAAQ;AAGxC,QAAI,KAAK,WAAY,MAAK,WAAW,cAAc;AAGnD,SAAK,eAAe,WAAW,MAAM;AACnC,UAAI,KAAK,SAAU,MAAK,SAAS,SAAS;AAC1C,UAAI,KAAK,UAAW,MAAK,UAAU,SAAS;AAC5C,WAAK,gBAAgB,YAAY;AACjC,UAAI,KAAK,WAAY,MAAK,WAAW,cAAc;AACnD,WAAK,eAAe;AAAA,IACtB,GAAG,GAAI;AAAA,EACT;AAAA,EAEQ,oBAAoB;AAC1B,QAAI,KAAK,iBAAiB,MAAM;AAC9B,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,eAAe,GAAG;AACxC,iBAAe,OAAO,iBAAiB,WAAW;AACpD;","names":[]}
@@ -0,0 +1,37 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-link-button.ts
6
+ var DbLinkButton = class extends DogsbayElement {
7
+ anchor = null;
8
+ setup() {
9
+ const href = this.getAttribute("href") || "#";
10
+ const variant = this.getAttribute("variant") || "primary";
11
+ const text = this.textContent?.trim() || href;
12
+ this.anchor = document.createElement("a");
13
+ this.anchor.href = href;
14
+ this.anchor.textContent = text;
15
+ this.anchor.className = "db-link-button-anchor";
16
+ this.anchor.dataset.variant = variant;
17
+ if (href.startsWith("http")) {
18
+ this.anchor.target = "_blank";
19
+ this.anchor.rel = "noopener noreferrer";
20
+ const icon = document.createElement("span");
21
+ icon.className = "db-link-button-icon";
22
+ icon.setAttribute("aria-hidden", "true");
23
+ icon.textContent = "\u2197";
24
+ this.anchor.appendChild(icon);
25
+ }
26
+ this.textContent = "";
27
+ this.appendChild(this.anchor);
28
+ }
29
+ };
30
+ if (!customElements.get("db-link-button")) {
31
+ customElements.define("db-link-button", DbLinkButton);
32
+ }
33
+
34
+ export {
35
+ DbLinkButton
36
+ };
37
+ //# sourceMappingURL=chunk-LFXZQ4YV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-link-button.ts"],"sourcesContent":["import { DogsbayElement } from \"./base.js\";\n\n/**\n * `<db-link-button>` — Styled link that looks like a button.\n *\n * Attributes:\n * href — target URL (required)\n * variant — \"primary\" | \"secondary\" | \"outline\" (default: \"primary\")\n *\n * Light DOM: renders as an <a> tag with button styling.\n * Works in both Astro (matches Button component) and Obsidian.\n *\n * In Astro, the format-astro serializer maps link-button TreeNode to\n * the Button.astro component with href prop.\n *\n * In Obsidian, the plugin emits <db-link-button> which this element\n * auto-upgrades with styling and keyboard navigation.\n */\nexport class DbLinkButton extends DogsbayElement {\n private anchor: HTMLAnchorElement | null = null;\n\n protected setup() {\n const href = this.getAttribute(\"href\") || \"#\";\n const variant = this.getAttribute(\"variant\") || \"primary\";\n const text = this.textContent?.trim() || href;\n\n // Create the anchor element\n this.anchor = document.createElement(\"a\");\n this.anchor.href = href;\n this.anchor.textContent = text;\n this.anchor.className = \"db-link-button-anchor\";\n this.anchor.dataset.variant = variant;\n\n // External links open in new tab\n if (href.startsWith(\"http\")) {\n this.anchor.target = \"_blank\";\n this.anchor.rel = \"noopener noreferrer\";\n\n // Add external icon\n const icon = document.createElement(\"span\");\n icon.className = \"db-link-button-icon\";\n icon.setAttribute(\"aria-hidden\", \"true\");\n icon.textContent = \"↗\";\n this.anchor.appendChild(icon);\n }\n\n this.textContent = \"\";\n this.appendChild(this.anchor);\n }\n}\n\nif (!customElements.get(\"db-link-button\")) {\n customElements.define(\"db-link-button\", DbLinkButton);\n}\n"],"mappings":";;;;;AAkBO,IAAM,eAAN,cAA2B,eAAe;AAAA,EACvC,SAAmC;AAAA,EAEjC,QAAQ;AAChB,UAAM,OAAO,KAAK,aAAa,MAAM,KAAK;AAC1C,UAAM,UAAU,KAAK,aAAa,SAAS,KAAK;AAChD,UAAM,OAAO,KAAK,aAAa,KAAK,KAAK;AAGzC,SAAK,SAAS,SAAS,cAAc,GAAG;AACxC,SAAK,OAAO,OAAO;AACnB,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,YAAY;AACxB,SAAK,OAAO,QAAQ,UAAU;AAG9B,QAAI,KAAK,WAAW,MAAM,GAAG;AAC3B,WAAK,OAAO,SAAS;AACrB,WAAK,OAAO,MAAM;AAGlB,YAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,WAAK,YAAY;AACjB,WAAK,aAAa,eAAe,MAAM;AACvC,WAAK,cAAc;AACnB,WAAK,OAAO,YAAY,IAAI;AAAA,IAC9B;AAEA,SAAK,cAAc;AACnB,SAAK,YAAY,KAAK,MAAM;AAAA,EAC9B;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,gBAAgB,GAAG;AACzC,iBAAe,OAAO,kBAAkB,YAAY;AACtD;","names":[]}
@@ -0,0 +1,161 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-tabs.ts
6
+ import { CompositeNavigation } from "@dogsbay/primitives/composite";
7
+ var idCounter = 0;
8
+ function uniqueId(prefix) {
9
+ return `${prefix}-${++idCounter}`;
10
+ }
11
+ var DbTabs = class extends DogsbayElement {
12
+ list;
13
+ triggers = [];
14
+ panels = [];
15
+ nav = null;
16
+ value = "";
17
+ syncKey = null;
18
+ orientation = "horizontal";
19
+ handleClick = (e) => {
20
+ const trigger = e.target.closest(
21
+ "[data-part='trigger']"
22
+ );
23
+ if (!trigger || trigger.hasAttribute("disabled")) return;
24
+ const value = trigger.dataset.value;
25
+ if (value) this.select(value);
26
+ };
27
+ handleStorage = (e) => {
28
+ if (!this.syncKey || e.key !== `db-tabs-sync:${this.syncKey}`) return;
29
+ const newValue = e.newValue;
30
+ if (newValue && this.value !== newValue) {
31
+ this.select(newValue);
32
+ }
33
+ };
34
+ handleSyncEvent = ((e) => {
35
+ const newValue = e.detail.value;
36
+ if (newValue && this.value !== newValue) {
37
+ this.select(newValue);
38
+ }
39
+ });
40
+ setup() {
41
+ const list = this.querySelector("[data-part='list']");
42
+ if (!list) return;
43
+ this.list = list;
44
+ this.triggers = Array.from(
45
+ list.querySelectorAll("[data-part='trigger']")
46
+ );
47
+ this.panels = Array.from(
48
+ this.querySelectorAll(":scope > [data-part='content']")
49
+ );
50
+ this.orientation = this.getAttribute("orientation") || "horizontal";
51
+ this.syncKey = this.getAttribute("sync-key") || null;
52
+ list.setAttribute("role", "tablist");
53
+ list.setAttribute("aria-orientation", this.orientation);
54
+ this.triggers.forEach((trigger) => {
55
+ const value = trigger.dataset.value;
56
+ trigger.setAttribute("role", "tab");
57
+ const triggerId = trigger.id || uniqueId("db-tab");
58
+ trigger.id = triggerId;
59
+ const panel = this.panels.find((p) => p.dataset.value === value);
60
+ if (panel) {
61
+ panel.setAttribute("role", "tabpanel");
62
+ const panelId = panel.id || uniqueId("db-tabpanel");
63
+ panel.id = panelId;
64
+ trigger.setAttribute("aria-controls", panelId);
65
+ panel.setAttribute("aria-labelledby", triggerId);
66
+ }
67
+ });
68
+ this.nav = new CompositeNavigation(list, "[data-part='trigger']", {
69
+ orientation: this.orientation,
70
+ loop: true,
71
+ homeEnd: true,
72
+ onHighlightedIndexChange: () => {
73
+ const focused = document.activeElement;
74
+ const value = focused?.dataset?.value;
75
+ if (value) this.select(value);
76
+ }
77
+ });
78
+ this.nav.activate();
79
+ const defaultValue = this.getAttribute("default-value") || this.triggers[0]?.dataset.value || "";
80
+ let initialValue = defaultValue;
81
+ if (this.syncKey) {
82
+ const stored = localStorage.getItem(`db-tabs-sync:${this.syncKey}`);
83
+ if (stored && this.triggers.some((t) => t.dataset.value === stored)) {
84
+ initialValue = stored;
85
+ }
86
+ }
87
+ const hash = window.location.hash.slice(1);
88
+ if (hash && this.triggers.some((t) => t.dataset.value === hash)) {
89
+ initialValue = hash;
90
+ }
91
+ this.select(initialValue);
92
+ }
93
+ connect() {
94
+ this.list?.addEventListener("click", this.handleClick);
95
+ if (this.syncKey) {
96
+ window.addEventListener("storage", this.handleStorage);
97
+ document.addEventListener(
98
+ `db-tabs-sync:${this.syncKey}`,
99
+ this.handleSyncEvent
100
+ );
101
+ }
102
+ }
103
+ disconnect() {
104
+ this.list?.removeEventListener("click", this.handleClick);
105
+ if (this.syncKey) {
106
+ window.removeEventListener("storage", this.handleStorage);
107
+ document.removeEventListener(
108
+ `db-tabs-sync:${this.syncKey}`,
109
+ this.handleSyncEvent
110
+ );
111
+ }
112
+ }
113
+ select(value) {
114
+ if (this.value === value) return;
115
+ this.value = value;
116
+ this.triggers.forEach((trigger) => {
117
+ const isSelected = trigger.dataset.value === value;
118
+ trigger.setAttribute("aria-selected", String(isSelected));
119
+ trigger.setAttribute("tabindex", isSelected ? "0" : "-1");
120
+ if (isSelected) {
121
+ trigger.setAttribute("data-state", "active");
122
+ } else {
123
+ trigger.removeAttribute("data-state");
124
+ }
125
+ });
126
+ this.panels.forEach((panel) => {
127
+ const isActive = panel.dataset.value === value;
128
+ panel.hidden = !isActive;
129
+ if (isActive) {
130
+ panel.setAttribute("data-state", "active");
131
+ if (!panel.hasAttribute("tabindex")) {
132
+ panel.setAttribute("tabindex", "0");
133
+ }
134
+ } else {
135
+ panel.removeAttribute("data-state");
136
+ }
137
+ });
138
+ if (this.syncKey) {
139
+ localStorage.setItem(`db-tabs-sync:${this.syncKey}`, value);
140
+ document.dispatchEvent(
141
+ new CustomEvent(`db-tabs-sync:${this.syncKey}`, {
142
+ detail: { value, source: this }
143
+ })
144
+ );
145
+ }
146
+ this.dispatchEvent(
147
+ new CustomEvent("db-tabs:change", {
148
+ detail: { value },
149
+ bubbles: true
150
+ })
151
+ );
152
+ }
153
+ };
154
+ if (!customElements.get("db-tabs")) {
155
+ customElements.define("db-tabs", DbTabs);
156
+ }
157
+
158
+ export {
159
+ DbTabs
160
+ };
161
+ //# sourceMappingURL=chunk-LVXR7KTB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-tabs.ts"],"sourcesContent":["import { CompositeNavigation } from \"@dogsbay/primitives/composite\";\nimport type { Orientation } from \"@dogsbay/primitives/composite\";\nimport { DogsbayElement } from \"./base.js\";\n\nlet idCounter = 0;\nfunction uniqueId(prefix: string) {\n return `${prefix}-${++idCounter}`;\n}\n\n/**\n * `<db-tabs>` — Accessible tabbed interface.\n *\n * Attributes:\n * default-value — initial selected tab value\n * orientation — \"horizontal\" (default) or \"vertical\"\n * sync-key — sync selection across instances via localStorage\n *\n * Children:\n * [data-part=\"list\"] — tablist container\n * [data-part=\"trigger\"] — tab buttons (must have data-value)\n * [data-part=\"content\"] — tab panels (must have data-value)\n *\n * Events:\n * db-tabs:change — fired on selection change, detail: { value }\n */\nexport class DbTabs extends DogsbayElement {\n private list!: HTMLElement;\n private triggers: HTMLElement[] = [];\n private panels: HTMLElement[] = [];\n private nav: CompositeNavigation | null = null;\n private value = \"\";\n private syncKey: string | null = null;\n private orientation: Orientation = \"horizontal\";\n\n private handleClick = (e: Event) => {\n const trigger = (e.target as HTMLElement).closest(\n \"[data-part='trigger']\",\n ) as HTMLElement | null;\n if (!trigger || trigger.hasAttribute(\"disabled\")) return;\n const value = trigger.dataset.value;\n if (value) this.select(value);\n };\n\n private handleStorage = (e: StorageEvent) => {\n if (!this.syncKey || e.key !== `db-tabs-sync:${this.syncKey}`) return;\n const newValue = e.newValue;\n if (newValue && this.value !== newValue) {\n this.select(newValue);\n }\n };\n\n private handleSyncEvent = ((e: CustomEvent) => {\n const newValue = e.detail.value;\n if (newValue && this.value !== newValue) {\n this.select(newValue);\n }\n }) as EventListener;\n\n protected setup() {\n const list = this.querySelector(\"[data-part='list']\") as HTMLElement | null;\n if (!list) return;\n this.list = list;\n\n this.triggers = Array.from(\n list.querySelectorAll(\"[data-part='trigger']\"),\n ) as HTMLElement[];\n this.panels = Array.from(\n this.querySelectorAll(\":scope > [data-part='content']\"),\n ) as HTMLElement[];\n\n this.orientation =\n (this.getAttribute(\"orientation\") as Orientation) || \"horizontal\";\n this.syncKey = this.getAttribute(\"sync-key\") || null;\n\n // Set orientation on tablist\n list.setAttribute(\"role\", \"tablist\");\n list.setAttribute(\"aria-orientation\", this.orientation);\n\n // Generate IDs and link triggers ↔ panels\n this.triggers.forEach((trigger) => {\n const value = trigger.dataset.value!;\n trigger.setAttribute(\"role\", \"tab\");\n const triggerId = trigger.id || uniqueId(\"db-tab\");\n trigger.id = triggerId;\n\n const panel = this.panels.find((p) => p.dataset.value === value);\n if (panel) {\n panel.setAttribute(\"role\", \"tabpanel\");\n const panelId = panel.id || uniqueId(\"db-tabpanel\");\n panel.id = panelId;\n trigger.setAttribute(\"aria-controls\", panelId);\n panel.setAttribute(\"aria-labelledby\", triggerId);\n }\n });\n\n // Set up composite navigation\n this.nav = new CompositeNavigation(list, \"[data-part='trigger']\", {\n orientation: this.orientation,\n loop: true,\n homeEnd: true,\n onHighlightedIndexChange: () => {\n const focused = document.activeElement as HTMLElement;\n const value = focused?.dataset?.value;\n if (value) this.select(value);\n },\n });\n\n this.nav.activate();\n\n // Determine initial value: hash > localStorage > default-value > first trigger\n const defaultValue =\n this.getAttribute(\"default-value\") ||\n this.triggers[0]?.dataset.value ||\n \"\";\n\n let initialValue = defaultValue;\n if (this.syncKey) {\n const stored = localStorage.getItem(`db-tabs-sync:${this.syncKey}`);\n if (stored && this.triggers.some((t) => t.dataset.value === stored)) {\n initialValue = stored;\n }\n }\n const hash = window.location.hash.slice(1);\n if (hash && this.triggers.some((t) => t.dataset.value === hash)) {\n initialValue = hash;\n }\n\n this.select(initialValue);\n }\n\n protected connect() {\n this.list?.addEventListener(\"click\", this.handleClick);\n if (this.syncKey) {\n window.addEventListener(\"storage\", this.handleStorage);\n document.addEventListener(\n `db-tabs-sync:${this.syncKey}`,\n this.handleSyncEvent,\n );\n }\n }\n\n protected disconnect() {\n this.list?.removeEventListener(\"click\", this.handleClick);\n if (this.syncKey) {\n window.removeEventListener(\"storage\", this.handleStorage);\n document.removeEventListener(\n `db-tabs-sync:${this.syncKey}`,\n this.handleSyncEvent,\n );\n }\n }\n\n select(value: string) {\n if (this.value === value) return;\n this.value = value;\n\n // Update triggers\n this.triggers.forEach((trigger) => {\n const isSelected = trigger.dataset.value === value;\n trigger.setAttribute(\"aria-selected\", String(isSelected));\n trigger.setAttribute(\"tabindex\", isSelected ? \"0\" : \"-1\");\n if (isSelected) {\n trigger.setAttribute(\"data-state\", \"active\");\n } else {\n trigger.removeAttribute(\"data-state\");\n }\n });\n\n // Update panels\n this.panels.forEach((panel) => {\n const isActive = panel.dataset.value === value;\n panel.hidden = !isActive;\n if (isActive) {\n panel.setAttribute(\"data-state\", \"active\");\n if (!panel.hasAttribute(\"tabindex\")) {\n panel.setAttribute(\"tabindex\", \"0\");\n }\n // Lazy init: upgrade any nested db-tabs that haven't connected yet\n // (browser handles this automatically via connectedCallback)\n } else {\n panel.removeAttribute(\"data-state\");\n }\n });\n\n // Sync to localStorage and other instances\n if (this.syncKey) {\n localStorage.setItem(`db-tabs-sync:${this.syncKey}`, value);\n document.dispatchEvent(\n new CustomEvent(`db-tabs-sync:${this.syncKey}`, {\n detail: { value, source: this },\n }),\n );\n }\n\n // Dispatch change event\n this.dispatchEvent(\n new CustomEvent(\"db-tabs:change\", {\n detail: { value },\n bubbles: true,\n }),\n );\n }\n}\n\nif (!customElements.get(\"db-tabs\")) {\n customElements.define(\"db-tabs\", DbTabs);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,46 @@
1
+ import {
2
+ DogsbayElement
3
+ } from "./chunk-XBMLE4N3.js";
4
+
5
+ // src/db-collapsible.ts
6
+ import { Collapsible } from "@dogsbay/primitives/collapsible";
7
+ var DbCollapsible = class extends DogsbayElement {
8
+ collapsible = null;
9
+ setup() {
10
+ const trigger = this.querySelector("[data-part='trigger']");
11
+ const content = this.querySelector("[data-part='content']");
12
+ if (!trigger || !content) return;
13
+ const disabled = this.hasAttribute("disabled");
14
+ if (disabled) {
15
+ trigger.setAttribute("disabled", "");
16
+ trigger.setAttribute("aria-disabled", "true");
17
+ }
18
+ this.collapsible = new Collapsible(trigger, content, {
19
+ onToggle: (open) => {
20
+ this.setAttribute("data-state", open ? "open" : "closed");
21
+ content.setAttribute("data-state", open ? "open" : "closed");
22
+ this.dispatchEvent(
23
+ new CustomEvent("db-collapsible:toggle", {
24
+ detail: { open },
25
+ bubbles: true
26
+ })
27
+ );
28
+ }
29
+ });
30
+ if (this.hasAttribute("default-open")) {
31
+ this.collapsible.expand();
32
+ content.setAttribute("data-state", "open");
33
+ } else {
34
+ this.setAttribute("data-state", "closed");
35
+ content.setAttribute("data-state", "closed");
36
+ }
37
+ }
38
+ };
39
+ if (!customElements.get("db-collapsible")) {
40
+ customElements.define("db-collapsible", DbCollapsible);
41
+ }
42
+
43
+ export {
44
+ DbCollapsible
45
+ };
46
+ //# sourceMappingURL=chunk-TTNTPXBA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-collapsible.ts"],"sourcesContent":["import { Collapsible } from \"@dogsbay/primitives/collapsible\";\nimport { DogsbayElement } from \"./base.js\";\n\n/**\n * `<db-collapsible>` — Accessible expand/collapse panel.\n *\n * Attributes:\n * default-open — start expanded\n * disabled — prevent toggling\n *\n * Children:\n * [data-part=\"trigger\"] — toggle button\n * [data-part=\"content\"] — collapsible panel\n *\n * Events:\n * db-collapsible:toggle — fired on state change, detail: { open }\n */\nexport class DbCollapsible extends DogsbayElement {\n private collapsible: Collapsible | null = null;\n\n protected setup() {\n const trigger = this.querySelector<HTMLElement>(\"[data-part='trigger']\");\n const content = this.querySelector<HTMLElement>(\"[data-part='content']\");\n if (!trigger || !content) return;\n\n const disabled = this.hasAttribute(\"disabled\");\n if (disabled) {\n trigger.setAttribute(\"disabled\", \"\");\n trigger.setAttribute(\"aria-disabled\", \"true\");\n }\n\n this.collapsible = new Collapsible(trigger, content, {\n onToggle: (open) => {\n this.setAttribute(\"data-state\", open ? \"open\" : \"closed\");\n content.setAttribute(\"data-state\", open ? \"open\" : \"closed\");\n this.dispatchEvent(\n new CustomEvent(\"db-collapsible:toggle\", {\n detail: { open },\n bubbles: true,\n }),\n );\n },\n });\n\n if (this.hasAttribute(\"default-open\")) {\n this.collapsible.expand();\n content.setAttribute(\"data-state\", \"open\");\n } else {\n this.setAttribute(\"data-state\", \"closed\");\n content.setAttribute(\"data-state\", \"closed\");\n }\n }\n}\n\nif (!customElements.get(\"db-collapsible\")) {\n customElements.define(\"db-collapsible\", DbCollapsible);\n}\n"],"mappings":";;;;;AAAA,SAAS,mBAAmB;AAiBrB,IAAM,gBAAN,cAA4B,eAAe;AAAA,EACxC,cAAkC;AAAA,EAEhC,QAAQ;AAChB,UAAM,UAAU,KAAK,cAA2B,uBAAuB;AACvE,UAAM,UAAU,KAAK,cAA2B,uBAAuB;AACvE,QAAI,CAAC,WAAW,CAAC,QAAS;AAE1B,UAAM,WAAW,KAAK,aAAa,UAAU;AAC7C,QAAI,UAAU;AACZ,cAAQ,aAAa,YAAY,EAAE;AACnC,cAAQ,aAAa,iBAAiB,MAAM;AAAA,IAC9C;AAEA,SAAK,cAAc,IAAI,YAAY,SAAS,SAAS;AAAA,MACnD,UAAU,CAAC,SAAS;AAClB,aAAK,aAAa,cAAc,OAAO,SAAS,QAAQ;AACxD,gBAAQ,aAAa,cAAc,OAAO,SAAS,QAAQ;AAC3D,aAAK;AAAA,UACH,IAAI,YAAY,yBAAyB;AAAA,YACvC,QAAQ,EAAE,KAAK;AAAA,YACf,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,KAAK,aAAa,cAAc,GAAG;AACrC,WAAK,YAAY,OAAO;AACxB,cAAQ,aAAa,cAAc,MAAM;AAAA,IAC3C,OAAO;AACL,WAAK,aAAa,cAAc,QAAQ;AACxC,cAAQ,aAAa,cAAc,QAAQ;AAAA,IAC7C;AAAA,EACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,gBAAgB,GAAG;AACzC,iBAAe,OAAO,kBAAkB,aAAa;AACvD;","names":[]}
@@ -0,0 +1,28 @@
1
+ // src/base.ts
2
+ var DogsbayElement = class extends HTMLElement {
3
+ _initialized = false;
4
+ connectedCallback() {
5
+ if (!this._initialized) {
6
+ this.setup();
7
+ this._initialized = true;
8
+ }
9
+ this.connect();
10
+ }
11
+ disconnectedCallback() {
12
+ this.disconnect();
13
+ }
14
+ /** One-time setup: query children, generate IDs, set ARIA. */
15
+ setup() {
16
+ }
17
+ /** Called on every connect: attach event listeners. */
18
+ connect() {
19
+ }
20
+ /** Called on every disconnect: remove event listeners. */
21
+ disconnect() {
22
+ }
23
+ };
24
+
25
+ export {
26
+ DogsbayElement
27
+ };
28
+ //# sourceMappingURL=chunk-XBMLE4N3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/base.ts"],"sourcesContent":["/**\n * Base class for Dogsbay custom elements.\n *\n * Handles the connect/disconnect lifecycle and ensures one-time setup\n * runs only once even when Obsidian's virtual scrolling removes and\n * re-adds elements to the DOM.\n */\nexport abstract class DogsbayElement extends HTMLElement {\n private _initialized = false;\n\n connectedCallback() {\n if (!this._initialized) {\n this.setup();\n this._initialized = true;\n }\n this.connect();\n }\n\n disconnectedCallback() {\n this.disconnect();\n }\n\n /** One-time setup: query children, generate IDs, set ARIA. */\n protected setup() {}\n\n /** Called on every connect: attach event listeners. */\n protected connect() {}\n\n /** Called on every disconnect: remove event listeners. */\n protected disconnect() {}\n}\n"],"mappings":";AAOO,IAAe,iBAAf,cAAsC,YAAY;AAAA,EAC/C,eAAe;AAAA,EAEvB,oBAAoB;AAClB,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,MAAM;AACX,WAAK,eAAe;AAAA,IACtB;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,uBAAuB;AACrB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGU,QAAQ;AAAA,EAAC;AAAA;AAAA,EAGT,UAAU;AAAA,EAAC;AAAA;AAAA,EAGX,aAAa;AAAA,EAAC;AAC1B;","names":[]}
@@ -0,0 +1,28 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-accordion>` — Accessible accordion with single/multiple mode.
5
+ *
6
+ * Attributes:
7
+ * type — "single" (default) or "multiple"
8
+ * default-value — comma-separated values to open initially
9
+ *
10
+ * Children:
11
+ * [data-part="item"] with data-value — accordion items
12
+ * [data-part="trigger"] — toggle button (inside item)
13
+ * [data-part="content"] — collapsible panel (inside item)
14
+ *
15
+ * Events:
16
+ * db-accordion:change — detail: { value, open, openValues }
17
+ */
18
+ declare class DbAccordion extends DogsbayElement {
19
+ private items;
20
+ private nav;
21
+ private openValues;
22
+ private type;
23
+ protected setup(): void;
24
+ private onItemExpanded;
25
+ private onItemCollapsed;
26
+ }
27
+
28
+ export { DbAccordion };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbAccordion
3
+ } from "./chunk-7M7SFLKN.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbAccordion
7
+ };
8
+ //# sourceMappingURL=db-accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,30 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-card>` — Accessible content card with optional link behavior.
5
+ *
6
+ * Attributes:
7
+ * href — if present, the card is clickable and navigates on click/Enter/Space
8
+ *
9
+ * Children:
10
+ * [data-part="icon"] — icon (optional)
11
+ * [data-part="title"] — card title (optional)
12
+ * [data-part="description"] — card description (optional)
13
+ * [data-part="content"] — card body content (optional)
14
+ *
15
+ * Events:
16
+ * db-card:navigate — fired when a linked card is activated, detail: { href }
17
+ * The host environment (Obsidian plugin or Astro) handles
18
+ * actual navigation by listening for this event.
19
+ */
20
+ declare class DbCard extends DogsbayElement {
21
+ private href;
22
+ private handleClick;
23
+ private handleKeydown;
24
+ protected setup(): void;
25
+ protected connect(): void;
26
+ protected disconnect(): void;
27
+ private navigate;
28
+ }
29
+
30
+ export { DbCard };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbCard
3
+ } from "./chunk-7BIVQSGP.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbCard
7
+ };
8
+ //# sourceMappingURL=db-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,35 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-code-block>` — Code block with copy-to-clipboard.
5
+ *
6
+ * Attributes:
7
+ * data-copy-text — raw code text to copy (preferred over parsing DOM)
8
+ *
9
+ * Children:
10
+ * [data-part="header"] — header bar (optional)
11
+ * [data-part="label"] — title/language label (inside header, optional)
12
+ * [data-part="copy"] — copy button
13
+ * [data-part="copy-icon"] — copy icon SVG (inside copy button)
14
+ * [data-part="check-icon"] — check icon SVG (inside copy button, starts hidden)
15
+ * [data-part="code"] — code content container
16
+ *
17
+ * Events:
18
+ * db-code-block:copied — fired after successful copy, detail: { text }
19
+ */
20
+ declare class DbCodeBlock extends DogsbayElement {
21
+ private copyBtn;
22
+ private copyIcon;
23
+ private checkIcon;
24
+ private liveRegion;
25
+ private resetTimeout;
26
+ private handleCopy;
27
+ protected setup(): void;
28
+ protected connect(): void;
29
+ protected disconnect(): void;
30
+ private getCopyText;
31
+ private showCopiedFeedback;
32
+ private clearResetTimeout;
33
+ }
34
+
35
+ export { DbCodeBlock };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbCodeBlock
3
+ } from "./chunk-FWAAU5UY.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbCodeBlock
7
+ };
8
+ //# sourceMappingURL=db-code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,22 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-collapsible>` — Accessible expand/collapse panel.
5
+ *
6
+ * Attributes:
7
+ * default-open — start expanded
8
+ * disabled — prevent toggling
9
+ *
10
+ * Children:
11
+ * [data-part="trigger"] — toggle button
12
+ * [data-part="content"] — collapsible panel
13
+ *
14
+ * Events:
15
+ * db-collapsible:toggle — fired on state change, detail: { open }
16
+ */
17
+ declare class DbCollapsible extends DogsbayElement {
18
+ private collapsible;
19
+ protected setup(): void;
20
+ }
21
+
22
+ export { DbCollapsible };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbCollapsible
3
+ } from "./chunk-TTNTPXBA.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbCollapsible
7
+ };
8
+ //# sourceMappingURL=db-collapsible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-link-button>` — Styled link that looks like a button.
5
+ *
6
+ * Attributes:
7
+ * href — target URL (required)
8
+ * variant — "primary" | "secondary" | "outline" (default: "primary")
9
+ *
10
+ * Light DOM: renders as an <a> tag with button styling.
11
+ * Works in both Astro (matches Button component) and Obsidian.
12
+ *
13
+ * In Astro, the format-astro serializer maps link-button TreeNode to
14
+ * the Button.astro component with href prop.
15
+ *
16
+ * In Obsidian, the plugin emits <db-link-button> which this element
17
+ * auto-upgrades with styling and keyboard navigation.
18
+ */
19
+ declare class DbLinkButton extends DogsbayElement {
20
+ private anchor;
21
+ protected setup(): void;
22
+ }
23
+
24
+ export { DbLinkButton };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbLinkButton
3
+ } from "./chunk-LFXZQ4YV.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbLinkButton
7
+ };
8
+ //# sourceMappingURL=db-link-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,19 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-steps>` — Accessible step-by-step list.
5
+ *
6
+ * A read-only component that renders numbered steps with ARIA semantics.
7
+ * Visual styling (numbered circles, connector lines) is handled by CSS
8
+ * using counter(step), matching the Astro Steps component.
9
+ *
10
+ * Children:
11
+ * [data-part="item"] — step items
12
+ * [data-part="title"] — step title (inside item, optional)
13
+ * [data-part="content"] — step content (inside item, optional)
14
+ */
15
+ declare class DbSteps extends DogsbayElement {
16
+ protected setup(): void;
17
+ }
18
+
19
+ export { DbSteps };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbSteps
3
+ } from "./chunk-5T4OXQA2.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbSteps
7
+ };
8
+ //# sourceMappingURL=db-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,36 @@
1
+ import { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+
3
+ /**
4
+ * `<db-tabs>` — Accessible tabbed interface.
5
+ *
6
+ * Attributes:
7
+ * default-value — initial selected tab value
8
+ * orientation — "horizontal" (default) or "vertical"
9
+ * sync-key — sync selection across instances via localStorage
10
+ *
11
+ * Children:
12
+ * [data-part="list"] — tablist container
13
+ * [data-part="trigger"] — tab buttons (must have data-value)
14
+ * [data-part="content"] — tab panels (must have data-value)
15
+ *
16
+ * Events:
17
+ * db-tabs:change — fired on selection change, detail: { value }
18
+ */
19
+ declare class DbTabs extends DogsbayElement {
20
+ private list;
21
+ private triggers;
22
+ private panels;
23
+ private nav;
24
+ private value;
25
+ private syncKey;
26
+ private orientation;
27
+ private handleClick;
28
+ private handleStorage;
29
+ private handleSyncEvent;
30
+ protected setup(): void;
31
+ protected connect(): void;
32
+ protected disconnect(): void;
33
+ select(value: string): void;
34
+ }
35
+
36
+ export { DbTabs };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbTabs
3
+ } from "./chunk-LVXR7KTB.js";
4
+ import "./chunk-XBMLE4N3.js";
5
+ export {
6
+ DbTabs
7
+ };
8
+ //# sourceMappingURL=db-tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,8 @@
1
+ export { D as DogsbayElement } from './base-BtvRtAsC.js';
2
+ export { DbTabs } from './db-tabs.js';
3
+ export { DbCollapsible } from './db-collapsible.js';
4
+ export { DbAccordion } from './db-accordion.js';
5
+ export { DbSteps } from './db-steps.js';
6
+ export { DbCodeBlock } from './db-code-block.js';
7
+ export { DbCard } from './db-card.js';
8
+ export { DbLinkButton } from './db-link-button.js';
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ import {
2
+ DbAccordion
3
+ } from "./chunk-7M7SFLKN.js";
4
+ import {
5
+ DbCard
6
+ } from "./chunk-7BIVQSGP.js";
7
+ import {
8
+ DbCodeBlock
9
+ } from "./chunk-FWAAU5UY.js";
10
+ import {
11
+ DbCollapsible
12
+ } from "./chunk-TTNTPXBA.js";
13
+ import {
14
+ DbLinkButton
15
+ } from "./chunk-LFXZQ4YV.js";
16
+ import {
17
+ DbSteps
18
+ } from "./chunk-5T4OXQA2.js";
19
+ import {
20
+ DbTabs
21
+ } from "./chunk-LVXR7KTB.js";
22
+ import {
23
+ DogsbayElement
24
+ } from "./chunk-XBMLE4N3.js";
25
+ export {
26
+ DbAccordion,
27
+ DbCard,
28
+ DbCodeBlock,
29
+ DbCollapsible,
30
+ DbLinkButton,
31
+ DbSteps,
32
+ DbTabs,
33
+ DogsbayElement
34
+ };
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@dogsbay/elements",
3
+ "version": "0.2.0-beta.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./db-tabs": {
13
+ "types": "./dist/db-tabs.d.ts",
14
+ "import": "./dist/db-tabs.js"
15
+ },
16
+ "./db-collapsible": {
17
+ "types": "./dist/db-collapsible.d.ts",
18
+ "import": "./dist/db-collapsible.js"
19
+ },
20
+ "./db-accordion": {
21
+ "types": "./dist/db-accordion.d.ts",
22
+ "import": "./dist/db-accordion.js"
23
+ },
24
+ "./db-steps": {
25
+ "types": "./dist/db-steps.d.ts",
26
+ "import": "./dist/db-steps.js"
27
+ },
28
+ "./db-code-block": {
29
+ "types": "./dist/db-code-block.d.ts",
30
+ "import": "./dist/db-code-block.js"
31
+ },
32
+ "./db-card": {
33
+ "types": "./dist/db-card.d.ts",
34
+ "import": "./dist/db-card.js"
35
+ },
36
+ "./db-link-button": {
37
+ "types": "./dist/db-link-button.d.ts",
38
+ "import": "./dist/db-link-button.js"
39
+ }
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "dependencies": {
45
+ "@dogsbay/primitives": "0.2.0-beta.0"
46
+ },
47
+ "devDependencies": {
48
+ "happy-dom": "^20.8.9",
49
+ "tsup": "^8.4.0",
50
+ "typescript": "^5.8.0",
51
+ "vitest": "^3.1.0"
52
+ },
53
+ "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/dogsbay/dogsbay.git",
57
+ "directory": "packages/elements"
58
+ },
59
+ "homepage": "https://github.com/dogsbay/dogsbay/tree/main/packages/elements",
60
+ "bugs": {
61
+ "url": "https://github.com/dogsbay/dogsbay/issues"
62
+ },
63
+ "scripts": {
64
+ "build": "tsup",
65
+ "dev": "tsup --watch",
66
+ "test": "vitest run",
67
+ "test:watch": "vitest",
68
+ "typecheck": "tsc --noEmit"
69
+ }
70
+ }