@kohaku-ui/renderer-wc 0.1.0
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/LICENSE +201 -0
- package/README.md +18 -0
- package/dist/dom.d.ts +23 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +132 -0
- package/dist/dom.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/kohaku-surface.d.ts +42 -0
- package/dist/kohaku-surface.d.ts.map +1 -0
- package/dist/kohaku-surface.js +157 -0
- package/dist/kohaku-surface.js.map +1 -0
- package/dist/parts/action-button.d.ts +8 -0
- package/dist/parts/action-button.d.ts.map +1 -0
- package/dist/parts/action-button.js +38 -0
- package/dist/parts/action-button.js.map +1 -0
- package/dist/parts/chart-svg.d.ts +21 -0
- package/dist/parts/chart-svg.d.ts.map +1 -0
- package/dist/parts/chart-svg.js +181 -0
- package/dist/parts/chart-svg.js.map +1 -0
- package/dist/parts/chart.d.ts +9 -0
- package/dist/parts/chart.d.ts.map +1 -0
- package/dist/parts/chart.js +107 -0
- package/dist/parts/chart.js.map +1 -0
- package/dist/parts/control-select.d.ts +9 -0
- package/dist/parts/control-select.d.ts.map +1 -0
- package/dist/parts/control-select.js +56 -0
- package/dist/parts/control-select.js.map +1 -0
- package/dist/parts/form.d.ts +10 -0
- package/dist/parts/form.d.ts.map +1 -0
- package/dist/parts/form.js +346 -0
- package/dist/parts/form.js.map +1 -0
- package/dist/parts/kit.d.ts +25 -0
- package/dist/parts/kit.d.ts.map +1 -0
- package/dist/parts/kit.js +41 -0
- package/dist/parts/kit.js.map +1 -0
- package/dist/parts/layout.d.ts +6 -0
- package/dist/parts/layout.d.ts.map +1 -0
- package/dist/parts/layout.js +29 -0
- package/dist/parts/layout.js.map +1 -0
- package/dist/parts/list.d.ts +8 -0
- package/dist/parts/list.d.ts.map +1 -0
- package/dist/parts/list.js +60 -0
- package/dist/parts/list.js.map +1 -0
- package/dist/parts/loading.d.ts +7 -0
- package/dist/parts/loading.d.ts.map +1 -0
- package/dist/parts/loading.js +37 -0
- package/dist/parts/loading.js.map +1 -0
- package/dist/parts/metric.d.ts +11 -0
- package/dist/parts/metric.d.ts.map +1 -0
- package/dist/parts/metric.js +37 -0
- package/dist/parts/metric.js.map +1 -0
- package/dist/parts/overlay.d.ts +20 -0
- package/dist/parts/overlay.d.ts.map +1 -0
- package/dist/parts/overlay.js +131 -0
- package/dist/parts/overlay.js.map +1 -0
- package/dist/parts/spreadsheet.d.ts +11 -0
- package/dist/parts/spreadsheet.d.ts.map +1 -0
- package/dist/parts/spreadsheet.js +206 -0
- package/dist/parts/spreadsheet.js.map +1 -0
- package/dist/parts/tabs.d.ts +11 -0
- package/dist/parts/tabs.d.ts.map +1 -0
- package/dist/parts/tabs.js +109 -0
- package/dist/parts/tabs.js.map +1 -0
- package/dist/parts/text.d.ts +9 -0
- package/dist/parts/text.d.ts.map +1 -0
- package/dist/parts/text.js +72 -0
- package/dist/parts/text.js.map +1 -0
- package/dist/registry.d.ts +8 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +38 -0
- package/dist/registry.js.map +1 -0
- package/dist/sandbox-mount.d.ts +10 -0
- package/dist/sandbox-mount.d.ts.map +1 -0
- package/dist/sandbox-mount.js +73 -0
- package/dist/sandbox-mount.js.map +1 -0
- package/dist/tree.d.ts +24 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +156 -0
- package/dist/tree.js.map +1 -0
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loading.js","sourceRoot":"","sources":["../../src/parts/loading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IAE5C,MAAM,SAAS,GAAG,EAAE,CAClB,KAAK,EACL,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,EAC/D,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CACrG,CAAC;IAEF,MAAM,GAAG,GAAG,KAAK,CACf,KAAK,EACL,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,EAC1E;QACE,UAAU,EAAE,CAAC;KACd,CACF,CAAC;IACF,GAAG,CAAC,WAAW,CACb,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CACjG,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE;QACzB,CAAC,EAAE,qBAAqB;QACxB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,KAAK;QACb,cAAc,EAAE,GAAG;QACnB,gBAAgB,EAAE,OAAO;KAC1B,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CACd,KAAK,CAAC,kBAAkB,EAAE;QACxB,aAAa,EAAE,WAAW;QAC1B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,SAAS;QACb,GAAG,EAAE,MAAM;QACX,WAAW,EAAE,YAAY;KAC1B,CAAC,CACH,CAAC;IACF,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEtB,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3B,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;AAClC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PartBuilder } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* presentMetric — presentation of a single KPI value (same markup / a11y as renderer-react's PresentMetric).
|
|
4
|
+
* Shows the value and its change large, from the first row of the data reference. The change is made explicit beyond color, via a symbol (▲/▼) + a signed value.
|
|
5
|
+
* The whole is composed into a single aria-label, and the decorative text is aria-hidden. The container carries
|
|
6
|
+
* `role="group"` because a plain div's implicit role does not permit `aria-label` (ARIA in HTML AAM); `group` does,
|
|
7
|
+
* and it does not add the container to the page landmark structure.
|
|
8
|
+
* The view model (value/delta formatting, delta color, aria label) comes from renderer-core's resolveMetricView; only the markup is emitted here.
|
|
9
|
+
*/
|
|
10
|
+
export declare const presentMetric: PartBuilder;
|
|
11
|
+
//# sourceMappingURL=metric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.d.ts","sourceRoot":"","sources":["../../src/parts/metric.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAG9D;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,WAC0D,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { resolveMetricView } from "@kohaku-ui/renderer-core";
|
|
2
|
+
import { el, text } from "../dom.js";
|
|
3
|
+
import { dataStateNotice, mountBoundPart, tokenStr } from "./kit.js";
|
|
4
|
+
/**
|
|
5
|
+
* presentMetric — presentation of a single KPI value (same markup / a11y as renderer-react's PresentMetric).
|
|
6
|
+
* Shows the value and its change large, from the first row of the data reference. The change is made explicit beyond color, via a symbol (▲/▼) + a signed value.
|
|
7
|
+
* The whole is composed into a single aria-label, and the decorative text is aria-hidden. The container carries
|
|
8
|
+
* `role="group"` because a plain div's implicit role does not permit `aria-label` (ARIA in HTML AAM); `group` does,
|
|
9
|
+
* and it does not add the container to the page landmark structure.
|
|
10
|
+
* The view model (value/delta formatting, delta color, aria label) comes from renderer-core's resolveMetricView; only the markup is emitted here.
|
|
11
|
+
*/
|
|
12
|
+
export const presentMetric = (rt, parent, node) => mountBoundPart(rt, parent, node, (state) => ({ el: renderMetric(rt, node, state) }));
|
|
13
|
+
function renderMetric(rt, node, state) {
|
|
14
|
+
if (state.status !== "ready") {
|
|
15
|
+
// Non-ready states show a DataStateNotice (which has no data-kohaku). On ready it swaps to the metric body.
|
|
16
|
+
return dataStateNotice(rt, state);
|
|
17
|
+
}
|
|
18
|
+
const muted = tokenStr(rt, "color.muted");
|
|
19
|
+
const view = resolveMetricView(node, state.data.rows[0], {
|
|
20
|
+
muted,
|
|
21
|
+
positive: tokenStr(rt, "color.positive"),
|
|
22
|
+
negative: tokenStr(rt, "color.negative"),
|
|
23
|
+
}, rt.messages, rt.locale);
|
|
24
|
+
const container = el("div", { "data-kohaku": node.id, role: "group", "aria-label": view.ariaLabel }, { display: "flex", flexDirection: "column", gap: 4, padding: "12px 14px" });
|
|
25
|
+
const labelSpan = el("span", { "aria-hidden": "true" }, { fontSize: 12.5, color: muted });
|
|
26
|
+
labelSpan.appendChild(text(view.label));
|
|
27
|
+
const valueSpan = el("span", { "aria-hidden": "true" }, { fontSize: 28, fontWeight: 700, lineHeight: 1.1 });
|
|
28
|
+
valueSpan.appendChild(text(view.valueText));
|
|
29
|
+
container.append(labelSpan, valueSpan);
|
|
30
|
+
if (view.delta != null) {
|
|
31
|
+
const deltaSpan = el("span", { "aria-hidden": "true" }, { fontSize: 13, color: view.deltaColor, fontWeight: 600 });
|
|
32
|
+
deltaSpan.appendChild(text(`${view.delta.arrow} ${view.delta.signed}`));
|
|
33
|
+
container.appendChild(deltaSpan);
|
|
34
|
+
}
|
|
35
|
+
return container;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.js","sourceRoot":"","sources":["../../src/parts/metric.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAErE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAC7D,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAEvF,SAAS,YAAY,CAAC,EAAiB,EAAE,IAAmB,EAAE,KAAgB;IAC5E,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,4GAA4G;QAC5G,OAAO,eAAe,CAAC,EAAE,EAAE,KAAK,CAAE,CAAC;IACrC,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,iBAAiB,CAC5B,IAAI,EACJ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAClB;QACE,KAAK;QACL,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC;QACxC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC;KACzC,EACD,EAAE,CAAC,QAAQ,EACX,EAAE,CAAC,MAAM,CACV,CAAC;IAEF,MAAM,SAAS,GAAG,EAAE,CAClB,KAAK,EACL,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,EACvE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAC3E,CAAC;IAEF,MAAM,SAAS,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1F,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5G,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAEvC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,EAAE,CAClB,MAAM,EACN,EAAE,aAAa,EAAE,MAAM,EAAE,EACzB,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAC1D,CAAC;QACF,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACxE,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PartBuilder } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* A modal dialog (overlay.dialog, semantically equivalent to renderer-react's OverlayDialog).
|
|
4
|
+
* Since open/close is handled by visibleWhen, this builder being called = the moment it opens / teardown = the moment it closes.
|
|
5
|
+
* Focus management:
|
|
6
|
+
* - On open: remember the launcher (the currently-focused element) and move focus to the first focusable element. The visibleWhen
|
|
7
|
+
* reactive slot (tree.ts) runs the builder on a detached container and then inserts it into the DOM, so focus is
|
|
8
|
+
* deferred to "after insertion" via queueMicrotask (insertion runs synchronously within the same task after the builder returns).
|
|
9
|
+
* - Focus trap: keep the Tab / Shift+Tab cycle within the dialog (the current position is the shadow root's activeElement).
|
|
10
|
+
* - Esc / × button / backdrop click: fire close (forwarded only when declared; usually toggles the open flag via state.set).
|
|
11
|
+
* - On close (teardown): return focus to the launcher (only if it is still connected).
|
|
12
|
+
*/
|
|
13
|
+
export declare const overlayDialog: PartBuilder;
|
|
14
|
+
/**
|
|
15
|
+
* A toast notification (overlay.toast, semantically equivalent to renderer-react's OverlayToast). Visibility is controlled by visibleWhen,
|
|
16
|
+
* and after durationMs elapses it fires dismiss and disappears automatically (closing itself if a state.set is declared). It does not
|
|
17
|
+
* steal focus (role=status/alert only). The × button also fires dismiss. The timer is always cleared in teardown.
|
|
18
|
+
*/
|
|
19
|
+
export declare const overlayToast: PartBuilder;
|
|
20
|
+
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/parts/overlay.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAuB/C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,EAAE,WAgF3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAwB1B,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { dialogBoxStyle, dialogCloseButtonStyle, dialogDescriptionStyle, dialogHeaderStyle, dialogOverlayStyle, dialogTitleStyle, FOCUSABLE_SELECTOR, focusTrapTarget, toastDismissButtonStyle, toastRole, toastStyle, toastToneColors, } from "@kohaku-ui/renderer-core";
|
|
2
|
+
import { el, text } from "../dom.js";
|
|
3
|
+
import { tokenStr } from "./kit.js";
|
|
4
|
+
/**
|
|
5
|
+
* Gets the deepest currently-focused element within the shadow DOM (equivalent to renderer-react's document.activeElement).
|
|
6
|
+
* When focus is inside a shadow root, document.activeElement points to the host element, so we traverse shadowRoots.
|
|
7
|
+
*/
|
|
8
|
+
function deepActiveElement() {
|
|
9
|
+
let active = document.activeElement;
|
|
10
|
+
while (active != null) {
|
|
11
|
+
const sr = active.shadowRoot;
|
|
12
|
+
if (sr?.activeElement == null)
|
|
13
|
+
break;
|
|
14
|
+
active = sr.activeElement;
|
|
15
|
+
}
|
|
16
|
+
return active;
|
|
17
|
+
}
|
|
18
|
+
/** The activeElement of the root that container belongs to (shadow root or document). Used to determine the current position for the focus trap. */
|
|
19
|
+
function activeInRoot(container) {
|
|
20
|
+
const root = container.getRootNode();
|
|
21
|
+
return root.activeElement;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A modal dialog (overlay.dialog, semantically equivalent to renderer-react's OverlayDialog).
|
|
25
|
+
* Since open/close is handled by visibleWhen, this builder being called = the moment it opens / teardown = the moment it closes.
|
|
26
|
+
* Focus management:
|
|
27
|
+
* - On open: remember the launcher (the currently-focused element) and move focus to the first focusable element. The visibleWhen
|
|
28
|
+
* reactive slot (tree.ts) runs the builder on a detached container and then inserts it into the DOM, so focus is
|
|
29
|
+
* deferred to "after insertion" via queueMicrotask (insertion runs synchronously within the same task after the builder returns).
|
|
30
|
+
* - Focus trap: keep the Tab / Shift+Tab cycle within the dialog (the current position is the shadow root's activeElement).
|
|
31
|
+
* - Esc / × button / backdrop click: fire close (forwarded only when declared; usually toggles the open flag via state.set).
|
|
32
|
+
* - On close (teardown): return focus to the launcher (only if it is still connected).
|
|
33
|
+
*/
|
|
34
|
+
export const overlayDialog = (rt, parent, node, row) => {
|
|
35
|
+
const danger = tokenStr(rt, "color.danger");
|
|
36
|
+
const title = String(node.props["title"] ?? "");
|
|
37
|
+
const description = node.props["description"] != null ? String(node.props["description"]) : null;
|
|
38
|
+
const variant = node.props["variant"] ?? "default";
|
|
39
|
+
const accentBorder = variant === "danger" ? danger : "transparent";
|
|
40
|
+
const titleColor = variant === "danger" ? danger : tokenStr(rt, "color.text");
|
|
41
|
+
const titleId = `${node.id}-title`;
|
|
42
|
+
const descId = description != null ? `${node.id}-desc` : undefined;
|
|
43
|
+
// Capture the launcher at build time (the synchronous moment when focus still remains on the trigger).
|
|
44
|
+
const restore = deepActiveElement();
|
|
45
|
+
const close = () => rt.emit(node, "close", {}, row);
|
|
46
|
+
const overlay = el("div", { "data-kohaku": node.id }, dialogOverlayStyle);
|
|
47
|
+
const box = el("div", { role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, "aria-describedby": descId }, dialogBoxStyle(rt.theme, accentBorder));
|
|
48
|
+
const header = el("div", {}, dialogHeaderStyle);
|
|
49
|
+
const heading = el("h2", { id: titleId }, dialogTitleStyle(titleColor));
|
|
50
|
+
heading.appendChild(text(title));
|
|
51
|
+
const closeBtn = el("button", { type: "button", "aria-label": "Close" }, dialogCloseButtonStyle(rt.theme));
|
|
52
|
+
closeBtn.appendChild(text("×"));
|
|
53
|
+
closeBtn.addEventListener("click", () => close());
|
|
54
|
+
header.append(heading, closeBtn);
|
|
55
|
+
box.appendChild(header);
|
|
56
|
+
if (description != null) {
|
|
57
|
+
const desc = el("p", { id: descId }, dialogDescriptionStyle(rt.theme));
|
|
58
|
+
desc.appendChild(text(description));
|
|
59
|
+
box.appendChild(desc);
|
|
60
|
+
}
|
|
61
|
+
overlay.appendChild(box);
|
|
62
|
+
// Only a backdrop (overlay itself) click closes. Clicks inside the box are ignored.
|
|
63
|
+
overlay.addEventListener("click", (e) => {
|
|
64
|
+
if (e.target === overlay)
|
|
65
|
+
close();
|
|
66
|
+
});
|
|
67
|
+
overlay.addEventListener("keydown", (e) => {
|
|
68
|
+
if (e.key === "Escape") {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
close();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (e.key !== "Tab")
|
|
74
|
+
return;
|
|
75
|
+
const focusables = [...box.querySelectorAll(FOCUSABLE_SELECTOR)];
|
|
76
|
+
const target = focusTrapTarget(focusables, activeInRoot(box), e.shiftKey);
|
|
77
|
+
if (target === "block") {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (target != null) {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
target.focus();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
parent.appendChild(overlay);
|
|
87
|
+
const childTeardown = rt.mountChildren(box, node.children, row);
|
|
88
|
+
// On-open focus: run after insertion into the DOM (waits for the synchronous insertion after the builder returns).
|
|
89
|
+
queueMicrotask(() => {
|
|
90
|
+
if (!box.isConnected)
|
|
91
|
+
return;
|
|
92
|
+
const first = box.querySelector(FOCUSABLE_SELECTOR) ?? box;
|
|
93
|
+
first.focus();
|
|
94
|
+
});
|
|
95
|
+
return () => {
|
|
96
|
+
childTeardown();
|
|
97
|
+
overlay.remove();
|
|
98
|
+
// On close: return focus to the launcher (only if it is still connected).
|
|
99
|
+
if (restore?.isConnected)
|
|
100
|
+
restore.focus();
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* A toast notification (overlay.toast, semantically equivalent to renderer-react's OverlayToast). Visibility is controlled by visibleWhen,
|
|
105
|
+
* and after durationMs elapses it fires dismiss and disappears automatically (closing itself if a state.set is declared). It does not
|
|
106
|
+
* steal focus (role=status/alert only). The × button also fires dismiss. The timer is always cleared in teardown.
|
|
107
|
+
*/
|
|
108
|
+
export const overlayToast = (rt, parent, node, row) => {
|
|
109
|
+
const message = String(node.props["message"] ?? "");
|
|
110
|
+
const tone = node.props["tone"] ?? "info";
|
|
111
|
+
const durationMs = node.props["durationMs"];
|
|
112
|
+
const colors = toastToneColors(rt.theme, tone);
|
|
113
|
+
const toast = el("div", { "data-kohaku": node.id, role: toastRole(tone) }, toastStyle(colors));
|
|
114
|
+
const label = el("span");
|
|
115
|
+
label.appendChild(text(message));
|
|
116
|
+
const dismissBtn = el("button", { type: "button", "aria-label": "Close" }, toastDismissButtonStyle);
|
|
117
|
+
dismissBtn.appendChild(text("×"));
|
|
118
|
+
dismissBtn.addEventListener("click", () => rt.emit(node, "dismiss", {}, row));
|
|
119
|
+
toast.append(label, dismissBtn);
|
|
120
|
+
parent.appendChild(toast);
|
|
121
|
+
let timer = null;
|
|
122
|
+
if (typeof durationMs === "number") {
|
|
123
|
+
timer = setTimeout(() => rt.emit(node, "dismiss", {}, row), durationMs);
|
|
124
|
+
}
|
|
125
|
+
return () => {
|
|
126
|
+
if (timer != null)
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
toast.remove();
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/parts/overlay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PartBuilder } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* presentSpreadsheet — a table (same behavior as renderer-react's PresentSpreadsheet).
|
|
4
|
+
* In-column sorting is an "operation that does not change intent" so it uses local state; a row click is an "operation
|
|
5
|
+
* that changes intent" so it goes upstream via a Spec-declared event. In serverSide (opt-in), sorting/paging is done via
|
|
6
|
+
* binding.resolve refetches. Current sort is indicated by aria-sort / ▲▼.
|
|
7
|
+
*
|
|
8
|
+
* The serverSide refetch state machine's single source of truth is renderer-core's SpreadsheetRemoteController.
|
|
9
|
+
*/
|
|
10
|
+
export declare const presentSpreadsheet: PartBuilder;
|
|
11
|
+
//# sourceMappingURL=spreadsheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spreadsheet.d.ts","sourceRoot":"","sources":["../../src/parts/spreadsheet.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAG9D;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,WA8GhC,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { applyLocalView, createSpreadsheetRemoteController, describeSortHeader, formatCell, hasDeclaredEvent, isActivationKey, resolveColumns, spreadsheetFooterBarStyle, spreadsheetFooterTotalStyle, spreadsheetPagerButtonStyle, spreadsheetSortButtonStyle, spreadsheetTdStyle, spreadsheetThStyle, } from "@kohaku-ui/renderer-core";
|
|
2
|
+
import { resolveBoundRef } from "@kohaku-ui/spec-core";
|
|
3
|
+
import { el, text } from "../dom.js";
|
|
4
|
+
import { dataStateNotice, tokenStr } from "./kit.js";
|
|
5
|
+
/**
|
|
6
|
+
* presentSpreadsheet — a table (same behavior as renderer-react's PresentSpreadsheet).
|
|
7
|
+
* In-column sorting is an "operation that does not change intent" so it uses local state; a row click is an "operation
|
|
8
|
+
* that changes intent" so it goes upstream via a Spec-declared event. In serverSide (opt-in), sorting/paging is done via
|
|
9
|
+
* binding.resolve refetches. Current sort is indicated by aria-sort / ▲▼.
|
|
10
|
+
*
|
|
11
|
+
* The serverSide refetch state machine's single source of truth is renderer-core's SpreadsheetRemoteController.
|
|
12
|
+
*/
|
|
13
|
+
export const presentSpreadsheet = (rt, parent, node) => {
|
|
14
|
+
const border = tokenStr(rt, "color.border");
|
|
15
|
+
const headerBg = tokenStr(rt, "color.surface");
|
|
16
|
+
const accent = tokenStr(rt, "color.primary");
|
|
17
|
+
const muted = tokenStr(rt, "color.muted");
|
|
18
|
+
const serverSide = node.props["serverSide"] === true;
|
|
19
|
+
const ref = node.data?.$ref;
|
|
20
|
+
const pageSize = node.props["pageSize"];
|
|
21
|
+
const declaredSort = node.props["sortBy"];
|
|
22
|
+
const rowClickable = hasDeclaredEvent(rt.spec, node.id, "rowClick");
|
|
23
|
+
const ctrl = createSpreadsheetRemoteController({
|
|
24
|
+
binding: rt.binding,
|
|
25
|
+
bus: rt.bus,
|
|
26
|
+
ref,
|
|
27
|
+
pageSize,
|
|
28
|
+
serverSide,
|
|
29
|
+
declaredSort,
|
|
30
|
+
});
|
|
31
|
+
// base (resolved from the Spec-derived version). The BoundDataController guarantees last-write-wins, invalidation, and freshness matching.
|
|
32
|
+
let base = { status: "idle" };
|
|
33
|
+
// The base attach is toggled on/off as ctrl's remoteActive flag changes (see syncBaseAttach below,
|
|
34
|
+
// mirroring renderer-react's PresentSpreadsheet: `enabled: !(serverSide && snap.remoteActive)`). base
|
|
35
|
+
// is disabled only while the remote controller is *actually* the active fetch source (sortBy/pageSize
|
|
36
|
+
// declared, or the user has interacted) — a serverSide spreadsheet that declares neither and hasn't
|
|
37
|
+
// been interacted with yet still relies on base for its display, exactly like non-serverSide.
|
|
38
|
+
let baseDetach = () => { };
|
|
39
|
+
let baseEnabled = null;
|
|
40
|
+
let current = document.createComment(`kohaku:bound:${node.id}`);
|
|
41
|
+
parent.appendChild(current);
|
|
42
|
+
const swap = (next) => {
|
|
43
|
+
current.replaceWith(next);
|
|
44
|
+
current = next;
|
|
45
|
+
};
|
|
46
|
+
const displayed = () => {
|
|
47
|
+
const { remote } = ctrl.getSnapshot();
|
|
48
|
+
return serverSide && remote != null ? remote : base;
|
|
49
|
+
};
|
|
50
|
+
const rerender = () => {
|
|
51
|
+
const snap = ctrl.getSnapshot();
|
|
52
|
+
swap(renderTable(rt, node, displayed(), {
|
|
53
|
+
serverSide,
|
|
54
|
+
sort: snap.sort,
|
|
55
|
+
cursor: snap.cursor,
|
|
56
|
+
pageSize,
|
|
57
|
+
rowClickable,
|
|
58
|
+
colors: { border, headerBg, accent, muted },
|
|
59
|
+
onToggleSort: (colKey) => ctrl.toggleSort(colKey),
|
|
60
|
+
onFirstPage: () => ctrl.goFirstPage(),
|
|
61
|
+
onNextPage: (next) => ctrl.goNextPage(next),
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
// (Re-)attaches base with the currently-correct `enabled` flag, only when that flag actually
|
|
65
|
+
// changed since the last attach (toggling attach/detach is not free — a fresh attach synchronously
|
|
66
|
+
// reports idle/loading again). Node/spec are fixed for this part instance's lifetime (a Spec swap
|
|
67
|
+
// rebuilds the whole tree elsewhere — see kohaku-surface.ts), so only ctrl's remoteActive can move
|
|
68
|
+
// this decision after the initial call.
|
|
69
|
+
const syncBaseAttach = () => {
|
|
70
|
+
const enabled = !(serverSide && ctrl.getSnapshot().remoteActive);
|
|
71
|
+
if (enabled === baseEnabled)
|
|
72
|
+
return;
|
|
73
|
+
baseEnabled = enabled;
|
|
74
|
+
baseDetach();
|
|
75
|
+
baseDetach = rt.controller.attach(node, rt.spec, (state) => {
|
|
76
|
+
base = state;
|
|
77
|
+
rerender();
|
|
78
|
+
}, { enabled });
|
|
79
|
+
};
|
|
80
|
+
// ctrl.subscribe is registered before ctrl.start() so that a synchronous initial refetch (when
|
|
81
|
+
// sortBy/pageSize is declared) notifies here too, keeping base's (dis)attachment and the very first
|
|
82
|
+
// paint's remote/base choice consistent from the start (see the "single initial fetch" parity test).
|
|
83
|
+
const unsubCtrl = ctrl.subscribe(() => {
|
|
84
|
+
syncBaseAttach();
|
|
85
|
+
rerender();
|
|
86
|
+
});
|
|
87
|
+
const stopCtrl = ctrl.start();
|
|
88
|
+
// Keep the controller's ref following data.bind + $state (mirrors renderer-react's
|
|
89
|
+
// useSpreadsheetRemote effect: see use-spreadsheet-remote.ts) so sort/page refetches target the
|
|
90
|
+
// node's currently effective ref, not the raw ref this part was constructed with. setRef itself
|
|
91
|
+
// no-ops when the ref is unchanged, so calling it eagerly here and on every state change is cheap.
|
|
92
|
+
const computeEffectiveRef = () => node.data != null ? resolveBoundRef(node.data, rt.store.values) : undefined;
|
|
93
|
+
ctrl.setRef(computeEffectiveRef());
|
|
94
|
+
const unsubState = rt.store.subscribe(() => ctrl.setRef(computeEffectiveRef()));
|
|
95
|
+
// Idempotent: a no-op if ctrl.start()'s own synchronous refetch already ran syncBaseAttach above
|
|
96
|
+
// (serverSide + sortBy/pageSize declared); otherwise this is what performs the initial base attach
|
|
97
|
+
// (serverSide=false, or serverSide=true but inactive).
|
|
98
|
+
syncBaseAttach();
|
|
99
|
+
return () => {
|
|
100
|
+
baseDetach();
|
|
101
|
+
unsubCtrl();
|
|
102
|
+
stopCtrl();
|
|
103
|
+
unsubState();
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
function renderTable(rt, node, state, opts) {
|
|
107
|
+
if (state.status !== "ready") {
|
|
108
|
+
// dataStateNotice renders nothing for "idle" (no display element yet), but swap() requires a real
|
|
109
|
+
// Node — fall back to an empty placeholder rather than passing null to replaceWith. Reachable for a
|
|
110
|
+
// serverSide spreadsheet that starts inactive (no declaredSort/pageSize/interaction yet): the remote
|
|
111
|
+
// controller's own start()/setRef can notify while the base (BoundDataController) is still idle,
|
|
112
|
+
// ahead of its own first onChange.
|
|
113
|
+
return dataStateNotice(rt, state) ?? document.createComment(`kohaku:idle:${node.id}`);
|
|
114
|
+
}
|
|
115
|
+
const data = state.data;
|
|
116
|
+
const { border, headerBg, accent } = opts.colors;
|
|
117
|
+
const columns = resolveColumns(node, data);
|
|
118
|
+
const rows = opts.serverSide ? data.rows : applyLocalView(data.rows, opts.sort, opts.pageSize, rt.locale);
|
|
119
|
+
const wrapper = el("div", { "data-kohaku": node.id }, { width: "100%", overflowX: "auto" });
|
|
120
|
+
const table = el("table", {}, { width: "100%", borderCollapse: "collapse", fontSize: 13.5 });
|
|
121
|
+
// ---- thead ----
|
|
122
|
+
const thead = el("thead");
|
|
123
|
+
const headRow = el("tr");
|
|
124
|
+
for (const col of columns) {
|
|
125
|
+
// aria-sort / label / arrow are all derived by renderer-core's describeSortHeader (single source of truth
|
|
126
|
+
// shared with renderer-react).
|
|
127
|
+
const h = describeSortHeader(col, opts.sort);
|
|
128
|
+
const th = el("th", {}, spreadsheetThStyle({ headerBg, border }));
|
|
129
|
+
if (h.ariaSort != null)
|
|
130
|
+
th.setAttribute("aria-sort", h.ariaSort);
|
|
131
|
+
const btn = el("button", { type: "button" }, spreadsheetSortButtonStyle({ numeric: h.numeric }));
|
|
132
|
+
btn.appendChild(text(h.label));
|
|
133
|
+
if (h.arrow != null) {
|
|
134
|
+
const arrow = el("span", { "aria-hidden": "true" }, { color: accent });
|
|
135
|
+
arrow.appendChild(text(h.arrow));
|
|
136
|
+
btn.appendChild(arrow);
|
|
137
|
+
}
|
|
138
|
+
btn.addEventListener("click", () => opts.onToggleSort(col.key));
|
|
139
|
+
th.appendChild(btn);
|
|
140
|
+
headRow.appendChild(th);
|
|
141
|
+
}
|
|
142
|
+
thead.appendChild(headRow);
|
|
143
|
+
table.appendChild(thead);
|
|
144
|
+
// ---- tbody ----
|
|
145
|
+
const tbody = el("tbody");
|
|
146
|
+
for (const row of rows) {
|
|
147
|
+
const tr = el("tr", {}, { cursor: opts.rowClickable ? "pointer" : "default", borderBottom: `1px solid ${border}` });
|
|
148
|
+
if (opts.rowClickable) {
|
|
149
|
+
tr.setAttribute("role", "button");
|
|
150
|
+
tr.tabIndex = 0;
|
|
151
|
+
tr.addEventListener("click", () => rt.emit(node, "rowClick", { row }, null));
|
|
152
|
+
tr.addEventListener("keydown", (e) => {
|
|
153
|
+
if (isActivationKey(e.key)) {
|
|
154
|
+
if (e.key === " ")
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
rt.emit(node, "rowClick", { row }, null);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
for (const col of columns) {
|
|
161
|
+
const td = el("td", {}, spreadsheetTdStyle({ numeric: col.type === "number" }));
|
|
162
|
+
td.appendChild(text(formatCell(row[col.key], col, rt.locale)));
|
|
163
|
+
tr.appendChild(td);
|
|
164
|
+
}
|
|
165
|
+
tbody.appendChild(tr);
|
|
166
|
+
}
|
|
167
|
+
table.appendChild(tbody);
|
|
168
|
+
wrapper.appendChild(table);
|
|
169
|
+
// ---- footer / pager ----
|
|
170
|
+
appendFooter(rt, wrapper, data, rows.length, opts);
|
|
171
|
+
return wrapper;
|
|
172
|
+
}
|
|
173
|
+
function appendFooter(rt, wrapper, data, shown, opts) {
|
|
174
|
+
const { border, accent, muted } = opts.colors;
|
|
175
|
+
if (opts.serverSide) {
|
|
176
|
+
const bar = el("div", {}, spreadsheetFooterBarStyle({ muted }));
|
|
177
|
+
if (data.total != null) {
|
|
178
|
+
const span = el("span");
|
|
179
|
+
span.appendChild(text(rt.messages.spreadsheetTotal(data.total.toLocaleString(rt.locale), shown)));
|
|
180
|
+
bar.appendChild(span);
|
|
181
|
+
}
|
|
182
|
+
if (opts.cursor != null) {
|
|
183
|
+
const b = pagerButton(rt.messages.spreadsheetFirstPage, { border, accent });
|
|
184
|
+
b.addEventListener("click", () => opts.onFirstPage());
|
|
185
|
+
bar.appendChild(b);
|
|
186
|
+
}
|
|
187
|
+
if (data.nextCursor != null) {
|
|
188
|
+
const next = data.nextCursor;
|
|
189
|
+
const b = pagerButton(rt.messages.spreadsheetNextPage, { border, accent });
|
|
190
|
+
b.addEventListener("click", () => opts.onNextPage(next));
|
|
191
|
+
bar.appendChild(b);
|
|
192
|
+
}
|
|
193
|
+
wrapper.appendChild(bar);
|
|
194
|
+
}
|
|
195
|
+
else if (data.total != null && data.total > shown) {
|
|
196
|
+
const div = el("div", {}, spreadsheetFooterTotalStyle({ muted }));
|
|
197
|
+
div.appendChild(text(rt.messages.spreadsheetTotal(data.total.toLocaleString(rt.locale), shown)));
|
|
198
|
+
wrapper.appendChild(div);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function pagerButton(label, tokens) {
|
|
202
|
+
const b = el("button", { type: "button" }, spreadsheetPagerButtonStyle(tokens));
|
|
203
|
+
b.appendChild(text(label));
|
|
204
|
+
return b;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=spreadsheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spreadsheet.js","sourceRoot":"","sources":["../../src/parts/spreadsheet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PartBuilder } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* layout.tabs — a tab container (same as renderer-react's LayoutTabs). The source of truth for selection is $state.<stateKey>.
|
|
4
|
+
* Tab switching calls store.set directly as an in-component local operation (does not require an events declaration). If a "select"
|
|
5
|
+
* declaration exists, it additionally emits. The panel builds only the selected layout.tab; unselected ones are not built (lazy loading).
|
|
6
|
+
* a11y: role=tablist/tab/tabpanel + aria-selected + arrow keys to move between tabs.
|
|
7
|
+
*/
|
|
8
|
+
export declare const layoutTabs: PartBuilder;
|
|
9
|
+
/** layout.tab — a single tab's panel (same as renderer-react's LayoutTab). A simple container. */
|
|
10
|
+
export declare const layoutTab: PartBuilder;
|
|
11
|
+
//# sourceMappingURL=tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/parts/tabs.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AAGxE;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,WA2GxB,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,SAAS,EAAE,WAavB,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describeTab, nextTabIndex, resolveTabs, tabButtonStyle, } from "@kohaku-ui/renderer-core";
|
|
2
|
+
import { el, noop, setStyle, text } from "../dom.js";
|
|
3
|
+
import { tokenStr } from "./kit.js";
|
|
4
|
+
/**
|
|
5
|
+
* layout.tabs — a tab container (same as renderer-react's LayoutTabs). The source of truth for selection is $state.<stateKey>.
|
|
6
|
+
* Tab switching calls store.set directly as an in-component local operation (does not require an events declaration). If a "select"
|
|
7
|
+
* declaration exists, it additionally emits. The panel builds only the selected layout.tab; unselected ones are not built (lazy loading).
|
|
8
|
+
* a11y: role=tablist/tab/tabpanel + aria-selected + arrow keys to move between tabs.
|
|
9
|
+
*/
|
|
10
|
+
export const layoutTabs = (rt, parent, node, row) => {
|
|
11
|
+
const accent = tokenStr(rt, "color.primary");
|
|
12
|
+
const border = tokenStr(rt, "color.border");
|
|
13
|
+
const muted = tokenStr(rt, "color.muted");
|
|
14
|
+
const stateKey = String(node.props["stateKey"] ?? "");
|
|
15
|
+
const childIds = node.children ?? [];
|
|
16
|
+
const tabs = resolveTabs(childIds, (id) => rt.byId.get(id));
|
|
17
|
+
if (tabs.length === 0) {
|
|
18
|
+
const empty = el("div", { "data-kohaku": node.id });
|
|
19
|
+
parent.appendChild(empty);
|
|
20
|
+
return () => empty.remove();
|
|
21
|
+
}
|
|
22
|
+
const container = el("div", { "data-kohaku": node.id }, {
|
|
23
|
+
display: "flex",
|
|
24
|
+
flexDirection: "column",
|
|
25
|
+
gap: 12,
|
|
26
|
+
width: "100%",
|
|
27
|
+
});
|
|
28
|
+
const tablist = el("div", { role: "tablist" }, {
|
|
29
|
+
display: "flex",
|
|
30
|
+
gap: 4,
|
|
31
|
+
borderBottom: `1px solid ${border}`,
|
|
32
|
+
});
|
|
33
|
+
const panel = el("div", { role: "tabpanel" });
|
|
34
|
+
container.append(tablist, panel);
|
|
35
|
+
parent.appendChild(container);
|
|
36
|
+
const currentValue = () => rt.store.get(stateKey);
|
|
37
|
+
const selectedOf = () => tabs.find((t) => String(t.value) === String(currentValue())) ?? tabs[0];
|
|
38
|
+
const buttons = [];
|
|
39
|
+
const select = (tab) => {
|
|
40
|
+
rt.store.set(stateKey, tab.value);
|
|
41
|
+
// If "select" is declared, notify upstream (if undeclared, it is discarded inside rt.emit).
|
|
42
|
+
rt.emit(node, "select", { value: tab.value }, row);
|
|
43
|
+
};
|
|
44
|
+
const onKeyDown = (e, pos) => {
|
|
45
|
+
const next = nextTabIndex(e.key, pos, tabs.length);
|
|
46
|
+
if (next == null)
|
|
47
|
+
return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
select(tabs[next]);
|
|
50
|
+
buttons[next]?.focus();
|
|
51
|
+
};
|
|
52
|
+
tabs.forEach((tab, pos) => {
|
|
53
|
+
const btn = el("button", {
|
|
54
|
+
role: "tab",
|
|
55
|
+
type: "button",
|
|
56
|
+
id: describeTab(node.id, tab.value).tabId,
|
|
57
|
+
});
|
|
58
|
+
btn.appendChild(text(tab.label));
|
|
59
|
+
btn.addEventListener("click", () => select(tab));
|
|
60
|
+
btn.addEventListener("keydown", (e) => onKeyDown(e, pos));
|
|
61
|
+
buttons.push(btn);
|
|
62
|
+
tablist.appendChild(btn);
|
|
63
|
+
});
|
|
64
|
+
// Reflect the appearance/aria and panel content according to the selection. The panel builds only the selected tab's child.
|
|
65
|
+
let panelTeardown = noop;
|
|
66
|
+
let appliedValue = null;
|
|
67
|
+
let built = false;
|
|
68
|
+
const applySelection = () => {
|
|
69
|
+
const selected = selectedOf();
|
|
70
|
+
// On a state change where the selected value is unchanged (originating from another part), do not rebuild the panel (preserves the lazy-load state).
|
|
71
|
+
if (built && appliedValue === selected.value)
|
|
72
|
+
return;
|
|
73
|
+
built = true;
|
|
74
|
+
appliedValue = selected.value;
|
|
75
|
+
const selectedIds = describeTab(node.id, selected.value);
|
|
76
|
+
tabs.forEach((tab, pos) => {
|
|
77
|
+
const btn = buttons[pos];
|
|
78
|
+
const isSelected = tab.value === selected.value;
|
|
79
|
+
btn.setAttribute("aria-selected", String(isSelected));
|
|
80
|
+
btn.setAttribute("aria-controls", selectedIds.panelId);
|
|
81
|
+
btn.tabIndex = isSelected ? 0 : -1;
|
|
82
|
+
setStyle(btn, tabButtonStyle({ accent, muted }, { active: isSelected }));
|
|
83
|
+
});
|
|
84
|
+
panel.setAttribute("id", selectedIds.panelId);
|
|
85
|
+
panel.setAttribute("aria-labelledby", selectedIds.tabId);
|
|
86
|
+
panelTeardown();
|
|
87
|
+
panel.replaceChildren();
|
|
88
|
+
panelTeardown = rt.mountNode(panel, selected.id, row);
|
|
89
|
+
};
|
|
90
|
+
applySelection();
|
|
91
|
+
const unsub = rt.store.subscribe(() => applySelection());
|
|
92
|
+
return () => {
|
|
93
|
+
unsub();
|
|
94
|
+
panelTeardown();
|
|
95
|
+
container.remove();
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
/** layout.tab — a single tab's panel (same as renderer-react's LayoutTab). A simple container. */
|
|
99
|
+
export const layoutTab = (rt, parent, node, row) => {
|
|
100
|
+
const container = el("div", { "data-kohaku": node.id }, {
|
|
101
|
+
display: "flex",
|
|
102
|
+
flexDirection: "column",
|
|
103
|
+
gap: 16,
|
|
104
|
+
width: "100%",
|
|
105
|
+
});
|
|
106
|
+
parent.appendChild(container);
|
|
107
|
+
return rt.mountChildren(container, node.children, row);
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/parts/tabs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PartBuilder } from "../types.js";
|
|
2
|
+
/** text.heading — a heading (same markup as renderer-react's TextHeading). */
|
|
3
|
+
export declare const textHeading: PartBuilder;
|
|
4
|
+
/**
|
|
5
|
+
* presentMarkdown — zero-dependency rendering of a Markdown subset (same as renderer-react's PresentMarkdown).
|
|
6
|
+
* The AST is shared via renderer-core's parseMarkdownBlocks / parseMarkdownInline (empty text segments are also preserved).
|
|
7
|
+
*/
|
|
8
|
+
export declare const presentMarkdown: PartBuilder;
|
|
9
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/parts/text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,8EAA8E;AAC9E,eAAO,MAAM,WAAW,EAAE,WAWzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAuC7B,CAAC"}
|