@dogsbay/elements 0.2.0-beta.14 → 0.2.0-beta.140
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.
- package/dist/{base-BtvRtAsC.d.ts → base-D1Rz70fn.d.ts} +1 -0
- package/dist/chunk-2ZMWJ74J.js +233 -0
- package/dist/{chunk-7M7SFLKN.js → chunk-5KHESKQR.js} +4 -3
- package/dist/{chunk-TTNTPXBA.js → chunk-5WY3DHVB.js} +4 -3
- package/dist/chunk-6QAYHFIQ.js +115 -0
- package/dist/{chunk-LVXR7KTB.js → chunk-6ZKFQBCF.js} +40 -12
- package/dist/{chunk-5T4OXQA2.js → chunk-AVQ7KRRE.js} +5 -6
- package/dist/{chunk-FWAAU5UY.js → chunk-CD3G6HKT.js} +4 -3
- package/dist/chunk-EPHDSTM7.js +85 -0
- package/dist/chunk-GC5HL7FU.js +255 -0
- package/dist/chunk-HMNRE3FZ.js +382 -0
- package/dist/chunk-HMV62CBN.js +139 -0
- package/dist/{chunk-7BIVQSGP.js → chunk-JRAYNKQ6.js} +4 -3
- package/dist/chunk-KFY2MTR3.js +190 -0
- package/dist/chunk-KXCPLIQD.js +77 -0
- package/dist/chunk-MZDGSTI4.js +72 -0
- package/dist/chunk-RZ3KZOM3.js +207 -0
- package/dist/{chunk-LFXZQ4YV.js → chunk-US4H4ZPZ.js} +4 -3
- package/dist/db-accordion.d.ts +1 -1
- package/dist/db-accordion.js +2 -3
- package/dist/db-card.d.ts +1 -1
- package/dist/db-card.js +2 -3
- package/dist/db-code-block.d.ts +1 -1
- package/dist/db-code-block.js +2 -3
- package/dist/db-collapsible.d.ts +1 -1
- package/dist/db-collapsible.js +2 -3
- package/dist/db-combobox.d.ts +70 -0
- package/dist/db-combobox.js +8 -0
- package/dist/db-details-sheet.d.ts +53 -0
- package/dist/db-details-sheet.js +8 -0
- package/dist/db-dialog.d.ts +62 -0
- package/dist/db-dialog.js +8 -0
- package/dist/db-link-button.d.ts +1 -1
- package/dist/db-link-button.js +2 -3
- package/dist/db-nav-tree.d.ts +83 -0
- package/dist/db-nav-tree.js +8 -0
- package/dist/db-popover.d.ts +42 -0
- package/dist/db-popover.js +8 -0
- package/dist/db-select.d.ts +72 -0
- package/dist/db-select.js +8 -0
- package/dist/db-steps.d.ts +1 -1
- package/dist/db-steps.js +2 -3
- package/dist/db-tabs.d.ts +28 -1
- package/dist/db-tabs.js +2 -3
- package/dist/db-toc.d.ts +32 -0
- package/dist/db-toc.js +8 -0
- package/dist/db-tooltip.d.ts +48 -0
- package/dist/db-tooltip.js +8 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +44 -12
- package/package.json +38 -6
- package/dist/chunk-5T4OXQA2.js.map +0 -1
- package/dist/chunk-7BIVQSGP.js.map +0 -1
- package/dist/chunk-7M7SFLKN.js.map +0 -1
- package/dist/chunk-FWAAU5UY.js.map +0 -1
- package/dist/chunk-LFXZQ4YV.js.map +0 -1
- package/dist/chunk-LVXR7KTB.js.map +0 -1
- package/dist/chunk-TTNTPXBA.js.map +0 -1
- package/dist/chunk-XBMLE4N3.js +0 -28
- package/dist/chunk-XBMLE4N3.js.map +0 -1
- package/dist/db-accordion.js.map +0 -1
- package/dist/db-card.js.map +0 -1
- package/dist/db-code-block.js.map +0 -1
- package/dist/db-collapsible.js.map +0 -1
- package/dist/db-link-button.js.map +0 -1
- package/dist/db-steps.js.map +0 -1
- package/dist/db-tabs.js.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import {
|
|
2
|
+
own,
|
|
3
|
+
uid
|
|
4
|
+
} from "./chunk-KXCPLIQD.js";
|
|
5
|
+
import {
|
|
6
|
+
DogsbayElement,
|
|
7
|
+
ensureDefaultDisplay
|
|
8
|
+
} from "./chunk-MZDGSTI4.js";
|
|
9
|
+
|
|
10
|
+
// src/db-nav-tree.ts
|
|
11
|
+
var DbNavTree = class extends DogsbayElement {
|
|
12
|
+
/** Nav data for lazy sections. Falls back to `window[data-source]`. */
|
|
13
|
+
navData = null;
|
|
14
|
+
onClick = (e) => {
|
|
15
|
+
const toggle = e.target.closest("[data-part='toggle']");
|
|
16
|
+
if (!toggle || toggle.closest("db-nav-tree") !== this) return;
|
|
17
|
+
const item = toggle.closest("[data-part='item']");
|
|
18
|
+
if (item) this.toggle(item);
|
|
19
|
+
};
|
|
20
|
+
onKey = (e) => {
|
|
21
|
+
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
22
|
+
const active = document.activeElement;
|
|
23
|
+
if (!active || !this.contains(active)) return;
|
|
24
|
+
const rows = this.visibleRows();
|
|
25
|
+
const row = active.closest("[data-part='row']");
|
|
26
|
+
const i = row ? rows.indexOf(row) : -1;
|
|
27
|
+
if (i < 0) return;
|
|
28
|
+
const item = row.closest("[data-part='item']");
|
|
29
|
+
const hasGroup = !!this.groupOf(item);
|
|
30
|
+
const focusRow = (r) => {
|
|
31
|
+
if (!r) return;
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
this.primary(r)?.focus();
|
|
34
|
+
};
|
|
35
|
+
switch (e.key) {
|
|
36
|
+
case "ArrowDown":
|
|
37
|
+
return focusRow(rows[i + 1]);
|
|
38
|
+
case "ArrowUp":
|
|
39
|
+
return focusRow(rows[i - 1]);
|
|
40
|
+
case "Home":
|
|
41
|
+
return focusRow(rows[0]);
|
|
42
|
+
case "End":
|
|
43
|
+
return focusRow(rows[rows.length - 1]);
|
|
44
|
+
case "ArrowRight":
|
|
45
|
+
if (!hasGroup) return;
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
if (!this.isOpen(item)) this.setOpen(item, true);
|
|
48
|
+
else focusRow(this.visibleRows()[i + 1]);
|
|
49
|
+
return;
|
|
50
|
+
case "ArrowLeft": {
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
if (hasGroup && this.isOpen(item)) return this.setOpen(item, false);
|
|
53
|
+
const parent = item.parentElement?.closest("[data-part='item']");
|
|
54
|
+
if (parent && this.contains(parent)) {
|
|
55
|
+
const pr = parent.querySelector(":scope > [data-part='row']");
|
|
56
|
+
if (pr) this.primary(pr)?.focus();
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
setup() {
|
|
63
|
+
for (const item of own(this, "[data-part='item']")) this.prepareItem(item);
|
|
64
|
+
}
|
|
65
|
+
connect() {
|
|
66
|
+
this.addEventListener("click", this.onClick);
|
|
67
|
+
this.addEventListener("keydown", this.onKey);
|
|
68
|
+
for (const g of own(this, "[data-part='group'][data-lazy]")) {
|
|
69
|
+
const item = g.closest("[data-part='item']");
|
|
70
|
+
if (item && this.isOpen(item)) this.fill(g);
|
|
71
|
+
}
|
|
72
|
+
if (this.hasAttribute("scroll-current")) requestAnimationFrame(() => this.revealCurrent());
|
|
73
|
+
}
|
|
74
|
+
disconnect() {
|
|
75
|
+
this.removeEventListener("click", this.onClick);
|
|
76
|
+
this.removeEventListener("keydown", this.onKey);
|
|
77
|
+
}
|
|
78
|
+
prepareItem(item) {
|
|
79
|
+
const group = this.groupOf(item);
|
|
80
|
+
const toggle = item.querySelector(":scope > [data-part='row'] > [data-part='toggle']");
|
|
81
|
+
if (!group || !toggle) return;
|
|
82
|
+
group.id ||= uid("db-nav-group");
|
|
83
|
+
toggle.setAttribute("aria-controls", group.id);
|
|
84
|
+
if (toggle instanceof HTMLButtonElement && !toggle.hasAttribute("type")) toggle.type = "button";
|
|
85
|
+
const open = toggle.getAttribute("aria-expanded") === "true" || item.getAttribute("data-state") === "open";
|
|
86
|
+
this.apply(item, open);
|
|
87
|
+
}
|
|
88
|
+
groupOf(item) {
|
|
89
|
+
return item.querySelector(":scope > [data-part='group']");
|
|
90
|
+
}
|
|
91
|
+
toggleOf(item) {
|
|
92
|
+
return item.querySelector(":scope > [data-part='row'] > [data-part='toggle']");
|
|
93
|
+
}
|
|
94
|
+
/** The row's main focus target: its link, or its toggle for a label-only section. */
|
|
95
|
+
primary(row) {
|
|
96
|
+
return row.querySelector(":scope > [data-part='link']") ?? row.querySelector(":scope > [data-part='toggle']");
|
|
97
|
+
}
|
|
98
|
+
visibleRows() {
|
|
99
|
+
return own(this, "[data-part='row']").filter((r) => !r.closest("[hidden]"));
|
|
100
|
+
}
|
|
101
|
+
isOpen(item) {
|
|
102
|
+
return item.getAttribute("data-state") === "open";
|
|
103
|
+
}
|
|
104
|
+
toggle(item) {
|
|
105
|
+
this.setOpen(item, !this.isOpen(item));
|
|
106
|
+
}
|
|
107
|
+
setOpen(item, open) {
|
|
108
|
+
const group = this.groupOf(item);
|
|
109
|
+
if (!group || this.isOpen(item) === open) return;
|
|
110
|
+
if (open && group.hasAttribute("data-lazy")) this.fill(group);
|
|
111
|
+
this.apply(item, open);
|
|
112
|
+
this.dispatchEvent(new CustomEvent("db-nav-tree:toggle", { detail: { item, open }, bubbles: true }));
|
|
113
|
+
}
|
|
114
|
+
apply(item, open) {
|
|
115
|
+
const group = this.groupOf(item);
|
|
116
|
+
const toggle = this.toggleOf(item);
|
|
117
|
+
if (group) group.hidden = !open;
|
|
118
|
+
toggle?.setAttribute("aria-expanded", String(open));
|
|
119
|
+
item.setAttribute("data-state", open ? "open" : "closed");
|
|
120
|
+
}
|
|
121
|
+
/** Expand every section on the path to the current page. */
|
|
122
|
+
revealCurrent() {
|
|
123
|
+
const cur = this.querySelector("[aria-current='page']");
|
|
124
|
+
if (!cur) return;
|
|
125
|
+
for (let item = cur.closest("[data-part='item']"); item && this.contains(item); item = item.parentElement?.closest("[data-part='item']") ?? null) {
|
|
126
|
+
if (this.groupOf(item) && !this.groupOf(item).contains(cur)) continue;
|
|
127
|
+
if (this.groupOf(item)) this.setOpen(item, true);
|
|
128
|
+
}
|
|
129
|
+
const scroller = scrollParent(this);
|
|
130
|
+
if (!scroller) return;
|
|
131
|
+
const r = cur.getBoundingClientRect();
|
|
132
|
+
const s = scroller.getBoundingClientRect();
|
|
133
|
+
if (r.top < s.top || r.bottom > s.bottom) scroller.scrollTop += r.top - s.top - s.height / 2 + r.height / 2;
|
|
134
|
+
}
|
|
135
|
+
data() {
|
|
136
|
+
if (this.navData) return this.navData;
|
|
137
|
+
const name = this.getAttribute("data-source");
|
|
138
|
+
const g = name ? globalThis[name] : void 0;
|
|
139
|
+
return Array.isArray(g) ? g : null;
|
|
140
|
+
}
|
|
141
|
+
/** Fill a lazy group from nav data. */
|
|
142
|
+
fill(group) {
|
|
143
|
+
const data = this.data();
|
|
144
|
+
const path = group.dataset.path;
|
|
145
|
+
if (!data || path == null) return;
|
|
146
|
+
let list = data;
|
|
147
|
+
let node;
|
|
148
|
+
for (const i of path.split(".").map(Number)) {
|
|
149
|
+
node = list?.[i];
|
|
150
|
+
list = node?.[2];
|
|
151
|
+
}
|
|
152
|
+
if (!node?.[2]) return;
|
|
153
|
+
group.replaceChildren(...this.build(node[2], path));
|
|
154
|
+
group.removeAttribute("data-lazy");
|
|
155
|
+
}
|
|
156
|
+
build(items, path) {
|
|
157
|
+
const base = this.getAttribute("base") ?? "";
|
|
158
|
+
const tmpl = this.getAttribute("toggle-label") ?? "Toggle {label}";
|
|
159
|
+
const current = location.href.split("#")[0];
|
|
160
|
+
return items.map(([label, url, kids, noCurrent], i) => {
|
|
161
|
+
const here = `${path}.${i}`;
|
|
162
|
+
const li = document.createElement("li");
|
|
163
|
+
li.setAttribute("data-part", "item");
|
|
164
|
+
li.style.setProperty("--db-level", String(here.split(".").length - 1));
|
|
165
|
+
const row = document.createElement("div");
|
|
166
|
+
row.setAttribute("data-part", "row");
|
|
167
|
+
li.appendChild(row);
|
|
168
|
+
const probe = url?.replace(/[\u0000-\u0020]/g, "") ?? "";
|
|
169
|
+
if (url != null && /^[a-z][a-z0-9+.-]*:/i.test(probe) && !/^(?:https?|mailto):/i.test(probe)) url = null;
|
|
170
|
+
const external = url != null && /^[a-z][a-z0-9+.-]*:|^\/\//i.test(probe);
|
|
171
|
+
let toggle = null;
|
|
172
|
+
if (kids?.length) {
|
|
173
|
+
toggle = document.createElement("button");
|
|
174
|
+
toggle.type = "button";
|
|
175
|
+
toggle.setAttribute("data-part", "toggle");
|
|
176
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
177
|
+
if (url != null) toggle.setAttribute("aria-label", tmpl.replace("{label}", () => label));
|
|
178
|
+
else {
|
|
179
|
+
const span = document.createElement("span");
|
|
180
|
+
span.setAttribute("data-part", "label");
|
|
181
|
+
span.textContent = label;
|
|
182
|
+
toggle.appendChild(span);
|
|
183
|
+
}
|
|
184
|
+
toggle.insertAdjacentHTML("beforeend", CHEVRON);
|
|
185
|
+
}
|
|
186
|
+
const atEnd = this.getAttribute("toggle-position") === "end";
|
|
187
|
+
if (toggle && !atEnd) row.appendChild(toggle);
|
|
188
|
+
if (url != null) {
|
|
189
|
+
const a = document.createElement("a");
|
|
190
|
+
a.setAttribute("data-part", "link");
|
|
191
|
+
a.textContent = label;
|
|
192
|
+
a.href = external ? url : base + url;
|
|
193
|
+
if (external) a.rel = "noopener";
|
|
194
|
+
if (!noCurrent && a.href.split("#")[0] === current) a.setAttribute("aria-current", "page");
|
|
195
|
+
row.appendChild(a);
|
|
196
|
+
}
|
|
197
|
+
if (url == null && !kids?.length) {
|
|
198
|
+
const span = document.createElement("span");
|
|
199
|
+
span.setAttribute("data-part", "label");
|
|
200
|
+
span.textContent = label;
|
|
201
|
+
row.appendChild(span);
|
|
202
|
+
}
|
|
203
|
+
if (toggle && atEnd) row.appendChild(toggle);
|
|
204
|
+
if (kids?.length) {
|
|
205
|
+
const ul = document.createElement("ul");
|
|
206
|
+
ul.setAttribute("data-part", "group");
|
|
207
|
+
ul.dataset.lazy = "";
|
|
208
|
+
ul.dataset.path = here;
|
|
209
|
+
ul.hidden = true;
|
|
210
|
+
li.setAttribute("data-state", "closed");
|
|
211
|
+
li.appendChild(ul);
|
|
212
|
+
this.prepareItem(li);
|
|
213
|
+
}
|
|
214
|
+
return li;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
var CHEVRON = '<svg data-part="chevron" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false"><path d="m9 18 6-6-6-6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
219
|
+
function scrollParent(el) {
|
|
220
|
+
for (let p = el.parentElement; p; p = p.parentElement) {
|
|
221
|
+
const o = getComputedStyle(p).overflowY;
|
|
222
|
+
if ((o === "auto" || o === "scroll") && p.scrollHeight > p.clientHeight) return p;
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
ensureDefaultDisplay();
|
|
227
|
+
if (!customElements.get("db-nav-tree")) {
|
|
228
|
+
customElements.define("db-nav-tree", DbNavTree);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export {
|
|
232
|
+
DbNavTree
|
|
233
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DogsbayElement
|
|
3
|
-
|
|
2
|
+
DogsbayElement,
|
|
3
|
+
ensureDefaultDisplay
|
|
4
|
+
} from "./chunk-MZDGSTI4.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,3 @@ if (!customElements.get("db-accordion")) {
|
|
|
92
94
|
export {
|
|
93
95
|
DbAccordion
|
|
94
96
|
};
|
|
95
|
-
//# sourceMappingURL=chunk-7M7SFLKN.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DogsbayElement
|
|
3
|
-
|
|
2
|
+
DogsbayElement,
|
|
3
|
+
ensureDefaultDisplay
|
|
4
|
+
} from "./chunk-MZDGSTI4.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,3 @@ if (!customElements.get("db-collapsible")) {
|
|
|
43
45
|
export {
|
|
44
46
|
DbCollapsible
|
|
45
47
|
};
|
|
46
|
-
//# sourceMappingURL=chunk-TTNTPXBA.js.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
focusables,
|
|
3
|
+
hideFloating,
|
|
4
|
+
ownOne,
|
|
5
|
+
resolveAsChild,
|
|
6
|
+
showFloating,
|
|
7
|
+
uid
|
|
8
|
+
} from "./chunk-KXCPLIQD.js";
|
|
9
|
+
import {
|
|
10
|
+
DogsbayElement,
|
|
11
|
+
ensureDefaultDisplay
|
|
12
|
+
} from "./chunk-MZDGSTI4.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
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DogsbayElement
|
|
3
|
-
|
|
2
|
+
DogsbayElement,
|
|
3
|
+
ensureDefaultDisplay
|
|
4
|
+
} from "./chunk-MZDGSTI4.js";
|
|
4
5
|
|
|
5
6
|
// src/db-tabs.ts
|
|
6
7
|
import { CompositeNavigation } from "@dogsbay/primitives/composite";
|
|
@@ -24,29 +25,56 @@ var DbTabs = class extends DogsbayElement {
|
|
|
24
25
|
const value = trigger.dataset.value;
|
|
25
26
|
if (value) this.select(value);
|
|
26
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* A synced group follows only a value it HAS. Groups sharing a key need
|
|
30
|
+
* not share a tab set (a web-only snippet group beside an all-SDK one), and
|
|
31
|
+
* selecting a value with no trigger here left the group with every panel
|
|
32
|
+
* hidden and no tab selected.
|
|
33
|
+
*/
|
|
34
|
+
has(value) {
|
|
35
|
+
return this.triggers.some((t) => t.dataset.value === value);
|
|
36
|
+
}
|
|
27
37
|
handleStorage = (e) => {
|
|
28
38
|
if (!this.syncKey || e.key !== `db-tabs-sync:${this.syncKey}`) return;
|
|
29
39
|
const newValue = e.newValue;
|
|
30
|
-
if (newValue && this.value !== newValue) {
|
|
40
|
+
if (newValue && this.value !== newValue && this.has(newValue)) {
|
|
31
41
|
this.select(newValue);
|
|
32
42
|
}
|
|
33
43
|
};
|
|
34
44
|
handleSyncEvent = ((e) => {
|
|
35
45
|
const newValue = e.detail.value;
|
|
36
|
-
if (newValue && this.value !== newValue) {
|
|
46
|
+
if (newValue && this.value !== newValue && this.has(newValue)) {
|
|
37
47
|
this.select(newValue);
|
|
38
48
|
}
|
|
39
49
|
});
|
|
50
|
+
/**
|
|
51
|
+
* Descendants belonging to THIS tab group.
|
|
52
|
+
*
|
|
53
|
+
* Not `:scope >`, and not a bare descendant query — both were wrong
|
|
54
|
+
* here, in opposite directions:
|
|
55
|
+
*
|
|
56
|
+
* - Panels used `:scope > [data-part='content']`, so any wrapper
|
|
57
|
+
* between the element and its panels hid them. The vertical example
|
|
58
|
+
* wraps its list and panels in a flex row to sit them side by side,
|
|
59
|
+
* so `panels` was EMPTY: triggers moved `aria-selected`, and the
|
|
60
|
+
* content never changed. Nothing threw, and the server-rendered
|
|
61
|
+
* initial state looked right, so it read as working.
|
|
62
|
+
* - Triggers used a bare descendant query, which would reach into a
|
|
63
|
+
* NESTED tab group and drive the wrong panels.
|
|
64
|
+
*
|
|
65
|
+
* `closest("db-tabs") === this` allows arbitrary wrappers while
|
|
66
|
+
* stopping at a nested group, which is a real case — Obsidian
|
|
67
|
+
* alternates fence characters by depth precisely so tabs can nest.
|
|
68
|
+
*/
|
|
69
|
+
own(selector) {
|
|
70
|
+
return Array.from(this.querySelectorAll(selector)).filter((el) => el.closest("db-tabs") === this);
|
|
71
|
+
}
|
|
40
72
|
setup() {
|
|
41
|
-
const list = this.
|
|
73
|
+
const list = this.own("[data-part='list']")[0] ?? null;
|
|
42
74
|
if (!list) return;
|
|
43
75
|
this.list = list;
|
|
44
|
-
this.triggers =
|
|
45
|
-
|
|
46
|
-
);
|
|
47
|
-
this.panels = Array.from(
|
|
48
|
-
this.querySelectorAll(":scope > [data-part='content']")
|
|
49
|
-
);
|
|
76
|
+
this.triggers = this.own("[data-part='trigger']");
|
|
77
|
+
this.panels = this.own("[data-part='content']");
|
|
50
78
|
this.orientation = this.getAttribute("orientation") || "horizontal";
|
|
51
79
|
this.syncKey = this.getAttribute("sync-key") || null;
|
|
52
80
|
list.setAttribute("role", "tablist");
|
|
@@ -151,6 +179,7 @@ var DbTabs = class extends DogsbayElement {
|
|
|
151
179
|
);
|
|
152
180
|
}
|
|
153
181
|
};
|
|
182
|
+
ensureDefaultDisplay();
|
|
154
183
|
if (!customElements.get("db-tabs")) {
|
|
155
184
|
customElements.define("db-tabs", DbTabs);
|
|
156
185
|
}
|
|
@@ -158,4 +187,3 @@ if (!customElements.get("db-tabs")) {
|
|
|
158
187
|
export {
|
|
159
188
|
DbTabs
|
|
160
189
|
};
|
|
161
|
-
//# sourceMappingURL=chunk-LVXR7KTB.js.map
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DogsbayElement
|
|
3
|
-
|
|
2
|
+
DogsbayElement,
|
|
3
|
+
ensureDefaultDisplay
|
|
4
|
+
} from "./chunk-MZDGSTI4.js";
|
|
4
5
|
|
|
5
6
|
// src/db-steps.ts
|
|
6
7
|
var DbSteps = class extends DogsbayElement {
|
|
7
8
|
setup() {
|
|
8
9
|
this.setAttribute("role", "list");
|
|
9
|
-
const items = this.querySelectorAll(
|
|
10
|
-
":scope > [data-part='item']"
|
|
11
|
-
);
|
|
10
|
+
const items = Array.from(this.querySelectorAll("[data-part='item']")).filter((el) => el.closest("db-steps") === this);
|
|
12
11
|
for (const item of items) {
|
|
13
12
|
item.setAttribute("role", "listitem");
|
|
14
13
|
}
|
|
15
14
|
}
|
|
16
15
|
};
|
|
16
|
+
ensureDefaultDisplay();
|
|
17
17
|
if (!customElements.get("db-steps")) {
|
|
18
18
|
customElements.define("db-steps", DbSteps);
|
|
19
19
|
}
|
|
@@ -21,4 +21,3 @@ if (!customElements.get("db-steps")) {
|
|
|
21
21
|
export {
|
|
22
22
|
DbSteps
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=chunk-5T4OXQA2.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DogsbayElement
|
|
3
|
-
|
|
2
|
+
DogsbayElement,
|
|
3
|
+
ensureDefaultDisplay
|
|
4
|
+
} from "./chunk-MZDGSTI4.js";
|
|
4
5
|
|
|
5
6
|
// src/db-code-block.ts
|
|
6
7
|
var DbCodeBlock = class extends DogsbayElement {
|
|
@@ -79,6 +80,7 @@ var DbCodeBlock = class extends DogsbayElement {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
};
|
|
83
|
+
ensureDefaultDisplay();
|
|
82
84
|
if (!customElements.get("db-code-block")) {
|
|
83
85
|
customElements.define("db-code-block", DbCodeBlock);
|
|
84
86
|
}
|
|
@@ -86,4 +88,3 @@ if (!customElements.get("db-code-block")) {
|
|
|
86
88
|
export {
|
|
87
89
|
DbCodeBlock
|
|
88
90
|
};
|
|
89
|
-
//# sourceMappingURL=chunk-FWAAU5UY.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
safeDecode
|
|
3
|
+
} from "./chunk-KXCPLIQD.js";
|
|
4
|
+
import {
|
|
5
|
+
DogsbayElement,
|
|
6
|
+
ensureDefaultDisplay
|
|
7
|
+
} from "./chunk-MZDGSTI4.js";
|
|
8
|
+
|
|
9
|
+
// src/db-toc.ts
|
|
10
|
+
var DbToc = class extends DogsbayElement {
|
|
11
|
+
links = [];
|
|
12
|
+
headings = [];
|
|
13
|
+
observer = null;
|
|
14
|
+
active = null;
|
|
15
|
+
slugOf(a) {
|
|
16
|
+
return a.getAttribute("data-toc-slug") ?? safeDecode(a.getAttribute("href").slice(1));
|
|
17
|
+
}
|
|
18
|
+
// Headings in a short tail never reach the observed band; at the bottom of the
|
|
19
|
+
// page the last one is current.
|
|
20
|
+
onScroll = () => {
|
|
21
|
+
const doc = document.documentElement;
|
|
22
|
+
if (window.innerHeight + window.scrollY >= doc.scrollHeight - 2 && this.headings.length) {
|
|
23
|
+
this.setActive(this.headings[this.headings.length - 1].id);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
setup() {
|
|
27
|
+
this.links = Array.from(this.querySelectorAll("a[href^='#'], a[data-toc-link]"));
|
|
28
|
+
}
|
|
29
|
+
onHash = () => {
|
|
30
|
+
const id = safeDecode(location.hash.slice(1));
|
|
31
|
+
if (id && this.headings.some((h) => h.id === id)) this.setActive(id);
|
|
32
|
+
};
|
|
33
|
+
connect() {
|
|
34
|
+
this.headings = this.links.map((a) => document.getElementById(this.slugOf(a))).filter((h) => !!h);
|
|
35
|
+
if (!this.headings.length) return;
|
|
36
|
+
const offset = Number(this.getAttribute("offset") ?? 80);
|
|
37
|
+
if (typeof IntersectionObserver !== "undefined") {
|
|
38
|
+
this.observer = new IntersectionObserver(
|
|
39
|
+
(entries) => {
|
|
40
|
+
const hit = entries.find((e) => e.isIntersecting);
|
|
41
|
+
if (hit) return this.setActive(hit.target.id);
|
|
42
|
+
this.setActive(this.lastAbove(offset)?.id ?? null);
|
|
43
|
+
},
|
|
44
|
+
{ rootMargin: `-${offset}px 0px -70% 0px`, threshold: 0 }
|
|
45
|
+
);
|
|
46
|
+
this.headings.forEach((h) => this.observer.observe(h));
|
|
47
|
+
}
|
|
48
|
+
window.addEventListener("hashchange", this.onHash);
|
|
49
|
+
window.addEventListener("scroll", this.onScroll, { passive: true });
|
|
50
|
+
this.setActive(this.lastAbove(offset)?.id ?? this.headings[0].id);
|
|
51
|
+
}
|
|
52
|
+
disconnect() {
|
|
53
|
+
this.observer?.disconnect();
|
|
54
|
+
this.observer = null;
|
|
55
|
+
window.removeEventListener("hashchange", this.onHash);
|
|
56
|
+
window.removeEventListener("scroll", this.onScroll);
|
|
57
|
+
}
|
|
58
|
+
lastAbove(offset) {
|
|
59
|
+
let last = null;
|
|
60
|
+
for (const h of this.headings) if (h.getBoundingClientRect().top <= offset + 20) last = h;
|
|
61
|
+
return last;
|
|
62
|
+
}
|
|
63
|
+
setActive(id) {
|
|
64
|
+
if (!id || id === this.active) return;
|
|
65
|
+
this.active = id;
|
|
66
|
+
for (const a of this.links) {
|
|
67
|
+
if (this.slugOf(a) === id) {
|
|
68
|
+
a.setAttribute("aria-current", "location");
|
|
69
|
+
a.setAttribute("data-active", "");
|
|
70
|
+
} else {
|
|
71
|
+
a.removeAttribute("aria-current");
|
|
72
|
+
a.removeAttribute("data-active");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.dispatchEvent(new CustomEvent("db-toc:change", { detail: { id }, bubbles: true }));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
ensureDefaultDisplay();
|
|
79
|
+
if (!customElements.get("db-toc")) {
|
|
80
|
+
customElements.define("db-toc", DbToc);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
DbToc
|
|
85
|
+
};
|