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

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 (56) hide show
  1. package/dist/{chunk-S62ZVVO3.js → chunk-2ZMWJ74J.js} +3 -3
  2. package/dist/{chunk-CLUADA3G.js → chunk-5KHESKQR.js} +2 -2
  3. package/dist/{chunk-LAUNXWKJ.js → chunk-5WY3DHVB.js} +2 -2
  4. package/dist/{chunk-EGU66XCL.js → chunk-6QAYHFIQ.js} +3 -3
  5. package/dist/{chunk-4YPDR3W6.js → chunk-6ZKFQBCF.js} +2 -2
  6. package/dist/{chunk-VW7HZY2B.js → chunk-AVQ7KRRE.js} +2 -2
  7. package/dist/{chunk-V4P3UR4I.js → chunk-CD3G6HKT.js} +2 -2
  8. package/dist/{chunk-FIJZRZEN.js → chunk-EPHDSTM7.js} +5 -9
  9. package/dist/chunk-EPHDSTM7.js.map +1 -0
  10. package/dist/{chunk-MAD6XJY4.js → chunk-GC5HL7FU.js} +3 -3
  11. package/dist/{chunk-3FMXAKOU.js → chunk-HMNRE3FZ.js} +3 -3
  12. package/dist/{chunk-MEOIAZDF.js → chunk-HMV62CBN.js} +3 -3
  13. package/dist/{chunk-ETBBSA3I.js → chunk-JRAYNKQ6.js} +2 -2
  14. package/dist/{chunk-3AEQ6KHV.js → chunk-KXCPLIQD.js} +10 -2
  15. package/dist/{chunk-3AEQ6KHV.js.map → chunk-KXCPLIQD.js.map} +1 -1
  16. package/dist/{chunk-K6DPDBAG.js → chunk-MZDGSTI4.js} +2 -1
  17. package/dist/chunk-MZDGSTI4.js.map +1 -0
  18. package/dist/chunk-P7QNCZF7.js +176 -0
  19. package/dist/chunk-P7QNCZF7.js.map +1 -0
  20. package/dist/{chunk-SLJG53M7.js → chunk-RZ3KZOM3.js} +3 -3
  21. package/dist/{chunk-QSRUT67Y.js → chunk-US4H4ZPZ.js} +2 -2
  22. package/dist/db-accordion.js +2 -2
  23. package/dist/db-card.js +2 -2
  24. package/dist/db-code-block.js +2 -2
  25. package/dist/db-collapsible.js +2 -2
  26. package/dist/db-combobox.js +3 -3
  27. package/dist/db-details-sheet.d.ts +52 -0
  28. package/dist/db-details-sheet.js +9 -0
  29. package/dist/db-details-sheet.js.map +1 -0
  30. package/dist/db-dialog.js +3 -3
  31. package/dist/db-link-button.js +2 -2
  32. package/dist/db-nav-tree.js +3 -3
  33. package/dist/db-popover.js +3 -3
  34. package/dist/db-select.js +3 -3
  35. package/dist/db-steps.js +2 -2
  36. package/dist/db-tabs.js +2 -2
  37. package/dist/db-toc.js +3 -2
  38. package/dist/db-tooltip.js +3 -3
  39. package/dist/index.d.ts +1 -0
  40. package/dist/index.js +22 -18
  41. package/package.json +6 -2
  42. package/dist/chunk-FIJZRZEN.js.map +0 -1
  43. package/dist/chunk-K6DPDBAG.js.map +0 -1
  44. /package/dist/{chunk-S62ZVVO3.js.map → chunk-2ZMWJ74J.js.map} +0 -0
  45. /package/dist/{chunk-CLUADA3G.js.map → chunk-5KHESKQR.js.map} +0 -0
  46. /package/dist/{chunk-LAUNXWKJ.js.map → chunk-5WY3DHVB.js.map} +0 -0
  47. /package/dist/{chunk-EGU66XCL.js.map → chunk-6QAYHFIQ.js.map} +0 -0
  48. /package/dist/{chunk-4YPDR3W6.js.map → chunk-6ZKFQBCF.js.map} +0 -0
  49. /package/dist/{chunk-VW7HZY2B.js.map → chunk-AVQ7KRRE.js.map} +0 -0
  50. /package/dist/{chunk-V4P3UR4I.js.map → chunk-CD3G6HKT.js.map} +0 -0
  51. /package/dist/{chunk-MAD6XJY4.js.map → chunk-GC5HL7FU.js.map} +0 -0
  52. /package/dist/{chunk-3FMXAKOU.js.map → chunk-HMNRE3FZ.js.map} +0 -0
  53. /package/dist/{chunk-MEOIAZDF.js.map → chunk-HMV62CBN.js.map} +0 -0
  54. /package/dist/{chunk-ETBBSA3I.js.map → chunk-JRAYNKQ6.js.map} +0 -0
  55. /package/dist/{chunk-SLJG53M7.js.map → chunk-RZ3KZOM3.js.map} +0 -0
  56. /package/dist/{chunk-QSRUT67Y.js.map → chunk-US4H4ZPZ.js.map} +0 -0
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  own,
3
3
  uid
4
- } from "./chunk-3AEQ6KHV.js";
4
+ } from "./chunk-KXCPLIQD.js";
5
5
  import {
6
6
  DogsbayElement,
7
7
  ensureDefaultDisplay
8
- } from "./chunk-K6DPDBAG.js";
8
+ } from "./chunk-MZDGSTI4.js";
9
9
 
10
10
  // src/db-nav-tree.ts
11
11
  var DbNavTree = class extends DogsbayElement {
@@ -231,4 +231,4 @@ if (!customElements.get("db-nav-tree")) {
231
231
  export {
232
232
  DbNavTree
233
233
  };
234
- //# sourceMappingURL=chunk-S62ZVVO3.js.map
234
+ //# sourceMappingURL=chunk-2ZMWJ74J.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-accordion.ts
7
7
  import { CompositeNavigation } from "@dogsbay/primitives/composite";
@@ -94,4 +94,4 @@ if (!customElements.get("db-accordion")) {
94
94
  export {
95
95
  DbAccordion
96
96
  };
97
- //# sourceMappingURL=chunk-CLUADA3G.js.map
97
+ //# sourceMappingURL=chunk-5KHESKQR.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-collapsible.ts
7
7
  import { Collapsible } from "@dogsbay/primitives/collapsible";
@@ -45,4 +45,4 @@ if (!customElements.get("db-collapsible")) {
45
45
  export {
46
46
  DbCollapsible
47
47
  };
48
- //# sourceMappingURL=chunk-LAUNXWKJ.js.map
48
+ //# sourceMappingURL=chunk-5WY3DHVB.js.map
@@ -5,11 +5,11 @@ import {
5
5
  resolveAsChild,
6
6
  showFloating,
7
7
  uid
8
- } from "./chunk-3AEQ6KHV.js";
8
+ } from "./chunk-KXCPLIQD.js";
9
9
  import {
10
10
  DogsbayElement,
11
11
  ensureDefaultDisplay
12
- } from "./chunk-K6DPDBAG.js";
12
+ } from "./chunk-MZDGSTI4.js";
13
13
 
14
14
  // src/db-popover.ts
15
15
  import { DismissController } from "@dogsbay/primitives/dismiss";
@@ -113,4 +113,4 @@ if (!customElements.get("db-popover")) {
113
113
  export {
114
114
  DbPopover
115
115
  };
116
- //# sourceMappingURL=chunk-EGU66XCL.js.map
116
+ //# sourceMappingURL=chunk-6QAYHFIQ.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-tabs.ts
7
7
  import { CompositeNavigation } from "@dogsbay/primitives/composite";
@@ -187,4 +187,4 @@ if (!customElements.get("db-tabs")) {
187
187
  export {
188
188
  DbTabs
189
189
  };
190
- //# sourceMappingURL=chunk-4YPDR3W6.js.map
190
+ //# sourceMappingURL=chunk-6ZKFQBCF.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-steps.ts
7
7
  var DbSteps = class extends DogsbayElement {
@@ -21,4 +21,4 @@ if (!customElements.get("db-steps")) {
21
21
  export {
22
22
  DbSteps
23
23
  };
24
- //# sourceMappingURL=chunk-VW7HZY2B.js.map
24
+ //# sourceMappingURL=chunk-AVQ7KRRE.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-code-block.ts
7
7
  var DbCodeBlock = class extends DogsbayElement {
@@ -88,4 +88,4 @@ if (!customElements.get("db-code-block")) {
88
88
  export {
89
89
  DbCodeBlock
90
90
  };
91
- //# sourceMappingURL=chunk-V4P3UR4I.js.map
91
+ //# sourceMappingURL=chunk-CD3G6HKT.js.map
@@ -1,7 +1,10 @@
1
+ import {
2
+ safeDecode
3
+ } from "./chunk-KXCPLIQD.js";
1
4
  import {
2
5
  DogsbayElement,
3
6
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
7
+ } from "./chunk-MZDGSTI4.js";
5
8
 
6
9
  // src/db-toc.ts
7
10
  var DbToc = class extends DogsbayElement {
@@ -72,13 +75,6 @@ var DbToc = class extends DogsbayElement {
72
75
  this.dispatchEvent(new CustomEvent("db-toc:change", { detail: { id }, bubbles: true }));
73
76
  }
74
77
  };
75
- function safeDecode(s) {
76
- try {
77
- return decodeURIComponent(s);
78
- } catch {
79
- return s;
80
- }
81
- }
82
78
  ensureDefaultDisplay();
83
79
  if (!customElements.get("db-toc")) {
84
80
  customElements.define("db-toc", DbToc);
@@ -87,4 +83,4 @@ if (!customElements.get("db-toc")) {
87
83
  export {
88
84
  DbToc
89
85
  };
90
- //# sourceMappingURL=chunk-FIJZRZEN.js.map
86
+ //# sourceMappingURL=chunk-EPHDSTM7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-toc.ts"],"sourcesContent":["import { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\nimport { safeDecode } from \"./utils.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\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-toc\")) {\n customElements.define(\"db-toc\", DbToc);\n}\n"],"mappings":"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","names":[]}
@@ -2,11 +2,11 @@ import {
2
2
  isDisabled,
3
3
  ownOne,
4
4
  uid
5
- } from "./chunk-3AEQ6KHV.js";
5
+ } from "./chunk-KXCPLIQD.js";
6
6
  import {
7
7
  DogsbayElement,
8
8
  ensureDefaultDisplay
9
- } from "./chunk-K6DPDBAG.js";
9
+ } from "./chunk-MZDGSTI4.js";
10
10
 
11
11
  // src/db-combobox.ts
12
12
  var DbCombobox = class extends DogsbayElement {
@@ -253,4 +253,4 @@ if (!customElements.get("db-combobox")) {
253
253
  export {
254
254
  DbCombobox
255
255
  };
256
- //# sourceMappingURL=chunk-MAD6XJY4.js.map
256
+ //# sourceMappingURL=chunk-GC5HL7FU.js.map
@@ -5,11 +5,11 @@ import {
5
5
  ownOne,
6
6
  showFloating,
7
7
  uid
8
- } from "./chunk-3AEQ6KHV.js";
8
+ } from "./chunk-KXCPLIQD.js";
9
9
  import {
10
10
  DogsbayElement,
11
11
  ensureDefaultDisplay
12
- } from "./chunk-K6DPDBAG.js";
12
+ } from "./chunk-MZDGSTI4.js";
13
13
 
14
14
  // src/db-select.ts
15
15
  import { DismissController } from "@dogsbay/primitives/dismiss";
@@ -380,4 +380,4 @@ if (!customElements.get("db-select")) {
380
380
  export {
381
381
  DbSelect
382
382
  };
383
- //# sourceMappingURL=chunk-3FMXAKOU.js.map
383
+ //# sourceMappingURL=chunk-HMNRE3FZ.js.map
@@ -4,11 +4,11 @@ import {
4
4
  resolveAsChild,
5
5
  showFloating,
6
6
  uid
7
- } from "./chunk-3AEQ6KHV.js";
7
+ } from "./chunk-KXCPLIQD.js";
8
8
  import {
9
9
  DogsbayElement,
10
10
  ensureDefaultDisplay
11
- } from "./chunk-K6DPDBAG.js";
11
+ } from "./chunk-MZDGSTI4.js";
12
12
 
13
13
  // src/db-tooltip.ts
14
14
  import { setupFloating } from "@dogsbay/primitives/floating";
@@ -137,4 +137,4 @@ if (!customElements.get("db-tooltip")) {
137
137
  export {
138
138
  DbTooltip
139
139
  };
140
- //# sourceMappingURL=chunk-MEOIAZDF.js.map
140
+ //# sourceMappingURL=chunk-HMV62CBN.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-card.ts
7
7
  var DbCard = class extends DogsbayElement {
@@ -51,4 +51,4 @@ if (!customElements.get("db-card")) {
51
51
  export {
52
52
  DbCard
53
53
  };
54
- //# sourceMappingURL=chunk-ETBBSA3I.js.map
54
+ //# sourceMappingURL=chunk-JRAYNKQ6.js.map
@@ -55,6 +55,13 @@ function afterAnimations(el, done) {
55
55
  if (!anims.length) return done();
56
56
  Promise.all(anims.map((a) => a.finished)).then(done, done);
57
57
  }
58
+ function safeDecode(s) {
59
+ try {
60
+ return decodeURIComponent(s);
61
+ } catch {
62
+ return s;
63
+ }
64
+ }
58
65
 
59
66
  export {
60
67
  uid,
@@ -65,6 +72,7 @@ export {
65
72
  showFloating,
66
73
  hideFloating,
67
74
  focusables,
68
- afterAnimations
75
+ afterAnimations,
76
+ safeDecode
69
77
  };
70
- //# sourceMappingURL=chunk-3AEQ6KHV.js.map
78
+ //# sourceMappingURL=chunk-KXCPLIQD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["/**\n * Shared helpers for the elements. Nothing here touches the DOM at\n * import time, so modules stay safe to import in non-browser tooling.\n */\n\nlet counter = 0;\n\n/** A document-unique id with a readable prefix. */\nexport function uid(prefix: string): string {\n return `${prefix}-${++counter}`;\n}\n\n/**\n * Descendants of `host` matching `selector` that belong to THIS element,\n * not to a nested element of the same tag. Wrappers are allowed.\n */\nexport function own<T extends HTMLElement = HTMLElement>(host: HTMLElement, selector: string): T[] {\n const tag = host.localName;\n return (Array.from(host.querySelectorAll(selector)) as T[]).filter((el) => el.closest(tag) === host);\n}\n\n/** First own descendant matching `selector`, or null. */\nexport function ownOne<T extends HTMLElement = HTMLElement>(host: HTMLElement, selector: string): T | null {\n return own<T>(host, selector)[0] ?? null;\n}\n\n/**\n * The Astro components' `asChild` pattern: a wrapper `<span data-part=\"x\"\n * data-as-child>` stands in for its first child, which receives the part.\n */\nexport function resolveAsChild(el: HTMLElement | null): HTMLElement | null {\n if (!el || !el.hasAttribute(\"data-as-child\")) return el;\n const child = el.firstElementChild as HTMLElement | null;\n if (!child) return el;\n const part = el.getAttribute(\"data-part\");\n if (part) child.setAttribute(\"data-part\", part);\n return child;\n}\n\nexport function isDisabled(el: Element): boolean {\n return el.hasAttribute(\"disabled\") || el.getAttribute(\"aria-disabled\") === \"true\" || el.getAttribute(\"data-disabled\") === \"true\";\n}\n\n/**\n * True when the browser supports the Popover API, which puts floating\n * content in the top layer: never clipped by `overflow`, always above\n * other stacking contexts, and no portal needed.\n */\nexport function supportsPopover(): boolean {\n return typeof HTMLElement !== \"undefined\" && typeof (HTMLElement.prototype as { showPopover?: unknown }).showPopover === \"function\";\n}\n\n/** Show floating content, in the top layer when the browser allows it. */\nexport function showFloating(el: HTMLElement): \"top-layer\" | \"inline\" {\n el.hidden = false;\n if (!supportsPopover()) return \"inline\";\n if (!el.hasAttribute(\"popover\")) el.setAttribute(\"popover\", \"manual\");\n // The UA stylesheet centres popovers in the viewport; floating-ui positions them instead.\n el.style.inset = \"auto\";\n el.style.margin = \"0\";\n try {\n if (!el.matches(\":popover-open\")) el.showPopover();\n } catch {\n return \"inline\";\n }\n return \"top-layer\";\n}\n\nexport function hideFloating(el: HTMLElement): void {\n if (supportsPopover()) {\n try {\n if (el.matches(\":popover-open\")) el.hidePopover();\n } catch {\n /* not a popover */\n }\n }\n el.hidden = true;\n}\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\n/** Focusable descendants in document order, skipping hidden ones. */\nexport function focusables(root: HTMLElement): HTMLElement[] {\n return (Array.from(root.querySelectorAll(FOCUSABLE)) as HTMLElement[]).filter((el) => !el.closest(\"[hidden]\") && !isDisabled(el));\n}\n\n/** Wait for running CSS animations on `el` (exit animations), then run `done`. */\nexport function afterAnimations(el: HTMLElement, done: () => void): void {\n const anims = typeof el.getAnimations === \"function\" ? el.getAnimations() : [];\n if (!anims.length) return done();\n Promise.all(anims.map((a) => a.finished)).then(done, done);\n}\n"],"mappings":";AAKA,IAAI,UAAU;AAGP,SAAS,IAAI,QAAwB;AAC1C,SAAO,GAAG,MAAM,IAAI,EAAE,OAAO;AAC/B;AAMO,SAAS,IAAyC,MAAmB,UAAuB;AACjG,QAAM,MAAM,KAAK;AACjB,SAAQ,MAAM,KAAK,KAAK,iBAAiB,QAAQ,CAAC,EAAU,OAAO,CAAC,OAAO,GAAG,QAAQ,GAAG,MAAM,IAAI;AACrG;AAGO,SAAS,OAA4C,MAAmB,UAA4B;AACzG,SAAO,IAAO,MAAM,QAAQ,EAAE,CAAC,KAAK;AACtC;AAMO,SAAS,eAAe,IAA4C;AACzE,MAAI,CAAC,MAAM,CAAC,GAAG,aAAa,eAAe,EAAG,QAAO;AACrD,QAAM,QAAQ,GAAG;AACjB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,GAAG,aAAa,WAAW;AACxC,MAAI,KAAM,OAAM,aAAa,aAAa,IAAI;AAC9C,SAAO;AACT;AAEO,SAAS,WAAW,IAAsB;AAC/C,SAAO,GAAG,aAAa,UAAU,KAAK,GAAG,aAAa,eAAe,MAAM,UAAU,GAAG,aAAa,eAAe,MAAM;AAC5H;AAOO,SAAS,kBAA2B;AACzC,SAAO,OAAO,gBAAgB,eAAe,OAAQ,YAAY,UAAwC,gBAAgB;AAC3H;AAGO,SAAS,aAAa,IAAyC;AACpE,KAAG,SAAS;AACZ,MAAI,CAAC,gBAAgB,EAAG,QAAO;AAC/B,MAAI,CAAC,GAAG,aAAa,SAAS,EAAG,IAAG,aAAa,WAAW,QAAQ;AAEpE,KAAG,MAAM,QAAQ;AACjB,KAAG,MAAM,SAAS;AAClB,MAAI;AACF,QAAI,CAAC,GAAG,QAAQ,eAAe,EAAG,IAAG,YAAY;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,aAAa,IAAuB;AAClD,MAAI,gBAAgB,GAAG;AACrB,QAAI;AACF,UAAI,GAAG,QAAQ,eAAe,EAAG,IAAG,YAAY;AAAA,IAClD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,KAAG,SAAS;AACd;AAEA,IAAM,YACJ;AAGK,SAAS,WAAW,MAAkC;AAC3D,SAAQ,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC,EAAoB,OAAO,CAAC,OAAO,CAAC,GAAG,QAAQ,UAAU,KAAK,CAAC,WAAW,EAAE,CAAC;AAClI;AAGO,SAAS,gBAAgB,IAAiB,MAAwB;AACvE,QAAM,QAAQ,OAAO,GAAG,kBAAkB,aAAa,GAAG,cAAc,IAAI,CAAC;AAC7E,MAAI,CAAC,MAAM,OAAQ,QAAO,KAAK;AAC/B,UAAQ,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,MAAM,IAAI;AAC3D;","names":[]}
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["/**\n * Shared helpers for the elements. Nothing here touches the DOM at\n * import time, so modules stay safe to import in non-browser tooling.\n */\n\nlet counter = 0;\n\n/** A document-unique id with a readable prefix. */\nexport function uid(prefix: string): string {\n return `${prefix}-${++counter}`;\n}\n\n/**\n * Descendants of `host` matching `selector` that belong to THIS element,\n * not to a nested element of the same tag. Wrappers are allowed.\n */\nexport function own<T extends HTMLElement = HTMLElement>(host: HTMLElement, selector: string): T[] {\n const tag = host.localName;\n return (Array.from(host.querySelectorAll(selector)) as T[]).filter((el) => el.closest(tag) === host);\n}\n\n/** First own descendant matching `selector`, or null. */\nexport function ownOne<T extends HTMLElement = HTMLElement>(host: HTMLElement, selector: string): T | null {\n return own<T>(host, selector)[0] ?? null;\n}\n\n/**\n * The Astro components' `asChild` pattern: a wrapper `<span data-part=\"x\"\n * data-as-child>` stands in for its first child, which receives the part.\n */\nexport function resolveAsChild(el: HTMLElement | null): HTMLElement | null {\n if (!el || !el.hasAttribute(\"data-as-child\")) return el;\n const child = el.firstElementChild as HTMLElement | null;\n if (!child) return el;\n const part = el.getAttribute(\"data-part\");\n if (part) child.setAttribute(\"data-part\", part);\n return child;\n}\n\nexport function isDisabled(el: Element): boolean {\n return el.hasAttribute(\"disabled\") || el.getAttribute(\"aria-disabled\") === \"true\" || el.getAttribute(\"data-disabled\") === \"true\";\n}\n\n/**\n * True when the browser supports the Popover API, which puts floating\n * content in the top layer: never clipped by `overflow`, always above\n * other stacking contexts, and no portal needed.\n */\nexport function supportsPopover(): boolean {\n return typeof HTMLElement !== \"undefined\" && typeof (HTMLElement.prototype as { showPopover?: unknown }).showPopover === \"function\";\n}\n\n/** Show floating content, in the top layer when the browser allows it. */\nexport function showFloating(el: HTMLElement): \"top-layer\" | \"inline\" {\n el.hidden = false;\n if (!supportsPopover()) return \"inline\";\n if (!el.hasAttribute(\"popover\")) el.setAttribute(\"popover\", \"manual\");\n // The UA stylesheet centres popovers in the viewport; floating-ui positions them instead.\n el.style.inset = \"auto\";\n el.style.margin = \"0\";\n try {\n if (!el.matches(\":popover-open\")) el.showPopover();\n } catch {\n return \"inline\";\n }\n return \"top-layer\";\n}\n\nexport function hideFloating(el: HTMLElement): void {\n if (supportsPopover()) {\n try {\n if (el.matches(\":popover-open\")) el.hidePopover();\n } catch {\n /* not a popover */\n }\n }\n el.hidden = true;\n}\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\n/** Focusable descendants in document order, skipping hidden ones. */\nexport function focusables(root: HTMLElement): HTMLElement[] {\n return (Array.from(root.querySelectorAll(FOCUSABLE)) as HTMLElement[]).filter((el) => !el.closest(\"[hidden]\") && !isDisabled(el));\n}\n\n/** Wait for running CSS animations on `el` (exit animations), then run `done`. */\nexport function afterAnimations(el: HTMLElement, done: () => void): void {\n const anims = typeof el.getAnimations === \"function\" ? el.getAnimations() : [];\n if (!anims.length) return done();\n Promise.all(anims.map((a) => a.finished)).then(done, done);\n}\n\n/** decodeURIComponent that returns the input on a malformed escape (`#%E0%A4%A`) instead of throwing. */\nexport function safeDecode(s: string): string {\n try {\n return decodeURIComponent(s);\n } catch {\n return s;\n }\n}\n"],"mappings":";AAKA,IAAI,UAAU;AAGP,SAAS,IAAI,QAAwB;AAC1C,SAAO,GAAG,MAAM,IAAI,EAAE,OAAO;AAC/B;AAMO,SAAS,IAAyC,MAAmB,UAAuB;AACjG,QAAM,MAAM,KAAK;AACjB,SAAQ,MAAM,KAAK,KAAK,iBAAiB,QAAQ,CAAC,EAAU,OAAO,CAAC,OAAO,GAAG,QAAQ,GAAG,MAAM,IAAI;AACrG;AAGO,SAAS,OAA4C,MAAmB,UAA4B;AACzG,SAAO,IAAO,MAAM,QAAQ,EAAE,CAAC,KAAK;AACtC;AAMO,SAAS,eAAe,IAA4C;AACzE,MAAI,CAAC,MAAM,CAAC,GAAG,aAAa,eAAe,EAAG,QAAO;AACrD,QAAM,QAAQ,GAAG;AACjB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,GAAG,aAAa,WAAW;AACxC,MAAI,KAAM,OAAM,aAAa,aAAa,IAAI;AAC9C,SAAO;AACT;AAEO,SAAS,WAAW,IAAsB;AAC/C,SAAO,GAAG,aAAa,UAAU,KAAK,GAAG,aAAa,eAAe,MAAM,UAAU,GAAG,aAAa,eAAe,MAAM;AAC5H;AAOO,SAAS,kBAA2B;AACzC,SAAO,OAAO,gBAAgB,eAAe,OAAQ,YAAY,UAAwC,gBAAgB;AAC3H;AAGO,SAAS,aAAa,IAAyC;AACpE,KAAG,SAAS;AACZ,MAAI,CAAC,gBAAgB,EAAG,QAAO;AAC/B,MAAI,CAAC,GAAG,aAAa,SAAS,EAAG,IAAG,aAAa,WAAW,QAAQ;AAEpE,KAAG,MAAM,QAAQ;AACjB,KAAG,MAAM,SAAS;AAClB,MAAI;AACF,QAAI,CAAC,GAAG,QAAQ,eAAe,EAAG,IAAG,YAAY;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,aAAa,IAAuB;AAClD,MAAI,gBAAgB,GAAG;AACrB,QAAI;AACF,UAAI,GAAG,QAAQ,eAAe,EAAG,IAAG,YAAY;AAAA,IAClD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,KAAG,SAAS;AACd;AAEA,IAAM,YACJ;AAGK,SAAS,WAAW,MAAkC;AAC3D,SAAQ,MAAM,KAAK,KAAK,iBAAiB,SAAS,CAAC,EAAoB,OAAO,CAAC,OAAO,CAAC,GAAG,QAAQ,UAAU,KAAK,CAAC,WAAW,EAAE,CAAC;AAClI;AAGO,SAAS,gBAAgB,IAAiB,MAAwB;AACvE,QAAM,QAAQ,OAAO,GAAG,kBAAkB,aAAa,GAAG,cAAc,IAAI,CAAC;AAC7E,MAAI,CAAC,MAAM,OAAQ,QAAO,KAAK;AAC/B,UAAQ,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,MAAM,IAAI;AAC3D;AAGO,SAAS,WAAW,GAAmB;AAC5C,MAAI;AACF,WAAO,mBAAmB,CAAC;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -40,6 +40,7 @@ var DEFAULT_DISPLAY = {
40
40
  "db-tabs": "block",
41
41
  "db-accordion": "block",
42
42
  "db-collapsible": "block",
43
+ "db-details-sheet": "block",
43
44
  "db-card": "block",
44
45
  "db-steps": "block",
45
46
  "db-code-block": "block",
@@ -69,4 +70,4 @@ export {
69
70
  DogsbayElement,
70
71
  ensureDefaultDisplay
71
72
  };
72
- //# sourceMappingURL=chunk-K6DPDBAG.js.map
73
+ //# sourceMappingURL=chunk-MZDGSTI4.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-details-sheet\": \"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,oBAAoB;AAAA,EACpB,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":[]}
@@ -0,0 +1,176 @@
1
+ import {
2
+ safeDecode,
3
+ uid
4
+ } from "./chunk-KXCPLIQD.js";
5
+ import {
6
+ DogsbayElement,
7
+ ensureDefaultDisplay
8
+ } from "./chunk-MZDGSTI4.js";
9
+
10
+ // src/db-details-sheet.ts
11
+ var DbDetailsSheet = class extends DogsbayElement {
12
+ details = null;
13
+ summary = null;
14
+ dialog = null;
15
+ body = null;
16
+ /** Where the moved nodes came from, and the nodes, while the sheet is open. */
17
+ source = null;
18
+ moved = [];
19
+ /** The fragment already acted on: moving a nested sheet in and out of a
20
+ * dialog reconnects it, and reopening on every connect made it undismissable. */
21
+ handledHash = null;
22
+ get open() {
23
+ return !!this.dialog?.open;
24
+ }
25
+ onSummaryClick = (e) => {
26
+ const t = e.target;
27
+ if (t && t !== this.summary && t.closest?.("a[href], button, input, select, textarea, label")?.closest("summary") === this.summary) return;
28
+ e.preventDefault();
29
+ this.show();
30
+ };
31
+ // A click on the ::backdrop targets the dialog itself, outside its box.
32
+ onDialogClick = (e) => {
33
+ const d = this.dialog;
34
+ if (!d || e.target !== d) return;
35
+ const r = d.getBoundingClientRect();
36
+ const inside = e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom;
37
+ if (!inside && (e.clientX !== 0 || e.clientY !== 0)) d.close();
38
+ };
39
+ // Every way the dialog closes (Escape, backdrop, button, api) ends here.
40
+ onDialogClose = () => this.restore();
41
+ onHash = () => {
42
+ this.handledHash = null;
43
+ this.openForHash();
44
+ };
45
+ setup() {
46
+ const details = Array.from(this.children).find((c) => c.tagName === "DETAILS") ?? null;
47
+ const summary = details ? Array.from(details.children).find((c) => c.tagName === "SUMMARY") ?? null : null;
48
+ const dialogOk = typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
49
+ if (!details || !summary || !dialogOk) return;
50
+ for (const c of Array.from(details.children)) if (c.getAttribute("role") === "status") c.setAttribute("aria-live", "off");
51
+ this.details = details;
52
+ this.summary = summary;
53
+ details.open = false;
54
+ ensureSheetStyles();
55
+ const title = (summary.querySelector("[data-part='title']")?.textContent ?? summary.textContent ?? "").trim();
56
+ const dialog = document.createElement("dialog");
57
+ dialog.className = "db-sheet";
58
+ dialog.id = uid("db-sheet");
59
+ const heading = document.createElement("h2");
60
+ heading.className = "db-sheet-title";
61
+ heading.id = uid("db-sheet-title");
62
+ heading.textContent = title;
63
+ dialog.setAttribute("aria-labelledby", heading.id);
64
+ const close = document.createElement("button");
65
+ close.type = "button";
66
+ close.className = "db-sheet-close";
67
+ close.setAttribute("aria-label", this.getAttribute("close-label") || "Close");
68
+ close.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
69
+ close.addEventListener("click", () => dialog.close());
70
+ const header = document.createElement("div");
71
+ header.className = "db-sheet-header";
72
+ header.append(heading, close);
73
+ const body = document.createElement("div");
74
+ body.className = "db-sheet-body";
75
+ dialog.append(header, body);
76
+ this.append(dialog);
77
+ this.dialog = dialog;
78
+ this.body = body;
79
+ summary.setAttribute("aria-haspopup", "dialog");
80
+ summary.setAttribute("aria-controls", dialog.id);
81
+ summary.setAttribute("aria-expanded", "false");
82
+ this.setAttribute("data-state", "closed");
83
+ }
84
+ connect() {
85
+ if (!this.dialog) return;
86
+ this.summary.addEventListener("click", this.onSummaryClick);
87
+ this.dialog.addEventListener("click", this.onDialogClick);
88
+ this.dialog.addEventListener("close", this.onDialogClose);
89
+ window.addEventListener("hashchange", this.onHash);
90
+ queueMicrotask(() => this.isConnected && this.openForHash());
91
+ }
92
+ disconnect() {
93
+ if (!this.dialog) return;
94
+ if (this.dialog.open) this.dialog.close();
95
+ this.restore(false);
96
+ this.summary.removeEventListener("click", this.onSummaryClick);
97
+ this.dialog.removeEventListener("click", this.onDialogClick);
98
+ this.dialog.removeEventListener("close", this.onDialogClose);
99
+ window.removeEventListener("hashchange", this.onHash);
100
+ }
101
+ show(focusTarget) {
102
+ const { dialog, details, body } = this;
103
+ if (!dialog || !details || !body || dialog.open) return;
104
+ const rest = Array.from(details.childNodes).filter((n) => n !== this.summary);
105
+ const elements = rest.filter((n) => n.nodeType === Node.ELEMENT_NODE);
106
+ const wrapper = elements.length === 1 && rest.every((n) => n === elements[0] || !n.textContent?.trim()) ? elements[0] : null;
107
+ this.source = wrapper ?? details;
108
+ this.moved = wrapper ? Array.from(wrapper.childNodes) : rest;
109
+ body.append(...this.moved);
110
+ dialog.showModal();
111
+ this.summary.setAttribute("aria-expanded", "true");
112
+ this.setAttribute("data-state", "open");
113
+ if (focusTarget && focusTarget !== details) focusTarget.scrollIntoView?.({ block: "start" });
114
+ this.dispatchEvent(new CustomEvent("db-details-sheet:open", { bubbles: true }));
115
+ }
116
+ close() {
117
+ this.dialog?.close();
118
+ }
119
+ restore(focus = true) {
120
+ if (!this.source) return;
121
+ this.source.append(...this.moved);
122
+ this.source = null;
123
+ this.moved = [];
124
+ this.summary.setAttribute("aria-expanded", "false");
125
+ this.setAttribute("data-state", "closed");
126
+ if (focus && this.isConnected && this.summary.checkVisibility?.() !== false) this.summary.focus();
127
+ this.dispatchEvent(new CustomEvent("db-details-sheet:close", { bubbles: true }));
128
+ }
129
+ /** Open when the URL fragment names the details or something in its body. */
130
+ openForHash() {
131
+ const id = safeDecode(location.hash.slice(1));
132
+ if (!id || !this.details || this.handledHash === location.hash) return;
133
+ this.handledHash = location.hash;
134
+ if (this.open) return;
135
+ const target = document.getElementById(id);
136
+ if (target && this.details.contains(target)) this.show(target);
137
+ }
138
+ };
139
+ var STYLE_ID = "dogsbay-details-sheet";
140
+ function ensureSheetStyles() {
141
+ if (document.getElementById(STYLE_ID)) return;
142
+ const style = document.createElement("style");
143
+ style.id = STYLE_ID;
144
+ style.textContent = [
145
+ "dialog.db-sheet{position:fixed;inset:0 0 0 auto;margin:0;height:100dvh;max-height:none;width:min(32rem,100vw);max-width:100vw;padding:0;border:0;border-left:1px solid var(--border);background:var(--background);color:var(--foreground);box-shadow:0 10px 15px -3px rgb(0 0 0/.1),0 4px 6px -4px rgb(0 0 0/.1);flex-direction:column}",
146
+ "dialog.db-sheet[open]{display:flex}",
147
+ "dialog.db-sheet::backdrop{background:rgb(0 0 0/.6)}",
148
+ ".db-sheet-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1rem 1.5rem;border-bottom:1px solid var(--border)}",
149
+ // The dialog sits inside the page's prose: its h2 rule (border, margins)
150
+ // would otherwise style the title. Element + class beats `.docs-prose h2`.
151
+ "dialog.db-sheet h2.db-sheet-title{margin:0;padding:0;border:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;scroll-margin:0}",
152
+ ".db-sheet-close{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:.375rem;background:transparent;color:var(--muted-foreground);cursor:pointer}",
153
+ ".db-sheet-close:hover{background:var(--accent,var(--muted));color:var(--foreground)}",
154
+ ".db-sheet-close:focus-visible{outline:2px solid var(--ring);outline-offset:2px}",
155
+ ".db-sheet-body{flex:1;overflow-y:auto;padding:1.5rem;font-size:.875rem;line-height:1.625}",
156
+ // Beats `.docs-prose p` (0,2,1): the first paragraph sat 12px down
157
+ "dialog.db-sheet .db-sheet-body>:first-child{margin-top:0}",
158
+ // A modal sheet: the page under it does not scroll
159
+ "html:has(dialog.db-sheet[open]){overflow:hidden}",
160
+ // The summary opens a panel, not a fold: its chevron points to the side.
161
+ "db-details-sheet>details>summary>span:last-child{transform:rotate(-90deg)}",
162
+ "@media (prefers-reduced-motion:no-preference){dialog.db-sheet[open]{animation:db-sheet-in .2s ease-out}dialog.db-sheet[open]::backdrop{animation:db-sheet-fade .2s ease-out}}",
163
+ "@keyframes db-sheet-in{from{transform:translateX(100%)}}",
164
+ "@keyframes db-sheet-fade{from{opacity:0}}"
165
+ ].join("");
166
+ document.head.append(style);
167
+ }
168
+ ensureDefaultDisplay();
169
+ if (!customElements.get("db-details-sheet")) {
170
+ customElements.define("db-details-sheet", DbDetailsSheet);
171
+ }
172
+
173
+ export {
174
+ DbDetailsSheet
175
+ };
176
+ //# sourceMappingURL=chunk-P7QNCZF7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db-details-sheet.ts"],"sourcesContent":["import { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\nimport { safeDecode, uid } from \"./utils.js\";\n\n/**\n * `<db-details-sheet>` — a `<details>` that opens as a side sheet.\n *\n * The markup is an ordinary `<details>` (the CollapsibleAlert markup), so\n * with no script — `js: none`, a blocked script, print, an agent reading the\n * HTML — it is a working collapsible block and nothing is hidden. With the\n * script, activating the summary opens the body in a native modal `<dialog>`\n * on the right instead: the browser puts it in the top layer, makes the page\n * inert and handles Escape.\n *\n * The body is MOVED into the sheet while it is open and back when it closes,\n * so ids, anchors and nested elements exist once. A URL fragment naming the\n * details or anything in its body opens the sheet, so a cross-reference lands.\n *\n * Attributes:\n * close-label — the close button's accessible name (default \"Close\")\n *\n * Children:\n * <details> with a <summary> — the summary's `[data-part=\"title\"]`, or its\n * text, titles the sheet\n *\n * Events: db-details-sheet:open, db-details-sheet:close\n */\nexport class DbDetailsSheet extends DogsbayElement {\n private details: HTMLDetailsElement | null = null;\n private summary: HTMLElement | null = null;\n private dialog: HTMLDialogElement | null = null;\n private body: HTMLElement | null = null;\n /** Where the moved nodes came from, and the nodes, while the sheet is open. */\n private source: HTMLElement | null = null;\n private moved: Node[] = [];\n /** The fragment already acted on: moving a nested sheet in and out of a\n * dialog reconnects it, and reopening on every connect made it undismissable. */\n private handledHash: string | null = null;\n\n get open(): boolean {\n return !!this.dialog?.open;\n }\n\n private onSummaryClick = (e: Event) => {\n // A link or control inside the title does its own thing\n const t = e.target as Element | null;\n if (t && t !== this.summary && t.closest?.(\"a[href], button, input, select, textarea, label\")?.closest(\"summary\") === this.summary) return;\n e.preventDefault(); // the details must not expand in place\n this.show();\n };\n\n // A click on the ::backdrop targets the dialog itself, outside its box.\n private onDialogClick = (e: MouseEvent) => {\n const d = this.dialog;\n if (!d || e.target !== d) return;\n const r = d.getBoundingClientRect();\n const inside = e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom;\n if (!inside && (e.clientX !== 0 || e.clientY !== 0)) d.close();\n };\n\n // Every way the dialog closes (Escape, backdrop, button, api) ends here.\n private onDialogClose = () => this.restore();\n\n private onHash = () => {\n this.handledHash = null;\n this.openForHash();\n };\n\n protected setup() {\n const details = Array.from(this.children).find((c): c is HTMLDetailsElement => c.tagName === \"DETAILS\") ?? null;\n const summary = details ? (Array.from(details.children).find((c) => c.tagName === \"SUMMARY\") as HTMLElement | undefined) ?? null : null;\n // No native modal dialog (an old browser, a test DOM): stay a details.\n const dialogOk = typeof HTMLDialogElement !== \"undefined\" && typeof HTMLDialogElement.prototype.showModal === \"function\";\n if (!details || !summary || !dialogOk) return;\n // CollapsibleAlert marks some variants' body role=\"status\" (a live region):\n // moving the body back on close would be announced as an update\n for (const c of Array.from(details.children)) if (c.getAttribute(\"role\") === \"status\") c.setAttribute(\"aria-live\", \"off\");\n this.details = details;\n this.summary = summary;\n details.open = false;\n ensureSheetStyles();\n\n const title = (summary.querySelector(\"[data-part='title']\")?.textContent ?? summary.textContent ?? \"\").trim();\n const dialog = document.createElement(\"dialog\");\n dialog.className = \"db-sheet\";\n dialog.id = uid(\"db-sheet\");\n const heading = document.createElement(\"h2\");\n heading.className = \"db-sheet-title\";\n heading.id = uid(\"db-sheet-title\");\n heading.textContent = title;\n dialog.setAttribute(\"aria-labelledby\", heading.id);\n const close = document.createElement(\"button\");\n close.type = \"button\";\n close.className = \"db-sheet-close\";\n close.setAttribute(\"aria-label\", this.getAttribute(\"close-label\") || \"Close\");\n close.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>';\n close.addEventListener(\"click\", () => dialog.close());\n const header = document.createElement(\"div\");\n header.className = \"db-sheet-header\";\n header.append(heading, close);\n const body = document.createElement(\"div\");\n body.className = \"db-sheet-body\";\n dialog.append(header, body);\n // Inside the element, never moved out of it: nested elements keep working.\n this.append(dialog);\n this.dialog = dialog;\n this.body = body;\n\n summary.setAttribute(\"aria-haspopup\", \"dialog\");\n summary.setAttribute(\"aria-controls\", dialog.id);\n summary.setAttribute(\"aria-expanded\", \"false\");\n this.setAttribute(\"data-state\", \"closed\");\n }\n\n protected connect() {\n if (!this.dialog) return;\n this.summary!.addEventListener(\"click\", this.onSummaryClick);\n this.dialog.addEventListener(\"click\", this.onDialogClick);\n this.dialog.addEventListener(\"close\", this.onDialogClose);\n window.addEventListener(\"hashchange\", this.onHash);\n queueMicrotask(() => this.isConnected && this.openForHash());\n }\n\n protected disconnect() {\n if (!this.dialog) return;\n // Put the body back NOW: the dialog's close event fires in a later task,\n // after this listener is gone, and the body stayed in the dialog for good\n if (this.dialog.open) this.dialog.close();\n this.restore(false);\n this.summary!.removeEventListener(\"click\", this.onSummaryClick);\n this.dialog.removeEventListener(\"click\", this.onDialogClick);\n this.dialog.removeEventListener(\"close\", this.onDialogClose);\n window.removeEventListener(\"hashchange\", this.onHash);\n }\n\n show(focusTarget?: Element | null) {\n const { dialog, details, body } = this;\n if (!dialog || !details || !body || dialog.open) return;\n // The body: a single wrapper's children (CollapsibleAlert's tinted panel\n // would look out of place in a sheet), else every node after the summary.\n const rest = Array.from(details.childNodes).filter((n) => n !== this.summary);\n const elements = rest.filter((n) => n.nodeType === Node.ELEMENT_NODE) as HTMLElement[];\n const wrapper = elements.length === 1 && rest.every((n) => n === elements[0] || !n.textContent?.trim()) ? elements[0] : null;\n this.source = wrapper ?? details;\n this.moved = wrapper ? Array.from(wrapper.childNodes) : rest;\n body.append(...this.moved);\n dialog.showModal();\n this.summary!.setAttribute(\"aria-expanded\", \"true\");\n this.setAttribute(\"data-state\", \"open\");\n if (focusTarget && focusTarget !== details) (focusTarget as HTMLElement).scrollIntoView?.({ block: \"start\" });\n this.dispatchEvent(new CustomEvent(\"db-details-sheet:open\", { bubbles: true }));\n }\n\n close() {\n this.dialog?.close();\n }\n\n private restore(focus = true) {\n if (!this.source) return;\n this.source.append(...this.moved);\n this.source = null;\n this.moved = [];\n this.summary!.setAttribute(\"aria-expanded\", \"false\");\n this.setAttribute(\"data-state\", \"closed\");\n // Not into a hidden summary (an inactive tab panel): focus would be lost\n if (focus && this.isConnected && this.summary!.checkVisibility?.() !== false) this.summary!.focus();\n this.dispatchEvent(new CustomEvent(\"db-details-sheet:close\", { bubbles: true }));\n }\n\n /** Open when the URL fragment names the details or something in its body. */\n private openForHash() {\n const id = safeDecode(location.hash.slice(1));\n if (!id || !this.details || this.handledHash === location.hash) return;\n this.handledHash = location.hash;\n if (this.open) return;\n const target = document.getElementById(id);\n if (target && this.details.contains(target)) this.show(target);\n }\n}\n\nconst STYLE_ID = \"dogsbay-details-sheet\";\n\n/**\n * The sheet's look, from the theme tokens every page defines. Injected (as\n * the elements' default display is) because the dialog is built here: a\n * renderer that compiles CSS from the page's own classes never sees these.\n * Sizes follow SheetContent.astro (right side, border-l, shadow).\n */\nfunction ensureSheetStyles() {\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement(\"style\");\n style.id = STYLE_ID;\n style.textContent = [\n \"dialog.db-sheet{position:fixed;inset:0 0 0 auto;margin:0;height:100dvh;max-height:none;width:min(32rem,100vw);max-width:100vw;padding:0;border:0;border-left:1px solid var(--border);background:var(--background);color:var(--foreground);box-shadow:0 10px 15px -3px rgb(0 0 0/.1),0 4px 6px -4px rgb(0 0 0/.1);flex-direction:column}\",\n \"dialog.db-sheet[open]{display:flex}\",\n \"dialog.db-sheet::backdrop{background:rgb(0 0 0/.6)}\",\n \".db-sheet-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1rem 1.5rem;border-bottom:1px solid var(--border)}\",\n // The dialog sits inside the page's prose: its h2 rule (border, margins)\n // would otherwise style the title. Element + class beats `.docs-prose h2`.\n \"dialog.db-sheet h2.db-sheet-title{margin:0;padding:0;border:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;scroll-margin:0}\",\n \".db-sheet-close{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:.375rem;background:transparent;color:var(--muted-foreground);cursor:pointer}\",\n \".db-sheet-close:hover{background:var(--accent,var(--muted));color:var(--foreground)}\",\n \".db-sheet-close:focus-visible{outline:2px solid var(--ring);outline-offset:2px}\",\n \".db-sheet-body{flex:1;overflow-y:auto;padding:1.5rem;font-size:.875rem;line-height:1.625}\",\n // Beats `.docs-prose p` (0,2,1): the first paragraph sat 12px down\n \"dialog.db-sheet .db-sheet-body>:first-child{margin-top:0}\",\n // A modal sheet: the page under it does not scroll\n \"html:has(dialog.db-sheet[open]){overflow:hidden}\",\n // The summary opens a panel, not a fold: its chevron points to the side.\n \"db-details-sheet>details>summary>span:last-child{transform:rotate(-90deg)}\",\n \"@media (prefers-reduced-motion:no-preference){dialog.db-sheet[open]{animation:db-sheet-in .2s ease-out}dialog.db-sheet[open]::backdrop{animation:db-sheet-fade .2s ease-out}}\",\n \"@keyframes db-sheet-in{from{transform:translateX(100%)}}\",\n \"@keyframes db-sheet-fade{from{opacity:0}}\",\n ].join(\"\");\n document.head.append(style);\n}\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-details-sheet\")) {\n customElements.define(\"db-details-sheet\", DbDetailsSheet);\n}\n"],"mappings":";;;;;;;;;;AA0BO,IAAM,iBAAN,cAA6B,eAAe;AAAA,EACzC,UAAqC;AAAA,EACrC,UAA8B;AAAA,EAC9B,SAAmC;AAAA,EACnC,OAA2B;AAAA;AAAA,EAE3B,SAA6B;AAAA,EAC7B,QAAgB,CAAC;AAAA;AAAA;AAAA,EAGjB,cAA6B;AAAA,EAErC,IAAI,OAAgB;AAClB,WAAO,CAAC,CAAC,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEQ,iBAAiB,CAAC,MAAa;AAErC,UAAM,IAAI,EAAE;AACZ,QAAI,KAAK,MAAM,KAAK,WAAW,EAAE,UAAU,iDAAiD,GAAG,QAAQ,SAAS,MAAM,KAAK,QAAS;AACpI,MAAE,eAAe;AACjB,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA,EAGQ,gBAAgB,CAAC,MAAkB;AACzC,UAAM,IAAI,KAAK;AACf,QAAI,CAAC,KAAK,EAAE,WAAW,EAAG;AAC1B,UAAM,IAAI,EAAE,sBAAsB;AAClC,UAAM,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE;AACnG,QAAI,CAAC,WAAW,EAAE,YAAY,KAAK,EAAE,YAAY,GAAI,GAAE,MAAM;AAAA,EAC/D;AAAA;AAAA,EAGQ,gBAAgB,MAAM,KAAK,QAAQ;AAAA,EAEnC,SAAS,MAAM;AACrB,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEU,QAAQ;AAChB,UAAM,UAAU,MAAM,KAAK,KAAK,QAAQ,EAAE,KAAK,CAAC,MAA+B,EAAE,YAAY,SAAS,KAAK;AAC3G,UAAM,UAAU,UAAW,MAAM,KAAK,QAAQ,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,SAAS,KAAiC,OAAO;AAEnI,UAAM,WAAW,OAAO,sBAAsB,eAAe,OAAO,kBAAkB,UAAU,cAAc;AAC9G,QAAI,CAAC,WAAW,CAAC,WAAW,CAAC,SAAU;AAGvC,eAAW,KAAK,MAAM,KAAK,QAAQ,QAAQ,EAAG,KAAI,EAAE,aAAa,MAAM,MAAM,SAAU,GAAE,aAAa,aAAa,KAAK;AACxH,SAAK,UAAU;AACf,SAAK,UAAU;AACf,YAAQ,OAAO;AACf,sBAAkB;AAElB,UAAM,SAAS,QAAQ,cAAc,qBAAqB,GAAG,eAAe,QAAQ,eAAe,IAAI,KAAK;AAC5G,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,YAAY;AACnB,WAAO,KAAK,IAAI,UAAU;AAC1B,UAAM,UAAU,SAAS,cAAc,IAAI;AAC3C,YAAQ,YAAY;AACpB,YAAQ,KAAK,IAAI,gBAAgB;AACjC,YAAQ,cAAc;AACtB,WAAO,aAAa,mBAAmB,QAAQ,EAAE;AACjD,UAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,UAAM,OAAO;AACb,UAAM,YAAY;AAClB,UAAM,aAAa,cAAc,KAAK,aAAa,aAAa,KAAK,OAAO;AAC5E,UAAM,YAAY;AAClB,UAAM,iBAAiB,SAAS,MAAM,OAAO,MAAM,CAAC;AACpD,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,YAAY;AACnB,WAAO,OAAO,SAAS,KAAK;AAC5B,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,YAAY;AACjB,WAAO,OAAO,QAAQ,IAAI;AAE1B,SAAK,OAAO,MAAM;AAClB,SAAK,SAAS;AACd,SAAK,OAAO;AAEZ,YAAQ,aAAa,iBAAiB,QAAQ;AAC9C,YAAQ,aAAa,iBAAiB,OAAO,EAAE;AAC/C,YAAQ,aAAa,iBAAiB,OAAO;AAC7C,SAAK,aAAa,cAAc,QAAQ;AAAA,EAC1C;AAAA,EAEU,UAAU;AAClB,QAAI,CAAC,KAAK,OAAQ;AAClB,SAAK,QAAS,iBAAiB,SAAS,KAAK,cAAc;AAC3D,SAAK,OAAO,iBAAiB,SAAS,KAAK,aAAa;AACxD,SAAK,OAAO,iBAAiB,SAAS,KAAK,aAAa;AACxD,WAAO,iBAAiB,cAAc,KAAK,MAAM;AACjD,mBAAe,MAAM,KAAK,eAAe,KAAK,YAAY,CAAC;AAAA,EAC7D;AAAA,EAEU,aAAa;AACrB,QAAI,CAAC,KAAK,OAAQ;AAGlB,QAAI,KAAK,OAAO,KAAM,MAAK,OAAO,MAAM;AACxC,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAS,oBAAoB,SAAS,KAAK,cAAc;AAC9D,SAAK,OAAO,oBAAoB,SAAS,KAAK,aAAa;AAC3D,SAAK,OAAO,oBAAoB,SAAS,KAAK,aAAa;AAC3D,WAAO,oBAAoB,cAAc,KAAK,MAAM;AAAA,EACtD;AAAA,EAEA,KAAK,aAA8B;AACjC,UAAM,EAAE,QAAQ,SAAS,KAAK,IAAI;AAClC,QAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,OAAO,KAAM;AAGjD,UAAM,OAAO,MAAM,KAAK,QAAQ,UAAU,EAAE,OAAO,CAAC,MAAM,MAAM,KAAK,OAAO;AAC5E,UAAM,WAAW,KAAK,OAAO,CAAC,MAAM,EAAE,aAAa,KAAK,YAAY;AACpE,UAAM,UAAU,SAAS,WAAW,KAAK,KAAK,MAAM,CAAC,MAAM,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,aAAa,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI;AACxH,SAAK,SAAS,WAAW;AACzB,SAAK,QAAQ,UAAU,MAAM,KAAK,QAAQ,UAAU,IAAI;AACxD,SAAK,OAAO,GAAG,KAAK,KAAK;AACzB,WAAO,UAAU;AACjB,SAAK,QAAS,aAAa,iBAAiB,MAAM;AAClD,SAAK,aAAa,cAAc,MAAM;AACtC,QAAI,eAAe,gBAAgB,QAAS,CAAC,YAA4B,iBAAiB,EAAE,OAAO,QAAQ,CAAC;AAC5G,SAAK,cAAc,IAAI,YAAY,yBAAyB,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,EAChF;AAAA,EAEA,QAAQ;AACN,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA,EAEQ,QAAQ,QAAQ,MAAM;AAC5B,QAAI,CAAC,KAAK,OAAQ;AAClB,SAAK,OAAO,OAAO,GAAG,KAAK,KAAK;AAChC,SAAK,SAAS;AACd,SAAK,QAAQ,CAAC;AACd,SAAK,QAAS,aAAa,iBAAiB,OAAO;AACnD,SAAK,aAAa,cAAc,QAAQ;AAExC,QAAI,SAAS,KAAK,eAAe,KAAK,QAAS,kBAAkB,MAAM,MAAO,MAAK,QAAS,MAAM;AAClG,SAAK,cAAc,IAAI,YAAY,0BAA0B,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,EACjF;AAAA;AAAA,EAGQ,cAAc;AACpB,UAAM,KAAK,WAAW,SAAS,KAAK,MAAM,CAAC,CAAC;AAC5C,QAAI,CAAC,MAAM,CAAC,KAAK,WAAW,KAAK,gBAAgB,SAAS,KAAM;AAChE,SAAK,cAAc,SAAS;AAC5B,QAAI,KAAK,KAAM;AACf,UAAM,SAAS,SAAS,eAAe,EAAE;AACzC,QAAI,UAAU,KAAK,QAAQ,SAAS,MAAM,EAAG,MAAK,KAAK,MAAM;AAAA,EAC/D;AACF;AAEA,IAAM,WAAW;AAQjB,SAAS,oBAAoB;AAC3B,MAAI,SAAS,eAAe,QAAQ,EAAG;AACvC,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,EAAE;AACT,WAAS,KAAK,OAAO,KAAK;AAC5B;AAEA,qBAAqB;AAErB,IAAI,CAAC,eAAe,IAAI,kBAAkB,GAAG;AAC3C,iBAAe,OAAO,oBAAoB,cAAc;AAC1D;","names":[]}
@@ -3,11 +3,11 @@ import {
3
3
  ownOne,
4
4
  resolveAsChild,
5
5
  uid
6
- } from "./chunk-3AEQ6KHV.js";
6
+ } from "./chunk-KXCPLIQD.js";
7
7
  import {
8
8
  DogsbayElement,
9
9
  ensureDefaultDisplay
10
- } from "./chunk-K6DPDBAG.js";
10
+ } from "./chunk-MZDGSTI4.js";
11
11
 
12
12
  // src/db-dialog.ts
13
13
  import { FocusTrap } from "@dogsbay/primitives/focus-trap";
@@ -205,4 +205,4 @@ if (!customElements.get("db-dialog")) {
205
205
  export {
206
206
  DbDialog
207
207
  };
208
- //# sourceMappingURL=chunk-SLJG53M7.js.map
208
+ //# sourceMappingURL=chunk-RZ3KZOM3.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DogsbayElement,
3
3
  ensureDefaultDisplay
4
- } from "./chunk-K6DPDBAG.js";
4
+ } from "./chunk-MZDGSTI4.js";
5
5
 
6
6
  // src/db-link-button.ts
7
7
  var DbLinkButton = class extends DogsbayElement {
@@ -36,4 +36,4 @@ if (!customElements.get("db-link-button")) {
36
36
  export {
37
37
  DbLinkButton
38
38
  };
39
- //# sourceMappingURL=chunk-QSRUT67Y.js.map
39
+ //# sourceMappingURL=chunk-US4H4ZPZ.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbAccordion
3
- } from "./chunk-CLUADA3G.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-5KHESKQR.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbAccordion
7
7
  };
package/dist/db-card.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbCard
3
- } from "./chunk-ETBBSA3I.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-JRAYNKQ6.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbCard
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbCodeBlock
3
- } from "./chunk-V4P3UR4I.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-CD3G6HKT.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbCodeBlock
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbCollapsible
3
- } from "./chunk-LAUNXWKJ.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-5WY3DHVB.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbCollapsible
7
7
  };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbCombobox
3
- } from "./chunk-MAD6XJY4.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-GC5HL7FU.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbCombobox
8
8
  };
@@ -0,0 +1,52 @@
1
+ import { D as DogsbayElement } from './base-D1Rz70fn.js';
2
+
3
+ /**
4
+ * `<db-details-sheet>` — a `<details>` that opens as a side sheet.
5
+ *
6
+ * The markup is an ordinary `<details>` (the CollapsibleAlert markup), so
7
+ * with no script — `js: none`, a blocked script, print, an agent reading the
8
+ * HTML — it is a working collapsible block and nothing is hidden. With the
9
+ * script, activating the summary opens the body in a native modal `<dialog>`
10
+ * on the right instead: the browser puts it in the top layer, makes the page
11
+ * inert and handles Escape.
12
+ *
13
+ * The body is MOVED into the sheet while it is open and back when it closes,
14
+ * so ids, anchors and nested elements exist once. A URL fragment naming the
15
+ * details or anything in its body opens the sheet, so a cross-reference lands.
16
+ *
17
+ * Attributes:
18
+ * close-label — the close button's accessible name (default "Close")
19
+ *
20
+ * Children:
21
+ * <details> with a <summary> — the summary's `[data-part="title"]`, or its
22
+ * text, titles the sheet
23
+ *
24
+ * Events: db-details-sheet:open, db-details-sheet:close
25
+ */
26
+ declare class DbDetailsSheet extends DogsbayElement {
27
+ private details;
28
+ private summary;
29
+ private dialog;
30
+ private body;
31
+ /** Where the moved nodes came from, and the nodes, while the sheet is open. */
32
+ private source;
33
+ private moved;
34
+ /** The fragment already acted on: moving a nested sheet in and out of a
35
+ * dialog reconnects it, and reopening on every connect made it undismissable. */
36
+ private handledHash;
37
+ get open(): boolean;
38
+ private onSummaryClick;
39
+ private onDialogClick;
40
+ private onDialogClose;
41
+ private onHash;
42
+ protected setup(): void;
43
+ protected connect(): void;
44
+ protected disconnect(): void;
45
+ show(focusTarget?: Element | null): void;
46
+ close(): void;
47
+ private restore;
48
+ /** Open when the URL fragment names the details or something in its body. */
49
+ private openForHash;
50
+ }
51
+
52
+ export { DbDetailsSheet };
@@ -0,0 +1,9 @@
1
+ import {
2
+ DbDetailsSheet
3
+ } from "./chunk-P7QNCZF7.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
+ export {
7
+ DbDetailsSheet
8
+ };
9
+ //# sourceMappingURL=db-details-sheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/db-dialog.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbDialog
3
- } from "./chunk-SLJG53M7.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-RZ3KZOM3.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbDialog
8
8
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbLinkButton
3
- } from "./chunk-QSRUT67Y.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-US4H4ZPZ.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbLinkButton
7
7
  };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbNavTree
3
- } from "./chunk-S62ZVVO3.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-2ZMWJ74J.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbNavTree
8
8
  };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbPopover
3
- } from "./chunk-EGU66XCL.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-6QAYHFIQ.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbPopover
8
8
  };
package/dist/db-select.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbSelect
3
- } from "./chunk-3FMXAKOU.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-HMNRE3FZ.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbSelect
8
8
  };
package/dist/db-steps.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbSteps
3
- } from "./chunk-VW7HZY2B.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-AVQ7KRRE.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbSteps
7
7
  };
package/dist/db-tabs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DbTabs
3
- } from "./chunk-4YPDR3W6.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-6ZKFQBCF.js";
4
+ import "./chunk-MZDGSTI4.js";
5
5
  export {
6
6
  DbTabs
7
7
  };
package/dist/db-toc.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  DbToc
3
- } from "./chunk-FIJZRZEN.js";
4
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-EPHDSTM7.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
5
6
  export {
6
7
  DbToc
7
8
  };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  DbTooltip
3
- } from "./chunk-MEOIAZDF.js";
4
- import "./chunk-3AEQ6KHV.js";
5
- import "./chunk-K6DPDBAG.js";
3
+ } from "./chunk-HMV62CBN.js";
4
+ import "./chunk-KXCPLIQD.js";
5
+ import "./chunk-MZDGSTI4.js";
6
6
  export {
7
7
  DbTooltip
8
8
  };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ 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';
package/dist/index.js CHANGED
@@ -1,55 +1,59 @@
1
+ import {
2
+ DbNavTree
3
+ } from "./chunk-2ZMWJ74J.js";
1
4
  import {
2
5
  DbPopover
3
- } from "./chunk-EGU66XCL.js";
6
+ } from "./chunk-6QAYHFIQ.js";
4
7
  import {
5
8
  DbSelect
6
- } from "./chunk-3FMXAKOU.js";
9
+ } from "./chunk-HMNRE3FZ.js";
7
10
  import {
8
11
  DbSteps
9
- } from "./chunk-VW7HZY2B.js";
12
+ } from "./chunk-AVQ7KRRE.js";
10
13
  import {
11
14
  DbTabs
12
- } from "./chunk-4YPDR3W6.js";
15
+ } from "./chunk-6ZKFQBCF.js";
13
16
  import {
14
17
  DbToc
15
- } from "./chunk-FIJZRZEN.js";
18
+ } from "./chunk-EPHDSTM7.js";
16
19
  import {
17
20
  DbTooltip
18
- } from "./chunk-MEOIAZDF.js";
21
+ } from "./chunk-HMV62CBN.js";
19
22
  import {
20
23
  DbAccordion
21
- } from "./chunk-CLUADA3G.js";
24
+ } from "./chunk-5KHESKQR.js";
22
25
  import {
23
26
  DbCard
24
- } from "./chunk-ETBBSA3I.js";
27
+ } from "./chunk-JRAYNKQ6.js";
25
28
  import {
26
29
  DbCodeBlock
27
- } from "./chunk-V4P3UR4I.js";
30
+ } from "./chunk-CD3G6HKT.js";
28
31
  import {
29
32
  DbCollapsible
30
- } from "./chunk-LAUNXWKJ.js";
33
+ } from "./chunk-5WY3DHVB.js";
31
34
  import {
32
35
  DbCombobox
33
- } from "./chunk-MAD6XJY4.js";
36
+ } from "./chunk-GC5HL7FU.js";
37
+ import {
38
+ DbDetailsSheet
39
+ } from "./chunk-P7QNCZF7.js";
34
40
  import {
35
41
  DbDialog
36
- } from "./chunk-SLJG53M7.js";
42
+ } from "./chunk-RZ3KZOM3.js";
43
+ import "./chunk-KXCPLIQD.js";
37
44
  import {
38
45
  DbLinkButton
39
- } from "./chunk-QSRUT67Y.js";
40
- import {
41
- DbNavTree
42
- } from "./chunk-S62ZVVO3.js";
43
- import "./chunk-3AEQ6KHV.js";
46
+ } from "./chunk-US4H4ZPZ.js";
44
47
  import {
45
48
  DogsbayElement
46
- } from "./chunk-K6DPDBAG.js";
49
+ } from "./chunk-MZDGSTI4.js";
47
50
  export {
48
51
  DbAccordion,
49
52
  DbCard,
50
53
  DbCodeBlock,
51
54
  DbCollapsible,
52
55
  DbCombobox,
56
+ DbDetailsSheet,
53
57
  DbDialog,
54
58
  DbLinkButton,
55
59
  DbNavTree,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/elements",
3
- "version": "0.2.0-beta.120",
3
+ "version": "0.2.0-beta.122",
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"
@@ -70,7 +74,7 @@
70
74
  "dist"
71
75
  ],
72
76
  "dependencies": {
73
- "@dogsbay/primitives": "0.2.0-beta.120"
77
+ "@dogsbay/primitives": "0.2.0-beta.122"
74
78
  },
75
79
  "devDependencies": {
76
80
  "happy-dom": "^20.10.6",
@@ -1 +0,0 @@
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":"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","names":[]}
@@ -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 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":[]}