@nizivo/react 0.1.0 → 0.2.1
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/THIRD_PARTY_NOTICES +12 -5
- package/dist/_engines/react-aria/dialog.client.js +16 -24
- package/dist/_engines/react-aria/drawer.client.js +8 -0
- package/dist/_engines/react-aria/file-upload.client.js +50 -0
- package/dist/_engines/react-aria/menu.client.js +17 -13
- package/dist/_engines/react-aria/open-state.client.js +53 -0
- package/dist/_engines/react-aria/outside-press.client.js +61 -0
- package/dist/_engines/react-aria/overlay.client.js +6 -1
- package/dist/_engines/react-aria/popover.client.js +148 -0
- package/dist/_engines/react-aria/popup.client.js +31 -5
- package/dist/_engines/react-aria/select.client.js +22 -12
- package/dist/_engines/react-aria/toast.client.js +38 -0
- package/dist/_engines/react-aria/tooltip.client.js +11 -11
- package/dist/_internal/data-status.d.ts +3 -0
- package/dist/_internal/data-status.js +13 -0
- package/dist/_internal/glyphs.js +54 -1
- package/dist/_internal/modal.client.js +54 -0
- package/dist/_internal/nested-focus.js +33 -0
- package/dist/alert/alert-dismiss.client.d.ts +1 -1
- package/dist/alert/alert-dismiss.client.js +3 -1
- package/dist/app-shell/app-shell.d.ts +24 -0
- package/dist/app-shell/app-shell.js +56 -0
- package/dist/app-shell/index.d.ts +2 -0
- package/dist/app-shell/index.js +1 -0
- package/dist/avatar/avatar.d.ts +96 -0
- package/dist/avatar/avatar.js +94 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +1 -0
- package/dist/banner/banner-dismiss.client.d.ts +32 -0
- package/dist/banner/banner-dismiss.client.js +38 -0
- package/dist/banner/banner.d.ts +34 -0
- package/dist/banner/banner.js +47 -0
- package/dist/banner/index.d.ts +3 -0
- package/dist/banner/index.js +3 -0
- package/dist/breadcrumb/breadcrumb.d.ts +46 -0
- package/dist/breadcrumb/breadcrumb.js +46 -0
- package/dist/breadcrumb/breadcrumb.parts.d.ts +6 -0
- package/dist/breadcrumb/breadcrumb.parts.js +9 -0
- package/dist/breadcrumb/index.d.ts +3 -0
- package/dist/breadcrumb/index.js +3 -0
- package/dist/button/button.d.ts +3 -2
- package/dist/card/card.d.ts +9 -2
- package/dist/chip-group/chip-group.client.d.ts +88 -0
- package/dist/chip-group/chip-group.client.js +157 -0
- package/dist/chip-group/index.d.ts +2 -0
- package/dist/chip-group/index.js +1 -0
- package/dist/choice-card/choice-card.client.d.ts +66 -0
- package/dist/choice-card/choice-card.client.js +138 -0
- package/dist/choice-card/index.d.ts +2 -0
- package/dist/choice-card/index.js +1 -0
- package/dist/config/config.client.d.ts +16 -1
- package/dist/config/config.client.js +18 -3
- package/dist/config/index.d.ts +2 -2
- package/dist/contracts/index.d.ts +1 -1
- package/dist/css/app-shell.css +2 -0
- package/dist/css/avatar.css +2 -0
- package/dist/css/banner.css +2 -0
- package/dist/css/base.css +1 -1
- package/dist/css/breadcrumb.css +2 -0
- package/dist/css/card.css +1 -1
- package/dist/css/chip-group.css +2 -0
- package/dist/css/choice-card.css +2 -0
- package/dist/css/delta.css +1 -1
- package/dist/css/drawer.css +2 -0
- package/dist/css/file-upload.css +2 -0
- package/dist/css/form.css +2 -0
- package/dist/css/heading.css +1 -1
- package/dist/css/kpi-tile.css +2 -0
- package/dist/css/metric.css +2 -0
- package/dist/css/mobile-tab-bar.css +2 -0
- package/dist/css/mobile-top-bar.css +2 -0
- package/dist/css/motion.css +2 -0
- package/dist/css/nav-item.css +2 -0
- package/dist/css/number-value.css +2 -0
- package/dist/css/page-header.css +2 -0
- package/dist/css/pagination.css +2 -0
- package/dist/css/password-input.css +2 -0
- package/dist/css/popover.css +2 -0
- package/dist/css/ranked-list.css +2 -0
- package/dist/css/search-field.css +2 -0
- package/dist/css/sidebar.css +2 -0
- package/dist/css/split.css +2 -0
- package/dist/css/sticky-bar.css +2 -0
- package/dist/css/table-selection.css +2 -0
- package/dist/css/table.css +2 -0
- package/dist/css/text.css +1 -1
- package/dist/css/toast.css +2 -0
- package/dist/css/top-bar.css +2 -0
- package/dist/css/trend-card.css +2 -0
- package/dist/dialog/dialog.client.d.ts +1 -1
- package/dist/dialog/dialog.client.js +15 -37
- package/dist/drawer/drawer.client.d.ts +25 -0
- package/dist/drawer/drawer.client.js +154 -0
- package/dist/drawer/drawer.contract.d.ts +98 -0
- package/dist/drawer/drawer.parts.d.ts +6 -0
- package/dist/drawer/drawer.parts.js +16 -0
- package/dist/drawer/index.d.ts +5 -0
- package/dist/drawer/index.js +3 -0
- package/dist/field/field-scope.client.js +9 -2
- package/dist/file-upload/file-upload.client.d.ts +9 -0
- package/dist/file-upload/file-upload.client.js +406 -0
- package/dist/file-upload/file-upload.contract.d.ts +112 -0
- package/dist/file-upload/index.d.ts +3 -0
- package/dist/file-upload/index.js +1 -0
- package/dist/file-upload/seam.d.ts +1 -0
- package/dist/form/form.client.d.ts +38 -0
- package/dist/form/form.client.js +127 -0
- package/dist/form/form.d.ts +36 -0
- package/dist/form/form.js +29 -0
- package/dist/form/index.d.ts +4 -0
- package/dist/form/index.js +4 -0
- package/dist/form/submit-button.client.d.ts +20 -0
- package/dist/form/submit-button.client.js +19 -0
- package/dist/heading/heading.d.ts +4 -1
- package/dist/i18n/format-label.d.ts +24 -0
- package/dist/i18n/format-label.js +19 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +1 -0
- package/dist/icon-button/icon-button.client.js +1 -1
- package/dist/icon-button/icon-button.js +1 -1
- package/dist/index.d.ts +84 -5
- package/dist/index.js +49 -4
- package/dist/kpi-tile/index.d.ts +2 -0
- package/dist/kpi-tile/index.js +1 -0
- package/dist/kpi-tile/kpi-tile.d.ts +30 -0
- package/dist/kpi-tile/kpi-tile.js +48 -0
- package/dist/locales/en-US.d.ts +77 -0
- package/dist/locales/en-US.js +83 -0
- package/dist/menu/menu.contract.d.ts +1 -1
- package/dist/metric/index.d.ts +2 -0
- package/dist/metric/index.js +1 -0
- package/dist/metric/metric.d.ts +72 -0
- package/dist/metric/metric.js +116 -0
- package/dist/mobile-tab-bar/index.d.ts +4 -0
- package/dist/mobile-tab-bar/index.js +4 -0
- package/dist/mobile-tab-bar/mobile-tab-bar-inset.client.js +38 -0
- package/dist/mobile-tab-bar/mobile-tab-bar-more.client.d.ts +26 -0
- package/dist/mobile-tab-bar/mobile-tab-bar-more.client.js +60 -0
- package/dist/mobile-tab-bar/mobile-tab-bar.d.ts +39 -0
- package/dist/mobile-tab-bar/mobile-tab-bar.js +54 -0
- package/dist/mobile-tab-bar/mobile-tab-bar.parts.d.ts +6 -0
- package/dist/mobile-tab-bar/mobile-tab-bar.parts.js +9 -0
- package/dist/mobile-top-bar/index.d.ts +2 -0
- package/dist/mobile-top-bar/index.js +1 -0
- package/dist/mobile-top-bar/mobile-top-bar.d.ts +17 -0
- package/dist/mobile-top-bar/mobile-top-bar.js +31 -0
- package/dist/motion/count-up.client.d.ts +39 -0
- package/dist/motion/count-up.client.js +109 -0
- package/dist/motion/index.d.ts +2 -0
- package/dist/motion/index.js +1 -0
- package/dist/nav-item/index.d.ts +2 -0
- package/dist/nav-item/index.js +1 -0
- package/dist/nav-item/nav-item.d.ts +35 -0
- package/dist/nav-item/nav-item.js +50 -0
- package/dist/number-value/index.d.ts +2 -0
- package/dist/number-value/index.js +1 -0
- package/dist/number-value/number-value.d.ts +25 -0
- package/dist/number-value/number-value.js +26 -0
- package/dist/page-header/index.d.ts +2 -0
- package/dist/page-header/index.js +1 -0
- package/dist/page-header/page-header.d.ts +19 -0
- package/dist/page-header/page-header.js +39 -0
- package/dist/pagination/index.d.ts +2 -0
- package/dist/pagination/index.js +1 -0
- package/dist/pagination/pagination.d.ts +74 -0
- package/dist/pagination/pagination.js +136 -0
- package/dist/password-input/index.d.ts +2 -0
- package/dist/password-input/index.js +1 -0
- package/dist/password-input/password-input.client.d.ts +52 -0
- package/dist/password-input/password-input.client.js +106 -0
- package/dist/popover/index.d.ts +5 -0
- package/dist/popover/index.js +3 -0
- package/dist/popover/popover.client.d.ts +20 -0
- package/dist/popover/popover.client.js +113 -0
- package/dist/popover/popover.contract.d.ts +88 -0
- package/dist/popover/popover.parts.d.ts +6 -0
- package/dist/popover/popover.parts.js +13 -0
- package/dist/ranked-list/index.d.ts +3 -0
- package/dist/ranked-list/index.js +3 -0
- package/dist/ranked-list/ranked-list.d.ts +85 -0
- package/dist/ranked-list/ranked-list.js +153 -0
- package/dist/ranked-list/ranked-list.parts.d.ts +6 -0
- package/dist/ranked-list/ranked-list.parts.js +10 -0
- package/dist/search-field/index.d.ts +2 -0
- package/dist/search-field/index.js +1 -0
- package/dist/search-field/search-field.client.d.ts +55 -0
- package/dist/search-field/search-field.client.js +136 -0
- package/dist/select/select.contract.d.ts +1 -1
- package/dist/sidebar/index.d.ts +4 -0
- package/dist/sidebar/index.js +4 -0
- package/dist/sidebar/sidebar-item.client.d.ts +10 -0
- package/dist/sidebar/sidebar-item.client.js +55 -0
- package/dist/sidebar/sidebar.d.ts +45 -0
- package/dist/sidebar/sidebar.js +62 -0
- package/dist/sidebar/sidebar.parts.d.ts +6 -0
- package/dist/sidebar/sidebar.parts.js +11 -0
- package/dist/split/index.d.ts +3 -0
- package/dist/split/index.js +3 -0
- package/dist/split/split.d.ts +28 -0
- package/dist/split/split.js +33 -0
- package/dist/split/split.parts.d.ts +6 -0
- package/dist/split/split.parts.js +10 -0
- package/dist/sticky-bar/index.d.ts +2 -0
- package/dist/sticky-bar/index.js +1 -0
- package/dist/sticky-bar/sticky-bar.d.ts +16 -0
- package/dist/sticky-bar/sticky-bar.js +26 -0
- package/dist/styles.css +66 -7
- package/dist/table/index.d.ts +3 -0
- package/dist/table/index.js +3 -0
- package/dist/table/table.d.ts +101 -0
- package/dist/table/table.js +121 -0
- package/dist/table/table.parts.d.ts +6 -0
- package/dist/table/table.parts.js +18 -0
- package/dist/table-selection/index.d.ts +3 -0
- package/dist/table-selection/index.js +3 -0
- package/dist/table-selection/table-selection.client.d.ts +14 -0
- package/dist/table-selection/table-selection.client.js +84 -0
- package/dist/table-selection/table-selection.d.ts +34 -0
- package/dist/table-selection/table-selection.js +50 -0
- package/dist/text/text.d.ts +13 -2
- package/dist/toast/index.d.ts +4 -0
- package/dist/toast/index.js +3 -0
- package/dist/toast/seam.d.ts +2 -0
- package/dist/toast/store.d.ts +19 -0
- package/dist/toast/store.js +136 -0
- package/dist/toast/toast.contract.d.ts +56 -0
- package/dist/toast/toaster.client.d.ts +10 -0
- package/dist/toast/toaster.client.js +305 -0
- package/dist/tooltip/tooltip.contract.d.ts +1 -1
- package/dist/top-bar/index.d.ts +2 -0
- package/dist/top-bar/index.js +1 -0
- package/dist/top-bar/top-bar.d.ts +17 -0
- package/dist/top-bar/top-bar.js +35 -0
- package/dist/trend-card/index.d.ts +2 -0
- package/dist/trend-card/index.js +1 -0
- package/dist/trend-card/trend-card.d.ts +34 -0
- package/dist/trend-card/trend-card.js +74 -0
- package/package.json +167 -4
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { cx } from "../_internal/cx.js";
|
|
2
|
+
import { renderElement } from "../contracts/render.js";
|
|
3
|
+
import { InlineError } from "../inline-error/inline-error.js";
|
|
4
|
+
import { dataStatusAttrs } from "../_internal/data-status.js";
|
|
5
|
+
import { NumberValue } from "../number-value/number-value.js";
|
|
6
|
+
import { Skeleton } from "../skeleton/skeleton.js";
|
|
7
|
+
import { Children, cloneElement, isValidElement, useId } from "react";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/ranked-list/ranked-list.tsx
|
|
10
|
+
/** Percent of the track, 0–100 with up to 3 decimals: deterministic attribute text. */
|
|
11
|
+
function percent(value, max) {
|
|
12
|
+
const ratio = max > 0 && Number.isFinite(value) ? Math.min(1, Math.max(0, value / max)) : 0;
|
|
13
|
+
return `${Number((ratio * 100).toFixed(3))}%`;
|
|
14
|
+
}
|
|
15
|
+
function Bar({ width }) {
|
|
16
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
17
|
+
className: "nz-ranked-list-bar",
|
|
18
|
+
"data-slot": "ranked-list-bar",
|
|
19
|
+
width: "100%",
|
|
20
|
+
height: "100%",
|
|
21
|
+
"aria-hidden": "true",
|
|
22
|
+
focusable: "false",
|
|
23
|
+
children: /* @__PURE__ */ jsx("rect", {
|
|
24
|
+
className: "nz-ranked-list-fill",
|
|
25
|
+
width,
|
|
26
|
+
height: "100%",
|
|
27
|
+
rx: "3"
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** `template` with `{label}` replaced by the title node, or dropped when there is no title. */
|
|
32
|
+
function fill(template, title) {
|
|
33
|
+
const at = template.indexOf("{label}");
|
|
34
|
+
if (at < 0) return template;
|
|
35
|
+
const before = template.slice(0, at);
|
|
36
|
+
const after = template.slice(at + 7);
|
|
37
|
+
if (title == null) return `${before.trimEnd()}${after.trimStart()}`.trim();
|
|
38
|
+
if (typeof title === "string" || typeof title === "number") return `${before}${title}${after}`;
|
|
39
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
40
|
+
before,
|
|
41
|
+
title,
|
|
42
|
+
after
|
|
43
|
+
] });
|
|
44
|
+
}
|
|
45
|
+
/** A row of the ready geometry with no content, for loading and for the reserved height. */
|
|
46
|
+
function PlaceholderRow({ skeleton }) {
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
48
|
+
className: "nz-ranked-list-placeholder",
|
|
49
|
+
"data-slot": "ranked-list-placeholder",
|
|
50
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
51
|
+
className: "nz-ranked-list-row",
|
|
52
|
+
children: [skeleton && /* @__PURE__ */ jsx(Skeleton, { className: "nz-ranked-list-skeleton-label" }), skeleton && /* @__PURE__ */ jsx(Skeleton, { className: "nz-ranked-list-skeleton-value" })]
|
|
53
|
+
}), /* @__PURE__ */ jsx("span", { className: "nz-ranked-list-track" })]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function RankedListRoot({ title, titleLevel = 3, action, max, format, locale, status = "ready", pending = false, empty, error, rows = 5, labels, render, className, children, ...rest }) {
|
|
57
|
+
const titleId = `${useId()}-title`;
|
|
58
|
+
const items = Children.toArray(children);
|
|
59
|
+
const ranked = items.filter((child) => isValidElement(child) && child.type === RankedListItem);
|
|
60
|
+
const resolved = status === "ready" && items.length === 0 ? "empty" : status;
|
|
61
|
+
const leader = max ?? Math.max(0, ...ranked.map((item) => item.props.value));
|
|
62
|
+
const reserve = Array.from({ length: Math.max(0, Math.floor(rows)) }, (_, index) => index);
|
|
63
|
+
const Heading = `h${titleLevel}`;
|
|
64
|
+
let body;
|
|
65
|
+
if (resolved === "ready") body = /* @__PURE__ */ jsx("ol", {
|
|
66
|
+
className: "nz-ranked-list-list",
|
|
67
|
+
"data-slot": "ranked-list-list",
|
|
68
|
+
"aria-labelledby": title != null ? titleId : void 0,
|
|
69
|
+
children: items.map((child) => isValidElement(child) && child.type === RankedListItem ? cloneElement(child, {
|
|
70
|
+
max: child.props.max ?? leader,
|
|
71
|
+
format: child.props.format ?? format,
|
|
72
|
+
locale: child.props.locale ?? locale
|
|
73
|
+
}) : child)
|
|
74
|
+
});
|
|
75
|
+
else {
|
|
76
|
+
const message = resolved === "loading" ? /* @__PURE__ */ jsx("span", {
|
|
77
|
+
className: "nz-visually-hidden",
|
|
78
|
+
children: fill(labels?.loading ?? "Loading {label}", title)
|
|
79
|
+
}) : resolved === "error" ? error ?? /* @__PURE__ */ jsx(InlineError, { children: fill(labels?.error ?? "Could not load {label}", title) }) : empty ?? /* @__PURE__ */ jsx("p", {
|
|
80
|
+
className: "nz-ranked-list-empty",
|
|
81
|
+
children: fill(labels?.empty ?? "No data", title)
|
|
82
|
+
});
|
|
83
|
+
body = /* @__PURE__ */ jsxs("div", {
|
|
84
|
+
className: "nz-ranked-list-status",
|
|
85
|
+
"data-slot": "ranked-list-status",
|
|
86
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
87
|
+
className: "nz-ranked-list-reserve",
|
|
88
|
+
"aria-hidden": "true",
|
|
89
|
+
children: reserve.map((index) => /* @__PURE__ */ jsx(PlaceholderRow, { skeleton: resolved === "loading" }, index))
|
|
90
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
91
|
+
className: "nz-ranked-list-message",
|
|
92
|
+
"data-slot": "ranked-list-message",
|
|
93
|
+
children: message
|
|
94
|
+
})]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const busy = resolved === "ready" && pending;
|
|
98
|
+
return renderElement("div", render, {
|
|
99
|
+
status: resolved,
|
|
100
|
+
pending: busy
|
|
101
|
+
}, {
|
|
102
|
+
"data-slot": "ranked-list",
|
|
103
|
+
...dataStatusAttrs(resolved, busy),
|
|
104
|
+
...rest,
|
|
105
|
+
className: cx("nz-card", "nz-ranked-list", className),
|
|
106
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [(title != null || action != null) && /* @__PURE__ */ jsxs("div", {
|
|
107
|
+
className: "nz-ranked-list-header",
|
|
108
|
+
"data-slot": "ranked-list-header",
|
|
109
|
+
children: [title != null && /* @__PURE__ */ jsx(Heading, {
|
|
110
|
+
className: "nz-ranked-list-title",
|
|
111
|
+
"data-slot": "ranked-list-title",
|
|
112
|
+
id: titleId,
|
|
113
|
+
children: title
|
|
114
|
+
}), action]
|
|
115
|
+
}), body] })
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function RankedListItem({ label, value, max, format, locale = "en-US", render, className, ...rest }) {
|
|
119
|
+
const width = percent(value, max ?? value);
|
|
120
|
+
const ratio = Number.parseFloat(width) / 100;
|
|
121
|
+
return renderElement("li", render, { ratio }, {
|
|
122
|
+
"data-slot": "ranked-list-item",
|
|
123
|
+
...rest,
|
|
124
|
+
className: cx("nz-ranked-list-item", className),
|
|
125
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
|
|
126
|
+
className: "nz-ranked-list-row",
|
|
127
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
128
|
+
className: "nz-ranked-list-label",
|
|
129
|
+
"data-slot": "ranked-list-label",
|
|
130
|
+
children: label
|
|
131
|
+
}), /* @__PURE__ */ jsx(NumberValue, {
|
|
132
|
+
className: "nz-ranked-list-value",
|
|
133
|
+
value,
|
|
134
|
+
format: format ?? {},
|
|
135
|
+
locale
|
|
136
|
+
})]
|
|
137
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
138
|
+
className: "nz-ranked-list-track",
|
|
139
|
+
"data-slot": "ranked-list-track",
|
|
140
|
+
children: /* @__PURE__ */ jsx(Bar, { width })
|
|
141
|
+
})] })
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/** "View all": a real link, at least 24 px tall (WCAG 2.5.8; figma/04 issue 7). */
|
|
145
|
+
function RankedListAction({ render, className, ...rest }) {
|
|
146
|
+
return renderElement("a", render, {}, {
|
|
147
|
+
"data-slot": "ranked-list-action",
|
|
148
|
+
...rest,
|
|
149
|
+
className: cx("nz-ranked-list-action", className)
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { RankedListAction, RankedListItem, RankedListRoot };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RankedListAction, RankedListItem, RankedListRoot } from "./ranked-list.js";
|
|
2
|
+
declare namespace ranked_list_parts_d_exports {
|
|
3
|
+
export { RankedListAction as Action, RankedListItem as Item, RankedListRoot as Root };
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
export { RankedListAction as Action, RankedListItem as Item, RankedListRoot as Root, ranked_list_parts_d_exports };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { RankedListAction, RankedListItem, RankedListRoot } from "./ranked-list.js";
|
|
3
|
+
//#region src/ranked-list/ranked-list.parts.ts
|
|
4
|
+
var ranked_list_parts_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
Action: () => RankedListAction,
|
|
6
|
+
Item: () => RankedListItem,
|
|
7
|
+
Root: () => RankedListRoot
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { RankedListAction as Action, RankedListItem as Item, RankedListRoot as Root, ranked_list_parts_exports };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SearchField } from "./search-field.client.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { RenderProp } from "../contracts/render.js";
|
|
2
|
+
import { ControlSize } from "../augment.js";
|
|
3
|
+
import { ComponentPropsWithRef, JSX, ReactNode } from "react";
|
|
4
|
+
//#region src/search-field/search-field.client.d.ts
|
|
5
|
+
/** SearchField's own strings (§16.4): serialisable, English defaults. */
|
|
6
|
+
export interface SearchFieldLabels {
|
|
7
|
+
/**
|
|
8
|
+
* The input's name when nothing else names it: no Field, `aria-label` or `aria-labelledby`. The
|
|
9
|
+
* placeholder is not a label. @default 'Search'
|
|
10
|
+
*/
|
|
11
|
+
label: string;
|
|
12
|
+
/** The clear button's name. @default 'Clear search' */
|
|
13
|
+
clear: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SearchFieldState {
|
|
16
|
+
size: ControlSize;
|
|
17
|
+
/** An error message is presented (the Field's, or the `invalid` prop). */
|
|
18
|
+
invalid: boolean;
|
|
19
|
+
disabled: boolean;
|
|
20
|
+
readOnly: boolean;
|
|
21
|
+
pending: boolean;
|
|
22
|
+
/** The input has a value, so the clear button shows. */
|
|
23
|
+
filled: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface SearchFieldProps extends Omit<ComponentPropsWithRef<"input">, "type" | "size" | "prefix" | "children"> {
|
|
26
|
+
/** 32 / 40 / 48 px, as Input, Button and Select (Figma's 42 is off the scale). @default 'md' */
|
|
27
|
+
size?: ControlSize;
|
|
28
|
+
/**
|
|
29
|
+
* An error message is presented for this field (§8.3). Inside a Field, the Field sets it; an
|
|
30
|
+
* explicit value here wins.
|
|
31
|
+
*/
|
|
32
|
+
invalid?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* A keyboard shortcut such as `"mod+k"`, drawn at the end of the field with `Kbd` (⌘K on Apple
|
|
35
|
+
* platforms, Ctrl+K elsewhere) and announced through `aria-keyshortcuts`. The app binds the key
|
|
36
|
+
* itself (focus the field through its `ref`), as with IconButton's `shortcut`; hidden while the
|
|
37
|
+
* field has a value.
|
|
38
|
+
*/
|
|
39
|
+
shortcut?: string;
|
|
40
|
+
/** Replaces the magnifier before the value (decorative, 16 px). */
|
|
41
|
+
icon?: ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Results are on their way: the magnifier becomes a spinner and the root carries `data-pending`.
|
|
44
|
+
* Announce the outcome (the number of results) where the results are. @default false
|
|
45
|
+
*/
|
|
46
|
+
pending?: boolean;
|
|
47
|
+
labels?: Partial<SearchFieldLabels>;
|
|
48
|
+
/**
|
|
49
|
+
* Composition of the root, the `<search>` box around the native `<input>`. `className` and
|
|
50
|
+
* `style` go on the root too; every other prop, `ref` included, goes on the `<input>`.
|
|
51
|
+
*/
|
|
52
|
+
render?: RenderProp<SearchFieldState>;
|
|
53
|
+
}
|
|
54
|
+
export declare function SearchField({ size, id, name, required, disabled, readOnly, invalid, "aria-invalid": ariaInvalid, "aria-describedby": describedBy, shortcut, icon, pending, labels: labelsProp, render, className, style, ...rest }: SearchFieldProps): JSX.Element;
|
|
55
|
+
//#endregion
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../_internal/cx.js";
|
|
3
|
+
import { mergeProps } from "../contracts/merge-props.js";
|
|
4
|
+
import { renderElement } from "../contracts/render.js";
|
|
5
|
+
import { useLabels } from "../config/config.client.js";
|
|
6
|
+
import { CloseGlyph, SearchGlyph, SpinnerGlyph } from "../_internal/glyphs.js";
|
|
7
|
+
import { stateAttrs } from "../contracts/state.js";
|
|
8
|
+
import { useFieldControl } from "../field/field-scope.client.js";
|
|
9
|
+
import { ariaKeyShortcuts } from "../_internal/keys.js";
|
|
10
|
+
import { Kbd } from "../kbd/kbd.js";
|
|
11
|
+
import { useEffect, useRef, useState } from "react";
|
|
12
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
//#region src/search-field/search-field.client.tsx
|
|
14
|
+
function hasText(value) {
|
|
15
|
+
return value != null && String(value) !== "";
|
|
16
|
+
}
|
|
17
|
+
/** The native value setter, so React sees the change, then the `input` event a user's edit fires. */
|
|
18
|
+
function clearInput(input) {
|
|
19
|
+
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(input, "");
|
|
20
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
21
|
+
}
|
|
22
|
+
function SearchField({ size = "md", id, name, required, disabled, readOnly, invalid, "aria-invalid": ariaInvalid, "aria-describedby": describedBy, shortcut, icon, pending = false, labels: labelsProp, render, className, style, ...rest }) {
|
|
23
|
+
const labels = useLabels("searchField", labelsProp);
|
|
24
|
+
const field = useFieldControl({
|
|
25
|
+
id,
|
|
26
|
+
name,
|
|
27
|
+
required,
|
|
28
|
+
disabled,
|
|
29
|
+
readOnly,
|
|
30
|
+
invalid: invalid ?? (ariaInvalid === true || ariaInvalid === "true" ? true : void 0),
|
|
31
|
+
"aria-describedby": describedBy
|
|
32
|
+
});
|
|
33
|
+
const input = useRef(null);
|
|
34
|
+
const [typed, setTyped] = useState(() => hasText(rest.defaultValue));
|
|
35
|
+
const filled = rest.value === void 0 ? typed : hasText(rest.value);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const form = input.current?.form;
|
|
38
|
+
if (form == null) return void 0;
|
|
39
|
+
let timer;
|
|
40
|
+
const onReset = () => {
|
|
41
|
+
timer = setTimeout(() => setTyped((input.current?.value ?? "") !== ""), 0);
|
|
42
|
+
};
|
|
43
|
+
form.addEventListener("reset", onReset);
|
|
44
|
+
return () => {
|
|
45
|
+
form.removeEventListener("reset", onReset);
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
const unnamed = !field.inField && rest["aria-label"] === void 0 && rest["aria-labelledby"] === void 0;
|
|
50
|
+
const editable = !field.disabled && !field.readOnly;
|
|
51
|
+
const own = {
|
|
52
|
+
...field.controlProps,
|
|
53
|
+
ref: input,
|
|
54
|
+
"aria-label": unnamed ? labels?.label ?? "Search" : void 0,
|
|
55
|
+
"aria-keyshortcuts": shortcut === void 0 ? void 0 : ariaKeyShortcuts(shortcut),
|
|
56
|
+
onChange(event) {
|
|
57
|
+
setTyped(event.currentTarget.value !== "");
|
|
58
|
+
},
|
|
59
|
+
onKeyDown(event) {
|
|
60
|
+
const target = event.currentTarget;
|
|
61
|
+
if (event.key !== "Escape" || target.value === "" || target.readOnly) return;
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
event.stopPropagation();
|
|
64
|
+
clearInput(target);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const state = {
|
|
68
|
+
size,
|
|
69
|
+
invalid: field.invalid,
|
|
70
|
+
disabled: field.disabled,
|
|
71
|
+
readOnly: field.readOnly,
|
|
72
|
+
pending,
|
|
73
|
+
filled
|
|
74
|
+
};
|
|
75
|
+
return renderElement("search", render, state, {
|
|
76
|
+
"data-slot": "search-field",
|
|
77
|
+
"data-size": size,
|
|
78
|
+
...stateAttrs({
|
|
79
|
+
invalid: state.invalid,
|
|
80
|
+
disabled: state.disabled,
|
|
81
|
+
readOnly: state.readOnly,
|
|
82
|
+
pending
|
|
83
|
+
}),
|
|
84
|
+
className: cx("nz-search-field", className),
|
|
85
|
+
style,
|
|
86
|
+
onMouseDown: focusInput,
|
|
87
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
88
|
+
/* @__PURE__ */ jsx("span", {
|
|
89
|
+
className: "nz-search-field-icon",
|
|
90
|
+
"data-slot": "search-field-icon",
|
|
91
|
+
"aria-hidden": "true",
|
|
92
|
+
children: pending ? /* @__PURE__ */ jsx(SpinnerGlyph, {}) : icon ?? /* @__PURE__ */ jsx(SearchGlyph, {})
|
|
93
|
+
}),
|
|
94
|
+
/* @__PURE__ */ jsx("input", {
|
|
95
|
+
...mergeProps(own, rest),
|
|
96
|
+
type: "search",
|
|
97
|
+
className: "nz-search-field-control",
|
|
98
|
+
"data-slot": "search-field-control"
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ jsx("button", {
|
|
101
|
+
type: "button",
|
|
102
|
+
className: "nz-search-field-clear",
|
|
103
|
+
"data-slot": "search-field-clear",
|
|
104
|
+
"aria-label": labels?.clear ?? "Clear search",
|
|
105
|
+
tabIndex: -1,
|
|
106
|
+
hidden: !filled || !editable,
|
|
107
|
+
onClick: clearAndFocus,
|
|
108
|
+
children: /* @__PURE__ */ jsx(CloseGlyph, {})
|
|
109
|
+
}),
|
|
110
|
+
shortcut !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
111
|
+
className: "nz-search-field-shortcut",
|
|
112
|
+
"data-slot": "search-field-shortcut",
|
|
113
|
+
"aria-hidden": "true",
|
|
114
|
+
hidden: filled,
|
|
115
|
+
children: /* @__PURE__ */ jsx(Kbd, { keys: shortcut })
|
|
116
|
+
})
|
|
117
|
+
] })
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function control(root) {
|
|
121
|
+
return root?.querySelector(":scope > .nz-search-field-control") ?? null;
|
|
122
|
+
}
|
|
123
|
+
function focusInput(event) {
|
|
124
|
+
const input = control(event.currentTarget);
|
|
125
|
+
if (input === null || event.target === input || input.disabled) return;
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
input.focus();
|
|
128
|
+
}
|
|
129
|
+
function clearAndFocus(event) {
|
|
130
|
+
const input = control(event.currentTarget.parentElement);
|
|
131
|
+
if (input === null) return;
|
|
132
|
+
clearInput(input);
|
|
133
|
+
input.focus();
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { SearchField };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RenderProp } from "../contracts/render.js";
|
|
2
2
|
import { ControlSize } from "../augment.js";
|
|
3
3
|
import { ChangeDetails, OpenReason } from "../contracts/details.js";
|
|
4
|
-
import { Align, Side } from "../contracts/state.js";
|
|
5
4
|
import "../_internal/engine-part.js";
|
|
5
|
+
import { Align, Side } from "../contracts/state.js";
|
|
6
6
|
import { CSSProperties, ComponentPropsWithRef, ReactElement, ReactNode } from "react";
|
|
7
7
|
//#region src/select/select.contract.d.ts
|
|
8
8
|
export type SelectValueReason = "item-press" | "keyboard" | "typeahead" | "form-reset";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SidebarContent, SidebarContentProps, SidebarFooter, SidebarFooterProps, SidebarHeader, SidebarHeaderProps, SidebarLabels, SidebarRoot, SidebarRootProps } from "./sidebar.js";
|
|
2
|
+
import { SidebarItem, SidebarItemProps } from "./sidebar-item.client.js";
|
|
3
|
+
import { sidebar_parts_d_exports } from "./sidebar.parts.js";
|
|
4
|
+
export { sidebar_parts_d_exports as Sidebar, SidebarContent, type SidebarContentProps, SidebarFooter, type SidebarFooterProps, SidebarHeader, type SidebarHeaderProps, SidebarItem, type SidebarItemProps, type SidebarLabels, SidebarRoot, type SidebarRootProps };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SidebarContent, SidebarFooter, SidebarHeader, SidebarRoot } from "./sidebar.js";
|
|
2
|
+
import { SidebarItem } from "./sidebar-item.client.js";
|
|
3
|
+
import { sidebar_parts_exports } from "./sidebar.parts.js";
|
|
4
|
+
export { sidebar_parts_exports as Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarRoot };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NavItemProps } from "../nav-item/nav-item.js";
|
|
2
|
+
import { ReactElement } from "react";
|
|
3
|
+
//#region src/sidebar/sidebar-item.client.d.ts
|
|
4
|
+
export type SidebarItemProps = NavItemProps;
|
|
5
|
+
/**
|
|
6
|
+
* A `NavItem` for a Sidebar: the same link, with a Tooltip that names it while the Sidebar is the
|
|
7
|
+
* icon rail (hover after the delay, keyboard focus at once; Escape closes it).
|
|
8
|
+
*/
|
|
9
|
+
export declare function SidebarItem({ className, ref, disabled, ...item }: SidebarItemProps): ReactElement;
|
|
10
|
+
//#endregion
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../_internal/cx.js";
|
|
3
|
+
import { TooltipPopup, TooltipRoot, TooltipTrigger } from "../tooltip/tooltip.client.js";
|
|
4
|
+
import { NavItem } from "../nav-item/nav-item.js";
|
|
5
|
+
import { useRef, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/sidebar/sidebar-item.client.tsx
|
|
8
|
+
/** Whether `link`'s label is out of the layout: the rail's visually hidden label is 1 px wide. */
|
|
9
|
+
function inRail(link) {
|
|
10
|
+
const label = link?.querySelector(".nz-nav-item-label");
|
|
11
|
+
return label instanceof HTMLElement && label.getBoundingClientRect().width <= 1;
|
|
12
|
+
}
|
|
13
|
+
/** Writes `node` to every ref: the Tooltip trigger's (positioning), ours, and the consumer's. */
|
|
14
|
+
function allRefs(...refs) {
|
|
15
|
+
return (node) => {
|
|
16
|
+
for (const ref of refs) if (typeof ref === "function") ref(node);
|
|
17
|
+
else if (typeof ref === "object" && ref !== null && "current" in ref) ref.current = node;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A `NavItem` for a Sidebar: the same link, with a Tooltip that names it while the Sidebar is the
|
|
22
|
+
* icon rail (hover after the delay, keyboard focus at once; Escape closes it).
|
|
23
|
+
*/
|
|
24
|
+
function SidebarItem({ className, ref, disabled, ...item }) {
|
|
25
|
+
const link = useRef(null);
|
|
26
|
+
const [open, setOpen] = useState(false);
|
|
27
|
+
return /* @__PURE__ */ jsxs(TooltipRoot, {
|
|
28
|
+
open,
|
|
29
|
+
onOpenChange: (next) => setOpen(next && inRail(link.current)),
|
|
30
|
+
disabled: disabled === true,
|
|
31
|
+
children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: (props) => /* @__PURE__ */ jsx(NavItem, {
|
|
32
|
+
...item,
|
|
33
|
+
...triggerProps(props),
|
|
34
|
+
...disabled === void 0 ? {} : { disabled },
|
|
35
|
+
"data-slot": "sidebar-item",
|
|
36
|
+
className: cx("nz-sidebar-item", className),
|
|
37
|
+
ref: allRefs(props["ref"], link, ref)
|
|
38
|
+
}) }), /* @__PURE__ */ jsx(TooltipPopup, {
|
|
39
|
+
side: "end",
|
|
40
|
+
children: item.children
|
|
41
|
+
})]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Keeps the trigger's handlers. Drops what would make the DOM differ from NavItem's server path:
|
|
46
|
+
* the trigger's class, slot, `data-open` and `tabIndex` (a link is focusable already), the ref
|
|
47
|
+
* (merged above), and `aria-describedby`: the tooltip repeats the link's name, so describing the link
|
|
48
|
+
* by it would say the label twice.
|
|
49
|
+
*/
|
|
50
|
+
function triggerProps(props) {
|
|
51
|
+
const { className: _class, "data-slot": _slot, "data-open": _open, "aria-describedby": _described, tabIndex: _tabIndex, ref: _ref, type: _type, ...kept } = props;
|
|
52
|
+
return kept;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { SidebarItem };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { RenderProp } from "../contracts/render.js";
|
|
2
|
+
import { ComponentPropsWithRef, ReactElement, ReactNode } from "react";
|
|
3
|
+
//#region src/sidebar/sidebar.d.ts
|
|
4
|
+
type Empty = Record<string, never>;
|
|
5
|
+
/** Strings this part renders (§16.4). */
|
|
6
|
+
export interface SidebarLabels {
|
|
7
|
+
/** The navigation landmark's name. @default 'Primary' */
|
|
8
|
+
nav: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SidebarRootProps extends ComponentPropsWithRef<"nav"> {
|
|
11
|
+
/**
|
|
12
|
+
* Overrides the width the viewport gives: `true` keeps the icon rail and `false` the full sidebar
|
|
13
|
+
* at every width from 640 px, for an app with its own collapse control. Below 640 px the Sidebar
|
|
14
|
+
* is not shown either way. Absent, it follows the viewport.
|
|
15
|
+
*/
|
|
16
|
+
collapsed?: boolean;
|
|
17
|
+
labels?: Partial<SidebarLabels>;
|
|
18
|
+
render?: RenderProp<Empty>;
|
|
19
|
+
}
|
|
20
|
+
export interface SidebarHeaderProps extends Omit<ComponentPropsWithRef<"div">, "title"> {
|
|
21
|
+
/** The store's mark, for example a square `Avatar` (Figma's 32 px Store mark). The rail keeps it. */
|
|
22
|
+
mark?: ReactNode;
|
|
23
|
+
/** The store's name (Figma's Store). In the rail it leaves the layout and stays in the DOM. */
|
|
24
|
+
title?: ReactNode;
|
|
25
|
+
/** A line under the name, such as the store's domain. */
|
|
26
|
+
description?: ReactNode;
|
|
27
|
+
/** A link to the store's home or a store switcher's trigger: `render={<a href="/" />}`. */
|
|
28
|
+
render?: RenderProp<Empty>;
|
|
29
|
+
}
|
|
30
|
+
export interface SidebarContentProps extends ComponentPropsWithRef<"div"> {
|
|
31
|
+
render?: RenderProp<Empty>;
|
|
32
|
+
}
|
|
33
|
+
export interface SidebarFooterProps extends ComponentPropsWithRef<"div"> {
|
|
34
|
+
render?: RenderProp<Empty>;
|
|
35
|
+
}
|
|
36
|
+
/** The `<nav>` landmark around everything in the sidebar. */
|
|
37
|
+
export declare function SidebarRoot({ collapsed, labels, render, className, ...rest }: SidebarRootProps): ReactElement;
|
|
38
|
+
/** The store at the top: its mark, name and a line under it, on a card (Figma's Store Switcher). */
|
|
39
|
+
export declare function SidebarHeader({ mark, title, description, render, className, children, ...rest }: SidebarHeaderProps): ReactElement;
|
|
40
|
+
/** The destinations, `NavItem`s 4 px apart. */
|
|
41
|
+
export declare function SidebarContent({ render, className, ...rest }: SidebarContentProps): ReactElement;
|
|
42
|
+
/** Pushed to the bottom, for Settings (Figma's Spacer frame becomes an auto margin). */
|
|
43
|
+
export declare function SidebarFooter({ render, className, ...rest }: SidebarFooterProps): ReactElement;
|
|
44
|
+
//#endregion
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { cx } from "../_internal/cx.js";
|
|
2
|
+
import { renderElement } from "../contracts/render.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/sidebar/sidebar.tsx
|
|
5
|
+
/** The `<nav>` landmark around everything in the sidebar. */
|
|
6
|
+
function SidebarRoot({ collapsed, labels, render, className, ...rest }) {
|
|
7
|
+
return renderElement("nav", render, {}, {
|
|
8
|
+
"aria-label": labels?.nav ?? "Primary",
|
|
9
|
+
"data-slot": "sidebar",
|
|
10
|
+
"data-collapsed": collapsed === true ? "" : void 0,
|
|
11
|
+
"data-expanded": collapsed === false ? "" : void 0,
|
|
12
|
+
...rest,
|
|
13
|
+
className: cx("nz-sidebar", className)
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** The store at the top: its mark, name and a line under it, on a card (Figma's Store Switcher). */
|
|
17
|
+
function SidebarHeader({ mark, title, description, render, className, children, ...rest }) {
|
|
18
|
+
return renderElement("div", render, {}, {
|
|
19
|
+
"data-slot": "sidebar-header",
|
|
20
|
+
...rest,
|
|
21
|
+
className: cx("nz-sidebar-header", className),
|
|
22
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23
|
+
mark != null && /* @__PURE__ */ jsx("span", {
|
|
24
|
+
className: "nz-sidebar-header-mark",
|
|
25
|
+
"data-slot": "sidebar-header-mark",
|
|
26
|
+
children: mark
|
|
27
|
+
}),
|
|
28
|
+
(title != null || description != null) && /* @__PURE__ */ jsxs("span", {
|
|
29
|
+
className: "nz-sidebar-header-text",
|
|
30
|
+
"data-slot": "sidebar-header-text",
|
|
31
|
+
children: [title != null && /* @__PURE__ */ jsx("span", {
|
|
32
|
+
className: "nz-sidebar-header-title",
|
|
33
|
+
"data-slot": "sidebar-header-title",
|
|
34
|
+
children: title
|
|
35
|
+
}), description != null && /* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: "nz-sidebar-header-description",
|
|
37
|
+
"data-slot": "sidebar-header-description",
|
|
38
|
+
children: description
|
|
39
|
+
})]
|
|
40
|
+
}),
|
|
41
|
+
children
|
|
42
|
+
] })
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/** The destinations, `NavItem`s 4 px apart. */
|
|
46
|
+
function SidebarContent({ render, className, ...rest }) {
|
|
47
|
+
return renderElement("div", render, {}, {
|
|
48
|
+
"data-slot": "sidebar-content",
|
|
49
|
+
...rest,
|
|
50
|
+
className: cx("nz-sidebar-content", className)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Pushed to the bottom, for Settings (Figma's Spacer frame becomes an auto margin). */
|
|
54
|
+
function SidebarFooter({ render, className, ...rest }) {
|
|
55
|
+
return renderElement("div", render, {}, {
|
|
56
|
+
"data-slot": "sidebar-footer",
|
|
57
|
+
...rest,
|
|
58
|
+
className: cx("nz-sidebar-footer", className)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { SidebarContent, SidebarFooter, SidebarHeader, SidebarRoot };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SidebarContent, SidebarFooter, SidebarHeader, SidebarRoot } from "./sidebar.js";
|
|
2
|
+
declare namespace sidebar_parts_d_exports {
|
|
3
|
+
export { SidebarContent as Content, SidebarFooter as Footer, SidebarHeader as Header, SidebarRoot as Root };
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
export { SidebarContent as Content, SidebarFooter as Footer, SidebarHeader as Header, SidebarRoot as Root, sidebar_parts_d_exports };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { SidebarContent, SidebarFooter, SidebarHeader, SidebarRoot } from "./sidebar.js";
|
|
3
|
+
//#region src/sidebar/sidebar.parts.ts
|
|
4
|
+
var sidebar_parts_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
Content: () => SidebarContent,
|
|
6
|
+
Footer: () => SidebarFooter,
|
|
7
|
+
Header: () => SidebarHeader,
|
|
8
|
+
Root: () => SidebarRoot
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SidebarContent as Content, SidebarFooter as Footer, SidebarHeader as Header, SidebarRoot as Root, sidebar_parts_exports };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SplitAside, SplitAsideProps, SplitAsideWidth, SplitMain, SplitMainProps, SplitRoot, SplitRootProps } from "./split.js";
|
|
2
|
+
import { split_parts_d_exports } from "./split.parts.js";
|
|
3
|
+
export { split_parts_d_exports as Split, SplitAside, type SplitAsideProps, type SplitAsideWidth, SplitMain, type SplitMainProps, SplitRoot, type SplitRootProps };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RenderProp } from "../contracts/render.js";
|
|
2
|
+
import { ComponentPropsWithRef, ReactElement } from "react";
|
|
3
|
+
//#region src/split/split.d.ts
|
|
4
|
+
type Empty = Record<string, never>;
|
|
5
|
+
/** `wide` is 08's 360 px aside (the 8 + 4 split); `narrow` its 232 px Settings nav column. */
|
|
6
|
+
export type SplitAsideWidth = "narrow" | "wide";
|
|
7
|
+
export interface SplitRootProps extends ComponentPropsWithRef<"div"> {
|
|
8
|
+
/** The aside's width while the columns sit side by side. @default 'wide' */
|
|
9
|
+
aside?: SplitAsideWidth;
|
|
10
|
+
render?: RenderProp<Empty>;
|
|
11
|
+
}
|
|
12
|
+
export interface SplitMainProps extends ComponentPropsWithRef<"div"> {
|
|
13
|
+
render?: RenderProp<Empty>;
|
|
14
|
+
}
|
|
15
|
+
export interface SplitAsideProps extends ComponentPropsWithRef<"div"> {
|
|
16
|
+
render?: RenderProp<Empty>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The row. Put `Split.Main` and `Split.Aside` in reading order: the aside after the main column (an
|
|
20
|
+
* Overview's side panel), or first (a Settings page's section nav). They stack in that order.
|
|
21
|
+
*/
|
|
22
|
+
export declare function SplitRoot({ aside, render, className, ...rest }: SplitRootProps): ReactElement;
|
|
23
|
+
/** The main column: it takes the rest of the row. */
|
|
24
|
+
export declare function SplitMain({ render, className, ...rest }: SplitMainProps): ReactElement;
|
|
25
|
+
/** The side column, `aside` wide; pass `render={<aside />}` for complementary content. */
|
|
26
|
+
export declare function SplitAside({ render, className, ...rest }: SplitAsideProps): ReactElement;
|
|
27
|
+
//#endregion
|
|
28
|
+
export {};
|