@hjmds/react 1.1.1 → 1.2.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/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +12 -6
- package/dist/actions.js.map +1 -1
- package/dist/advanced-display.d.ts +21 -0
- package/dist/advanced-display.d.ts.map +1 -1
- package/dist/advanced-display.js +11 -0
- package/dist/advanced-display.js.map +1 -1
- package/dist/advanced-navigation.d.ts +2 -23
- package/dist/advanced-navigation.d.ts.map +1 -1
- package/dist/advanced-navigation.js +3 -24
- package/dist/advanced-navigation.js.map +1 -1
- package/dist/agreement.d.ts +20 -0
- package/dist/agreement.d.ts.map +1 -0
- package/dist/agreement.js +29 -0
- package/dist/agreement.js.map +1 -0
- package/dist/anchor.d.ts +24 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +110 -0
- package/dist/anchor.js.map +1 -0
- package/dist/asset.d.ts +40 -0
- package/dist/asset.d.ts.map +1 -0
- package/dist/asset.js +26 -0
- package/dist/asset.js.map +1 -0
- package/dist/bottom-cta.d.ts +32 -0
- package/dist/bottom-cta.d.ts.map +1 -0
- package/dist/bottom-cta.js +30 -0
- package/dist/bottom-cta.js.map +1 -0
- package/dist/bottom-info.d.ts +16 -0
- package/dist/bottom-info.d.ts.map +1 -0
- package/dist/bottom-info.js +12 -0
- package/dist/bottom-info.js.map +1 -0
- package/dist/breadcrumb.d.ts +9 -0
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +12 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/calendar.d.ts +30 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +69 -0
- package/dist/calendar.js.map +1 -0
- package/dist/carousel.d.ts +20 -0
- package/dist/carousel.d.ts.map +1 -0
- package/dist/carousel.js +70 -0
- package/dist/carousel.js.map +1 -0
- package/dist/clipboard.d.ts +33 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +40 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/collapsible.d.ts +11 -0
- package/dist/collapsible.d.ts.map +1 -0
- package/dist/collapsible.js +18 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/command-palette.d.ts +25 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +82 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/context-menu.d.ts +12 -0
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +111 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/data-table.d.ts +30 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +57 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +3 -1
- package/dist/date-picker.d.ts.map +1 -1
- package/dist/date-picker.js +16 -31
- package/dist/date-picker.js.map +1 -1
- package/dist/date-range.d.ts +24 -0
- package/dist/date-range.d.ts.map +1 -0
- package/dist/date-range.js +29 -0
- package/dist/date-range.js.map +1 -0
- package/dist/display.d.ts +16 -0
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +13 -1
- package/dist/display.js.map +1 -1
- package/dist/evidence.d.ts +481 -1
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +47 -2
- package/dist/evidence.js.map +1 -1
- package/dist/feedback.d.ts +18 -2
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +10 -2
- package/dist/feedback.js.map +1 -1
- package/dist/floating-action-button.d.ts +32 -0
- package/dist/floating-action-button.d.ts.map +1 -0
- package/dist/floating-action-button.js +58 -0
- package/dist/floating-action-button.js.map +1 -0
- package/dist/forms.d.ts +3 -3
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +18 -7
- package/dist/forms.js.map +1 -1
- package/dist/heading.d.ts +12 -0
- package/dist/heading.d.ts.map +1 -0
- package/dist/heading.js +25 -0
- package/dist/heading.js.map +1 -0
- package/dist/index.d.ts +35 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +1 -1
- package/dist/mentions.d.ts +28 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +84 -0
- package/dist/mentions.js.map +1 -0
- package/dist/menubar.d.ts +11 -0
- package/dist/menubar.d.ts.map +1 -0
- package/dist/menubar.js +137 -0
- package/dist/menubar.js.map +1 -0
- package/dist/modal.d.ts +67 -0
- package/dist/modal.d.ts.map +1 -0
- package/dist/modal.js +307 -0
- package/dist/modal.js.map +1 -0
- package/dist/overlay-stack.d.ts +28 -0
- package/dist/overlay-stack.d.ts.map +1 -0
- package/dist/overlay-stack.js +47 -0
- package/dist/overlay-stack.js.map +1 -0
- package/dist/overlays.d.ts +26 -43
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +62 -302
- package/dist/overlays.js.map +1 -1
- package/dist/pagination.d.ts +17 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +21 -0
- package/dist/pagination.js.map +1 -0
- package/dist/popover.d.ts +25 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +226 -0
- package/dist/popover.js.map +1 -0
- package/dist/portal.d.ts +5 -1
- package/dist/portal.d.ts.map +1 -1
- package/dist/portal.js +24 -1
- package/dist/portal.js.map +1 -1
- package/dist/provider-button.d.ts +21 -0
- package/dist/provider-button.d.ts.map +1 -0
- package/dist/provider-button.js +26 -0
- package/dist/provider-button.js.map +1 -0
- package/dist/provider.d.ts +13 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +12 -2
- package/dist/provider.js.map +1 -1
- package/dist/selection.d.ts +5 -1
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +2 -2
- package/dist/selection.js.map +1 -1
- package/dist/side-panel.d.ts +34 -0
- package/dist/side-panel.d.ts.map +1 -0
- package/dist/side-panel.js +95 -0
- package/dist/side-panel.js.map +1 -0
- package/dist/sidebar.d.ts +22 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +29 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/skip-nav.d.ts +12 -0
- package/dist/skip-nav.d.ts.map +1 -0
- package/dist/skip-nav.js +29 -0
- package/dist/skip-nav.js.map +1 -0
- package/dist/splitter.d.ts +45 -0
- package/dist/splitter.d.ts.map +1 -0
- package/dist/splitter.js +116 -0
- package/dist/splitter.js.map +1 -0
- package/dist/styles.css +1063 -26
- package/dist/supplemental-display.d.ts +12 -0
- package/dist/supplemental-display.d.ts.map +1 -1
- package/dist/supplemental-display.js +6 -2
- package/dist/supplemental-display.js.map +1 -1
- package/dist/tags-input.d.ts +60 -0
- package/dist/tags-input.d.ts.map +1 -0
- package/dist/tags-input.js +90 -0
- package/dist/tags-input.js.map +1 -0
- package/dist/text-formats.d.ts +16 -0
- package/dist/text-formats.d.ts.map +1 -0
- package/dist/text-formats.js +24 -0
- package/dist/text-formats.js.map +1 -0
- package/dist/toast.d.ts +1 -1
- package/dist/toggle-group.d.ts +13 -0
- package/dist/toggle-group.d.ts.map +1 -0
- package/dist/toggle-group.js +21 -0
- package/dist/toggle-group.js.map +1 -0
- package/dist/top-bar.d.ts +27 -0
- package/dist/top-bar.d.ts.map +1 -0
- package/dist/top-bar.js +30 -0
- package/dist/top-bar.js.map +1 -0
- package/dist/top.d.ts +15 -0
- package/dist/top.d.ts.map +1 -0
- package/dist/top.js +18 -0
- package/dist/top.js.map +1 -0
- package/dist/tour.d.ts +21 -0
- package/dist/tour.d.ts.map +1 -0
- package/dist/tour.js +122 -0
- package/dist/tour.js.map +1 -0
- package/dist/transfer-list.d.ts +24 -0
- package/dist/transfer-list.d.ts.map +1 -0
- package/dist/transfer-list.js +109 -0
- package/dist/transfer-list.js.map +1 -0
- package/dist/tree.d.ts +29 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +120 -0
- package/dist/tree.js.map +1 -0
- package/package.json +173 -3
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { dataTableColumnDefaults, dataTableDefaults, getNextDataTableSortState, resolveDataTableSelectAllState, validateDataTableColumns, validateDataTableRows, validateDataTableSortState, } from "@hjmds/design-contracts/components/data-table";
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
import { useHjmDensityDefault } from "./provider.js";
|
|
5
|
+
import { classNames } from "./internal.js";
|
|
6
|
+
export const DataTable = forwardRef(function DataTable({ columns, rows, labels, renderCell, selection, sortState = null, sortCycle = dataTableDefaults.sortCycle, onSortChange, asyncState = { status: "idle" }, density: densityProp, footer, className, }, forwardedRef) {
|
|
7
|
+
// Unconditional: `??` on the hook call would break the rules of hooks.
|
|
8
|
+
const densityDefault = useHjmDensityDefault({ comfortable: "regular", compact: "compact" });
|
|
9
|
+
const density = densityProp ?? densityDefault;
|
|
10
|
+
validateDataTableColumns(columns);
|
|
11
|
+
validateDataTableRows(rows);
|
|
12
|
+
validateDataTableSortState(sortState, columns);
|
|
13
|
+
const multiple = selection?.mode === "multiple";
|
|
14
|
+
const single = selection?.mode === "single";
|
|
15
|
+
const selectedKeys = multiple
|
|
16
|
+
? selection.selectedKeys ?? selection.defaultSelectedKeys ?? new Set()
|
|
17
|
+
: single
|
|
18
|
+
? new Set(((selection.selectedKey ?? selection.defaultSelectedKey) ?? null) === null
|
|
19
|
+
? []
|
|
20
|
+
: [(selection.selectedKey ?? selection.defaultSelectedKey)])
|
|
21
|
+
: new Set();
|
|
22
|
+
const selectAllState = multiple ? resolveDataTableSelectAllState(rows, selectedKeys) : false;
|
|
23
|
+
const toggleRow = (row) => {
|
|
24
|
+
if (row.disabled || !selection || selection.mode === "none")
|
|
25
|
+
return;
|
|
26
|
+
if (selection.mode === "single") {
|
|
27
|
+
const current = selection.selectedKey ?? selection.defaultSelectedKey ?? null;
|
|
28
|
+
const next = current === row.id && selection.disallowEmptySelection !== true ? null : row.id;
|
|
29
|
+
selection.onSelectionChange?.(next);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const next = new Set(selectedKeys);
|
|
33
|
+
if (next.has(row.id))
|
|
34
|
+
next.delete(row.id);
|
|
35
|
+
else
|
|
36
|
+
next.add(row.id);
|
|
37
|
+
selection.onSelectionChange?.(next);
|
|
38
|
+
};
|
|
39
|
+
const toggleAll = () => {
|
|
40
|
+
if (!multiple)
|
|
41
|
+
return;
|
|
42
|
+
// Disabled rows stay out of both the denominator and the result, matching
|
|
43
|
+
// the shared select-all accounting.
|
|
44
|
+
const selectable = rows.filter((row) => !row.disabled);
|
|
45
|
+
const next = selectAllState === true
|
|
46
|
+
? new Set([...selectedKeys].filter((id) => !selectable.some((row) => row.id === id)))
|
|
47
|
+
: new Set([...selectedKeys, ...selectable.map((row) => row.id)]);
|
|
48
|
+
selection.onSelectionChange?.(next);
|
|
49
|
+
};
|
|
50
|
+
return (_jsxs("div", { className: classNames("hjm-data-table", className), "data-density": density, children: [asyncState.status === "idle" ? null : (_jsx("p", { className: "hjm-data-table__state", role: asyncState.status === "error" ? "alert" : "status", children: asyncState.message })), _jsxs("table", { ref: forwardedRef, className: "hjm-data-table__table", "aria-label": labels.table, "aria-busy": asyncState.status === "loading" || undefined, children: [_jsx("thead", { children: _jsxs("tr", { children: [selection && selection.mode !== "none" ? (_jsx("th", { scope: "col", className: "hjm-data-table__selector", children: multiple ? (_jsx("button", { type: "button", role: "checkbox", "aria-checked": selectAllState === "mixed" ? "mixed" : String(selectAllState === true), "aria-label": labels.selectAll, className: "hjm-data-table__check", onClick: toggleAll, children: selectAllState === true ? "✓" : selectAllState === "mixed" ? "–" : "" })) : null })) : null, columns.map((column) => {
|
|
51
|
+
const sorted = sortState?.columnId === column.id ? sortState.direction : null;
|
|
52
|
+
return (_jsx("th", { scope: "col", "aria-sort": sorted ?? undefined, style: { inlineSize: column.width, textAlign: column.align ?? dataTableColumnDefaults.align }, children: column.sortable ? (
|
|
53
|
+
// A button inside the header, never the header itself.
|
|
54
|
+
_jsxs("button", { type: "button", className: "hjm-data-table__sort", "aria-label": labels.sortColumn(column.header, sortState), onClick: () => onSortChange?.(getNextDataTableSortState(sortState, column.id, sortCycle)), children: [_jsx("span", { children: column.header }), _jsx("span", { "aria-hidden": "true", children: sorted === "ascending" ? "▲" : sorted === "descending" ? "▼" : "↕" })] })) : column.header }, column.id));
|
|
55
|
+
})] }) }), _jsx("tbody", { children: rows.map((row) => (_jsxs("tr", { "aria-selected": selection && selection.mode !== "none" ? selectedKeys.has(row.id) : undefined, "data-disabled": row.disabled || undefined, children: [selection && selection.mode !== "none" ? (_jsx("td", { className: "hjm-data-table__selector", children: _jsx("button", { type: "button", role: multiple ? "checkbox" : "radio", "aria-checked": selectedKeys.has(row.id), "aria-label": labels.selectRow(row.id), "aria-disabled": row.disabled || undefined, className: "hjm-data-table__check", onClick: () => toggleRow(row), children: selectedKeys.has(row.id) ? "✓" : "" }) })) : null, columns.map((column) => (_jsx("td", { style: { textAlign: column.align ?? dataTableColumnDefaults.align }, children: renderCell(row.id, column.id) }, column.id)))] }, row.id))) })] }), footer ? _jsx("div", { className: "hjm-data-table__footer", children: footer }) : null] }));
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=data-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.js","sourceRoot":"","sources":["../src/data-table.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,yBAAyB,EACzB,8BAA8B,EAC9B,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,GAQ3B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,UAAU,EAAsC,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AA4B3C,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,SAAS,CAIpD,EACE,OAAO,EACP,IAAI,EACJ,MAAM,EACN,UAAU,EACV,SAAS,EACT,SAAS,GAAG,IAAI,EAChB,SAAS,GAAG,iBAAiB,CAAC,SAAS,EACvC,YAAY,EACZ,UAAU,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAC/B,OAAO,EAAE,WAAW,EACpB,MAAM,EACN,SAAS,GACyB,EACpC,YAAyC;IAEzC,uEAAuE;IACvE,MAAM,cAAc,GAAG,oBAAoB,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,WAAW,IAAI,cAAc,CAAC;IAC9C,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,0BAA0B,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,SAAS,EAAE,IAAI,KAAK,UAAU,CAAC;IAChD,MAAM,MAAM,GAAG,SAAS,EAAE,IAAI,KAAK,QAAQ,CAAC;IAC5C,MAAM,YAAY,GAAwB,QAAQ;QAChD,CAAC,CAAC,SAAS,CAAC,YAAY,IAAI,SAAS,CAAC,mBAAmB,IAAI,IAAI,GAAG,EAAU;QAC9E,CAAC,CAAC,MAAM;YACN,CAAC,CAAC,IAAI,GAAG,CAAS,CAAC,CAAC,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI;gBAC1F,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,kBAAkB,CAAE,CAAC,CAAC;YAC/D,CAAC,CAAC,IAAI,GAAG,EAAU,CAAC;IACxB,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,8BAA8B,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAE7F,MAAM,SAAS,GAAG,CAAC,GAAmC,EAAE,EAAE;QACxD,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO;QACpE,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,kBAAkB,IAAI,IAAI,CAAC;YAC9E,MAAM,IAAI,GAAG,OAAO,KAAK,GAAG,CAAC,EAAE,IAAI,SAAS,CAAC,sBAAsB,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7F,SAAS,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;;YAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjE,SAAS,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC;IACF,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,0EAA0E;QAC1E,oCAAoC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,cAAc,KAAK,IAAI;YAClC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACrF,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnE,SAAS,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAE,UAAU,CAAC,gBAAgB,EAAE,SAAS,CAAC,kBAAgB,OAAO,aAC3E,UAAU,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACrC,YAAG,SAAS,EAAC,uBAAuB,EAAC,IAAI,EAAE,UAAU,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,YAAG,UAAU,CAAC,OAAO,GAAK,CACxH,EACD,iBAAO,GAAG,EAAE,YAAY,EAAE,SAAS,EAAC,uBAAuB,gBAAa,MAAM,CAAC,KAAK,eAAa,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,aAC3I,0BACE,yBACG,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CACxC,aAAI,KAAK,EAAC,KAAK,EAAC,SAAS,EAAC,0BAA0B,YACjD,QAAQ,CAAC,CAAC,CAAC,CACV,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,UAAU,kBACD,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,KAAK,IAAI,CAAqB,gBAC5F,MAAM,CAAC,SAAS,EAC5B,SAAS,EAAC,uBAAuB,EACjC,OAAO,EAAE,SAAS,YAEjB,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAC/D,CACV,CAAC,CAAC,CAAC,IAAI,GACL,CACN,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oCACtB,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;oCAC9E,OAAO,CACL,aAEE,KAAK,EAAC,KAAK,eAGA,MAAM,IAAI,SAAS,EAC9B,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI,uBAAuB,CAAC,KAAK,EAAmB,YAE7G,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;wCACjB,uDAAuD;wCACvD,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,sBAAsB,gBACpB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,SAAuC,CAAC,EACrF,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,aAEzF,yBAAO,MAAM,CAAC,MAAM,GAAQ,EAC5B,8BAAkB,MAAM,YAAE,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,IAC7F,CACV,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAlBZ,MAAM,CAAC,EAAE,CAmBX,CACN,CAAC;gCACJ,CAAC,CAAC,IACC,GACC,EACR,0BACG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,+BAAgC,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,mBAAiB,GAAG,CAAC,QAAQ,IAAI,SAAS,aACpJ,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CACxC,aAAI,SAAS,EAAC,0BAA0B,YACtC,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,kBACvB,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,gBAC1B,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,mBACrB,GAAG,CAAC,QAAQ,IAAI,SAAS,EACxC,SAAS,EAAC,uBAAuB,EACjC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,YAE5B,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAC7B,GACN,CACN,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,aAAoB,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI,uBAAuB,CAAC,KAAK,EAAmB,YACrG,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,IADvB,MAAM,CAAC,EAAE,CAEb,CACN,CAAC,KApBK,GAAG,CAAC,EAAE,CAqBV,CACN,CAAC,GACI,IACF,EAEP,MAAM,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,wBAAwB,YAAE,MAAM,GAAO,CAAC,CAAC,CAAC,IAAI,IACnE,CACP,CAAC;AACJ,CAAC,CAE6B,CAAC","sourcesContent":["import {\n dataTableColumnDefaults,\n dataTableDefaults,\n getNextDataTableSortState,\n resolveDataTableSelectAllState,\n validateDataTableColumns,\n validateDataTableRows,\n validateDataTableSortState,\n type DataTableAsyncState,\n type DataTableColumnDescriptor,\n type DataTableDensity,\n type DataTableRowDescriptor,\n type DataTableSelection,\n type DataTableSortCycle,\n type DataTableSortState,\n} from \"@hjmds/design-contracts/components/data-table\";\nimport { forwardRef, type CSSProperties, type ReactNode } from \"react\";\nimport { useHjmDensityDefault } from \"./provider.js\";\nimport { classNames } from \"./internal.js\";\n\nexport type DataTableLabels = Readonly<{\n /** Accessible name for the table itself. */\n table: string;\n selectAll: string;\n /** Composes one row's selection control name from its id. */\n selectRow: (rowId: string) => string;\n /** Composes a sortable header's action name, including its current direction. */\n sortColumn: (header: string, direction: DataTableSortState<string>) => string;\n}>;\n\nexport type DataTableProps<ColumnKey extends string = string, RowKey extends string = string> = Readonly<{\n columns: readonly DataTableColumnDescriptor<ColumnKey>[];\n rows: readonly DataTableRowDescriptor<RowKey>[];\n labels: DataTableLabels;\n renderCell: (rowId: RowKey, columnId: ColumnKey) => ReactNode;\n selection?: DataTableSelection<RowKey>;\n sortState?: DataTableSortState<ColumnKey>;\n sortCycle?: DataTableSortCycle;\n onSortChange?: (next: DataTableSortState<ColumnKey>) => void;\n asyncState?: DataTableAsyncState;\n density?: DataTableDensity;\n /** Composed beneath the table by the product — pagination, load more, totals. */\n footer?: ReactNode;\n className?: string;\n}>;\n\nexport const DataTable = forwardRef(function DataTable<\n ColumnKey extends string = string,\n RowKey extends string = string,\n>(\n {\n columns,\n rows,\n labels,\n renderCell,\n selection,\n sortState = null,\n sortCycle = dataTableDefaults.sortCycle,\n onSortChange,\n asyncState = { status: \"idle\" },\n density: densityProp,\n footer,\n className,\n }: DataTableProps<ColumnKey, RowKey>,\n forwardedRef: React.Ref<HTMLTableElement>,\n) {\n // Unconditional: `??` on the hook call would break the rules of hooks.\n const densityDefault = useHjmDensityDefault({ comfortable: \"regular\", compact: \"compact\" });\n const density = densityProp ?? densityDefault;\n validateDataTableColumns(columns);\n validateDataTableRows(rows);\n validateDataTableSortState(sortState, columns);\n const multiple = selection?.mode === \"multiple\";\n const single = selection?.mode === \"single\";\n const selectedKeys: ReadonlySet<RowKey> = multiple\n ? selection.selectedKeys ?? selection.defaultSelectedKeys ?? new Set<RowKey>()\n : single\n ? new Set<RowKey>(((selection.selectedKey ?? selection.defaultSelectedKey) ?? null) === null\n ? []\n : [(selection.selectedKey ?? selection.defaultSelectedKey)!])\n : new Set<RowKey>();\n const selectAllState = multiple ? resolveDataTableSelectAllState(rows, selectedKeys) : false;\n\n const toggleRow = (row: DataTableRowDescriptor<RowKey>) => {\n if (row.disabled || !selection || selection.mode === \"none\") return;\n if (selection.mode === \"single\") {\n const current = selection.selectedKey ?? selection.defaultSelectedKey ?? null;\n const next = current === row.id && selection.disallowEmptySelection !== true ? null : row.id;\n selection.onSelectionChange?.(next);\n return;\n }\n const next = new Set(selectedKeys);\n if (next.has(row.id)) next.delete(row.id); else next.add(row.id);\n selection.onSelectionChange?.(next);\n };\n const toggleAll = () => {\n if (!multiple) return;\n // Disabled rows stay out of both the denominator and the result, matching\n // the shared select-all accounting.\n const selectable = rows.filter((row) => !row.disabled);\n const next = selectAllState === true\n ? new Set([...selectedKeys].filter((id) => !selectable.some((row) => row.id === id)))\n : new Set([...selectedKeys, ...selectable.map((row) => row.id)]);\n selection.onSelectionChange?.(next);\n };\n\n return (\n <div className={classNames(\"hjm-data-table\", className)} data-density={density}>\n {asyncState.status === \"idle\" ? null : (\n <p className=\"hjm-data-table__state\" role={asyncState.status === \"error\" ? \"alert\" : \"status\"}>{asyncState.message}</p>\n )}\n <table ref={forwardedRef} className=\"hjm-data-table__table\" aria-label={labels.table} aria-busy={asyncState.status === \"loading\" || undefined}>\n <thead>\n <tr>\n {selection && selection.mode !== \"none\" ? (\n <th scope=\"col\" className=\"hjm-data-table__selector\">\n {multiple ? (\n <button\n type=\"button\"\n role=\"checkbox\"\n aria-checked={selectAllState === \"mixed\" ? \"mixed\" : String(selectAllState === true) as \"true\" | \"false\"}\n aria-label={labels.selectAll}\n className=\"hjm-data-table__check\"\n onClick={toggleAll}\n >\n {selectAllState === true ? \"✓\" : selectAllState === \"mixed\" ? \"–\" : \"\"}\n </button>\n ) : null}\n </th>\n ) : null}\n {columns.map((column) => {\n const sorted = sortState?.columnId === column.id ? sortState.direction : null;\n return (\n <th\n key={column.id}\n scope=\"col\"\n // The direction passes straight through to aria-sort; the\n // contract already speaks that vocabulary.\n aria-sort={sorted ?? undefined}\n style={{ inlineSize: column.width, textAlign: column.align ?? dataTableColumnDefaults.align } as CSSProperties}\n >\n {column.sortable ? (\n // A button inside the header, never the header itself.\n <button\n type=\"button\"\n className=\"hjm-data-table__sort\"\n aria-label={labels.sortColumn(column.header, sortState as DataTableSortState<string>)}\n onClick={() => onSortChange?.(getNextDataTableSortState(sortState, column.id, sortCycle))}\n >\n <span>{column.header}</span>\n <span aria-hidden=\"true\">{sorted === \"ascending\" ? \"▲\" : sorted === \"descending\" ? \"▼\" : \"↕\"}</span>\n </button>\n ) : column.header}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.id} aria-selected={selection && selection.mode !== \"none\" ? selectedKeys.has(row.id) : undefined} data-disabled={row.disabled || undefined}>\n {selection && selection.mode !== \"none\" ? (\n <td className=\"hjm-data-table__selector\">\n <button\n type=\"button\"\n role={multiple ? \"checkbox\" : \"radio\"}\n aria-checked={selectedKeys.has(row.id)}\n aria-label={labels.selectRow(row.id)}\n aria-disabled={row.disabled || undefined}\n className=\"hjm-data-table__check\"\n onClick={() => toggleRow(row)}\n >\n {selectedKeys.has(row.id) ? \"✓\" : \"\"}\n </button>\n </td>\n ) : null}\n {columns.map((column) => (\n <td key={column.id} style={{ textAlign: column.align ?? dataTableColumnDefaults.align } as CSSProperties}>\n {renderCell(row.id, column.id)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {/* Pagination or load-more is composed beneath the table, never owned by it. */}\n {footer ? <div className=\"hjm-data-table__footer\">{footer}</div> : null}\n </div>\n );\n}) as <ColumnKey extends string = string, RowKey extends string = string>(\n props: DataTableProps<ColumnKey, RowKey> & { ref?: React.Ref<HTMLTableElement> },\n) => React.ReactElement | null;\n"]}
|
package/dist/date-picker.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ComposeCalendarAccessibleName, type ResolvedCalendarDateCell } from "@hjmds/design-contracts/components/calendar";
|
|
2
2
|
import { type DatePickerDescriptor, type DatePickerSize } from "@hjmds/design-contracts/components/date-picker";
|
|
3
3
|
import { type ReactNode } from "react";
|
|
4
|
+
import { type CalendarOverflow, type CalendarHandle } from "./calendar.js";
|
|
4
5
|
export type DatePickerMonthAction = Readonly<{
|
|
5
6
|
month: string;
|
|
6
7
|
label: string;
|
|
@@ -16,9 +17,10 @@ export type DatePickerProps<Content = unknown> = Readonly<{
|
|
|
16
17
|
size?: DatePickerSize;
|
|
17
18
|
description?: ReactNode;
|
|
18
19
|
error?: ReactNode;
|
|
20
|
+
onNavigateBeyondGrid?: (detail: CalendarOverflow, focusDate: CalendarHandle["focusDate"]) => void;
|
|
19
21
|
renderCellContent?: (cell: ResolvedCalendarDateCell<Content>) => ReactNode;
|
|
20
22
|
className?: string;
|
|
21
23
|
}>;
|
|
22
24
|
/** Single-date field with an anchored, focus-bearing calendar dialog. */
|
|
23
|
-
export declare function DatePicker<Content>({ descriptor, monthLabel, composeAccessibleName, previousMonth, nextMonth, clearLabel, closeLabel, size, description, error, renderCellContent, className, }: DatePickerProps<Content>): import("react").JSX.Element;
|
|
25
|
+
export declare function DatePicker<Content>({ descriptor, monthLabel, composeAccessibleName, previousMonth, nextMonth, clearLabel, closeLabel, size, description, error, renderCellContent, onNavigateBeyondGrid, className, }: DatePickerProps<Content>): import("react").JSX.Element;
|
|
24
26
|
//# sourceMappingURL=date-picker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../src/date-picker.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../src/date-picker.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAGL,KAAK,oBAAoB,EAEzB,KAAK,cAAc,EACpB,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAY,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGrF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE/E,MAAM,MAAM,eAAe,CAAC,OAAO,GAAG,OAAO,IAAI,QAAQ,CAAC;IACxD,UAAU,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAC9D,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAClG,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,OAAO,EAAE,EAClC,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,EACV,IAAe,EACf,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,GACV,EAAE,eAAe,CAAC,OAAO,CAAC,+BAyF1B"}
|
package/dist/date-picker.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {} from "@hjmds/design-contracts/components/calendar";
|
|
3
|
+
import { resolveDatePickerTriggerText, validateDatePickerDescriptor, } from "@hjmds/design-contracts/components/date-picker";
|
|
4
4
|
import { useEffect, useId, useRef, useState, } from "react";
|
|
5
|
+
import { Calendar } from "./calendar.js";
|
|
5
6
|
import { classNames } from "./internal.js";
|
|
6
|
-
import { useOptionalHjmTheme } from "./provider.js";
|
|
7
7
|
/** Single-date field with an anchored, focus-bearing calendar dialog. */
|
|
8
|
-
export function DatePicker({ descriptor, monthLabel, composeAccessibleName, previousMonth, nextMonth, clearLabel, closeLabel, size = "medium", description, error, renderCellContent, className, }) {
|
|
8
|
+
export function DatePicker({ descriptor, monthLabel, composeAccessibleName, previousMonth, nextMonth, clearLabel, closeLabel, size = "medium", description, error, renderCellContent, onNavigateBeyondGrid, className, }) {
|
|
9
9
|
validateDatePickerDescriptor(descriptor);
|
|
10
|
-
const theme = useOptionalHjmTheme();
|
|
11
10
|
const generatedId = useId().replaceAll(":", "");
|
|
12
11
|
const dialogId = `hjm-date-picker-${generatedId}`;
|
|
13
12
|
const triggerRef = useRef(null);
|
|
@@ -18,16 +17,15 @@ export function DatePicker({ descriptor, monthLabel, composeAccessibleName, prev
|
|
|
18
17
|
const controlledSelection = descriptor.selectedDate !== undefined;
|
|
19
18
|
const [internalSelection, setInternalSelection] = useState(descriptor.defaultSelectedDate ?? null);
|
|
20
19
|
const selectedDate = controlledSelection ? descriptor.selectedDate ?? null : internalSelection;
|
|
21
|
-
const gridDescriptor = { ...descriptor, selectedDate };
|
|
22
|
-
const cells = resolveDatePickerGrid(gridDescriptor, { composeAccessibleName });
|
|
23
|
-
const firstDate = cells.find((cell) => !("filler" in cell));
|
|
24
|
-
const [focusedDate, setFocusedDate] = useState(selectedDate ?? firstDate?.date ?? "");
|
|
25
20
|
const requestOpen = (next, reason) => {
|
|
26
21
|
if (!controlledOpen)
|
|
27
22
|
setInternalOpen(next);
|
|
28
23
|
descriptor.onOpenChange?.(next, reason);
|
|
29
24
|
};
|
|
30
25
|
const commit = (date, reason) => {
|
|
26
|
+
// A controlled open field can become read-only while its grid remains mounted.
|
|
27
|
+
if (descriptor.disabled || descriptor.readOnly)
|
|
28
|
+
return;
|
|
31
29
|
if (!controlledSelection)
|
|
32
30
|
setInternalSelection(date);
|
|
33
31
|
descriptor.onSelectionChange?.(date, reason);
|
|
@@ -42,10 +40,6 @@ export function DatePicker({ descriptor, monthLabel, composeAccessibleName, prev
|
|
|
42
40
|
triggerRef.current?.focus();
|
|
43
41
|
return;
|
|
44
42
|
}
|
|
45
|
-
setFocusedDate(selectedDate ?? firstDate?.date ?? "");
|
|
46
|
-
const frame = requestAnimationFrame(() => {
|
|
47
|
-
dialogRef.current?.querySelector("[data-focus-date='true']")?.focus();
|
|
48
|
-
});
|
|
49
43
|
const outside = (event) => {
|
|
50
44
|
const target = event.target;
|
|
51
45
|
if (!dialogRef.current?.contains(target) && !triggerRef.current?.contains(target)) {
|
|
@@ -54,28 +48,19 @@ export function DatePicker({ descriptor, monthLabel, composeAccessibleName, prev
|
|
|
54
48
|
};
|
|
55
49
|
document.addEventListener("pointerdown", outside);
|
|
56
50
|
return () => {
|
|
57
|
-
cancelAnimationFrame(frame);
|
|
58
51
|
document.removeEventListener("pointerdown", outside);
|
|
59
52
|
};
|
|
60
53
|
}, [open]);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
const intent = getCalendarNavigationIntent(event.key, theme?.environment.direction ?? "ltr");
|
|
68
|
-
if (!intent)
|
|
69
|
-
return;
|
|
70
|
-
event.preventDefault();
|
|
71
|
-
const target = getCalendarNavigationTarget(descriptor.grid, date, intent);
|
|
72
|
-
if ("date" in target && target.date) {
|
|
73
|
-
setFocusedDate(target.date);
|
|
74
|
-
queueMicrotask(() => dialogRef.current?.querySelector(`[data-date='${target.date}']`)?.focus());
|
|
75
|
-
}
|
|
76
|
-
};
|
|
54
|
+
// The outer field owns selection; the shared grid receives only its resolved controlled value.
|
|
55
|
+
const { defaultSelectedDate: _defaultSelectedDate, ...calendarDescriptor } = descriptor;
|
|
56
|
+
const calendarGrid = descriptor.disabled || descriptor.readOnly
|
|
57
|
+
? { ...descriptor.grid, cells: descriptor.grid.cells.map((cell) => cell.date ? { ...cell, disabled: true } : cell) }
|
|
58
|
+
: descriptor.grid;
|
|
77
59
|
const label = descriptor.label ?? descriptor.accessibilityLabel;
|
|
78
60
|
const triggerText = resolveDatePickerTriggerText(descriptor);
|
|
79
|
-
return (_jsxs("div", { className: classNames("hjm-date-picker", className), "data-invalid": descriptor.invalid || error !== undefined || undefined, "data-size": size, children: [descriptor.label === undefined ? null : _jsx("span", { className: "hjm-date-picker__label", children: descriptor.label }), _jsxs("div", { className: "hjm-date-picker__anchor", children: [_jsxs("button", { "aria-controls": open ? dialogId : undefined, "aria-expanded": open, "aria-haspopup": "dialog", "aria-label": descriptor.accessibilityLabel, className: "hjm-date-picker__trigger", disabled: descriptor.disabled, onClick: () => !descriptor.readOnly && requestOpen(!open, "trigger"), ref: triggerRef, type: "button", children: [_jsx("span", { "aria-hidden": "true", children: "\u25A3" }), _jsx("span", { "data-placeholder": descriptor.displayValue === null || undefined, children: triggerText })] }), selectedDate === null ? null : (_jsx("button", { "aria-label": clearLabel, className: "hjm-date-picker__clear", disabled: descriptor.disabled || descriptor.readOnly, onClick: () => commit(null, "clear"), type: "button", children: "\u00D7" })), open ? (_jsxs("div", { "aria-label": label, className: "hjm-date-picker__popover", id: dialogId, ref: dialogRef, role: "dialog",
|
|
61
|
+
return (_jsxs("div", { className: classNames("hjm-date-picker", className), "data-invalid": descriptor.invalid || error !== undefined || undefined, "data-size": size, children: [descriptor.label === undefined ? null : _jsx("span", { className: "hjm-date-picker__label", children: descriptor.label }), _jsxs("div", { className: "hjm-date-picker__anchor", children: [_jsxs("button", { "aria-controls": open ? dialogId : undefined, "aria-expanded": open, "aria-haspopup": "dialog", "aria-label": descriptor.accessibilityLabel, className: "hjm-date-picker__trigger", disabled: descriptor.disabled, onClick: () => !descriptor.readOnly && requestOpen(!open, "trigger"), ref: triggerRef, type: "button", children: [_jsx("span", { "aria-hidden": "true", children: "\u25A3" }), _jsx("span", { "data-placeholder": descriptor.displayValue === null || undefined, children: triggerText })] }), selectedDate === null ? null : (_jsx("button", { "aria-label": clearLabel, className: "hjm-date-picker__clear", disabled: descriptor.disabled || descriptor.readOnly, onClick: () => commit(null, "clear"), type: "button", children: "\u00D7" })), open ? (_jsxs("div", { "aria-label": label, className: "hjm-date-picker__popover", id: dialogId, ref: dialogRef, role: "dialog", onKeyDown: (event) => { if (event.key === "Escape") {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
requestOpen(false, "escape");
|
|
64
|
+
} }, children: [_jsx("button", { "aria-label": closeLabel, className: "hjm-date-picker__calendar-close", onClick: () => requestOpen(false, "trigger"), type: "button", children: "\u00D7" }), _jsx(Calendar, { descriptor: { ...calendarDescriptor, grid: calendarGrid, monthLabel, selectedDate, onSelectionChange: (date) => commit(date, "activate") }, composeAccessibleName: composeAccessibleName, size: size, autoFocus: true, ...(previousMonth ? { previousMonth } : {}), ...(nextMonth ? { nextMonth } : {}), ...(renderCellContent ? { renderCellContent } : {}), ...(onNavigateBeyondGrid ? { onNavigateBeyondGrid } : {}) })] })) : null] }), description === undefined ? null : _jsx("span", { className: "hjm-date-picker__description", children: description }), error === undefined ? null : _jsx("span", { className: "hjm-date-picker__error", role: "alert", children: error })] }));
|
|
80
65
|
}
|
|
81
66
|
//# sourceMappingURL=date-picker.js.map
|
package/dist/date-picker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.js","sourceRoot":"","sources":["../src/date-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n getCalendarNavigationIntent,\n getCalendarNavigationTarget,\n type ComposeCalendarAccessibleName,\n type ResolvedCalendarDateCell,\n} from \"@hjmds/design-contracts/components/calendar\";\nimport {\n resolveDatePickerGrid,\n resolveDatePickerTriggerText,\n validateDatePickerDescriptor,\n type DatePickerDescriptor,\n type DatePickerOpenChangeReason,\n type DatePickerSize,\n} from \"@hjmds/design-contracts/components/date-picker\";\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nexport type DatePickerMonthAction = Readonly<{ month: string; label: string }>;\n\nexport type DatePickerProps<Content = unknown> = Readonly<{\n descriptor: DatePickerDescriptor<Content>;\n monthLabel: string;\n composeAccessibleName: ComposeCalendarAccessibleName<Content>;\n previousMonth?: DatePickerMonthAction;\n nextMonth?: DatePickerMonthAction;\n clearLabel: string;\n closeLabel: string;\n size?: DatePickerSize;\n description?: ReactNode;\n error?: ReactNode;\n renderCellContent?: (cell: ResolvedCalendarDateCell<Content>) => ReactNode;\n className?: string;\n}>;\n\n/** Single-date field with an anchored, focus-bearing calendar dialog. */\nexport function DatePicker<Content>({\n descriptor,\n monthLabel,\n composeAccessibleName,\n previousMonth,\n nextMonth,\n clearLabel,\n closeLabel,\n size = \"medium\",\n description,\n error,\n renderCellContent,\n className,\n}: DatePickerProps<Content>) {\n validateDatePickerDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n const generatedId = useId().replaceAll(\":\", \"\");\n const dialogId = `hjm-date-picker-${generatedId}`;\n const triggerRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const controlledOpen = descriptor.open !== undefined;\n const [internalOpen, setInternalOpen] = useState(descriptor.defaultOpen ?? false);\n const open = controlledOpen ? descriptor.open === true : internalOpen;\n const controlledSelection = descriptor.selectedDate !== undefined;\n const [internalSelection, setInternalSelection] = useState(\n descriptor.defaultSelectedDate ?? null,\n );\n const selectedDate = controlledSelection ? descriptor.selectedDate ?? null : internalSelection;\n const gridDescriptor = { ...descriptor, selectedDate } as DatePickerDescriptor<Content>;\n const cells = resolveDatePickerGrid(gridDescriptor, { composeAccessibleName });\n const firstDate = cells.find((cell): cell is ResolvedCalendarDateCell<Content> => !(\"filler\" in cell));\n const [focusedDate, setFocusedDate] = useState(selectedDate ?? firstDate?.date ?? \"\");\n\n const requestOpen = (next: boolean, reason: DatePickerOpenChangeReason) => {\n if (!controlledOpen) setInternalOpen(next);\n descriptor.onOpenChange?.(next, reason);\n };\n const commit = (date: string | null, reason: \"activate\" | \"clear\") => {\n if (!controlledSelection) setInternalSelection(date);\n descriptor.onSelectionChange?.(date, reason);\n requestOpen(false, reason === \"activate\" ? \"selection\" : \"clear\");\n };\n\n const wasOpenRef = useRef(open);\n useEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!open) {\n if (wasOpen) triggerRef.current?.focus();\n return;\n }\n setFocusedDate(selectedDate ?? firstDate?.date ?? \"\");\n const frame = requestAnimationFrame(() => {\n dialogRef.current?.querySelector<HTMLElement>(\"[data-focus-date='true']\")?.focus();\n });\n const outside = (event: PointerEvent) => {\n const target = event.target as Node;\n if (!dialogRef.current?.contains(target) && !triggerRef.current?.contains(target)) {\n requestOpen(false, \"outside\");\n }\n };\n document.addEventListener(\"pointerdown\", outside);\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener(\"pointerdown\", outside);\n };\n }, [open]);\n\n const handleGridKey = (event: KeyboardEvent<HTMLButtonElement>, date: string) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n requestOpen(false, \"escape\");\n return;\n }\n const intent = getCalendarNavigationIntent(\n event.key as Parameters<typeof getCalendarNavigationIntent>[0],\n theme?.environment.direction ?? \"ltr\",\n );\n if (!intent) return;\n event.preventDefault();\n const target = getCalendarNavigationTarget(descriptor.grid, date, intent);\n if (\"date\" in target && target.date) {\n setFocusedDate(target.date);\n queueMicrotask(() => dialogRef.current?.querySelector<HTMLElement>(`[data-date='${target.date}']`)?.focus());\n }\n };\n\n const label = descriptor.label ?? descriptor.accessibilityLabel;\n const triggerText = resolveDatePickerTriggerText(descriptor);\n return (\n <div className={classNames(\"hjm-date-picker\", className)} data-invalid={descriptor.invalid || error !== undefined || undefined} data-size={size}>\n {descriptor.label === undefined ? null : <span className=\"hjm-date-picker__label\">{descriptor.label}</span>}\n <div className=\"hjm-date-picker__anchor\">\n <button\n aria-controls={open ? dialogId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={descriptor.accessibilityLabel}\n className=\"hjm-date-picker__trigger\"\n disabled={descriptor.disabled}\n onClick={() => !descriptor.readOnly && requestOpen(!open, \"trigger\")}\n ref={triggerRef}\n type=\"button\"\n >\n <span aria-hidden=\"true\">▣</span>\n <span data-placeholder={descriptor.displayValue === null || undefined}>{triggerText}</span>\n </button>\n {selectedDate === null ? null : (\n <button aria-label={clearLabel} className=\"hjm-date-picker__clear\" disabled={descriptor.disabled || descriptor.readOnly} onClick={() => commit(null, \"clear\")} type=\"button\">×</button>\n )}\n {open ? (\n <div aria-label={label} className=\"hjm-date-picker__popover\" id={dialogId} ref={dialogRef} role=\"dialog\">\n <header className=\"hjm-date-picker__calendar-header\">\n {previousMonth ? <button aria-label={previousMonth.label} onClick={() => descriptor.onFocusedMonthChange?.(previousMonth.month, \"previous\")} type=\"button\">‹</button> : <span aria-hidden=\"true\" />}\n <strong>{monthLabel}</strong>\n {nextMonth ? <button aria-label={nextMonth.label} onClick={() => descriptor.onFocusedMonthChange?.(nextMonth.month, \"next\")} type=\"button\">›</button> : <span aria-hidden=\"true\" />}\n <button aria-label={closeLabel} onClick={() => requestOpen(false, \"trigger\")} type=\"button\">×</button>\n </header>\n <div className=\"hjm-date-picker__weekdays\" aria-hidden=\"true\">\n {descriptor.grid.weekdayLabels.map((weekday, index) => <span key={`${weekday}-${index}`}>{weekday}</span>)}\n </div>\n <div aria-label={monthLabel} className=\"hjm-date-picker__grid\" role=\"grid\">\n {Array.from({ length: cells.length / 7 }, (_, row) => (\n <div className=\"hjm-date-picker__week\" key={row} role=\"row\">\n {cells.slice(row * 7, row * 7 + 7).map((cell, column) => \"filler\" in cell ? (\n <span aria-hidden=\"true\" className=\"hjm-date-picker__day\" key={`filler-${row}-${column}`} role=\"gridcell\" />\n ) : (\n <button\n aria-label={cell.accessibleName}\n aria-selected={cell.isSelected}\n className=\"hjm-date-picker__day\"\n data-date={cell.date}\n data-disabled={!cell.selectable || undefined}\n data-focus-date={cell.date === focusedDate || undefined}\n data-outside={cell.outsideFocusedMonth || undefined}\n data-selected={cell.isSelected || undefined}\n data-today={cell.isToday || undefined}\n key={cell.date}\n onClick={() => cell.selectable && commit(cell.date, \"activate\")}\n onKeyDown={(event) => handleGridKey(event, cell.date)}\n role=\"gridcell\"\n tabIndex={cell.date === focusedDate ? 0 : -1}\n type=\"button\"\n >\n <span>{Number(cell.date.slice(-2))}</span>\n {renderCellContent?.(cell)}\n </button>\n ))}\n </div>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n {description === undefined ? null : <span className=\"hjm-date-picker__description\">{description}</span>}\n {error === undefined ? null : <span className=\"hjm-date-picker__error\" role=\"alert\">{error}</span>}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"date-picker.js","sourceRoot":"","sources":["../src/date-picker.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n type ComposeCalendarAccessibleName,\n type ResolvedCalendarDateCell,\n} from \"@hjmds/design-contracts/components/calendar\";\nimport {\n resolveDatePickerTriggerText,\n validateDatePickerDescriptor,\n type DatePickerDescriptor,\n type DatePickerOpenChangeReason,\n type DatePickerSize,\n} from \"@hjmds/design-contracts/components/date-picker\";\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport { Calendar, type CalendarOverflow, type CalendarHandle } from \"./calendar.js\";\nimport { classNames } from \"./internal.js\";\n\nexport type DatePickerMonthAction = Readonly<{ month: string; label: string }>;\n\nexport type DatePickerProps<Content = unknown> = Readonly<{\n descriptor: DatePickerDescriptor<Content>;\n monthLabel: string;\n composeAccessibleName: ComposeCalendarAccessibleName<Content>;\n previousMonth?: DatePickerMonthAction;\n nextMonth?: DatePickerMonthAction;\n clearLabel: string;\n closeLabel: string;\n size?: DatePickerSize;\n description?: ReactNode;\n error?: ReactNode;\n onNavigateBeyondGrid?: (detail: CalendarOverflow, focusDate: CalendarHandle[\"focusDate\"]) => void;\n renderCellContent?: (cell: ResolvedCalendarDateCell<Content>) => ReactNode;\n className?: string;\n}>;\n\n/** Single-date field with an anchored, focus-bearing calendar dialog. */\nexport function DatePicker<Content>({\n descriptor,\n monthLabel,\n composeAccessibleName,\n previousMonth,\n nextMonth,\n clearLabel,\n closeLabel,\n size = \"medium\",\n description,\n error,\n renderCellContent,\n onNavigateBeyondGrid,\n className,\n}: DatePickerProps<Content>) {\n validateDatePickerDescriptor(descriptor);\n const generatedId = useId().replaceAll(\":\", \"\");\n const dialogId = `hjm-date-picker-${generatedId}`;\n const triggerRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const controlledOpen = descriptor.open !== undefined;\n const [internalOpen, setInternalOpen] = useState(descriptor.defaultOpen ?? false);\n const open = controlledOpen ? descriptor.open === true : internalOpen;\n const controlledSelection = descriptor.selectedDate !== undefined;\n const [internalSelection, setInternalSelection] = useState(\n descriptor.defaultSelectedDate ?? null,\n );\n const selectedDate = controlledSelection ? descriptor.selectedDate ?? null : internalSelection;\n\n const requestOpen = (next: boolean, reason: DatePickerOpenChangeReason) => {\n if (!controlledOpen) setInternalOpen(next);\n descriptor.onOpenChange?.(next, reason);\n };\n const commit = (date: string | null, reason: \"activate\" | \"clear\") => {\n // A controlled open field can become read-only while its grid remains mounted.\n if (descriptor.disabled || descriptor.readOnly) return;\n if (!controlledSelection) setInternalSelection(date);\n descriptor.onSelectionChange?.(date, reason);\n requestOpen(false, reason === \"activate\" ? \"selection\" : \"clear\");\n };\n\n const wasOpenRef = useRef(open);\n useEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!open) {\n if (wasOpen) triggerRef.current?.focus();\n return;\n }\n const outside = (event: PointerEvent) => {\n const target = event.target as Node;\n if (!dialogRef.current?.contains(target) && !triggerRef.current?.contains(target)) {\n requestOpen(false, \"outside\");\n }\n };\n document.addEventListener(\"pointerdown\", outside);\n return () => {\n document.removeEventListener(\"pointerdown\", outside);\n };\n }, [open]);\n\n // The outer field owns selection; the shared grid receives only its resolved controlled value.\n const { defaultSelectedDate: _defaultSelectedDate, ...calendarDescriptor } = descriptor;\n const calendarGrid = descriptor.disabled || descriptor.readOnly\n ? { ...descriptor.grid, cells: descriptor.grid.cells.map((cell) => cell.date ? { ...cell, disabled: true } : cell) }\n : descriptor.grid;\n const label = descriptor.label ?? descriptor.accessibilityLabel;\n const triggerText = resolveDatePickerTriggerText(descriptor);\n return (\n <div className={classNames(\"hjm-date-picker\", className)} data-invalid={descriptor.invalid || error !== undefined || undefined} data-size={size}>\n {descriptor.label === undefined ? null : <span className=\"hjm-date-picker__label\">{descriptor.label}</span>}\n <div className=\"hjm-date-picker__anchor\">\n <button\n aria-controls={open ? dialogId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={descriptor.accessibilityLabel}\n className=\"hjm-date-picker__trigger\"\n disabled={descriptor.disabled}\n onClick={() => !descriptor.readOnly && requestOpen(!open, \"trigger\")}\n ref={triggerRef}\n type=\"button\"\n >\n <span aria-hidden=\"true\">▣</span>\n <span data-placeholder={descriptor.displayValue === null || undefined}>{triggerText}</span>\n </button>\n {selectedDate === null ? null : (\n <button aria-label={clearLabel} className=\"hjm-date-picker__clear\" disabled={descriptor.disabled || descriptor.readOnly} onClick={() => commit(null, \"clear\")} type=\"button\">×</button>\n )}\n {open ? (\n <div aria-label={label} className=\"hjm-date-picker__popover\" id={dialogId} ref={dialogRef} role=\"dialog\" onKeyDown={(event) => { if (event.key === \"Escape\") { event.preventDefault(); requestOpen(false, \"escape\"); } }}>\n <button aria-label={closeLabel} className=\"hjm-date-picker__calendar-close\" onClick={() => requestOpen(false, \"trigger\")} type=\"button\">×</button>\n <Calendar descriptor={{ ...calendarDescriptor, grid: calendarGrid, monthLabel, selectedDate, onSelectionChange: (date) => commit(date, \"activate\") }}\n composeAccessibleName={composeAccessibleName} size={size} autoFocus\n {...(previousMonth ? { previousMonth } : {})} {...(nextMonth ? { nextMonth } : {})}\n {...(renderCellContent ? { renderCellContent } : {})} {...(onNavigateBeyondGrid ? { onNavigateBeyondGrid } : {})} />\n </div>\n ) : null}\n </div>\n {description === undefined ? null : <span className=\"hjm-date-picker__description\">{description}</span>}\n {error === undefined ? null : <span className=\"hjm-date-picker__error\" role=\"alert\">{error}</span>}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type DateRangeValue } from "@hjmds/design-contracts/components/date-range";
|
|
2
|
+
import type { CalendarDescriptor, ComposeCalendarAccessibleName } from "@hjmds/design-contracts/components/calendar";
|
|
3
|
+
import { type ReactNode } from "react";
|
|
4
|
+
import { type CalendarMonthAction } from "./calendar.js";
|
|
5
|
+
export type DateRangePickerProps<Content = unknown> = Readonly<{
|
|
6
|
+
/** The same grid Calendar renders; the product still owns month data. */
|
|
7
|
+
descriptor: Omit<CalendarDescriptor<Content>, "selectedDate" | "defaultSelectedDate" | "onSelectionChange">;
|
|
8
|
+
composeAccessibleName: ComposeCalendarAccessibleName<Content>;
|
|
9
|
+
value?: DateRangeValue;
|
|
10
|
+
defaultValue?: DateRangeValue;
|
|
11
|
+
onValueChange?: (value: DateRangeValue) => void;
|
|
12
|
+
previousMonth?: CalendarMonthAction;
|
|
13
|
+
nextMonth?: CalendarMonthAction;
|
|
14
|
+
/** Localized suffixes appended to a day's name when it is a range edge. */
|
|
15
|
+
rangeLabels: Readonly<{
|
|
16
|
+
start: string;
|
|
17
|
+
end: string;
|
|
18
|
+
between: string;
|
|
19
|
+
}>;
|
|
20
|
+
renderCellContent?: (date: string) => ReactNode;
|
|
21
|
+
className?: string;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function DateRangePicker<Content = unknown>({ descriptor, composeAccessibleName, value: controlledValue, defaultValue, onValueChange, previousMonth, nextMonth, rangeLabels, renderCellContent, className, }: DateRangePickerProps<Content>): import("react").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=date-range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../src/date-range.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EACV,kBAAkB,EAClB,6BAA6B,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGnE,MAAM,MAAM,oBAAoB,CAAC,OAAO,GAAG,OAAO,IAAI,QAAQ,CAAC;IAC7D,yEAAyE;IACzE,UAAU,EAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC,CAAC;IAC5G,qBAAqB,EAAE,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAC9D,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,2EAA2E;IAC3E,WAAW,EAAE,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,wBAAgB,eAAe,CAAC,OAAO,GAAG,OAAO,EAAE,EACjD,UAAU,EACV,qBAAqB,EACrB,KAAK,EAAE,eAAe,EACtB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,SAAS,GACV,EAAE,oBAAoB,CAAC,OAAO,CAAC,+BA6C/B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { emptyDateRange, isCompleteDateRange, resolveDateRangeCellState, resolveDateRangeSelection, validateDateRange, } from "@hjmds/design-contracts/components/date-range";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Calendar } from "./calendar.js";
|
|
5
|
+
import { classNames, useControllableState } from "./internal.js";
|
|
6
|
+
export function DateRangePicker({ descriptor, composeAccessibleName, value: controlledValue, defaultValue, onValueChange, previousMonth, nextMonth, rangeLabels, renderCellContent, className, }) {
|
|
7
|
+
const [value, setValue] = useControllableState({
|
|
8
|
+
...(controlledValue === undefined ? {} : { value: controlledValue }),
|
|
9
|
+
defaultValue: defaultValue ?? emptyDateRange,
|
|
10
|
+
...(onValueChange === undefined ? {} : { onChange: onValueChange }),
|
|
11
|
+
});
|
|
12
|
+
validateDateRange(value);
|
|
13
|
+
// The hovered date previews the not-yet-committed end through the same cell
|
|
14
|
+
// state function the committed range uses.
|
|
15
|
+
const [hovered, setHovered] = useState(null);
|
|
16
|
+
return (_jsx("div", { className: classNames("hjm-date-range", className), "data-selecting": value.start !== null && value.end === null ? "" : undefined, "data-complete": isCompleteDateRange(value) || undefined, onMouseLeave: () => setHovered(null), children: _jsx(Calendar, { descriptor: {
|
|
17
|
+
...descriptor,
|
|
18
|
+
// Calendar keeps single selection: the range's own edges are painted
|
|
19
|
+
// through cell content and data attributes, not by lying to it.
|
|
20
|
+
selectedDate: value.end ?? value.start,
|
|
21
|
+
onSelectionChange: (date) => { if (date !== null)
|
|
22
|
+
setValue(resolveDateRangeSelection(value, date)); },
|
|
23
|
+
}, composeAccessibleName: (info) => {
|
|
24
|
+
const state = resolveDateRangeCellState(value, info.date, hovered);
|
|
25
|
+
const base = composeAccessibleName(info);
|
|
26
|
+
return state === "none" ? base : `${base}, ${rangeLabels[state]}`;
|
|
27
|
+
}, ...(previousMonth === undefined ? {} : { previousMonth }), ...(nextMonth === undefined ? {} : { nextMonth }), renderCellContent: (cell) => (_jsx("span", { className: "hjm-date-range__cell", "data-range": resolveDateRangeCellState(value, cell.date, hovered), onMouseEnter: () => setHovered(cell.date), children: renderCellContent?.(cell.date) ?? null })) }) }));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=date-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-range.js","sourceRoot":"","sources":["../src/date-range.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n emptyDateRange,\n isCompleteDateRange,\n resolveDateRangeCellState,\n resolveDateRangeSelection,\n validateDateRange,\n type DateRangeValue,\n} from \"@hjmds/design-contracts/components/date-range\";\nimport type {\n CalendarDescriptor,\n ComposeCalendarAccessibleName,\n} from \"@hjmds/design-contracts/components/calendar\";\nimport { useState, type ReactNode } from \"react\";\nimport { Calendar, type CalendarMonthAction } from \"./calendar.js\";\nimport { classNames, useControllableState } from \"./internal.js\";\n\nexport type DateRangePickerProps<Content = unknown> = Readonly<{\n /** The same grid Calendar renders; the product still owns month data. */\n descriptor: Omit<CalendarDescriptor<Content>, \"selectedDate\" | \"defaultSelectedDate\" | \"onSelectionChange\">;\n composeAccessibleName: ComposeCalendarAccessibleName<Content>;\n value?: DateRangeValue;\n defaultValue?: DateRangeValue;\n onValueChange?: (value: DateRangeValue) => void;\n previousMonth?: CalendarMonthAction;\n nextMonth?: CalendarMonthAction;\n /** Localized suffixes appended to a day's name when it is a range edge. */\n rangeLabels: Readonly<{ start: string; end: string; between: string }>;\n renderCellContent?: (date: string) => ReactNode;\n className?: string;\n}>;\n\nexport function DateRangePicker<Content = unknown>({\n descriptor,\n composeAccessibleName,\n value: controlledValue,\n defaultValue,\n onValueChange,\n previousMonth,\n nextMonth,\n rangeLabels,\n renderCellContent,\n className,\n}: DateRangePickerProps<Content>) {\n const [value, setValue] = useControllableState<DateRangeValue>({\n ...(controlledValue === undefined ? {} : { value: controlledValue }),\n defaultValue: defaultValue ?? emptyDateRange,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n validateDateRange(value);\n // The hovered date previews the not-yet-committed end through the same cell\n // state function the committed range uses.\n const [hovered, setHovered] = useState<string | null>(null);\n\n return (\n <div\n className={classNames(\"hjm-date-range\", className)}\n data-selecting={value.start !== null && value.end === null ? \"\" : undefined}\n data-complete={isCompleteDateRange(value) || undefined}\n onMouseLeave={() => setHovered(null)}\n >\n <Calendar<Content>\n descriptor={{\n ...descriptor,\n // Calendar keeps single selection: the range's own edges are painted\n // through cell content and data attributes, not by lying to it.\n selectedDate: value.end ?? value.start,\n onSelectionChange: (date) => { if (date !== null) setValue(resolveDateRangeSelection(value, date)); },\n } as CalendarDescriptor<Content>}\n composeAccessibleName={(info) => {\n const state = resolveDateRangeCellState(value, info.date, hovered);\n const base = composeAccessibleName(info);\n return state === \"none\" ? base : `${base}, ${rangeLabels[state]}`;\n }}\n {...(previousMonth === undefined ? {} : { previousMonth })}\n {...(nextMonth === undefined ? {} : { nextMonth })}\n renderCellContent={(cell) => (\n <span\n className=\"hjm-date-range__cell\"\n data-range={resolveDateRangeCellState(value, cell.date, hovered)}\n onMouseEnter={() => setHovered(cell.date)}\n >\n {renderCellContent?.(cell.date) ?? null}\n </span>\n )}\n />\n </div>\n );\n}\n"]}
|
package/dist/display.d.ts
CHANGED
|
@@ -71,6 +71,14 @@ export type ListRowProps = Omit<HTMLAttributes<HTMLElement>, "title" | "onClick"
|
|
|
71
71
|
leadingShape?: ListRowLeadingShape;
|
|
72
72
|
selected?: boolean;
|
|
73
73
|
disabled?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Placeholder row while the real one loads. It keeps the row's own height
|
|
76
|
+
* and slot geometry, so a list does not jump when the content arrives —
|
|
77
|
+
* which is exactly what a product-owned skeleton next to the list cannot do.
|
|
78
|
+
*/
|
|
79
|
+
loading?: boolean;
|
|
80
|
+
/** Localized status text announced while `loading`. */
|
|
81
|
+
loadingLabel?: string;
|
|
74
82
|
href?: string;
|
|
75
83
|
onClick?: MouseEventHandler<HTMLElement>;
|
|
76
84
|
/** Canonical layout-only placement. Controlled visual keys are excluded. */
|
|
@@ -86,6 +94,14 @@ export declare const ListRow: import("react").ForwardRefExoticComponent<Omit<HTM
|
|
|
86
94
|
leadingShape?: ListRowLeadingShape;
|
|
87
95
|
selected?: boolean;
|
|
88
96
|
disabled?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Placeholder row while the real one loads. It keeps the row's own height
|
|
99
|
+
* and slot geometry, so a list does not jump when the content arrives —
|
|
100
|
+
* which is exactly what a product-owned skeleton next to the list cannot do.
|
|
101
|
+
*/
|
|
102
|
+
loading?: boolean;
|
|
103
|
+
/** Localized status text announced while `loading`. */
|
|
104
|
+
loadingLabel?: string;
|
|
89
105
|
href?: string;
|
|
90
106
|
onClick?: MouseEventHandler<HTMLElement>;
|
|
91
107
|
/** Canonical layout-only placement. Controlled visual keys are excluded. */
|
package/dist/display.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,YAAY,IAAI,oBAAoB,EACzC,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAEL,KAAK,OAAO,EACb,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.tsx"],"names":[],"mappings":"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"}
|
package/dist/display.js
CHANGED
|
@@ -5,6 +5,7 @@ import { cardRecipe, } from "@hjmds/design-contracts/components/card";
|
|
|
5
5
|
import { surfaceGeometry, } from "@hjmds/design-contracts/recipes/base";
|
|
6
6
|
import { createElement, forwardRef, } from "react";
|
|
7
7
|
import { classNames } from "./internal.js";
|
|
8
|
+
import { useHjmDensityDefault } from "./provider.js";
|
|
8
9
|
import { Surface, Text } from "./layout.js";
|
|
9
10
|
export const Badge = forwardRef(function Badge({ tone = badgeRecipe.defaults.tone, size = badgeRecipe.defaults.size, variant = badgeRecipe.defaults.variant, leading, className, children, layoutStyle, style, ...props }, ref) {
|
|
10
11
|
return (_jsxs("span", { ...props, style: { ...style, ...layoutStyle }, ref: ref, className: classNames("hjm-badge", className), "data-tone": tone, "data-size": size, "data-variant": variant, children: [leading === undefined ? null : (_jsx("span", { "aria-hidden": "true", className: "hjm-badge__icon", children: leading })), _jsx("span", { className: "hjm-badge__label", children: children })] }));
|
|
@@ -22,7 +23,18 @@ export const Card = forwardRef(function Card({ title, description, leading, medi
|
|
|
22
23
|
? null
|
|
23
24
|
: createElement(`h${headingLevel}`, { className: "hjm-card__title", "data-slot": "title" }, title), description === undefined ? null : (_jsx(Text, { as: "p", tone: "muted", className: "hjm-card__description", "data-slot": "description", children: description }))] })] })) : null, children === undefined ? null : (_jsx("div", { className: "hjm-card__content", "data-slot": "content", children: children }))] }), actions ? _jsx("div", { className: "hjm-card__actions", "data-slot": "actions", children: actions }) : null] }));
|
|
24
25
|
});
|
|
25
|
-
export const ListRow = forwardRef(function ListRow({ title, description, leading, trailing, density
|
|
26
|
+
export const ListRow = forwardRef(function ListRow({ title, description, leading, trailing, density: densityProp, leadingShape = "square", selected = listRowRecipe.defaults.selected, disabled = false, loading = false, loadingLabel, href, onClick, className, layoutStyle, style, ...props }, ref) {
|
|
27
|
+
// The hook runs unconditionally — `??` would short-circuit it and break the
|
|
28
|
+
// rules of hooks on the very first row that passes `density`.
|
|
29
|
+
const densityDefault = useHjmDensityDefault({
|
|
30
|
+
comfortable: listRowRecipe.defaults.density,
|
|
31
|
+
compact: "compact",
|
|
32
|
+
});
|
|
33
|
+
const density = densityProp ?? densityDefault;
|
|
34
|
+
if (loading) {
|
|
35
|
+
// A loading row is never interactive: there is nothing to activate yet.
|
|
36
|
+
return (_jsxs("div", { ...props, ref: ref, role: "status", "aria-busy": "true", "aria-label": loadingLabel, className: classNames("hjm-list-row", "hjm-list-row--loading", className), "data-density": density, "data-lines": description ? "two" : "one", "data-state": "loading", style: { ...style, ...layoutStyle }, children: [leading ? _jsx("span", { className: "hjm-list-row__leading", "data-shape": leadingShape, "data-placeholder": "" }) : null, _jsxs("span", { className: "hjm-list-row__content", children: [_jsx("span", { className: "hjm-list-row__title", "data-placeholder": "" }), description ? _jsx("span", { className: "hjm-list-row__description", "data-placeholder": "" }) : null] }), trailing ? _jsx("span", { className: "hjm-list-row__trailing", "data-placeholder": "" }) : null] }));
|
|
37
|
+
}
|
|
26
38
|
const element = href ? "a" : onClick ? "button" : "div";
|
|
27
39
|
const interactiveProps = href
|
|
28
40
|
? {
|
package/dist/display.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n badgeRecipe,\n listRowRecipe,\n type BadgeSize,\n type BadgeTone,\n type BadgeVariant as ContractBadgeVariant,\n type ListRowDensity,\n type ListRowLeadingShape,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n resolveTagDescriptor,\n type TagTone,\n} from \"@hjmds/design-contracts/components/tag\";\nimport {\n cardRecipe,\n type CardHeadingLevel,\n} from \"@hjmds/design-contracts/components/card\";\nimport {\n surfaceGeometry,\n type SurfacePadding,\n type SurfaceRadius,\n type SurfaceTone,\n} from \"@hjmds/design-contracts/recipes/base\";\nimport {\n createElement,\n forwardRef,\n type HTMLAttributes,\n type MouseEventHandler,\n type ReactNode,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { Surface, Text } from \"./layout.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type { CardHeadingLevel } from \"@hjmds/design-contracts/components/card\";\nexport type { TagTone } from \"@hjmds/design-contracts/components/tag\";\nexport type BadgeVariant = ContractBadgeVariant;\n\nexport type BadgeProps = HTMLAttributes<HTMLSpanElement> &\n Readonly<{\n tone?: BadgeTone;\n size?: BadgeSize;\n variant?: BadgeVariant;\n leading?: ReactNode;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n {\n tone = badgeRecipe.defaults.tone,\n size = badgeRecipe.defaults.size,\n variant = badgeRecipe.defaults.variant,\n leading,\n className,\n children,\n layoutStyle,\n style,\n ...props\n },\n ref,\n) {\n return (\n <span\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-badge\", className)}\n data-tone={tone}\n data-size={size}\n data-variant={variant}\n >\n {leading === undefined ? null : (\n <span aria-hidden=\"true\" className=\"hjm-badge__icon\">\n {leading}\n </span>\n )}\n <span className=\"hjm-badge__label\">{children}</span>\n </span>\n );\n});\n\nexport type TagProps = Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> &\n Readonly<{\n children: string;\n tone?: TagTone;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Tag = forwardRef<HTMLSpanElement, TagProps>(function Tag(\n { children, tone, className, layoutStyle, style, ...props },\n ref,\n) {\n const descriptor = resolveTagDescriptor({\n label: children,\n ...(tone === undefined ? {} : { tone }),\n });\n return (\n <span\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-tag\", className)}\n data-tone={descriptor.tone}\n >\n <span className=\"hjm-tag__label\">{descriptor.label}</span>\n </span>\n );\n});\n\nexport type CardProps = Omit<HTMLAttributes<HTMLElement>, \"title\"> &\n Readonly<{\n title?: ReactNode;\n description?: ReactNode;\n leading?: ReactNode;\n media?: ReactNode;\n actions?: ReactNode;\n headingLevel?: CardHeadingLevel;\n selected?: boolean;\n tone?: SurfaceTone;\n bordered?: boolean;\n padding?: SurfacePadding;\n radius?: SurfaceRadius;\n }>;\n\nexport const Card = forwardRef<HTMLElement, CardProps>(function Card(\n {\n title,\n description,\n leading,\n media,\n actions,\n headingLevel = cardRecipe.defaults.headingLevel,\n selected = cardRecipe.defaults.selected,\n tone = cardRecipe.defaults.tone,\n bordered = cardRecipe.defaults.bordered,\n padding = cardRecipe.defaults.padding,\n radius,\n className,\n children,\n ...props\n },\n ref,\n) {\n const hasHeader =\n leading !== undefined || title !== undefined || description !== undefined;\n\n return (\n <Surface\n {...props}\n ref={ref}\n as=\"article\"\n tone={selected ? cardRecipe.selectedTone : tone}\n bordered={bordered}\n {...(radius === undefined ? {} : { radius })}\n className={classNames(\"hjm-card\", className)}\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {media ? <div className=\"hjm-card__media\" data-slot=\"media\">{media}</div> : null}\n <div\n className=\"hjm-card__body\"\n data-slot=\"body\"\n style={{ padding: surfaceGeometry.paddings[padding] }}\n >\n {hasHeader ? (\n <div className=\"hjm-card__header\" data-slot=\"header\">\n {leading === undefined ? null : (\n <span className=\"hjm-card__leading\" data-slot=\"leading\">\n {leading}\n </span>\n )}\n <div className=\"hjm-card__copy\">\n {title === undefined\n ? null\n : createElement(\n `h${headingLevel}`,\n { className: \"hjm-card__title\", \"data-slot\": \"title\" },\n title,\n )}\n {description === undefined ? null : (\n <Text\n as=\"p\"\n tone=\"muted\"\n className=\"hjm-card__description\"\n data-slot=\"description\"\n >\n {description}\n </Text>\n )}\n </div>\n </div>\n ) : null}\n {children === undefined ? null : (\n <div className=\"hjm-card__content\" data-slot=\"content\">{children}</div>\n )}\n </div>\n {actions ? <div className=\"hjm-card__actions\" data-slot=\"actions\">{actions}</div> : null}\n </Surface>\n );\n});\n\nexport type ListRowProps = Omit<HTMLAttributes<HTMLElement>, \"title\" | \"onClick\"> &\n Readonly<{\n title: ReactNode;\n description?: ReactNode;\n leading?: ReactNode;\n trailing?: ReactNode;\n density?: ListRowDensity;\n /** Frame the ListRow paints around `leading`; the recipe owns its size. */\n leadingShape?: ListRowLeadingShape;\n selected?: boolean;\n disabled?: boolean;\n href?: string;\n onClick?: MouseEventHandler<HTMLElement>;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const ListRow = forwardRef<HTMLElement, ListRowProps>(function ListRow(\n {\n title,\n description,\n leading,\n trailing,\n density = listRowRecipe.defaults.density,\n leadingShape = \"square\",\n selected = listRowRecipe.defaults.selected,\n disabled = false,\n href,\n onClick,\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n) {\n const element = href ? \"a\" : onClick ? \"button\" : \"div\";\n const interactiveProps = href\n ? {\n href: disabled ? undefined : href,\n \"aria-current\": selected ? (\"page\" as const) : undefined,\n \"aria-disabled\": disabled || undefined,\n tabIndex: disabled ? -1 : undefined,\n }\n : onClick\n ? {\n type: \"button\" as const,\n onClick: disabled ? undefined : onClick,\n disabled,\n \"aria-pressed\": selected,\n }\n : {};\n\n return createElement(\n element,\n {\n ...props,\n ...interactiveProps,\n ref,\n className: classNames(\"hjm-list-row\", className),\n \"data-density\": density,\n // One- and two-line rows have different minimum heights in the recipe;\n // the web renderer used a single hardcoded value until now.\n \"data-lines\": description ? \"two\" : \"one\",\n \"data-state\": disabled ? \"disabled\" : selected ? \"selected\" : \"idle\",\n // Placement wins over the legacy `style`, matching Surface's ordering.\n style: { ...style, ...layoutStyle },\n },\n leading\n ? <span className=\"hjm-list-row__leading\" data-shape={leadingShape}>{leading}</span>\n : null,\n <span className=\"hjm-list-row__content\">\n <span className=\"hjm-list-row__title\">{title}</span>\n {description ? (\n <span className=\"hjm-list-row__description\">{description}</span>\n ) : null}\n </span>,\n trailing ? <span className=\"hjm-list-row__trailing\">{trailing}</span> : null,\n );\n});\n"]}
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n badgeRecipe,\n listRowRecipe,\n type BadgeSize,\n type BadgeTone,\n type BadgeVariant as ContractBadgeVariant,\n type ListRowDensity,\n type ListRowLeadingShape,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n resolveTagDescriptor,\n type TagTone,\n} from \"@hjmds/design-contracts/components/tag\";\nimport {\n cardRecipe,\n type CardHeadingLevel,\n} from \"@hjmds/design-contracts/components/card\";\nimport {\n surfaceGeometry,\n type SurfacePadding,\n type SurfaceRadius,\n type SurfaceTone,\n} from \"@hjmds/design-contracts/recipes/base\";\nimport {\n createElement,\n forwardRef,\n type HTMLAttributes,\n type MouseEventHandler,\n type ReactNode,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useHjmDensityDefault } from \"./provider.js\";\nimport { Surface, Text } from \"./layout.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type { CardHeadingLevel } from \"@hjmds/design-contracts/components/card\";\nexport type { TagTone } from \"@hjmds/design-contracts/components/tag\";\nexport type BadgeVariant = ContractBadgeVariant;\n\nexport type BadgeProps = HTMLAttributes<HTMLSpanElement> &\n Readonly<{\n tone?: BadgeTone;\n size?: BadgeSize;\n variant?: BadgeVariant;\n leading?: ReactNode;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n {\n tone = badgeRecipe.defaults.tone,\n size = badgeRecipe.defaults.size,\n variant = badgeRecipe.defaults.variant,\n leading,\n className,\n children,\n layoutStyle,\n style,\n ...props\n },\n ref,\n) {\n return (\n <span\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-badge\", className)}\n data-tone={tone}\n data-size={size}\n data-variant={variant}\n >\n {leading === undefined ? null : (\n <span aria-hidden=\"true\" className=\"hjm-badge__icon\">\n {leading}\n </span>\n )}\n <span className=\"hjm-badge__label\">{children}</span>\n </span>\n );\n});\n\nexport type TagProps = Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> &\n Readonly<{\n children: string;\n tone?: TagTone;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Tag = forwardRef<HTMLSpanElement, TagProps>(function Tag(\n { children, tone, className, layoutStyle, style, ...props },\n ref,\n) {\n const descriptor = resolveTagDescriptor({\n label: children,\n ...(tone === undefined ? {} : { tone }),\n });\n return (\n <span\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-tag\", className)}\n data-tone={descriptor.tone}\n >\n <span className=\"hjm-tag__label\">{descriptor.label}</span>\n </span>\n );\n});\n\nexport type CardProps = Omit<HTMLAttributes<HTMLElement>, \"title\"> &\n Readonly<{\n title?: ReactNode;\n description?: ReactNode;\n leading?: ReactNode;\n media?: ReactNode;\n actions?: ReactNode;\n headingLevel?: CardHeadingLevel;\n selected?: boolean;\n tone?: SurfaceTone;\n bordered?: boolean;\n padding?: SurfacePadding;\n radius?: SurfaceRadius;\n }>;\n\nexport const Card = forwardRef<HTMLElement, CardProps>(function Card(\n {\n title,\n description,\n leading,\n media,\n actions,\n headingLevel = cardRecipe.defaults.headingLevel,\n selected = cardRecipe.defaults.selected,\n tone = cardRecipe.defaults.tone,\n bordered = cardRecipe.defaults.bordered,\n padding = cardRecipe.defaults.padding,\n radius,\n className,\n children,\n ...props\n },\n ref,\n) {\n const hasHeader =\n leading !== undefined || title !== undefined || description !== undefined;\n\n return (\n <Surface\n {...props}\n ref={ref}\n as=\"article\"\n tone={selected ? cardRecipe.selectedTone : tone}\n bordered={bordered}\n {...(radius === undefined ? {} : { radius })}\n className={classNames(\"hjm-card\", className)}\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {media ? <div className=\"hjm-card__media\" data-slot=\"media\">{media}</div> : null}\n <div\n className=\"hjm-card__body\"\n data-slot=\"body\"\n style={{ padding: surfaceGeometry.paddings[padding] }}\n >\n {hasHeader ? (\n <div className=\"hjm-card__header\" data-slot=\"header\">\n {leading === undefined ? null : (\n <span className=\"hjm-card__leading\" data-slot=\"leading\">\n {leading}\n </span>\n )}\n <div className=\"hjm-card__copy\">\n {title === undefined\n ? null\n : createElement(\n `h${headingLevel}`,\n { className: \"hjm-card__title\", \"data-slot\": \"title\" },\n title,\n )}\n {description === undefined ? null : (\n <Text\n as=\"p\"\n tone=\"muted\"\n className=\"hjm-card__description\"\n data-slot=\"description\"\n >\n {description}\n </Text>\n )}\n </div>\n </div>\n ) : null}\n {children === undefined ? null : (\n <div className=\"hjm-card__content\" data-slot=\"content\">{children}</div>\n )}\n </div>\n {actions ? <div className=\"hjm-card__actions\" data-slot=\"actions\">{actions}</div> : null}\n </Surface>\n );\n});\n\nexport type ListRowProps = Omit<HTMLAttributes<HTMLElement>, \"title\" | \"onClick\"> &\n Readonly<{\n title: ReactNode;\n description?: ReactNode;\n leading?: ReactNode;\n trailing?: ReactNode;\n density?: ListRowDensity;\n /** Frame the ListRow paints around `leading`; the recipe owns its size. */\n leadingShape?: ListRowLeadingShape;\n selected?: boolean;\n disabled?: boolean;\n /**\n * Placeholder row while the real one loads. It keeps the row's own height\n * and slot geometry, so a list does not jump when the content arrives —\n * which is exactly what a product-owned skeleton next to the list cannot do.\n */\n loading?: boolean;\n /** Localized status text announced while `loading`. */\n loadingLabel?: string;\n href?: string;\n onClick?: MouseEventHandler<HTMLElement>;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const ListRow = forwardRef<HTMLElement, ListRowProps>(function ListRow(\n {\n title,\n description,\n leading,\n trailing,\n density: densityProp,\n leadingShape = \"square\",\n selected = listRowRecipe.defaults.selected,\n disabled = false,\n loading = false,\n loadingLabel,\n href,\n onClick,\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n) {\n // The hook runs unconditionally — `??` would short-circuit it and break the\n // rules of hooks on the very first row that passes `density`.\n const densityDefault = useHjmDensityDefault({\n comfortable: listRowRecipe.defaults.density,\n compact: \"compact\",\n });\n const density = densityProp ?? densityDefault;\n if (loading) {\n // A loading row is never interactive: there is nothing to activate yet.\n return (\n <div\n {...props}\n ref={ref as React.Ref<HTMLDivElement>}\n role=\"status\"\n aria-busy=\"true\"\n aria-label={loadingLabel}\n className={classNames(\"hjm-list-row\", \"hjm-list-row--loading\", className)}\n data-density={density}\n data-lines={description ? \"two\" : \"one\"}\n data-state=\"loading\"\n style={{ ...style, ...layoutStyle }}\n >\n {leading ? <span className=\"hjm-list-row__leading\" data-shape={leadingShape} data-placeholder=\"\" /> : null}\n <span className=\"hjm-list-row__content\">\n <span className=\"hjm-list-row__title\" data-placeholder=\"\" />\n {description ? <span className=\"hjm-list-row__description\" data-placeholder=\"\" /> : null}\n </span>\n {trailing ? <span className=\"hjm-list-row__trailing\" data-placeholder=\"\" /> : null}\n </div>\n );\n }\n const element = href ? \"a\" : onClick ? \"button\" : \"div\";\n const interactiveProps = href\n ? {\n href: disabled ? undefined : href,\n \"aria-current\": selected ? (\"page\" as const) : undefined,\n \"aria-disabled\": disabled || undefined,\n tabIndex: disabled ? -1 : undefined,\n }\n : onClick\n ? {\n type: \"button\" as const,\n onClick: disabled ? undefined : onClick,\n disabled,\n \"aria-pressed\": selected,\n }\n : {};\n\n return createElement(\n element,\n {\n ...props,\n ...interactiveProps,\n ref,\n className: classNames(\"hjm-list-row\", className),\n \"data-density\": density,\n // One- and two-line rows have different minimum heights in the recipe;\n // the web renderer used a single hardcoded value until now.\n \"data-lines\": description ? \"two\" : \"one\",\n \"data-state\": disabled ? \"disabled\" : selected ? \"selected\" : \"idle\",\n // Placement wins over the legacy `style`, matching Surface's ordering.\n style: { ...style, ...layoutStyle },\n },\n leading\n ? <span className=\"hjm-list-row__leading\" data-shape={leadingShape}>{leading}</span>\n : null,\n <span className=\"hjm-list-row__content\">\n <span className=\"hjm-list-row__title\">{title}</span>\n {description ? (\n <span className=\"hjm-list-row__description\">{description}</span>\n ) : null}\n </span>,\n trailing ? <span className=\"hjm-list-row__trailing\">{trailing}</span> : null,\n );\n});\n"]}
|