@dogsbay/elements 0.2.0-beta.114 → 0.2.0-beta.116
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-3AEQ6KHV.js +70 -0
- package/dist/chunk-3AEQ6KHV.js.map +1 -0
- package/dist/chunk-3FMXAKOU.js +383 -0
- package/dist/chunk-3FMXAKOU.js.map +1 -0
- package/dist/{chunk-ZLIF4UYD.js → chunk-4YPDR3W6.js} +13 -4
- package/dist/chunk-4YPDR3W6.js.map +1 -0
- package/dist/{chunk-IMW234S2.js → chunk-CLUADA3G.js} +2 -2
- package/dist/chunk-EGU66XCL.js +116 -0
- package/dist/chunk-EGU66XCL.js.map +1 -0
- package/dist/{chunk-THLTJ2HB.js → chunk-ETBBSA3I.js} +2 -2
- package/dist/chunk-FIJZRZEN.js +90 -0
- package/dist/chunk-FIJZRZEN.js.map +1 -0
- package/dist/{chunk-ABP4WEKU.js → chunk-K6DPDBAG.js} +25 -2
- package/dist/chunk-K6DPDBAG.js.map +1 -0
- package/dist/{chunk-5S2MMI3R.js → chunk-LAUNXWKJ.js} +2 -2
- package/dist/chunk-MAD6XJY4.js +256 -0
- package/dist/chunk-MAD6XJY4.js.map +1 -0
- package/dist/chunk-MEOIAZDF.js +140 -0
- package/dist/chunk-MEOIAZDF.js.map +1 -0
- package/dist/{chunk-WTARNLNI.js → chunk-QSRUT67Y.js} +2 -2
- package/dist/chunk-S62ZVVO3.js +234 -0
- package/dist/chunk-S62ZVVO3.js.map +1 -0
- package/dist/chunk-SLJG53M7.js +208 -0
- package/dist/chunk-SLJG53M7.js.map +1 -0
- package/dist/{chunk-RVJC6M2U.js → chunk-V4P3UR4I.js} +2 -2
- package/dist/{chunk-VJXEM5O6.js → chunk-VW7HZY2B.js} +2 -2
- package/dist/db-accordion.d.ts +1 -1
- package/dist/db-accordion.js +2 -2
- package/dist/db-card.d.ts +1 -1
- package/dist/db-card.js +2 -2
- package/dist/db-code-block.d.ts +1 -1
- package/dist/db-code-block.js +2 -2
- package/dist/db-collapsible.d.ts +1 -1
- package/dist/db-collapsible.js +2 -2
- package/dist/db-combobox.d.ts +70 -0
- package/dist/db-combobox.js +9 -0
- package/dist/db-combobox.js.map +1 -0
- package/dist/db-dialog.d.ts +62 -0
- package/dist/db-dialog.js +9 -0
- package/dist/db-dialog.js.map +1 -0
- package/dist/db-link-button.d.ts +1 -1
- package/dist/db-link-button.js +2 -2
- package/dist/db-nav-tree.d.ts +83 -0
- package/dist/db-nav-tree.js +9 -0
- package/dist/db-nav-tree.js.map +1 -0
- package/dist/db-popover.d.ts +42 -0
- package/dist/db-popover.js +9 -0
- package/dist/db-popover.js.map +1 -0
- package/dist/db-select.d.ts +72 -0
- package/dist/db-select.js +9 -0
- package/dist/db-select.js.map +1 -0
- package/dist/db-steps.d.ts +1 -1
- package/dist/db-steps.js +2 -2
- package/dist/db-tabs.d.ts +8 -1
- package/dist/db-tabs.js +2 -2
- package/dist/db-toc.d.ts +32 -0
- package/dist/db-toc.js +8 -0
- package/dist/db-toc.js.map +1 -0
- package/dist/db-tooltip.d.ts +48 -0
- package/dist/db-tooltip.js +9 -0
- package/dist/db-tooltip.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +40 -11
- package/package.json +30 -2
- package/dist/chunk-ABP4WEKU.js.map +0 -1
- package/dist/chunk-ZLIF4UYD.js.map +0 -1
- /package/dist/{chunk-IMW234S2.js.map → chunk-CLUADA3G.js.map} +0 -0
- /package/dist/{chunk-THLTJ2HB.js.map → chunk-ETBBSA3I.js.map} +0 -0
- /package/dist/{chunk-5S2MMI3R.js.map → chunk-LAUNXWKJ.js.map} +0 -0
- /package/dist/{chunk-WTARNLNI.js.map → chunk-QSRUT67Y.js.map} +0 -0
- /package/dist/{chunk-RVJC6M2U.js.map → chunk-V4P3UR4I.js.map} +0 -0
- /package/dist/{chunk-VJXEM5O6.js.map → chunk-VW7HZY2B.js.map} +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
var counter = 0;
|
|
3
|
+
function uid(prefix) {
|
|
4
|
+
return `${prefix}-${++counter}`;
|
|
5
|
+
}
|
|
6
|
+
function own(host, selector) {
|
|
7
|
+
const tag = host.localName;
|
|
8
|
+
return Array.from(host.querySelectorAll(selector)).filter((el) => el.closest(tag) === host);
|
|
9
|
+
}
|
|
10
|
+
function ownOne(host, selector) {
|
|
11
|
+
return own(host, selector)[0] ?? null;
|
|
12
|
+
}
|
|
13
|
+
function resolveAsChild(el) {
|
|
14
|
+
if (!el || !el.hasAttribute("data-as-child")) return el;
|
|
15
|
+
const child = el.firstElementChild;
|
|
16
|
+
if (!child) return el;
|
|
17
|
+
const part = el.getAttribute("data-part");
|
|
18
|
+
if (part) child.setAttribute("data-part", part);
|
|
19
|
+
return child;
|
|
20
|
+
}
|
|
21
|
+
function isDisabled(el) {
|
|
22
|
+
return el.hasAttribute("disabled") || el.getAttribute("aria-disabled") === "true" || el.getAttribute("data-disabled") === "true";
|
|
23
|
+
}
|
|
24
|
+
function supportsPopover() {
|
|
25
|
+
return typeof HTMLElement !== "undefined" && typeof HTMLElement.prototype.showPopover === "function";
|
|
26
|
+
}
|
|
27
|
+
function showFloating(el) {
|
|
28
|
+
el.hidden = false;
|
|
29
|
+
if (!supportsPopover()) return "inline";
|
|
30
|
+
if (!el.hasAttribute("popover")) el.setAttribute("popover", "manual");
|
|
31
|
+
el.style.inset = "auto";
|
|
32
|
+
el.style.margin = "0";
|
|
33
|
+
try {
|
|
34
|
+
if (!el.matches(":popover-open")) el.showPopover();
|
|
35
|
+
} catch {
|
|
36
|
+
return "inline";
|
|
37
|
+
}
|
|
38
|
+
return "top-layer";
|
|
39
|
+
}
|
|
40
|
+
function hideFloating(el) {
|
|
41
|
+
if (supportsPopover()) {
|
|
42
|
+
try {
|
|
43
|
+
if (el.matches(":popover-open")) el.hidePopover();
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
el.hidden = true;
|
|
48
|
+
}
|
|
49
|
+
var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable="true"]';
|
|
50
|
+
function focusables(root) {
|
|
51
|
+
return Array.from(root.querySelectorAll(FOCUSABLE)).filter((el) => !el.closest("[hidden]") && !isDisabled(el));
|
|
52
|
+
}
|
|
53
|
+
function afterAnimations(el, done) {
|
|
54
|
+
const anims = typeof el.getAnimations === "function" ? el.getAnimations() : [];
|
|
55
|
+
if (!anims.length) return done();
|
|
56
|
+
Promise.all(anims.map((a) => a.finished)).then(done, done);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
uid,
|
|
61
|
+
own,
|
|
62
|
+
ownOne,
|
|
63
|
+
resolveAsChild,
|
|
64
|
+
isDisabled,
|
|
65
|
+
showFloating,
|
|
66
|
+
hideFloating,
|
|
67
|
+
focusables,
|
|
68
|
+
afterAnimations
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=chunk-3AEQ6KHV.js.map
|
|
@@ -0,0 +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":[]}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hideFloating,
|
|
3
|
+
isDisabled,
|
|
4
|
+
own,
|
|
5
|
+
ownOne,
|
|
6
|
+
showFloating,
|
|
7
|
+
uid
|
|
8
|
+
} from "./chunk-3AEQ6KHV.js";
|
|
9
|
+
import {
|
|
10
|
+
DogsbayElement,
|
|
11
|
+
ensureDefaultDisplay
|
|
12
|
+
} from "./chunk-K6DPDBAG.js";
|
|
13
|
+
|
|
14
|
+
// src/db-select.ts
|
|
15
|
+
import { DismissController } from "@dogsbay/primitives/dismiss";
|
|
16
|
+
import { setupFloating } from "@dogsbay/primitives/floating";
|
|
17
|
+
import { Typeahead } from "@dogsbay/primitives/typeahead";
|
|
18
|
+
var DbSelect = class extends DogsbayElement {
|
|
19
|
+
trigger = null;
|
|
20
|
+
content = null;
|
|
21
|
+
valueEl = null;
|
|
22
|
+
items = [];
|
|
23
|
+
nativeSelect = null;
|
|
24
|
+
hiddenInput = null;
|
|
25
|
+
labelEl = null;
|
|
26
|
+
onLabelClick = (e) => {
|
|
27
|
+
if (e.target.closest("[data-part='trigger']")) return;
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
this.trigger?.focus();
|
|
30
|
+
};
|
|
31
|
+
dismiss = null;
|
|
32
|
+
typeahead = null;
|
|
33
|
+
cleanupFloating = null;
|
|
34
|
+
_open = false;
|
|
35
|
+
_value = "";
|
|
36
|
+
highlighted = -1;
|
|
37
|
+
get open() {
|
|
38
|
+
return this._open;
|
|
39
|
+
}
|
|
40
|
+
get value() {
|
|
41
|
+
return this._value;
|
|
42
|
+
}
|
|
43
|
+
set value(v) {
|
|
44
|
+
const item = this.items.find((i) => i.dataset.value === v);
|
|
45
|
+
if (item) this.select(item, false);
|
|
46
|
+
}
|
|
47
|
+
/** Disabled when the host or the enhanced native select is. */
|
|
48
|
+
get isDisabled() {
|
|
49
|
+
return this.hasAttribute("disabled") || !!this.nativeSelect?.disabled;
|
|
50
|
+
}
|
|
51
|
+
syncing = false;
|
|
52
|
+
/** Re-read the native select's value (after script changes it or a form reset). */
|
|
53
|
+
refresh() {
|
|
54
|
+
const sel = this.nativeSelect;
|
|
55
|
+
if (!sel) return;
|
|
56
|
+
const item = this.items.find((i) => i.dataset.value === sel.value);
|
|
57
|
+
if (item) this.select(item, false);
|
|
58
|
+
this.trigger?.setAttribute("aria-disabled", String(this.isDisabled));
|
|
59
|
+
}
|
|
60
|
+
onNativeChange = () => {
|
|
61
|
+
if (!this.syncing) this.refresh();
|
|
62
|
+
};
|
|
63
|
+
onFormReset = () => setTimeout(() => this.refresh());
|
|
64
|
+
enabled() {
|
|
65
|
+
return this.items.filter((i) => !isDisabled(i));
|
|
66
|
+
}
|
|
67
|
+
setup() {
|
|
68
|
+
this.nativeSelect = ownOne(this, "select");
|
|
69
|
+
if (this.nativeSelect && !ownOne(this, "[data-part='trigger']")) this.buildFromNative(this.nativeSelect);
|
|
70
|
+
this.trigger = ownOne(this, "[data-part='trigger']");
|
|
71
|
+
this.content = ownOne(this, "[data-part='content']");
|
|
72
|
+
this.valueEl = ownOne(this, "[data-part='value']");
|
|
73
|
+
if (!this.trigger || !this.content) return;
|
|
74
|
+
const { trigger, content } = this;
|
|
75
|
+
this.items = own(this, "[data-part='item']");
|
|
76
|
+
const base = uid("db-select");
|
|
77
|
+
content.id ||= `${base}-listbox`;
|
|
78
|
+
content.setAttribute("role", "listbox");
|
|
79
|
+
content.hidden = true;
|
|
80
|
+
trigger.setAttribute("role", "combobox");
|
|
81
|
+
trigger.setAttribute("aria-haspopup", "listbox");
|
|
82
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
83
|
+
trigger.setAttribute("aria-controls", content.id);
|
|
84
|
+
if (trigger instanceof HTMLButtonElement && !trigger.hasAttribute("type")) trigger.type = "button";
|
|
85
|
+
if (this.isDisabled) trigger.setAttribute("aria-disabled", "true");
|
|
86
|
+
this.items.forEach((item, i) => {
|
|
87
|
+
item.id ||= `${base}-item-${i}`;
|
|
88
|
+
item.setAttribute("role", "option");
|
|
89
|
+
item.setAttribute("aria-selected", "false");
|
|
90
|
+
});
|
|
91
|
+
own(this, "[data-part='group']").forEach((group) => {
|
|
92
|
+
group.setAttribute("role", "group");
|
|
93
|
+
const label = group.querySelector("[data-part='label']");
|
|
94
|
+
if (label) {
|
|
95
|
+
label.id ||= uid("db-select-label");
|
|
96
|
+
group.setAttribute("aria-labelledby", label.id);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const name = this.getAttribute("name");
|
|
100
|
+
if (name && !this.nativeSelect) {
|
|
101
|
+
this.hiddenInput = document.createElement("input");
|
|
102
|
+
this.hiddenInput.type = "hidden";
|
|
103
|
+
this.hiddenInput.name = name;
|
|
104
|
+
if (this.hasAttribute("required")) this.hiddenInput.required = true;
|
|
105
|
+
this.appendChild(this.hiddenInput);
|
|
106
|
+
}
|
|
107
|
+
this.typeahead = new Typeahead({
|
|
108
|
+
getItemCount: () => this.enabled().length,
|
|
109
|
+
getItemText: (i) => this.enabled()[i]?.textContent?.trim() ?? "",
|
|
110
|
+
onMatch: (i) => {
|
|
111
|
+
const item = this.enabled()[i];
|
|
112
|
+
if (!item) return;
|
|
113
|
+
if (this._open) this.highlight(this.items.indexOf(item));
|
|
114
|
+
else this.select(item);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
this.dismiss = new DismissController(content, { onDismiss: (reason) => this.close(reason !== "outside-press") });
|
|
118
|
+
const initial = this.nativeSelect?.value ?? this.getAttribute("default-value") ?? "";
|
|
119
|
+
const initialItem = this.items.find((i) => i.dataset.value === initial);
|
|
120
|
+
if (initialItem && isDisabled(initialItem)) {
|
|
121
|
+
if (this.valueEl) {
|
|
122
|
+
this.valueEl.textContent = initialItem.textContent?.trim() ?? "";
|
|
123
|
+
this.valueEl.setAttribute("data-placeholder", "");
|
|
124
|
+
}
|
|
125
|
+
} else if (initialItem) this.select(initialItem, false);
|
|
126
|
+
this.setState("closed");
|
|
127
|
+
}
|
|
128
|
+
/** Build the trigger and listbox from a native <select>, and hide it. */
|
|
129
|
+
buildFromNative(sel) {
|
|
130
|
+
const trigger = document.createElement("button");
|
|
131
|
+
trigger.type = "button";
|
|
132
|
+
trigger.setAttribute("data-part", "trigger");
|
|
133
|
+
trigger.className = "db-select-trigger";
|
|
134
|
+
const label = sel.getAttribute("aria-label");
|
|
135
|
+
let labelledBy = sel.getAttribute("aria-labelledby");
|
|
136
|
+
const forLabel = !labelledBy && sel.id ? document.querySelector(`label[for="${CSS.escape(sel.id)}"]`) : null;
|
|
137
|
+
if (forLabel) labelledBy = forLabel.id ||= uid("db-select-for");
|
|
138
|
+
if (label) trigger.setAttribute("aria-label", label);
|
|
139
|
+
if (labelledBy) trigger.setAttribute("aria-labelledby", labelledBy);
|
|
140
|
+
const wrap = sel.closest("label");
|
|
141
|
+
if (wrap) {
|
|
142
|
+
this.labelEl = wrap;
|
|
143
|
+
if (!label && !labelledBy) {
|
|
144
|
+
const text = Array.from(wrap.childNodes).filter((n) => !(n instanceof Element && (n === sel || n.contains(sel) || n.localName === "db-select"))).map((n) => n.textContent ?? "").join(" ").replace(/\s+/g, " ").trim();
|
|
145
|
+
if (text) trigger.setAttribute("aria-label", text);
|
|
146
|
+
}
|
|
147
|
+
} else if (forLabel) this.labelEl = forLabel;
|
|
148
|
+
const value = document.createElement("span");
|
|
149
|
+
value.setAttribute("data-part", "value");
|
|
150
|
+
value.className = "db-select-value";
|
|
151
|
+
const chevron = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
152
|
+
chevron.setAttribute("viewBox", "0 0 24 24");
|
|
153
|
+
chevron.setAttribute("aria-hidden", "true");
|
|
154
|
+
chevron.setAttribute("class", "db-select-chevron");
|
|
155
|
+
chevron.innerHTML = '<path d="m6 9 6 6 6-6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
|
|
156
|
+
trigger.append(value, chevron);
|
|
157
|
+
const list = document.createElement("div");
|
|
158
|
+
list.setAttribute("data-part", "content");
|
|
159
|
+
list.className = "db-select-content";
|
|
160
|
+
const addOption = (o, parent) => {
|
|
161
|
+
const item = document.createElement("div");
|
|
162
|
+
item.setAttribute("data-part", "item");
|
|
163
|
+
item.className = "db-select-item";
|
|
164
|
+
item.dataset.value = o.value;
|
|
165
|
+
for (const [k, v] of Object.entries(o.dataset)) if (v != null) item.dataset[k] = v;
|
|
166
|
+
if (o.disabled) item.setAttribute("aria-disabled", "true");
|
|
167
|
+
item.textContent = o.textContent ?? o.value;
|
|
168
|
+
parent.appendChild(item);
|
|
169
|
+
};
|
|
170
|
+
for (const child of Array.from(sel.children)) {
|
|
171
|
+
if (child instanceof HTMLOptGroupElement) {
|
|
172
|
+
const group = document.createElement("div");
|
|
173
|
+
group.setAttribute("data-part", "group");
|
|
174
|
+
const gl = document.createElement("div");
|
|
175
|
+
gl.setAttribute("data-part", "label");
|
|
176
|
+
gl.className = "db-select-label";
|
|
177
|
+
gl.textContent = child.label;
|
|
178
|
+
group.appendChild(gl);
|
|
179
|
+
for (const o of Array.from(child.children)) if (o instanceof HTMLOptionElement) addOption(o, group);
|
|
180
|
+
list.appendChild(group);
|
|
181
|
+
} else if (child instanceof HTMLOptionElement) {
|
|
182
|
+
addOption(child, list);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
sel.hidden = true;
|
|
186
|
+
sel.tabIndex = -1;
|
|
187
|
+
sel.setAttribute("aria-hidden", "true");
|
|
188
|
+
this.append(trigger, list);
|
|
189
|
+
}
|
|
190
|
+
onTriggerClick = () => {
|
|
191
|
+
if (this.isDisabled) return;
|
|
192
|
+
if (this._open) this.close();
|
|
193
|
+
else this.show();
|
|
194
|
+
};
|
|
195
|
+
// Firefox fires click on keyup of Space even after keydown was cancelled; cancel it
|
|
196
|
+
// there too so Space does not toggle twice.
|
|
197
|
+
onTriggerKeyUp = (e) => {
|
|
198
|
+
if (e.key === " ") e.preventDefault();
|
|
199
|
+
};
|
|
200
|
+
onTriggerKey = (e) => {
|
|
201
|
+
if (this.isDisabled) return;
|
|
202
|
+
const enabled = this.enabled();
|
|
203
|
+
if (!this._open) {
|
|
204
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " " || e.altKey && e.key === "ArrowDown") {
|
|
205
|
+
e.preventDefault();
|
|
206
|
+
this.show();
|
|
207
|
+
if (e.key === "ArrowUp" && enabled.length) this.highlight(this.items.indexOf(enabled[enabled.length - 1]));
|
|
208
|
+
} else if (e.key === "Home" || e.key === "End") {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
this.show();
|
|
211
|
+
const t = e.key === "Home" ? enabled[0] : enabled[enabled.length - 1];
|
|
212
|
+
if (t) this.highlight(this.items.indexOf(t));
|
|
213
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
214
|
+
this.typeahead?.handle(e.key);
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!enabled.length) return;
|
|
219
|
+
const cur = this.highlighted >= 0 ? enabled.indexOf(this.items[this.highlighted]) : -1;
|
|
220
|
+
const go = (i) => {
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
this.highlight(this.items.indexOf(enabled[i]));
|
|
223
|
+
};
|
|
224
|
+
switch (e.key) {
|
|
225
|
+
case "ArrowDown":
|
|
226
|
+
return go(Math.min(cur + 1, enabled.length - 1));
|
|
227
|
+
case "ArrowUp":
|
|
228
|
+
if (e.altKey) {
|
|
229
|
+
e.preventDefault();
|
|
230
|
+
if (this.highlighted >= 0) this.select(this.items[this.highlighted]);
|
|
231
|
+
return this.close();
|
|
232
|
+
}
|
|
233
|
+
return go(Math.max(cur - 1, 0));
|
|
234
|
+
case "Home":
|
|
235
|
+
return go(0);
|
|
236
|
+
case "End":
|
|
237
|
+
return go(enabled.length - 1);
|
|
238
|
+
case "PageDown":
|
|
239
|
+
return go(Math.min(cur + 10, enabled.length - 1));
|
|
240
|
+
case "PageUp":
|
|
241
|
+
return go(Math.max(cur - 10, 0));
|
|
242
|
+
case "Enter":
|
|
243
|
+
case " ":
|
|
244
|
+
e.preventDefault();
|
|
245
|
+
if (this.highlighted >= 0) this.select(this.items[this.highlighted]);
|
|
246
|
+
return this.close();
|
|
247
|
+
case "Tab":
|
|
248
|
+
if (this.highlighted >= 0) this.select(this.items[this.highlighted]);
|
|
249
|
+
return this.close(false);
|
|
250
|
+
default:
|
|
251
|
+
if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) this.typeahead?.handle(e.key);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
onListClick = (e) => {
|
|
255
|
+
const item = e.target.closest("[data-part='item']");
|
|
256
|
+
if (!item || !this.items.includes(item) || isDisabled(item)) return;
|
|
257
|
+
this.select(item);
|
|
258
|
+
this.close();
|
|
259
|
+
};
|
|
260
|
+
onListPointer = (e) => {
|
|
261
|
+
const item = e.target.closest("[data-part='item']");
|
|
262
|
+
if (item && this.items.includes(item) && !isDisabled(item)) this.highlight(this.items.indexOf(item));
|
|
263
|
+
};
|
|
264
|
+
connect() {
|
|
265
|
+
this.trigger?.addEventListener("click", this.onTriggerClick);
|
|
266
|
+
this.trigger?.addEventListener("keydown", this.onTriggerKey);
|
|
267
|
+
this.trigger?.addEventListener("keyup", this.onTriggerKeyUp);
|
|
268
|
+
this.nativeSelect?.addEventListener("change", this.onNativeChange);
|
|
269
|
+
this.nativeSelect?.form?.addEventListener("reset", this.onFormReset);
|
|
270
|
+
this.labelEl?.addEventListener("click", this.onLabelClick);
|
|
271
|
+
this.content?.addEventListener("click", this.onListClick);
|
|
272
|
+
this.content?.addEventListener("pointermove", this.onListPointer);
|
|
273
|
+
this.content?.addEventListener("mousedown", this.preventBlur);
|
|
274
|
+
}
|
|
275
|
+
disconnect() {
|
|
276
|
+
this.trigger?.removeEventListener("click", this.onTriggerClick);
|
|
277
|
+
this.trigger?.removeEventListener("keydown", this.onTriggerKey);
|
|
278
|
+
this.trigger?.removeEventListener("keyup", this.onTriggerKeyUp);
|
|
279
|
+
this.nativeSelect?.removeEventListener("change", this.onNativeChange);
|
|
280
|
+
this.nativeSelect?.form?.removeEventListener("reset", this.onFormReset);
|
|
281
|
+
this.labelEl?.removeEventListener("click", this.onLabelClick);
|
|
282
|
+
this.content?.removeEventListener("click", this.onListClick);
|
|
283
|
+
this.content?.removeEventListener("pointermove", this.onListPointer);
|
|
284
|
+
this.content?.removeEventListener("mousedown", this.preventBlur);
|
|
285
|
+
if (this._open) this.close(false);
|
|
286
|
+
}
|
|
287
|
+
preventBlur = (e) => e.preventDefault();
|
|
288
|
+
setState(state) {
|
|
289
|
+
this.setAttribute("data-state", state);
|
|
290
|
+
this.content?.setAttribute("data-state", state);
|
|
291
|
+
}
|
|
292
|
+
show() {
|
|
293
|
+
const { trigger, content } = this;
|
|
294
|
+
if (!trigger || !content || this._open) return;
|
|
295
|
+
this._open = true;
|
|
296
|
+
const layer = showFloating(content);
|
|
297
|
+
this.setState("open");
|
|
298
|
+
trigger.setAttribute("aria-expanded", "true");
|
|
299
|
+
this.cleanupFloating = setupFloating(trigger, content, {
|
|
300
|
+
placement: "bottom-start",
|
|
301
|
+
offset: 4,
|
|
302
|
+
matchWidth: !this.hasAttribute("auto-width"),
|
|
303
|
+
strategy: layer === "top-layer" ? "fixed" : "absolute"
|
|
304
|
+
});
|
|
305
|
+
const selected = this.items.find((i) => i.dataset.value === this._value && !isDisabled(i));
|
|
306
|
+
const first = selected ?? this.enabled()[0];
|
|
307
|
+
if (first) this.highlight(this.items.indexOf(first));
|
|
308
|
+
this.dismiss?.activate();
|
|
309
|
+
this.typeahead?.reset();
|
|
310
|
+
trigger.focus();
|
|
311
|
+
}
|
|
312
|
+
/** Close the listbox. `refocus` is false for outside presses, which keep focus where the user clicked. */
|
|
313
|
+
close(refocus = true) {
|
|
314
|
+
const { trigger, content } = this;
|
|
315
|
+
if (!trigger || !content || !this._open) return;
|
|
316
|
+
this._open = false;
|
|
317
|
+
this.dismiss?.deactivate();
|
|
318
|
+
this.cleanupFloating?.();
|
|
319
|
+
this.cleanupFloating = null;
|
|
320
|
+
hideFloating(content);
|
|
321
|
+
this.setState("closed");
|
|
322
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
323
|
+
trigger.removeAttribute("aria-activedescendant");
|
|
324
|
+
this.items.forEach((i) => i.removeAttribute("data-highlighted"));
|
|
325
|
+
this.highlighted = -1;
|
|
326
|
+
this.typeahead?.reset();
|
|
327
|
+
if (refocus) trigger.focus();
|
|
328
|
+
}
|
|
329
|
+
highlight(index) {
|
|
330
|
+
const item = this.items[index];
|
|
331
|
+
const content = this.content;
|
|
332
|
+
if (!item || !content || !this.trigger) return;
|
|
333
|
+
if (this.highlighted >= 0) this.items[this.highlighted]?.removeAttribute("data-highlighted");
|
|
334
|
+
this.highlighted = index;
|
|
335
|
+
item.setAttribute("data-highlighted", "");
|
|
336
|
+
this.trigger.setAttribute("aria-activedescendant", item.id);
|
|
337
|
+
const top = item.offsetTop;
|
|
338
|
+
const bottom = top + item.offsetHeight;
|
|
339
|
+
if (top < content.scrollTop) content.scrollTop = top;
|
|
340
|
+
else if (bottom > content.scrollTop + content.clientHeight) content.scrollTop = bottom - content.clientHeight;
|
|
341
|
+
}
|
|
342
|
+
select(item, notify = true) {
|
|
343
|
+
if (isDisabled(item)) return;
|
|
344
|
+
const value = item.dataset.value ?? "";
|
|
345
|
+
const changed = value !== this._value;
|
|
346
|
+
this._value = value;
|
|
347
|
+
for (const i of this.items) {
|
|
348
|
+
const on = i === item;
|
|
349
|
+
i.setAttribute("aria-selected", String(on));
|
|
350
|
+
if (on) i.setAttribute("data-state", "checked");
|
|
351
|
+
else i.removeAttribute("data-state");
|
|
352
|
+
}
|
|
353
|
+
if (this.valueEl) {
|
|
354
|
+
this.valueEl.textContent = item.textContent?.trim() ?? "";
|
|
355
|
+
this.valueEl.removeAttribute("data-placeholder");
|
|
356
|
+
}
|
|
357
|
+
if (this.hiddenInput) this.hiddenInput.value = value;
|
|
358
|
+
if (!notify || !changed) {
|
|
359
|
+
if (this.nativeSelect) this.nativeSelect.value = value;
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (this.nativeSelect) {
|
|
363
|
+
this.nativeSelect.value = value;
|
|
364
|
+
this.syncing = true;
|
|
365
|
+
try {
|
|
366
|
+
this.nativeSelect.dispatchEvent(new Event("input", { bubbles: true }));
|
|
367
|
+
this.nativeSelect.dispatchEvent(new Event("change", { bubbles: true }));
|
|
368
|
+
} finally {
|
|
369
|
+
this.syncing = false;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
this.dispatchEvent(new CustomEvent("db-select:change", { detail: { value }, bubbles: true }));
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
ensureDefaultDisplay();
|
|
376
|
+
if (!customElements.get("db-select")) {
|
|
377
|
+
customElements.define("db-select", DbSelect);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export {
|
|
381
|
+
DbSelect
|
|
382
|
+
};
|
|
383
|
+
//# sourceMappingURL=chunk-3FMXAKOU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/db-select.ts"],"sourcesContent":["import { DismissController } from \"@dogsbay/primitives/dismiss\";\nimport { setupFloating } from \"@dogsbay/primitives/floating\";\nimport { Typeahead } from \"@dogsbay/primitives/typeahead\";\nimport { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\nimport { hideFloating, isDisabled, own, ownOne, showFloating, uid } from \"./utils.js\";\n\n/**\n * `<db-select>` — Select-only combobox (APG \"Select-Only Combobox\").\n *\n * Two ways to use it:\n *\n * 1. The Astro Select parts (same contract as `ui/src/select`):\n * [data-part=\"trigger\"] button, role=combobox (focus stays here)\n * [data-part=\"value\"] shows the selected label (data-placeholder)\n * [data-part=\"content\"] role=listbox\n * [data-part=\"item\"] role=option, data-value, aria-disabled\n * [data-part=\"group\"] / [data-part=\"label\"]\n *\n * 2. Progressive enhancement of a native `<select>` inside the element.\n * The element builds the parts from its options, keeps the native\n * select in sync (hidden, still submitted with forms) and dispatches a\n * native `change` on it, so existing listeners keep working. With no\n * JavaScript the native select is what the user gets.\n *\n * The listbox opens in the top layer where supported. Focus never leaves\n * the trigger: the highlighted option is exposed with aria-activedescendant.\n *\n * Attributes: name, default-value, required, disabled\n * Events: db-select:change (detail: { value })\n */\nexport class DbSelect extends DogsbayElement {\n private trigger: HTMLElement | null = null;\n private content: HTMLElement | null = null;\n private valueEl: HTMLElement | null = null;\n private items: HTMLElement[] = [];\n private nativeSelect: HTMLSelectElement | null = null;\n private hiddenInput: HTMLInputElement | null = null;\n private labelEl: HTMLLabelElement | null = null;\n\n private onLabelClick = (e: Event) => {\n if ((e.target as HTMLElement).closest(\"[data-part='trigger']\")) return;\n e.preventDefault();\n this.trigger?.focus();\n };\n private dismiss: DismissController | null = null;\n private typeahead: Typeahead | null = null;\n private cleanupFloating: (() => void) | null = null;\n private _open = false;\n private _value = \"\";\n private highlighted = -1;\n\n get open(): boolean {\n return this._open;\n }\n\n get value(): string {\n return this._value;\n }\n\n set value(v: string) {\n const item = this.items.find((i) => i.dataset.value === v);\n if (item) this.select(item, false);\n }\n\n /** Disabled when the host or the enhanced native select is. */\n private get isDisabled(): boolean {\n return this.hasAttribute(\"disabled\") || !!this.nativeSelect?.disabled;\n }\n\n private syncing = false;\n\n /** Re-read the native select's value (after script changes it or a form reset). */\n refresh() {\n const sel = this.nativeSelect;\n if (!sel) return;\n const item = this.items.find((i) => i.dataset.value === sel.value);\n if (item) this.select(item, false);\n this.trigger?.setAttribute(\"aria-disabled\", String(this.isDisabled));\n }\n\n private onNativeChange = () => {\n if (!this.syncing) this.refresh();\n };\n\n private onFormReset = () => setTimeout(() => this.refresh());\n\n private enabled(): HTMLElement[] {\n return this.items.filter((i) => !isDisabled(i));\n }\n\n protected setup() {\n this.nativeSelect = ownOne<HTMLSelectElement>(this, \"select\");\n if (this.nativeSelect && !ownOne(this, \"[data-part='trigger']\")) this.buildFromNative(this.nativeSelect);\n\n this.trigger = ownOne(this, \"[data-part='trigger']\");\n this.content = ownOne(this, \"[data-part='content']\");\n this.valueEl = ownOne(this, \"[data-part='value']\");\n if (!this.trigger || !this.content) return;\n const { trigger, content } = this;\n this.items = own(this, \"[data-part='item']\");\n\n const base = uid(\"db-select\");\n content.id ||= `${base}-listbox`;\n content.setAttribute(\"role\", \"listbox\");\n content.hidden = true;\n trigger.setAttribute(\"role\", \"combobox\");\n trigger.setAttribute(\"aria-haspopup\", \"listbox\");\n trigger.setAttribute(\"aria-expanded\", \"false\");\n trigger.setAttribute(\"aria-controls\", content.id);\n if (trigger instanceof HTMLButtonElement && !trigger.hasAttribute(\"type\")) trigger.type = \"button\";\n if (this.isDisabled) trigger.setAttribute(\"aria-disabled\", \"true\");\n this.items.forEach((item, i) => {\n item.id ||= `${base}-item-${i}`;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", \"false\");\n });\n own(this, \"[data-part='group']\").forEach((group) => {\n group.setAttribute(\"role\", \"group\");\n const label = group.querySelector<HTMLElement>(\"[data-part='label']\");\n if (label) {\n label.id ||= uid(\"db-select-label\");\n group.setAttribute(\"aria-labelledby\", label.id);\n }\n });\n\n const name = this.getAttribute(\"name\");\n if (name && !this.nativeSelect) {\n this.hiddenInput = document.createElement(\"input\");\n this.hiddenInput.type = \"hidden\";\n this.hiddenInput.name = name;\n if (this.hasAttribute(\"required\")) this.hiddenInput.required = true;\n this.appendChild(this.hiddenInput);\n }\n\n this.typeahead = new Typeahead({\n getItemCount: () => this.enabled().length,\n getItemText: (i) => this.enabled()[i]?.textContent?.trim() ?? \"\",\n onMatch: (i) => {\n const item = this.enabled()[i];\n if (!item) return;\n if (this._open) this.highlight(this.items.indexOf(item));\n else this.select(item);\n },\n });\n this.dismiss = new DismissController(content, { onDismiss: (reason) => this.close(reason !== \"outside-press\") });\n\n const initial = this.nativeSelect?.value ?? this.getAttribute(\"default-value\") ?? \"\";\n const initialItem = this.items.find((i) => i.dataset.value === initial);\n if (initialItem && isDisabled(initialItem)) {\n // A disabled placeholder option (\"Choose…\") is shown, not selected.\n if (this.valueEl) {\n this.valueEl.textContent = initialItem.textContent?.trim() ?? \"\";\n this.valueEl.setAttribute(\"data-placeholder\", \"\");\n }\n } else if (initialItem) this.select(initialItem, false);\n this.setState(\"closed\");\n }\n\n /** Build the trigger and listbox from a native <select>, and hide it. */\n private buildFromNative(sel: HTMLSelectElement) {\n const trigger = document.createElement(\"button\");\n trigger.type = \"button\";\n trigger.setAttribute(\"data-part\", \"trigger\");\n trigger.className = \"db-select-trigger\";\n // Carry the native select's accessible name over to the trigger.\n const label = sel.getAttribute(\"aria-label\");\n let labelledBy = sel.getAttribute(\"aria-labelledby\");\n const forLabel = !labelledBy && sel.id ? document.querySelector<HTMLLabelElement>(`label[for=\"${CSS.escape(sel.id)}\"]`) : null;\n if (forLabel) labelledBy = forLabel.id ||= uid(\"db-select-for\");\n if (label) trigger.setAttribute(\"aria-label\", label);\n if (labelledBy) trigger.setAttribute(\"aria-labelledby\", labelledBy);\n // A <label> wrapping the select: name the trigger with the label's own text (not the\n // options'), and send label clicks to the trigger rather than the hidden select.\n const wrap = sel.closest(\"label\");\n if (wrap) {\n this.labelEl = wrap;\n if (!label && !labelledBy) {\n const text = Array.from(wrap.childNodes)\n .filter((n) => !(n instanceof Element && (n === sel || n.contains(sel) || n.localName === \"db-select\")))\n .map((n) => n.textContent ?? \"\")\n .join(\" \")\n .replace(/\\s+/g, \" \")\n .trim();\n if (text) trigger.setAttribute(\"aria-label\", text);\n }\n } else if (forLabel) this.labelEl = forLabel;\n const value = document.createElement(\"span\");\n value.setAttribute(\"data-part\", \"value\");\n value.className = \"db-select-value\";\n const chevron = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n chevron.setAttribute(\"viewBox\", \"0 0 24 24\");\n chevron.setAttribute(\"aria-hidden\", \"true\");\n chevron.setAttribute(\"class\", \"db-select-chevron\");\n chevron.innerHTML = '<path d=\"m6 9 6 6 6-6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>';\n trigger.append(value, chevron);\n\n const list = document.createElement(\"div\");\n list.setAttribute(\"data-part\", \"content\");\n list.className = \"db-select-content\";\n const addOption = (o: HTMLOptionElement, parent: HTMLElement) => {\n const item = document.createElement(\"div\");\n item.setAttribute(\"data-part\", \"item\");\n item.className = \"db-select-item\";\n item.dataset.value = o.value;\n for (const [k, v] of Object.entries(o.dataset)) if (v != null) item.dataset[k] = v;\n if (o.disabled) item.setAttribute(\"aria-disabled\", \"true\");\n item.textContent = o.textContent ?? o.value;\n parent.appendChild(item);\n };\n for (const child of Array.from(sel.children)) {\n if (child instanceof HTMLOptGroupElement) {\n const group = document.createElement(\"div\");\n group.setAttribute(\"data-part\", \"group\");\n const gl = document.createElement(\"div\");\n gl.setAttribute(\"data-part\", \"label\");\n gl.className = \"db-select-label\";\n gl.textContent = child.label;\n group.appendChild(gl);\n for (const o of Array.from(child.children)) if (o instanceof HTMLOptionElement) addOption(o, group);\n list.appendChild(group);\n } else if (child instanceof HTMLOptionElement) {\n addOption(child, list);\n }\n }\n sel.hidden = true;\n sel.tabIndex = -1;\n sel.setAttribute(\"aria-hidden\", \"true\");\n this.append(trigger, list);\n }\n\n private onTriggerClick = () => {\n if (this.isDisabled) return;\n if (this._open) this.close();\n else this.show();\n };\n\n // Firefox fires click on keyup of Space even after keydown was cancelled; cancel it\n // there too so Space does not toggle twice.\n private onTriggerKeyUp = (e: KeyboardEvent) => {\n if (e.key === \" \") e.preventDefault();\n };\n\n private onTriggerKey = (e: KeyboardEvent) => {\n if (this.isDisabled) return;\n const enabled = this.enabled();\n if (!this._open) {\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\" || e.key === \"Enter\" || e.key === \" \" || (e.altKey && e.key === \"ArrowDown\")) {\n e.preventDefault();\n this.show();\n if (e.key === \"ArrowUp\" && enabled.length) this.highlight(this.items.indexOf(enabled[enabled.length - 1]));\n } else if (e.key === \"Home\" || e.key === \"End\") {\n e.preventDefault();\n this.show();\n const t = e.key === \"Home\" ? enabled[0] : enabled[enabled.length - 1];\n if (t) this.highlight(this.items.indexOf(t));\n } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n this.typeahead?.handle(e.key);\n }\n return;\n }\n if (!enabled.length) return;\n const cur = this.highlighted >= 0 ? enabled.indexOf(this.items[this.highlighted]) : -1;\n const go = (i: number) => {\n e.preventDefault();\n this.highlight(this.items.indexOf(enabled[i]));\n };\n switch (e.key) {\n case \"ArrowDown\":\n return go(Math.min(cur + 1, enabled.length - 1));\n case \"ArrowUp\":\n if (e.altKey) {\n e.preventDefault();\n if (this.highlighted >= 0) this.select(this.items[this.highlighted]);\n return this.close();\n }\n return go(Math.max(cur - 1, 0));\n case \"Home\":\n return go(0);\n case \"End\":\n return go(enabled.length - 1);\n case \"PageDown\":\n return go(Math.min(cur + 10, enabled.length - 1));\n case \"PageUp\":\n return go(Math.max(cur - 10, 0));\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (this.highlighted >= 0) this.select(this.items[this.highlighted]);\n return this.close();\n case \"Tab\":\n if (this.highlighted >= 0) this.select(this.items[this.highlighted]);\n return this.close(false);\n default:\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) this.typeahead?.handle(e.key);\n }\n };\n\n private onListClick = (e: Event) => {\n const item = (e.target as HTMLElement).closest<HTMLElement>(\"[data-part='item']\");\n if (!item || !this.items.includes(item) || isDisabled(item)) return;\n this.select(item);\n this.close();\n };\n\n private onListPointer = (e: PointerEvent) => {\n const item = (e.target as HTMLElement).closest<HTMLElement>(\"[data-part='item']\");\n if (item && this.items.includes(item) && !isDisabled(item)) this.highlight(this.items.indexOf(item));\n };\n\n protected connect() {\n this.trigger?.addEventListener(\"click\", this.onTriggerClick);\n this.trigger?.addEventListener(\"keydown\", this.onTriggerKey);\n this.trigger?.addEventListener(\"keyup\", this.onTriggerKeyUp);\n this.nativeSelect?.addEventListener(\"change\", this.onNativeChange);\n this.nativeSelect?.form?.addEventListener(\"reset\", this.onFormReset);\n this.labelEl?.addEventListener(\"click\", this.onLabelClick);\n this.content?.addEventListener(\"click\", this.onListClick);\n this.content?.addEventListener(\"pointermove\", this.onListPointer as EventListener);\n // Keep focus on the trigger when an option is pressed.\n this.content?.addEventListener(\"mousedown\", this.preventBlur);\n }\n\n protected disconnect() {\n this.trigger?.removeEventListener(\"click\", this.onTriggerClick);\n this.trigger?.removeEventListener(\"keydown\", this.onTriggerKey);\n this.trigger?.removeEventListener(\"keyup\", this.onTriggerKeyUp);\n this.nativeSelect?.removeEventListener(\"change\", this.onNativeChange);\n this.nativeSelect?.form?.removeEventListener(\"reset\", this.onFormReset);\n this.labelEl?.removeEventListener(\"click\", this.onLabelClick);\n this.content?.removeEventListener(\"click\", this.onListClick);\n this.content?.removeEventListener(\"pointermove\", this.onListPointer as EventListener);\n this.content?.removeEventListener(\"mousedown\", this.preventBlur);\n if (this._open) this.close(false);\n }\n\n private preventBlur = (e: Event) => e.preventDefault();\n\n private setState(state: \"open\" | \"closed\") {\n this.setAttribute(\"data-state\", state);\n this.content?.setAttribute(\"data-state\", state);\n }\n\n show() {\n const { trigger, content } = this;\n if (!trigger || !content || this._open) return;\n this._open = true;\n const layer = showFloating(content);\n this.setState(\"open\");\n trigger.setAttribute(\"aria-expanded\", \"true\");\n this.cleanupFloating = setupFloating(trigger, content, {\n placement: \"bottom-start\",\n offset: 4,\n matchWidth: !this.hasAttribute(\"auto-width\"),\n strategy: layer === \"top-layer\" ? \"fixed\" : \"absolute\",\n });\n const selected = this.items.find((i) => i.dataset.value === this._value && !isDisabled(i));\n const first = selected ?? this.enabled()[0];\n if (first) this.highlight(this.items.indexOf(first));\n this.dismiss?.activate();\n this.typeahead?.reset();\n trigger.focus();\n }\n\n /** Close the listbox. `refocus` is false for outside presses, which keep focus where the user clicked. */\n close(refocus = true) {\n const { trigger, content } = this;\n if (!trigger || !content || !this._open) return;\n this._open = false;\n this.dismiss?.deactivate();\n this.cleanupFloating?.();\n this.cleanupFloating = null;\n hideFloating(content);\n this.setState(\"closed\");\n trigger.setAttribute(\"aria-expanded\", \"false\");\n trigger.removeAttribute(\"aria-activedescendant\");\n this.items.forEach((i) => i.removeAttribute(\"data-highlighted\"));\n this.highlighted = -1;\n this.typeahead?.reset();\n if (refocus) trigger.focus();\n }\n\n private highlight(index: number) {\n const item = this.items[index];\n const content = this.content;\n if (!item || !content || !this.trigger) return;\n if (this.highlighted >= 0) this.items[this.highlighted]?.removeAttribute(\"data-highlighted\");\n this.highlighted = index;\n item.setAttribute(\"data-highlighted\", \"\");\n this.trigger.setAttribute(\"aria-activedescendant\", item.id);\n const top = item.offsetTop;\n const bottom = top + item.offsetHeight;\n if (top < content.scrollTop) content.scrollTop = top;\n else if (bottom > content.scrollTop + content.clientHeight) content.scrollTop = bottom - content.clientHeight;\n }\n\n private select(item: HTMLElement, notify = true) {\n if (isDisabled(item)) return;\n const value = item.dataset.value ?? \"\";\n const changed = value !== this._value;\n this._value = value;\n for (const i of this.items) {\n const on = i === item;\n i.setAttribute(\"aria-selected\", String(on));\n if (on) i.setAttribute(\"data-state\", \"checked\");\n else i.removeAttribute(\"data-state\");\n }\n if (this.valueEl) {\n this.valueEl.textContent = item.textContent?.trim() ?? \"\";\n this.valueEl.removeAttribute(\"data-placeholder\");\n }\n if (this.hiddenInput) this.hiddenInput.value = value;\n if (!notify || !changed) {\n if (this.nativeSelect) this.nativeSelect.value = value;\n return;\n }\n if (this.nativeSelect) {\n this.nativeSelect.value = value;\n this.syncing = true;\n try {\n this.nativeSelect.dispatchEvent(new Event(\"input\", { bubbles: true }));\n this.nativeSelect.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } finally {\n this.syncing = false;\n }\n }\n this.dispatchEvent(new CustomEvent(\"db-select:change\", { detail: { value }, bubbles: true }));\n }\n}\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-select\")) {\n customElements.define(\"db-select\", DbSelect);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DogsbayElement,
|
|
3
3
|
ensureDefaultDisplay
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-K6DPDBAG.js";
|
|
5
5
|
|
|
6
6
|
// src/db-tabs.ts
|
|
7
7
|
import { CompositeNavigation } from "@dogsbay/primitives/composite";
|
|
@@ -25,16 +25,25 @@ var DbTabs = class extends DogsbayElement {
|
|
|
25
25
|
const value = trigger.dataset.value;
|
|
26
26
|
if (value) this.select(value);
|
|
27
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
|
+
}
|
|
28
37
|
handleStorage = (e) => {
|
|
29
38
|
if (!this.syncKey || e.key !== `db-tabs-sync:${this.syncKey}`) return;
|
|
30
39
|
const newValue = e.newValue;
|
|
31
|
-
if (newValue && this.value !== newValue) {
|
|
40
|
+
if (newValue && this.value !== newValue && this.has(newValue)) {
|
|
32
41
|
this.select(newValue);
|
|
33
42
|
}
|
|
34
43
|
};
|
|
35
44
|
handleSyncEvent = ((e) => {
|
|
36
45
|
const newValue = e.detail.value;
|
|
37
|
-
if (newValue && this.value !== newValue) {
|
|
46
|
+
if (newValue && this.value !== newValue && this.has(newValue)) {
|
|
38
47
|
this.select(newValue);
|
|
39
48
|
}
|
|
40
49
|
});
|
|
@@ -178,4 +187,4 @@ if (!customElements.get("db-tabs")) {
|
|
|
178
187
|
export {
|
|
179
188
|
DbTabs
|
|
180
189
|
};
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
190
|
+
//# sourceMappingURL=chunk-4YPDR3W6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/db-tabs.ts"],"sourcesContent":["import { CompositeNavigation } from \"@dogsbay/primitives/composite\";\nimport type { Orientation } from \"@dogsbay/primitives/composite\";\nimport { DogsbayElement, ensureDefaultDisplay } from \"./base.js\";\n\nlet idCounter = 0;\nfunction uniqueId(prefix: string) {\n return `${prefix}-${++idCounter}`;\n}\n\n/**\n * `<db-tabs>` — Accessible tabbed interface.\n *\n * Attributes:\n * default-value — initial selected tab value\n * orientation — \"horizontal\" (default) or \"vertical\"\n * sync-key — sync selection across instances via localStorage\n *\n * Children:\n * [data-part=\"list\"] — tablist container\n * [data-part=\"trigger\"] — tab buttons (must have data-value)\n * [data-part=\"content\"] — tab panels (must have data-value)\n *\n * Events:\n * db-tabs:change — fired on selection change, detail: { value }\n */\nexport class DbTabs extends DogsbayElement {\n private list!: HTMLElement;\n private triggers: HTMLElement[] = [];\n private panels: HTMLElement[] = [];\n private nav: CompositeNavigation | null = null;\n private value = \"\";\n private syncKey: string | null = null;\n private orientation: Orientation = \"horizontal\";\n\n private handleClick = (e: Event) => {\n const trigger = (e.target as HTMLElement).closest(\n \"[data-part='trigger']\",\n ) as HTMLElement | null;\n if (!trigger || trigger.hasAttribute(\"disabled\")) return;\n const value = trigger.dataset.value;\n if (value) this.select(value);\n };\n\n /**\n * A synced group follows only a value it HAS. Groups sharing a key need\n * not share a tab set (a web-only snippet group beside an all-SDK one), and\n * selecting a value with no trigger here left the group with every panel\n * hidden and no tab selected.\n */\n private has(value: string): boolean {\n return this.triggers.some((t) => t.dataset.value === value);\n }\n\n private handleStorage = (e: StorageEvent) => {\n if (!this.syncKey || e.key !== `db-tabs-sync:${this.syncKey}`) return;\n const newValue = e.newValue;\n if (newValue && this.value !== newValue && this.has(newValue)) {\n this.select(newValue);\n }\n };\n\n private handleSyncEvent = ((e: CustomEvent) => {\n const newValue = e.detail.value;\n if (newValue && this.value !== newValue && this.has(newValue)) {\n this.select(newValue);\n }\n }) as EventListener;\n\n /**\n * Descendants belonging to THIS tab group.\n *\n * Not `:scope >`, and not a bare descendant query — both were wrong\n * here, in opposite directions:\n *\n * - Panels used `:scope > [data-part='content']`, so any wrapper\n * between the element and its panels hid them. The vertical example\n * wraps its list and panels in a flex row to sit them side by side,\n * so `panels` was EMPTY: triggers moved `aria-selected`, and the\n * content never changed. Nothing threw, and the server-rendered\n * initial state looked right, so it read as working.\n * - Triggers used a bare descendant query, which would reach into a\n * NESTED tab group and drive the wrong panels.\n *\n * `closest(\"db-tabs\") === this` allows arbitrary wrappers while\n * stopping at a nested group, which is a real case — Obsidian\n * alternates fence characters by depth precisely so tabs can nest.\n */\n private own(selector: string): HTMLElement[] {\n return (\n Array.from(this.querySelectorAll(selector)) as HTMLElement[]\n ).filter((el) => el.closest(\"db-tabs\") === this);\n }\n\n protected setup() {\n const list = this.own(\"[data-part='list']\")[0] ?? null;\n if (!list) return;\n this.list = list;\n\n this.triggers = this.own(\"[data-part='trigger']\");\n this.panels = this.own(\"[data-part='content']\");\n\n this.orientation =\n (this.getAttribute(\"orientation\") as Orientation) || \"horizontal\";\n this.syncKey = this.getAttribute(\"sync-key\") || null;\n\n // Set orientation on tablist\n list.setAttribute(\"role\", \"tablist\");\n list.setAttribute(\"aria-orientation\", this.orientation);\n\n // Generate IDs and link triggers ↔ panels\n this.triggers.forEach((trigger) => {\n const value = trigger.dataset.value!;\n trigger.setAttribute(\"role\", \"tab\");\n const triggerId = trigger.id || uniqueId(\"db-tab\");\n trigger.id = triggerId;\n\n const panel = this.panels.find((p) => p.dataset.value === value);\n if (panel) {\n panel.setAttribute(\"role\", \"tabpanel\");\n const panelId = panel.id || uniqueId(\"db-tabpanel\");\n panel.id = panelId;\n trigger.setAttribute(\"aria-controls\", panelId);\n panel.setAttribute(\"aria-labelledby\", triggerId);\n }\n });\n\n // Set up composite navigation\n this.nav = new CompositeNavigation(list, \"[data-part='trigger']\", {\n orientation: this.orientation,\n loop: true,\n homeEnd: true,\n onHighlightedIndexChange: () => {\n const focused = document.activeElement as HTMLElement;\n const value = focused?.dataset?.value;\n if (value) this.select(value);\n },\n });\n\n this.nav.activate();\n\n // Determine initial value: hash > localStorage > default-value > first trigger\n const defaultValue =\n this.getAttribute(\"default-value\") ||\n this.triggers[0]?.dataset.value ||\n \"\";\n\n let initialValue = defaultValue;\n if (this.syncKey) {\n const stored = localStorage.getItem(`db-tabs-sync:${this.syncKey}`);\n if (stored && this.triggers.some((t) => t.dataset.value === stored)) {\n initialValue = stored;\n }\n }\n const hash = window.location.hash.slice(1);\n if (hash && this.triggers.some((t) => t.dataset.value === hash)) {\n initialValue = hash;\n }\n\n this.select(initialValue);\n }\n\n protected connect() {\n this.list?.addEventListener(\"click\", this.handleClick);\n if (this.syncKey) {\n window.addEventListener(\"storage\", this.handleStorage);\n document.addEventListener(\n `db-tabs-sync:${this.syncKey}`,\n this.handleSyncEvent,\n );\n }\n }\n\n protected disconnect() {\n this.list?.removeEventListener(\"click\", this.handleClick);\n if (this.syncKey) {\n window.removeEventListener(\"storage\", this.handleStorage);\n document.removeEventListener(\n `db-tabs-sync:${this.syncKey}`,\n this.handleSyncEvent,\n );\n }\n }\n\n select(value: string) {\n if (this.value === value) return;\n this.value = value;\n\n // Update triggers\n this.triggers.forEach((trigger) => {\n const isSelected = trigger.dataset.value === value;\n trigger.setAttribute(\"aria-selected\", String(isSelected));\n trigger.setAttribute(\"tabindex\", isSelected ? \"0\" : \"-1\");\n if (isSelected) {\n trigger.setAttribute(\"data-state\", \"active\");\n } else {\n trigger.removeAttribute(\"data-state\");\n }\n });\n\n // Update panels\n this.panels.forEach((panel) => {\n const isActive = panel.dataset.value === value;\n panel.hidden = !isActive;\n if (isActive) {\n panel.setAttribute(\"data-state\", \"active\");\n if (!panel.hasAttribute(\"tabindex\")) {\n panel.setAttribute(\"tabindex\", \"0\");\n }\n // Lazy init: upgrade any nested db-tabs that haven't connected yet\n // (browser handles this automatically via connectedCallback)\n } else {\n panel.removeAttribute(\"data-state\");\n }\n });\n\n // Sync to localStorage and other instances\n if (this.syncKey) {\n localStorage.setItem(`db-tabs-sync:${this.syncKey}`, value);\n document.dispatchEvent(\n new CustomEvent(`db-tabs-sync:${this.syncKey}`, {\n detail: { value, source: this },\n }),\n );\n }\n\n // Dispatch change event\n this.dispatchEvent(\n new CustomEvent(\"db-tabs:change\", {\n detail: { value },\n bubbles: true,\n }),\n );\n }\n}\n\nensureDefaultDisplay();\n\nif (!customElements.get(\"db-tabs\")) {\n customElements.define(\"db-tabs\", DbTabs);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DogsbayElement,
|
|
3
3
|
ensureDefaultDisplay
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-K6DPDBAG.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-
|
|
97
|
+
//# sourceMappingURL=chunk-CLUADA3G.js.map
|