@dogsbay/elements 0.2.0-beta.12 → 0.2.0-beta.120

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 (80) hide show
  1. package/dist/{base-BtvRtAsC.d.ts → base-D1Rz70fn.d.ts} +1 -0
  2. package/dist/chunk-3AEQ6KHV.js +70 -0
  3. package/dist/chunk-3AEQ6KHV.js.map +1 -0
  4. package/dist/chunk-3FMXAKOU.js +383 -0
  5. package/dist/chunk-3FMXAKOU.js.map +1 -0
  6. package/dist/{chunk-LVXR7KTB.js → chunk-4YPDR3W6.js} +41 -12
  7. package/dist/chunk-4YPDR3W6.js.map +1 -0
  8. package/dist/{chunk-7M7SFLKN.js → chunk-CLUADA3G.js} +5 -3
  9. package/dist/chunk-CLUADA3G.js.map +1 -0
  10. package/dist/chunk-EGU66XCL.js +116 -0
  11. package/dist/chunk-EGU66XCL.js.map +1 -0
  12. package/dist/{chunk-7BIVQSGP.js → chunk-ETBBSA3I.js} +5 -3
  13. package/dist/chunk-ETBBSA3I.js.map +1 -0
  14. package/dist/chunk-FIJZRZEN.js +90 -0
  15. package/dist/chunk-FIJZRZEN.js.map +1 -0
  16. package/dist/chunk-K6DPDBAG.js +72 -0
  17. package/dist/chunk-K6DPDBAG.js.map +1 -0
  18. package/dist/{chunk-TTNTPXBA.js → chunk-LAUNXWKJ.js} +5 -3
  19. package/dist/chunk-LAUNXWKJ.js.map +1 -0
  20. package/dist/chunk-MAD6XJY4.js +256 -0
  21. package/dist/chunk-MAD6XJY4.js.map +1 -0
  22. package/dist/chunk-MEOIAZDF.js +140 -0
  23. package/dist/chunk-MEOIAZDF.js.map +1 -0
  24. package/dist/{chunk-LFXZQ4YV.js → chunk-QSRUT67Y.js} +5 -3
  25. package/dist/chunk-QSRUT67Y.js.map +1 -0
  26. package/dist/chunk-S62ZVVO3.js +234 -0
  27. package/dist/chunk-S62ZVVO3.js.map +1 -0
  28. package/dist/chunk-SLJG53M7.js +208 -0
  29. package/dist/chunk-SLJG53M7.js.map +1 -0
  30. package/dist/{chunk-FWAAU5UY.js → chunk-V4P3UR4I.js} +5 -3
  31. package/dist/chunk-V4P3UR4I.js.map +1 -0
  32. package/dist/{chunk-5T4OXQA2.js → chunk-VW7HZY2B.js} +6 -6
  33. package/dist/chunk-VW7HZY2B.js.map +1 -0
  34. package/dist/db-accordion.d.ts +1 -1
  35. package/dist/db-accordion.js +2 -2
  36. package/dist/db-card.d.ts +1 -1
  37. package/dist/db-card.js +2 -2
  38. package/dist/db-code-block.d.ts +1 -1
  39. package/dist/db-code-block.js +2 -2
  40. package/dist/db-collapsible.d.ts +1 -1
  41. package/dist/db-collapsible.js +2 -2
  42. package/dist/db-combobox.d.ts +70 -0
  43. package/dist/db-combobox.js +9 -0
  44. package/dist/db-combobox.js.map +1 -0
  45. package/dist/db-dialog.d.ts +62 -0
  46. package/dist/db-dialog.js +9 -0
  47. package/dist/db-dialog.js.map +1 -0
  48. package/dist/db-link-button.d.ts +1 -1
  49. package/dist/db-link-button.js +2 -2
  50. package/dist/db-nav-tree.d.ts +83 -0
  51. package/dist/db-nav-tree.js +9 -0
  52. package/dist/db-nav-tree.js.map +1 -0
  53. package/dist/db-popover.d.ts +42 -0
  54. package/dist/db-popover.js +9 -0
  55. package/dist/db-popover.js.map +1 -0
  56. package/dist/db-select.d.ts +72 -0
  57. package/dist/db-select.js +9 -0
  58. package/dist/db-select.js.map +1 -0
  59. package/dist/db-steps.d.ts +1 -1
  60. package/dist/db-steps.js +2 -2
  61. package/dist/db-tabs.d.ts +28 -1
  62. package/dist/db-tabs.js +2 -2
  63. package/dist/db-toc.d.ts +32 -0
  64. package/dist/db-toc.js +8 -0
  65. package/dist/db-toc.js.map +1 -0
  66. package/dist/db-tooltip.d.ts +48 -0
  67. package/dist/db-tooltip.js +9 -0
  68. package/dist/db-tooltip.js.map +1 -0
  69. package/dist/index.d.ts +8 -1
  70. package/dist/index.js +40 -11
  71. package/package.json +34 -6
  72. package/dist/chunk-5T4OXQA2.js.map +0 -1
  73. package/dist/chunk-7BIVQSGP.js.map +0 -1
  74. package/dist/chunk-7M7SFLKN.js.map +0 -1
  75. package/dist/chunk-FWAAU5UY.js.map +0 -1
  76. package/dist/chunk-LFXZQ4YV.js.map +0 -1
  77. package/dist/chunk-LVXR7KTB.js.map +0 -1
  78. package/dist/chunk-TTNTPXBA.js.map +0 -1
  79. package/dist/chunk-XBMLE4N3.js +0 -28
  80. package/dist/chunk-XBMLE4N3.js.map +0 -1
@@ -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, ensureDefaultDisplay } 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 /**\n * A synced group follows only a value it HAS. Groups sharing a key need\n * not share a tab set (a web-only snippet group beside an all-SDK one), and\n * selecting a value with no trigger here left the group with every panel\n * hidden and no tab selected.\n */\n private has(value: string): boolean {\n return this.triggers.some((t) => t.dataset.value === 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 && this.has(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 && this.has(newValue)) {\n this.select(newValue);\n }\n }) as EventListener;\n\n /**\n * Descendants belonging to THIS tab group.\n *\n * Not `:scope >`, and not a bare descendant query — both were wrong\n * here, in opposite directions:\n *\n * - Panels used `:scope > [data-part='content']`, so any wrapper\n * between the element and its panels hid them. The vertical example\n * wraps its list and panels in a flex row to sit them side by side,\n * so `panels` was EMPTY: triggers moved `aria-selected`, and the\n * content never changed. Nothing threw, and the server-rendered\n * initial state looked right, so it read as working.\n * - Triggers used a bare descendant query, which would reach into a\n * NESTED tab group and drive the wrong panels.\n *\n * `closest(\"db-tabs\") === this` allows arbitrary wrappers while\n * stopping at a nested group, which is a real case — Obsidian\n * alternates fence characters by depth precisely so tabs can nest.\n */\n private own(selector: string): HTMLElement[] {\n return (\n Array.from(this.querySelectorAll(selector)) as HTMLElement[]\n ).filter((el) => el.closest(\"db-tabs\") === this);\n }\n\n protected setup() {\n const list = this.own(\"[data-part='list']\")[0] ?? null;\n if (!list) return;\n this.list = list;\n\n this.triggers = this.own(\"[data-part='trigger']\");\n this.panels = this.own(\"[data-part='content']\");\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\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-tabs\")) {\n customElements.define(\"db-tabs\", DbTabs);\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
- DogsbayElement
3
- } from "./chunk-XBMLE4N3.js";
2
+ DogsbayElement,
3
+ ensureDefaultDisplay
4
+ } from "./chunk-K6DPDBAG.js";
4
5
 
5
6
  // src/db-accordion.ts
6
7
  import { CompositeNavigation } from "@dogsbay/primitives/composite";
@@ -85,6 +86,7 @@ var DbAccordion = class extends DogsbayElement {
85
86
  );
86
87
  }
87
88
  };
89
+ ensureDefaultDisplay();
88
90
  if (!customElements.get("db-accordion")) {
89
91
  customElements.define("db-accordion", DbAccordion);
90
92
  }
@@ -92,4 +94,4 @@ if (!customElements.get("db-accordion")) {
92
94
  export {
93
95
  DbAccordion
94
96
  };
95
- //# sourceMappingURL=chunk-7M7SFLKN.js.map
97
+ //# sourceMappingURL=chunk-CLUADA3G.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, ensureDefaultDisplay } 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\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-accordion\")) {\n customElements.define(\"db-accordion\", DbAccordion);\n}\n"],"mappings":";;;;;;AAAA,SAAS,2BAA2B;AACpC,SAAS,mBAAmB;AAyBrB,IAAM,cAAN,cAA0B,eAAe;AAAA,EACtC,QAAyB,CAAC;AAAA,EAC1B,MAAkC;AAAA,EAClC,aAAa,oBAAI,IAAY;AAAA,EAC7B,OAA8B;AAAA,EAE5B,QAAQ;AAChB,SAAK,OACF,KAAK,aAAa,MAAM,KAA+B;AAC1D,UAAM,aAAa,KAAK,aAAa,eAAe,KAAK;AACzD,UAAM,gBAAgB,aAAa,WAAW,MAAM,GAAG,IAAI,CAAC;AAE5D,UAAM,UAAU,MAAM;AAAA,MACpB,KAAK,iBAAiB,oBAAoB;AAAA,IAC5C;AAEA,SAAK,QAAQ,QACV,IAAI,CAAC,OAAO;AACX,YAAM,UAAU,GAAG,cAA2B,uBAAuB;AACrE,YAAM,UAAU,GAAG,cAA2B,uBAAuB;AACrE,UAAI,CAAC,WAAW,CAAC,QAAS,QAAO;AAEjC,YAAM,QAAQ,GAAG,QAAQ,SAAS;AAClC,YAAM,WAAW,GAAG,aAAa,eAAe;AAEhD,UAAI,UAAU;AACZ,gBAAQ,aAAa,YAAY,EAAE;AACnC,gBAAQ,aAAa,iBAAiB,MAAM;AAAA,MAC9C;AAEA,YAAM,cAAc,IAAI,YAAY,SAAS,SAAS;AAAA,QACpD,UAAU,CAAC,SAAS;AAClB,cAAI,MAAM;AACR,iBAAK,eAAe,KAAK;AAAA,UAC3B,OAAO;AACL,iBAAK,gBAAgB,KAAK;AAAA,UAC5B;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,EAAE,IAAI,OAAO,aAAa,SAAS;AAAA,IAC5C,CAAC,EACA,OAAO,OAAO;AAGjB,SAAK,MAAM,IAAI,oBAAoB,MAAM,yBAAyB;AAAA,MAChE,aAAa;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAED,SAAK,IAAI,SAAS;AAGlB,SAAK,MAAM,QAAQ,CAAC,MAAM,MAAM;AAC9B,WAAK,YAAY,QAAQ,aAAa,YAAY,MAAM,IAAI,MAAM,IAAI;AAAA,IACxE,CAAC;AAGD,kBAAc,QAAQ,CAAC,UAAU;AAC/B,YAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS,CAAC,EAAE,QAAQ;AACpE,UAAI,MAAM;AACR,aAAK,YAAY,OAAO;AAAA,MAC1B;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe,OAAe;AAEpC,QAAI,KAAK,SAAS,UAAU;AAC1B,iBAAW,aAAa,KAAK,YAAY;AACvC,YAAI,cAAc,OAAO;AACvB,gBAAM,QAAQ,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS;AAC1D,cAAI,MAAO,OAAM,YAAY,SAAS;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAEA,SAAK,WAAW,IAAI,KAAK;AACzB,UAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACrD,QAAI,KAAM,MAAK,GAAG,aAAa,cAAc,MAAM;AAEnD,SAAK;AAAA,MACH,IAAI,YAAY,uBAAuB;AAAA,QACrC,QAAQ,EAAE,OAAO,MAAM,MAAM,YAAY,CAAC,GAAG,KAAK,UAAU,EAAE;AAAA,QAC9D,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,gBAAgB,OAAe;AACrC,SAAK,WAAW,OAAO,KAAK;AAC5B,UAAM,OAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACrD,QAAI,KAAM,MAAK,GAAG,gBAAgB,YAAY;AAE9C,SAAK;AAAA,MACH,IAAI,YAAY,uBAAuB;AAAA,QACrC,QAAQ,EAAE,OAAO,MAAM,OAAO,YAAY,CAAC,GAAG,KAAK,UAAU,EAAE;AAAA,QAC/D,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,qBAAqB;AAErB,IAAI,CAAC,eAAe,IAAI,cAAc,GAAG;AACvC,iBAAe,OAAO,gBAAgB,WAAW;AACnD;","names":[]}
@@ -0,0 +1,116 @@
1
+ import {
2
+ focusables,
3
+ hideFloating,
4
+ ownOne,
5
+ resolveAsChild,
6
+ showFloating,
7
+ uid
8
+ } from "./chunk-3AEQ6KHV.js";
9
+ import {
10
+ DogsbayElement,
11
+ ensureDefaultDisplay
12
+ } from "./chunk-K6DPDBAG.js";
13
+
14
+ // src/db-popover.ts
15
+ import { DismissController } from "@dogsbay/primitives/dismiss";
16
+ import { setupFloating } from "@dogsbay/primitives/floating";
17
+ var DbPopover = class extends DogsbayElement {
18
+ trigger = null;
19
+ content = null;
20
+ dismiss = null;
21
+ cleanupFloating = null;
22
+ _open = false;
23
+ get open() {
24
+ return this._open;
25
+ }
26
+ onTriggerClick = () => this.toggle();
27
+ onContentClick = (e) => {
28
+ const close = e.target.closest("[data-part='close']");
29
+ if (close && close.closest("db-popover") === this) this.close("close-press");
30
+ };
31
+ setup() {
32
+ this.trigger = resolveAsChild(ownOne(this, "[data-part='trigger']"));
33
+ this.content = ownOne(this, "[data-part='content']");
34
+ if (!this.trigger || !this.content) return;
35
+ const content = this.content;
36
+ content.id ||= uid("db-popover");
37
+ if (!content.hasAttribute("role")) content.setAttribute("role", "dialog");
38
+ if (!content.hasAttribute("aria-labelledby") && !content.hasAttribute("aria-label")) {
39
+ this.trigger.id ||= uid("db-popover-trigger");
40
+ content.setAttribute("aria-labelledby", this.trigger.id);
41
+ }
42
+ content.hidden = true;
43
+ this.trigger.setAttribute("aria-haspopup", "dialog");
44
+ this.trigger.setAttribute("aria-controls", content.id);
45
+ this.trigger.setAttribute("aria-expanded", "false");
46
+ this.setState("closed");
47
+ this.dismiss = new DismissController(content, { onDismiss: (reason) => this.close(reason) });
48
+ }
49
+ connect() {
50
+ this.trigger?.addEventListener("click", this.onTriggerClick);
51
+ this.content?.addEventListener("click", this.onContentClick);
52
+ }
53
+ disconnect() {
54
+ this.trigger?.removeEventListener("click", this.onTriggerClick);
55
+ this.content?.removeEventListener("click", this.onContentClick);
56
+ if (this._open) this.close("api");
57
+ }
58
+ setState(state) {
59
+ this.setAttribute("data-state", state);
60
+ this.content?.setAttribute("data-state", state);
61
+ }
62
+ placement() {
63
+ const attr = this.getAttribute("placement");
64
+ if (attr) return attr;
65
+ const side = this.content?.dataset.side || "bottom";
66
+ const align = this.content?.dataset.align || "center";
67
+ return `${side}${align !== "center" ? `-${align}` : ""}`;
68
+ }
69
+ toggle() {
70
+ if (this._open) this.close("trigger-press");
71
+ else this.show();
72
+ }
73
+ show() {
74
+ const { trigger, content } = this;
75
+ if (!trigger || !content || this._open) return;
76
+ this._open = true;
77
+ const layer = showFloating(content);
78
+ this.setState("open");
79
+ trigger.setAttribute("aria-expanded", "true");
80
+ this.cleanupFloating = setupFloating(trigger, content, {
81
+ placement: this.placement(),
82
+ offset: Number(this.getAttribute("offset") ?? 8),
83
+ strategy: layer === "top-layer" ? "fixed" : "absolute"
84
+ });
85
+ this.dismiss?.activate();
86
+ if (!this.hasAttribute("no-autofocus")) {
87
+ requestAnimationFrame(() => {
88
+ if (this._open) (focusables(content)[0] ?? content).focus({ preventScroll: true });
89
+ });
90
+ }
91
+ this.dispatchEvent(new CustomEvent("db-popover:open", { bubbles: true }));
92
+ }
93
+ close(reason = "api") {
94
+ const { trigger, content } = this;
95
+ if (!trigger || !content || !this._open) return;
96
+ this._open = false;
97
+ this.dismiss?.deactivate();
98
+ this.cleanupFloating?.();
99
+ this.cleanupFloating = null;
100
+ const hadFocus = content.contains(document.activeElement);
101
+ hideFloating(content);
102
+ this.setState("closed");
103
+ trigger.setAttribute("aria-expanded", "false");
104
+ if (reason !== "outside-press" && (hadFocus || reason === "escape-key" || reason === "close-press")) trigger.focus();
105
+ this.dispatchEvent(new CustomEvent("db-popover:close", { detail: { reason }, bubbles: true }));
106
+ }
107
+ };
108
+ ensureDefaultDisplay();
109
+ if (!customElements.get("db-popover")) {
110
+ customElements.define("db-popover", DbPopover);
111
+ }
112
+
113
+ export {
114
+ DbPopover
115
+ };
116
+ //# sourceMappingURL=chunk-EGU66XCL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-popover.ts"],"sourcesContent":["import { DismissController } from \"@dogsbay/primitives/dismiss\";\nimport { setupFloating, type FloatingOptions } from \"@dogsbay/primitives/floating\";\nimport { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\nimport { focusables, hideFloating, ownOne, resolveAsChild, showFloating, uid } from \"./utils.js\";\n\ntype Placement = NonNullable<FloatingOptions[\"placement\"]>;\n\n/**\n * `<db-popover>` — Non-modal floating panel (APG \"Dialog\", non-modal).\n *\n * Same parts as the Astro Popover. The content opens in the browser's top\n * layer (Popover API) where available, so no ancestor's `overflow` clips it\n * and it needs no portal, and floating-ui positions it next to the trigger.\n *\n * Attributes:\n * placement — \"bottom\" (default), \"top-start\", … (or data-side/data-align on the content)\n * offset — gap in px (default 8)\n * no-autofocus — keep focus on the trigger when opening\n *\n * Parts: [data-part=\"trigger\"], [data-part=\"content\"], [data-part=\"close\"]\n *\n * Focus: opening moves focus to the first focusable element in the content.\n * Escape and the close part return focus to the trigger; an outside click\n * leaves focus where the user clicked.\n *\n * Events: db-popover:open, db-popover:close (detail: { reason })\n */\nexport class DbPopover extends DogsbayElement {\n private trigger: HTMLElement | null = null;\n private content: HTMLElement | null = null;\n private dismiss: DismissController | null = null;\n private cleanupFloating: (() => void) | null = null;\n private _open = false;\n\n get open(): boolean {\n return this._open;\n }\n\n private onTriggerClick = () => this.toggle();\n\n private onContentClick = (e: Event) => {\n const close = (e.target as HTMLElement).closest(\"[data-part='close']\");\n if (close && close.closest(\"db-popover\") === this) this.close(\"close-press\");\n };\n\n protected setup() {\n this.trigger = resolveAsChild(ownOne(this, \"[data-part='trigger']\"));\n this.content = ownOne(this, \"[data-part='content']\");\n if (!this.trigger || !this.content) return;\n const content = this.content;\n content.id ||= uid(\"db-popover\");\n if (!content.hasAttribute(\"role\")) content.setAttribute(\"role\", \"dialog\");\n if (!content.hasAttribute(\"aria-labelledby\") && !content.hasAttribute(\"aria-label\")) {\n this.trigger.id ||= uid(\"db-popover-trigger\");\n content.setAttribute(\"aria-labelledby\", this.trigger.id);\n }\n content.hidden = true;\n this.trigger.setAttribute(\"aria-haspopup\", \"dialog\");\n this.trigger.setAttribute(\"aria-controls\", content.id);\n this.trigger.setAttribute(\"aria-expanded\", \"false\");\n this.setState(\"closed\");\n this.dismiss = new DismissController(content, { onDismiss: (reason) => this.close(reason) });\n }\n\n protected connect() {\n this.trigger?.addEventListener(\"click\", this.onTriggerClick);\n this.content?.addEventListener(\"click\", this.onContentClick);\n }\n\n protected disconnect() {\n this.trigger?.removeEventListener(\"click\", this.onTriggerClick);\n this.content?.removeEventListener(\"click\", this.onContentClick);\n if (this._open) this.close(\"api\");\n }\n\n private setState(state: \"open\" | \"closed\") {\n this.setAttribute(\"data-state\", state);\n this.content?.setAttribute(\"data-state\", state);\n }\n\n private placement(): Placement {\n const attr = this.getAttribute(\"placement\");\n if (attr) return attr as Placement;\n const side = this.content?.dataset.side || \"bottom\";\n const align = this.content?.dataset.align || \"center\";\n return `${side}${align !== \"center\" ? `-${align}` : \"\"}` as Placement;\n }\n\n toggle() {\n if (this._open) this.close(\"trigger-press\");\n else this.show();\n }\n\n show() {\n const { trigger, content } = this;\n if (!trigger || !content || this._open) return;\n this._open = true;\n const layer = showFloating(content);\n this.setState(\"open\");\n trigger.setAttribute(\"aria-expanded\", \"true\");\n this.cleanupFloating = setupFloating(trigger, content, {\n placement: this.placement(),\n offset: Number(this.getAttribute(\"offset\") ?? 8),\n strategy: layer === \"top-layer\" ? \"fixed\" : \"absolute\",\n });\n this.dismiss?.activate();\n if (!this.hasAttribute(\"no-autofocus\")) {\n requestAnimationFrame(() => {\n if (this._open) (focusables(content)[0] ?? content).focus({ preventScroll: true });\n });\n }\n this.dispatchEvent(new CustomEvent(\"db-popover:open\", { bubbles: true }));\n }\n\n close(reason: string = \"api\") {\n const { trigger, content } = this;\n if (!trigger || !content || !this._open) return;\n this._open = false;\n this.dismiss?.deactivate();\n this.cleanupFloating?.();\n this.cleanupFloating = null;\n const hadFocus = content.contains(document.activeElement);\n hideFloating(content);\n this.setState(\"closed\");\n trigger.setAttribute(\"aria-expanded\", \"false\");\n if (reason !== \"outside-press\" && (hadFocus || reason === \"escape-key\" || reason === \"close-press\")) trigger.focus();\n this.dispatchEvent(new CustomEvent(\"db-popover:close\", { detail: { reason }, bubbles: true }));\n }\n}\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-popover\")) {\n customElements.define(\"db-popover\", DbPopover);\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
- DogsbayElement
3
- } from "./chunk-XBMLE4N3.js";
2
+ DogsbayElement,
3
+ ensureDefaultDisplay
4
+ } from "./chunk-K6DPDBAG.js";
4
5
 
5
6
  // src/db-card.ts
6
7
  var DbCard = class extends DogsbayElement {
@@ -42,6 +43,7 @@ var DbCard = class extends DogsbayElement {
42
43
  );
43
44
  }
44
45
  };
46
+ ensureDefaultDisplay();
45
47
  if (!customElements.get("db-card")) {
46
48
  customElements.define("db-card", DbCard);
47
49
  }
@@ -49,4 +51,4 @@ if (!customElements.get("db-card")) {
49
51
  export {
50
52
  DbCard
51
53
  };
52
- //# sourceMappingURL=chunk-7BIVQSGP.js.map
54
+ //# sourceMappingURL=chunk-ETBBSA3I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-card.ts"],"sourcesContent":["import { DogsbayElement, ensureDefaultDisplay } 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\nensureDefaultDisplay();\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,qBAAqB;AAErB,IAAI,CAAC,eAAe,IAAI,SAAS,GAAG;AAClC,iBAAe,OAAO,WAAW,MAAM;AACzC;","names":[]}
@@ -0,0 +1,90 @@
1
+ import {
2
+ DogsbayElement,
3
+ ensureDefaultDisplay
4
+ } from "./chunk-K6DPDBAG.js";
5
+
6
+ // src/db-toc.ts
7
+ var DbToc = class extends DogsbayElement {
8
+ links = [];
9
+ headings = [];
10
+ observer = null;
11
+ active = null;
12
+ slugOf(a) {
13
+ return a.getAttribute("data-toc-slug") ?? safeDecode(a.getAttribute("href").slice(1));
14
+ }
15
+ // Headings in a short tail never reach the observed band; at the bottom of the
16
+ // page the last one is current.
17
+ onScroll = () => {
18
+ const doc = document.documentElement;
19
+ if (window.innerHeight + window.scrollY >= doc.scrollHeight - 2 && this.headings.length) {
20
+ this.setActive(this.headings[this.headings.length - 1].id);
21
+ }
22
+ };
23
+ setup() {
24
+ this.links = Array.from(this.querySelectorAll("a[href^='#'], a[data-toc-link]"));
25
+ }
26
+ onHash = () => {
27
+ const id = safeDecode(location.hash.slice(1));
28
+ if (id && this.headings.some((h) => h.id === id)) this.setActive(id);
29
+ };
30
+ connect() {
31
+ this.headings = this.links.map((a) => document.getElementById(this.slugOf(a))).filter((h) => !!h);
32
+ if (!this.headings.length) return;
33
+ const offset = Number(this.getAttribute("offset") ?? 80);
34
+ if (typeof IntersectionObserver !== "undefined") {
35
+ this.observer = new IntersectionObserver(
36
+ (entries) => {
37
+ const hit = entries.find((e) => e.isIntersecting);
38
+ if (hit) return this.setActive(hit.target.id);
39
+ this.setActive(this.lastAbove(offset)?.id ?? null);
40
+ },
41
+ { rootMargin: `-${offset}px 0px -70% 0px`, threshold: 0 }
42
+ );
43
+ this.headings.forEach((h) => this.observer.observe(h));
44
+ }
45
+ window.addEventListener("hashchange", this.onHash);
46
+ window.addEventListener("scroll", this.onScroll, { passive: true });
47
+ this.setActive(this.lastAbove(offset)?.id ?? this.headings[0].id);
48
+ }
49
+ disconnect() {
50
+ this.observer?.disconnect();
51
+ this.observer = null;
52
+ window.removeEventListener("hashchange", this.onHash);
53
+ window.removeEventListener("scroll", this.onScroll);
54
+ }
55
+ lastAbove(offset) {
56
+ let last = null;
57
+ for (const h of this.headings) if (h.getBoundingClientRect().top <= offset + 20) last = h;
58
+ return last;
59
+ }
60
+ setActive(id) {
61
+ if (!id || id === this.active) return;
62
+ this.active = id;
63
+ for (const a of this.links) {
64
+ if (this.slugOf(a) === id) {
65
+ a.setAttribute("aria-current", "location");
66
+ a.setAttribute("data-active", "");
67
+ } else {
68
+ a.removeAttribute("aria-current");
69
+ a.removeAttribute("data-active");
70
+ }
71
+ }
72
+ this.dispatchEvent(new CustomEvent("db-toc:change", { detail: { id }, bubbles: true }));
73
+ }
74
+ };
75
+ function safeDecode(s) {
76
+ try {
77
+ return decodeURIComponent(s);
78
+ } catch {
79
+ return s;
80
+ }
81
+ }
82
+ ensureDefaultDisplay();
83
+ if (!customElements.get("db-toc")) {
84
+ customElements.define("db-toc", DbToc);
85
+ }
86
+
87
+ export {
88
+ DbToc
89
+ };
90
+ //# sourceMappingURL=chunk-FIJZRZEN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-toc.ts"],"sourcesContent":["import { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\n\n/**\n * `<db-toc>` — \"On this page\" links that follow the reader (scroll spy).\n *\n * Wraps plain in-page links, so it works as a list of links without\n * JavaScript. The link for the section in view gets `aria-current=\"location\"`\n * and `data-active` (the Astro TableOfContents contract).\n *\n * Links: `a[href^=\"#\"]`, or `[data-toc-link][data-toc-slug]` as in the Astro component.\n *\n * Attributes:\n * offset — px hidden under a sticky header (default 80)\n *\n * Events: db-toc:change (detail: { id })\n */\nexport class DbToc extends DogsbayElement {\n private links: HTMLAnchorElement[] = [];\n private headings: HTMLElement[] = [];\n private observer: IntersectionObserver | null = null;\n private active: string | null = null;\n\n private slugOf(a: HTMLAnchorElement): string {\n return a.getAttribute(\"data-toc-slug\") ?? safeDecode(a.getAttribute(\"href\")!.slice(1));\n }\n\n // Headings in a short tail never reach the observed band; at the bottom of the\n // page the last one is current.\n private onScroll = () => {\n const doc = document.documentElement;\n if (window.innerHeight + window.scrollY >= doc.scrollHeight - 2 && this.headings.length) {\n this.setActive(this.headings[this.headings.length - 1].id);\n }\n };\n\n protected setup() {\n this.links = Array.from(this.querySelectorAll<HTMLAnchorElement>(\"a[href^='#'], a[data-toc-link]\"));\n }\n\n private onHash = () => {\n const id = safeDecode(location.hash.slice(1));\n if (id && this.headings.some((h) => h.id === id)) this.setActive(id);\n };\n\n protected connect() {\n this.headings = this.links.map((a) => document.getElementById(this.slugOf(a))).filter((h): h is HTMLElement => !!h);\n if (!this.headings.length) return;\n const offset = Number(this.getAttribute(\"offset\") ?? 80);\n if (typeof IntersectionObserver !== \"undefined\") {\n this.observer = new IntersectionObserver(\n (entries) => {\n const hit = entries.find((e) => e.isIntersecting);\n if (hit) return this.setActive(hit.target.id);\n this.setActive(this.lastAbove(offset)?.id ?? null);\n },\n { rootMargin: `-${offset}px 0px -70% 0px`, threshold: 0 },\n );\n this.headings.forEach((h) => this.observer!.observe(h));\n }\n window.addEventListener(\"hashchange\", this.onHash);\n window.addEventListener(\"scroll\", this.onScroll, { passive: true });\n this.setActive(this.lastAbove(offset)?.id ?? this.headings[0].id);\n }\n\n protected disconnect() {\n this.observer?.disconnect();\n this.observer = null;\n window.removeEventListener(\"hashchange\", this.onHash);\n window.removeEventListener(\"scroll\", this.onScroll);\n }\n\n private lastAbove(offset: number): HTMLElement | null {\n let last: HTMLElement | null = null;\n for (const h of this.headings) if (h.getBoundingClientRect().top <= offset + 20) last = h;\n return last;\n }\n\n private setActive(id: string | null) {\n if (!id || id === this.active) return;\n this.active = id;\n for (const a of this.links) {\n if (this.slugOf(a) === id) {\n a.setAttribute(\"aria-current\", \"location\");\n a.setAttribute(\"data-active\", \"\");\n } else {\n a.removeAttribute(\"aria-current\");\n a.removeAttribute(\"data-active\");\n }\n }\n this.dispatchEvent(new CustomEvent(\"db-toc:change\", { detail: { id }, bubbles: true }));\n }\n}\n\nfunction safeDecode(s: string): string {\n try {\n return decodeURIComponent(s);\n } catch {\n return s;\n }\n}\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-toc\")) {\n customElements.define(\"db-toc\", DbToc);\n}\n"],"mappings":";;;;;;AAgBO,IAAM,QAAN,cAAoB,eAAe;AAAA,EAChC,QAA6B,CAAC;AAAA,EAC9B,WAA0B,CAAC;AAAA,EAC3B,WAAwC;AAAA,EACxC,SAAwB;AAAA,EAExB,OAAO,GAA8B;AAC3C,WAAO,EAAE,aAAa,eAAe,KAAK,WAAW,EAAE,aAAa,MAAM,EAAG,MAAM,CAAC,CAAC;AAAA,EACvF;AAAA;AAAA;AAAA,EAIQ,WAAW,MAAM;AACvB,UAAM,MAAM,SAAS;AACrB,QAAI,OAAO,cAAc,OAAO,WAAW,IAAI,eAAe,KAAK,KAAK,SAAS,QAAQ;AACvF,WAAK,UAAU,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC,EAAE,EAAE;AAAA,IAC3D;AAAA,EACF;AAAA,EAEU,QAAQ;AAChB,SAAK,QAAQ,MAAM,KAAK,KAAK,iBAAoC,gCAAgC,CAAC;AAAA,EACpG;AAAA,EAEQ,SAAS,MAAM;AACrB,UAAM,KAAK,WAAW,SAAS,KAAK,MAAM,CAAC,CAAC;AAC5C,QAAI,MAAM,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG,MAAK,UAAU,EAAE;AAAA,EACrE;AAAA,EAEU,UAAU;AAClB,SAAK,WAAW,KAAK,MAAM,IAAI,CAAC,MAAM,SAAS,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,MAAwB,CAAC,CAAC,CAAC;AAClH,QAAI,CAAC,KAAK,SAAS,OAAQ;AAC3B,UAAM,SAAS,OAAO,KAAK,aAAa,QAAQ,KAAK,EAAE;AACvD,QAAI,OAAO,yBAAyB,aAAa;AAC/C,WAAK,WAAW,IAAI;AAAA,QAClB,CAAC,YAAY;AACX,gBAAM,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,cAAc;AAChD,cAAI,IAAK,QAAO,KAAK,UAAU,IAAI,OAAO,EAAE;AAC5C,eAAK,UAAU,KAAK,UAAU,MAAM,GAAG,MAAM,IAAI;AAAA,QACnD;AAAA,QACA,EAAE,YAAY,IAAI,MAAM,mBAAmB,WAAW,EAAE;AAAA,MAC1D;AACA,WAAK,SAAS,QAAQ,CAAC,MAAM,KAAK,SAAU,QAAQ,CAAC,CAAC;AAAA,IACxD;AACA,WAAO,iBAAiB,cAAc,KAAK,MAAM;AACjD,WAAO,iBAAiB,UAAU,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAClE,SAAK,UAAU,KAAK,UAAU,MAAM,GAAG,MAAM,KAAK,SAAS,CAAC,EAAE,EAAE;AAAA,EAClE;AAAA,EAEU,aAAa;AACrB,SAAK,UAAU,WAAW;AAC1B,SAAK,WAAW;AAChB,WAAO,oBAAoB,cAAc,KAAK,MAAM;AACpD,WAAO,oBAAoB,UAAU,KAAK,QAAQ;AAAA,EACpD;AAAA,EAEQ,UAAU,QAAoC;AACpD,QAAI,OAA2B;AAC/B,eAAW,KAAK,KAAK,SAAU,KAAI,EAAE,sBAAsB,EAAE,OAAO,SAAS,GAAI,QAAO;AACxF,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,IAAmB;AACnC,QAAI,CAAC,MAAM,OAAO,KAAK,OAAQ;AAC/B,SAAK,SAAS;AACd,eAAW,KAAK,KAAK,OAAO;AAC1B,UAAI,KAAK,OAAO,CAAC,MAAM,IAAI;AACzB,UAAE,aAAa,gBAAgB,UAAU;AACzC,UAAE,aAAa,eAAe,EAAE;AAAA,MAClC,OAAO;AACL,UAAE,gBAAgB,cAAc;AAChC,UAAE,gBAAgB,aAAa;AAAA,MACjC;AAAA,IACF;AACA,SAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQ,EAAE,GAAG,GAAG,SAAS,KAAK,CAAC,CAAC;AAAA,EACxF;AACF;AAEA,SAAS,WAAW,GAAmB;AACrC,MAAI;AACF,WAAO,mBAAmB,CAAC;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,qBAAqB;AAErB,IAAI,CAAC,eAAe,IAAI,QAAQ,GAAG;AACjC,iBAAe,OAAO,UAAU,KAAK;AACvC;","names":[]}
@@ -0,0 +1,72 @@
1
+ // src/base.ts
2
+ var DogsbayElement = class extends HTMLElement {
3
+ _initialized = false;
4
+ _deferred = false;
5
+ connectedCallback() {
6
+ if (!this._initialized && !this.firstElementChild && typeof document !== "undefined" && document.readyState === "loading") {
7
+ if (!this._deferred) {
8
+ this._deferred = true;
9
+ document.addEventListener(
10
+ "DOMContentLoaded",
11
+ () => {
12
+ this._deferred = false;
13
+ if (this.isConnected) this.connectedCallback();
14
+ },
15
+ { once: true }
16
+ );
17
+ }
18
+ return;
19
+ }
20
+ if (!this._initialized) {
21
+ this.setup();
22
+ this._initialized = true;
23
+ }
24
+ this.connect();
25
+ }
26
+ disconnectedCallback() {
27
+ this.disconnect();
28
+ }
29
+ /** One-time setup: query children, generate IDs, set ARIA. */
30
+ setup() {
31
+ }
32
+ /** Called on every connect: attach event listeners. */
33
+ connect() {
34
+ }
35
+ /** Called on every disconnect: remove event listeners. */
36
+ disconnect() {
37
+ }
38
+ };
39
+ var DEFAULT_DISPLAY = {
40
+ "db-tabs": "block",
41
+ "db-accordion": "block",
42
+ "db-collapsible": "block",
43
+ "db-card": "block",
44
+ "db-steps": "block",
45
+ "db-code-block": "block",
46
+ // A link styled as a button — sits in a line of prose.
47
+ "db-link-button": "inline-block",
48
+ // A dialog host only groups its trigger and content; it takes no box of its own.
49
+ "db-dialog": "contents",
50
+ "db-popover": "inline-block",
51
+ "db-tooltip": "inline-block",
52
+ "db-select": "inline-block",
53
+ "db-combobox": "block",
54
+ "db-nav-tree": "block",
55
+ "db-toc": "block"
56
+ };
57
+ var STYLE_ID = "dogsbay-elements-display";
58
+ function ensureDefaultDisplay() {
59
+ if (typeof document === "undefined") return;
60
+ if (document.getElementById(STYLE_ID)) return;
61
+ const rules = Object.entries(DEFAULT_DISPLAY).map(([tag, display]) => `:where(${tag}){display:${display}}`).join("");
62
+ const style = document.createElement("style");
63
+ style.id = STYLE_ID;
64
+ style.textContent = rules;
65
+ document.head.prepend(style);
66
+ }
67
+
68
+ export {
69
+ DogsbayElement,
70
+ ensureDefaultDisplay
71
+ };
72
+ //# sourceMappingURL=chunk-K6DPDBAG.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 private _deferred = false;\n\n connectedCallback() {\n // A script that runs before the markup is parsed (a classic script in\n // <head>) connects each element at its start tag, before its children\n // exist. Wait for the document so setup sees the whole subtree.\n if (!this._initialized && !this.firstElementChild && typeof document !== \"undefined\" && document.readyState === \"loading\") {\n // One pending deferral: moving the element while the page loads must not\n // queue a second one (connect() would then run twice).\n if (!this._deferred) {\n this._deferred = true;\n document.addEventListener(\n \"DOMContentLoaded\",\n () => {\n this._deferred = false;\n if (this.isConnected) this.connectedCallback();\n },\n { once: true },\n );\n }\n return;\n }\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\n/**\n * Default `display` for each element.\n *\n * Custom elements have NO user-agent style, so an unstyled one is\n * `display: inline`. That is silently wrong for a container: `w-full`\n * does nothing on an inline box, and a border renders as detached\n * fragments at the start and end of the inline run rather than around\n * the content.\n *\n * `<db-tabs>` carries `border rounded-lg overflow-hidden w-full` from\n * Tabs.astro, so it showed short vertical bars above and below every\n * tab group on every generated site. The other six had the same defect\n * without a border to make it visible.\n */\nconst DEFAULT_DISPLAY: Record<string, string> = {\n \"db-tabs\": \"block\",\n \"db-accordion\": \"block\",\n \"db-collapsible\": \"block\",\n \"db-card\": \"block\",\n \"db-steps\": \"block\",\n \"db-code-block\": \"block\",\n // A link styled as a button — sits in a line of prose.\n \"db-link-button\": \"inline-block\",\n // A dialog host only groups its trigger and content; it takes no box of its own.\n \"db-dialog\": \"contents\",\n \"db-popover\": \"inline-block\",\n \"db-tooltip\": \"inline-block\",\n \"db-select\": \"inline-block\",\n \"db-combobox\": \"block\",\n \"db-nav-tree\": \"block\",\n \"db-toc\": \"block\",\n};\n\nconst STYLE_ID = \"dogsbay-elements-display\";\n\n/**\n * Give the elements a sane default `display`.\n *\n * Injected from here rather than shipped as CSS because a Dogsbay site\n * scaffolds `global.css` ONCE and copies UI components as source — so\n * neither updates when a package does. The element JS is the only part\n * of an existing site that a version bump actually reaches.\n *\n * `:where()` keeps specificity at zero, so ANY author rule or utility\n * class overrides it — this sets a default, it does not win arguments.\n *\n * Idempotent: safe to call from every element module, and Obsidian's\n * virtual scrolling re-registers freely.\n */\nexport function ensureDefaultDisplay(): void {\n if (typeof document === \"undefined\") return;\n if (document.getElementById(STYLE_ID)) return;\n\n const rules = Object.entries(DEFAULT_DISPLAY)\n .map(([tag, display]) => `:where(${tag}){display:${display}}`)\n .join(\"\");\n\n const style = document.createElement(\"style\");\n style.id = STYLE_ID;\n style.textContent = rules;\n // Prepend so a later author stylesheet wins on equal specificity.\n document.head.prepend(style);\n}\n"],"mappings":";AAOO,IAAe,iBAAf,cAAsC,YAAY;AAAA,EAC/C,eAAe;AAAA,EACf,YAAY;AAAA,EAEpB,oBAAoB;AAIlB,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,qBAAqB,OAAO,aAAa,eAAe,SAAS,eAAe,WAAW;AAGzH,UAAI,CAAC,KAAK,WAAW;AACnB,aAAK,YAAY;AACjB,iBAAS;AAAA,UACP;AAAA,UACA,MAAM;AACJ,iBAAK,YAAY;AACjB,gBAAI,KAAK,YAAa,MAAK,kBAAkB;AAAA,UAC/C;AAAA,UACA,EAAE,MAAM,KAAK;AAAA,QACf;AAAA,MACF;AACA;AAAA,IACF;AACA,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;AAgBA,IAAM,kBAA0C;AAAA,EAC9C,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,iBAAiB;AAAA;AAAA,EAEjB,kBAAkB;AAAA;AAAA,EAElB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,aAAa;AAAA,EACb,eAAe;AAAA,EACf,eAAe;AAAA,EACf,UAAU;AACZ;AAEA,IAAM,WAAW;AAgBV,SAAS,uBAA6B;AAC3C,MAAI,OAAO,aAAa,YAAa;AACrC,MAAI,SAAS,eAAe,QAAQ,EAAG;AAEvC,QAAM,QAAQ,OAAO,QAAQ,eAAe,EACzC,IAAI,CAAC,CAAC,KAAK,OAAO,MAAM,UAAU,GAAG,aAAa,OAAO,GAAG,EAC5D,KAAK,EAAE;AAEV,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,cAAc;AAEpB,WAAS,KAAK,QAAQ,KAAK;AAC7B;","names":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
- DogsbayElement
3
- } from "./chunk-XBMLE4N3.js";
2
+ DogsbayElement,
3
+ ensureDefaultDisplay
4
+ } from "./chunk-K6DPDBAG.js";
4
5
 
5
6
  // src/db-collapsible.ts
6
7
  import { Collapsible } from "@dogsbay/primitives/collapsible";
@@ -36,6 +37,7 @@ var DbCollapsible = class extends DogsbayElement {
36
37
  }
37
38
  }
38
39
  };
40
+ ensureDefaultDisplay();
39
41
  if (!customElements.get("db-collapsible")) {
40
42
  customElements.define("db-collapsible", DbCollapsible);
41
43
  }
@@ -43,4 +45,4 @@ if (!customElements.get("db-collapsible")) {
43
45
  export {
44
46
  DbCollapsible
45
47
  };
46
- //# sourceMappingURL=chunk-TTNTPXBA.js.map
48
+ //# sourceMappingURL=chunk-LAUNXWKJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-collapsible.ts"],"sourcesContent":["import { Collapsible } from \"@dogsbay/primitives/collapsible\";\nimport { DogsbayElement, ensureDefaultDisplay } 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\nensureDefaultDisplay();\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,qBAAqB;AAErB,IAAI,CAAC,eAAe,IAAI,gBAAgB,GAAG;AACzC,iBAAe,OAAO,kBAAkB,aAAa;AACvD;","names":[]}