@dogsbay/elements 0.2.0-beta.14 → 0.2.0-beta.141

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 (68) hide show
  1. package/dist/{base-BtvRtAsC.d.ts → base-D1Rz70fn.d.ts} +1 -0
  2. package/dist/chunk-2ZMWJ74J.js +233 -0
  3. package/dist/{chunk-7M7SFLKN.js → chunk-5KHESKQR.js} +4 -3
  4. package/dist/{chunk-TTNTPXBA.js → chunk-5WY3DHVB.js} +4 -3
  5. package/dist/chunk-6QAYHFIQ.js +115 -0
  6. package/dist/{chunk-LVXR7KTB.js → chunk-6ZKFQBCF.js} +40 -12
  7. package/dist/{chunk-5T4OXQA2.js → chunk-AVQ7KRRE.js} +5 -6
  8. package/dist/{chunk-FWAAU5UY.js → chunk-CD3G6HKT.js} +4 -3
  9. package/dist/chunk-EPHDSTM7.js +85 -0
  10. package/dist/chunk-GC5HL7FU.js +255 -0
  11. package/dist/chunk-HMNRE3FZ.js +382 -0
  12. package/dist/chunk-HMV62CBN.js +139 -0
  13. package/dist/{chunk-7BIVQSGP.js → chunk-JRAYNKQ6.js} +4 -3
  14. package/dist/chunk-KFY2MTR3.js +190 -0
  15. package/dist/chunk-KXCPLIQD.js +77 -0
  16. package/dist/chunk-MZDGSTI4.js +72 -0
  17. package/dist/chunk-RZ3KZOM3.js +207 -0
  18. package/dist/{chunk-LFXZQ4YV.js → chunk-US4H4ZPZ.js} +4 -3
  19. package/dist/db-accordion.d.ts +1 -1
  20. package/dist/db-accordion.js +2 -3
  21. package/dist/db-card.d.ts +1 -1
  22. package/dist/db-card.js +2 -3
  23. package/dist/db-code-block.d.ts +1 -1
  24. package/dist/db-code-block.js +2 -3
  25. package/dist/db-collapsible.d.ts +1 -1
  26. package/dist/db-collapsible.js +2 -3
  27. package/dist/db-combobox.d.ts +70 -0
  28. package/dist/db-combobox.js +8 -0
  29. package/dist/db-details-sheet.d.ts +53 -0
  30. package/dist/db-details-sheet.js +8 -0
  31. package/dist/db-dialog.d.ts +62 -0
  32. package/dist/db-dialog.js +8 -0
  33. package/dist/db-link-button.d.ts +1 -1
  34. package/dist/db-link-button.js +2 -3
  35. package/dist/db-nav-tree.d.ts +83 -0
  36. package/dist/db-nav-tree.js +8 -0
  37. package/dist/db-popover.d.ts +42 -0
  38. package/dist/db-popover.js +8 -0
  39. package/dist/db-select.d.ts +72 -0
  40. package/dist/db-select.js +8 -0
  41. package/dist/db-steps.d.ts +1 -1
  42. package/dist/db-steps.js +2 -3
  43. package/dist/db-tabs.d.ts +28 -1
  44. package/dist/db-tabs.js +2 -3
  45. package/dist/db-toc.d.ts +32 -0
  46. package/dist/db-toc.js +8 -0
  47. package/dist/db-tooltip.d.ts +48 -0
  48. package/dist/db-tooltip.js +8 -0
  49. package/dist/index.d.ts +9 -1
  50. package/dist/index.js +44 -12
  51. package/package.json +38 -6
  52. package/dist/chunk-5T4OXQA2.js.map +0 -1
  53. package/dist/chunk-7BIVQSGP.js.map +0 -1
  54. package/dist/chunk-7M7SFLKN.js.map +0 -1
  55. package/dist/chunk-FWAAU5UY.js.map +0 -1
  56. package/dist/chunk-LFXZQ4YV.js.map +0 -1
  57. package/dist/chunk-LVXR7KTB.js.map +0 -1
  58. package/dist/chunk-TTNTPXBA.js.map +0 -1
  59. package/dist/chunk-XBMLE4N3.js +0 -28
  60. package/dist/chunk-XBMLE4N3.js.map +0 -1
  61. package/dist/db-accordion.js.map +0 -1
  62. package/dist/db-card.js.map +0 -1
  63. package/dist/db-code-block.js.map +0 -1
  64. package/dist/db-collapsible.js.map +0 -1
  65. package/dist/db-link-button.js.map +0 -1
  66. package/dist/db-steps.js.map +0 -1
  67. package/dist/db-tabs.js.map +0 -1
  68. package/dist/index.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbPopover
3
+ } from "./chunk-6QAYHFIQ.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
+ export {
7
+ DbPopover
8
+ };
@@ -0,0 +1,72 @@
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
+
3
+ /**
4
+ * `<db-select>` — Select-only combobox (APG "Select-Only Combobox").
5
+ *
6
+ * Two ways to use it:
7
+ *
8
+ * 1. The Astro Select parts (same contract as `ui/src/select`):
9
+ * [data-part="trigger"] button, role=combobox (focus stays here)
10
+ * [data-part="value"] shows the selected label (data-placeholder)
11
+ * [data-part="content"] role=listbox
12
+ * [data-part="item"] role=option, data-value, aria-disabled
13
+ * [data-part="group"] / [data-part="label"]
14
+ *
15
+ * 2. Progressive enhancement of a native `<select>` inside the element.
16
+ * The element builds the parts from its options, keeps the native
17
+ * select in sync (hidden, still submitted with forms) and dispatches a
18
+ * native `change` on it, so existing listeners keep working. With no
19
+ * JavaScript the native select is what the user gets.
20
+ *
21
+ * The listbox opens in the top layer where supported. Focus never leaves
22
+ * the trigger: the highlighted option is exposed with aria-activedescendant.
23
+ *
24
+ * Attributes: name, default-value, required, disabled
25
+ * Events: db-select:change (detail: { value })
26
+ */
27
+ declare class DbSelect extends DogsbayElement {
28
+ private trigger;
29
+ private content;
30
+ private valueEl;
31
+ private items;
32
+ private nativeSelect;
33
+ private hiddenInput;
34
+ private labelEl;
35
+ private onLabelClick;
36
+ private dismiss;
37
+ private typeahead;
38
+ private cleanupFloating;
39
+ private _open;
40
+ private _value;
41
+ private highlighted;
42
+ get open(): boolean;
43
+ get value(): string;
44
+ set value(v: string);
45
+ /** Disabled when the host or the enhanced native select is. */
46
+ private get isDisabled();
47
+ private syncing;
48
+ /** Re-read the native select's value (after script changes it or a form reset). */
49
+ refresh(): void;
50
+ private onNativeChange;
51
+ private onFormReset;
52
+ private enabled;
53
+ protected setup(): void;
54
+ /** Build the trigger and listbox from a native <select>, and hide it. */
55
+ private buildFromNative;
56
+ private onTriggerClick;
57
+ private onTriggerKeyUp;
58
+ private onTriggerKey;
59
+ private onListClick;
60
+ private onListPointer;
61
+ protected connect(): void;
62
+ protected disconnect(): void;
63
+ private preventBlur;
64
+ private setState;
65
+ show(): void;
66
+ /** Close the listbox. `refocus` is false for outside presses, which keep focus where the user clicked. */
67
+ close(refocus?: boolean): void;
68
+ private highlight;
69
+ private select;
70
+ }
71
+
72
+ export { DbSelect };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbSelect
3
+ } from "./chunk-HMNRE3FZ.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
+ export {
7
+ DbSelect
8
+ };
@@ -1,4 +1,4 @@
1
- import { D as DogsbayElement } from './base-BtvRtAsC.js';
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
2
 
3
3
  /**
4
4
  * `<db-steps>` — Accessible step-by-step list.
package/dist/db-steps.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  DbSteps
3
- } from "./chunk-5T4OXQA2.js";
4
- import "./chunk-XBMLE4N3.js";
3
+ } from "./chunk-AVQ7KRRE.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbSteps
7
7
  };
8
- //# sourceMappingURL=db-steps.js.map
package/dist/db-tabs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as DogsbayElement } from './base-BtvRtAsC.js';
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
2
 
3
3
  /**
4
4
  * `<db-tabs>` — Accessible tabbed interface.
@@ -25,8 +25,35 @@ declare class DbTabs extends DogsbayElement {
25
25
  private syncKey;
26
26
  private orientation;
27
27
  private handleClick;
28
+ /**
29
+ * A synced group follows only a value it HAS. Groups sharing a key need
30
+ * not share a tab set (a web-only snippet group beside an all-SDK one), and
31
+ * selecting a value with no trigger here left the group with every panel
32
+ * hidden and no tab selected.
33
+ */
34
+ private has;
28
35
  private handleStorage;
29
36
  private handleSyncEvent;
37
+ /**
38
+ * Descendants belonging to THIS tab group.
39
+ *
40
+ * Not `:scope >`, and not a bare descendant query — both were wrong
41
+ * here, in opposite directions:
42
+ *
43
+ * - Panels used `:scope > [data-part='content']`, so any wrapper
44
+ * between the element and its panels hid them. The vertical example
45
+ * wraps its list and panels in a flex row to sit them side by side,
46
+ * so `panels` was EMPTY: triggers moved `aria-selected`, and the
47
+ * content never changed. Nothing threw, and the server-rendered
48
+ * initial state looked right, so it read as working.
49
+ * - Triggers used a bare descendant query, which would reach into a
50
+ * NESTED tab group and drive the wrong panels.
51
+ *
52
+ * `closest("db-tabs") === this` allows arbitrary wrappers while
53
+ * stopping at a nested group, which is a real case — Obsidian
54
+ * alternates fence characters by depth precisely so tabs can nest.
55
+ */
56
+ private own;
30
57
  protected setup(): void;
31
58
  protected connect(): void;
32
59
  protected disconnect(): void;
package/dist/db-tabs.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  DbTabs
3
- } from "./chunk-LVXR7KTB.js";
4
- import "./chunk-XBMLE4N3.js";
3
+ } from "./chunk-6ZKFQBCF.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbTabs
7
7
  };
8
- //# sourceMappingURL=db-tabs.js.map
@@ -0,0 +1,32 @@
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
+
3
+ /**
4
+ * `<db-toc>` — "On this page" links that follow the reader (scroll spy).
5
+ *
6
+ * Wraps plain in-page links, so it works as a list of links without
7
+ * JavaScript. The link for the section in view gets `aria-current="location"`
8
+ * and `data-active` (the Astro TableOfContents contract).
9
+ *
10
+ * Links: `a[href^="#"]`, or `[data-toc-link][data-toc-slug]` as in the Astro component.
11
+ *
12
+ * Attributes:
13
+ * offset — px hidden under a sticky header (default 80)
14
+ *
15
+ * Events: db-toc:change (detail: { id })
16
+ */
17
+ declare class DbToc extends DogsbayElement {
18
+ private links;
19
+ private headings;
20
+ private observer;
21
+ private active;
22
+ private slugOf;
23
+ private onScroll;
24
+ protected setup(): void;
25
+ private onHash;
26
+ protected connect(): void;
27
+ protected disconnect(): void;
28
+ private lastAbove;
29
+ private setActive;
30
+ }
31
+
32
+ export { DbToc };
package/dist/db-toc.js ADDED
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbToc
3
+ } from "./chunk-EPHDSTM7.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
+ export {
7
+ DbToc
8
+ };
@@ -0,0 +1,48 @@
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
+
3
+ /**
4
+ * `<db-tooltip>` — Short description shown on hover and keyboard focus
5
+ * (APG "Tooltip"). The trigger is described by the content
6
+ * (aria-describedby), so screen readers announce it without showing it.
7
+ *
8
+ * WCAG 1.4.13 (content on hover or focus):
9
+ * - hoverable: the pointer can move from the trigger onto the tooltip
10
+ * without it closing (`close-delay`, default 100 ms);
11
+ * - dismissible: Escape hides it, whether it opened from hover or focus;
12
+ * - persistent: it stays until the pointer leaves, focus moves or Escape.
13
+ *
14
+ * Attributes:
15
+ * delay — ms before showing on hover (default 200)
16
+ * close-delay — ms grace period on leave (default 100)
17
+ * placement — "top" (default), or data-side on the content
18
+ *
19
+ * Parts: [data-part="trigger"] (`data-as-child` supported), [data-part="content"]
20
+ *
21
+ * Events: db-tooltip:open, db-tooltip:close
22
+ */
23
+ declare class DbTooltip extends DogsbayElement {
24
+ private trigger;
25
+ private content;
26
+ private cleanupFloating;
27
+ private showTimer;
28
+ private hideTimer;
29
+ private _open;
30
+ get open(): boolean;
31
+ private num;
32
+ private onEnter;
33
+ private onLeave;
34
+ private onContentEnter;
35
+ private onFocus;
36
+ private onBlur;
37
+ private onPress;
38
+ private onKey;
39
+ protected setup(): void;
40
+ protected connect(): void;
41
+ protected disconnect(): void;
42
+ private clearTimers;
43
+ private setState;
44
+ show(): void;
45
+ hide(): void;
46
+ }
47
+
48
+ export { DbTooltip };
@@ -0,0 +1,8 @@
1
+ import {
2
+ DbTooltip
3
+ } from "./chunk-HMV62CBN.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
+ export {
7
+ DbTooltip
8
+ };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,16 @@
1
- export { D as DogsbayElement } from './base-BtvRtAsC.js';
1
+ export { D as DogsbayElement } from './base-D1Rz70fn.js';
2
2
  export { DbTabs } from './db-tabs.js';
3
3
  export { DbCollapsible } from './db-collapsible.js';
4
4
  export { DbAccordion } from './db-accordion.js';
5
+ export { DbDetailsSheet } from './db-details-sheet.js';
5
6
  export { DbSteps } from './db-steps.js';
6
7
  export { DbCodeBlock } from './db-code-block.js';
7
8
  export { DbCard } from './db-card.js';
8
9
  export { DbLinkButton } from './db-link-button.js';
10
+ export { DbDialog } from './db-dialog.js';
11
+ export { DbPopover } from './db-popover.js';
12
+ export { DbTooltip } from './db-tooltip.js';
13
+ export { DbSelect } from './db-select.js';
14
+ export { DbCombobox } from './db-combobox.js';
15
+ export { DbNavTree, NavData } from './db-nav-tree.js';
16
+ export { DbToc } from './db-toc.js';
package/dist/index.js CHANGED
@@ -1,35 +1,67 @@
1
+ import {
2
+ DbNavTree
3
+ } from "./chunk-2ZMWJ74J.js";
4
+ import {
5
+ DbPopover
6
+ } from "./chunk-6QAYHFIQ.js";
7
+ import {
8
+ DbSelect
9
+ } from "./chunk-HMNRE3FZ.js";
10
+ import {
11
+ DbSteps
12
+ } from "./chunk-AVQ7KRRE.js";
13
+ import {
14
+ DbTabs
15
+ } from "./chunk-6ZKFQBCF.js";
16
+ import {
17
+ DbToc
18
+ } from "./chunk-EPHDSTM7.js";
19
+ import {
20
+ DbTooltip
21
+ } from "./chunk-HMV62CBN.js";
1
22
  import {
2
23
  DbAccordion
3
- } from "./chunk-7M7SFLKN.js";
24
+ } from "./chunk-5KHESKQR.js";
4
25
  import {
5
26
  DbCard
6
- } from "./chunk-7BIVQSGP.js";
27
+ } from "./chunk-JRAYNKQ6.js";
7
28
  import {
8
29
  DbCodeBlock
9
- } from "./chunk-FWAAU5UY.js";
30
+ } from "./chunk-CD3G6HKT.js";
10
31
  import {
11
32
  DbCollapsible
12
- } from "./chunk-TTNTPXBA.js";
33
+ } from "./chunk-5WY3DHVB.js";
13
34
  import {
14
- DbLinkButton
15
- } from "./chunk-LFXZQ4YV.js";
35
+ DbCombobox
36
+ } from "./chunk-GC5HL7FU.js";
16
37
  import {
17
- DbSteps
18
- } from "./chunk-5T4OXQA2.js";
38
+ DbDetailsSheet
39
+ } from "./chunk-KFY2MTR3.js";
19
40
  import {
20
- DbTabs
21
- } from "./chunk-LVXR7KTB.js";
41
+ DbDialog
42
+ } from "./chunk-RZ3KZOM3.js";
43
+ import "./chunk-KXCPLIQD.js";
44
+ import {
45
+ DbLinkButton
46
+ } from "./chunk-US4H4ZPZ.js";
22
47
  import {
23
48
  DogsbayElement
24
- } from "./chunk-XBMLE4N3.js";
49
+ } from "./chunk-MZDGSTI4.js";
25
50
  export {
26
51
  DbAccordion,
27
52
  DbCard,
28
53
  DbCodeBlock,
29
54
  DbCollapsible,
55
+ DbCombobox,
56
+ DbDetailsSheet,
57
+ DbDialog,
30
58
  DbLinkButton,
59
+ DbNavTree,
60
+ DbPopover,
61
+ DbSelect,
31
62
  DbSteps,
32
63
  DbTabs,
64
+ DbToc,
65
+ DbTooltip,
33
66
  DogsbayElement
34
67
  };
35
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/elements",
3
- "version": "0.2.0-beta.14",
3
+ "version": "0.2.0-beta.141",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -21,6 +21,10 @@
21
21
  "types": "./dist/db-accordion.d.ts",
22
22
  "import": "./dist/db-accordion.js"
23
23
  },
24
+ "./db-details-sheet": {
25
+ "types": "./dist/db-details-sheet.d.ts",
26
+ "import": "./dist/db-details-sheet.js"
27
+ },
24
28
  "./db-steps": {
25
29
  "types": "./dist/db-steps.d.ts",
26
30
  "import": "./dist/db-steps.js"
@@ -36,19 +40,47 @@
36
40
  "./db-link-button": {
37
41
  "types": "./dist/db-link-button.d.ts",
38
42
  "import": "./dist/db-link-button.js"
43
+ },
44
+ "./db-dialog": {
45
+ "types": "./dist/db-dialog.d.ts",
46
+ "import": "./dist/db-dialog.js"
47
+ },
48
+ "./db-popover": {
49
+ "types": "./dist/db-popover.d.ts",
50
+ "import": "./dist/db-popover.js"
51
+ },
52
+ "./db-tooltip": {
53
+ "types": "./dist/db-tooltip.d.ts",
54
+ "import": "./dist/db-tooltip.js"
55
+ },
56
+ "./db-select": {
57
+ "types": "./dist/db-select.d.ts",
58
+ "import": "./dist/db-select.js"
59
+ },
60
+ "./db-combobox": {
61
+ "types": "./dist/db-combobox.d.ts",
62
+ "import": "./dist/db-combobox.js"
63
+ },
64
+ "./db-nav-tree": {
65
+ "types": "./dist/db-nav-tree.d.ts",
66
+ "import": "./dist/db-nav-tree.js"
67
+ },
68
+ "./db-toc": {
69
+ "types": "./dist/db-toc.d.ts",
70
+ "import": "./dist/db-toc.js"
39
71
  }
40
72
  },
41
73
  "files": [
42
74
  "dist"
43
75
  ],
44
76
  "dependencies": {
45
- "@dogsbay/primitives": "0.2.0-beta.14"
77
+ "@dogsbay/primitives": "0.2.0-beta.141"
46
78
  },
47
79
  "devDependencies": {
48
- "happy-dom": "^20.8.9",
49
- "tsup": "^8.4.0",
50
- "typescript": "^5.8.0",
51
- "vitest": "^3.1.0"
80
+ "happy-dom": "^20.10.6",
81
+ "tsup": "^8.5.1",
82
+ "typescript": "^5.9.3",
83
+ "vitest": "^4.1.10"
52
84
  },
53
85
  "license": "MIT",
54
86
  "repository": {
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
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":[]}
@@ -1,28 +0,0 @@
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
@@ -1 +0,0 @@
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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}