@glyphui/ui 0.2.0 → 0.4.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/README.md +65 -12
- package/dist/chart.d.ts +202 -0
- package/dist/chart.js +466 -0
- package/dist/color-mode-script-Bf7LYkOj.js +13 -0
- package/dist/color-mode-script-KdwItKN2.d.ts +16 -0
- package/dist/data-table.js +3 -2
- package/dist/{field-CCecIzdq.js → field-CVbywksE.js} +21 -5
- package/dist/{field-context-B6WOcK5m.js → field-context-7I-cWvvS.js} +3 -57
- package/dist/form.d.ts +11 -4
- package/dist/form.js +34 -8
- package/dist/glyph-context-DxGJrdvr.d.ts +50 -0
- package/dist/{index-BWK4czIG.d.ts → index-Bi7rZ6ba.d.ts} +11 -0
- package/dist/index.d.ts +2334 -283
- package/dist/index.js +2952 -326
- package/dist/react-router.d.ts +18 -0
- package/dist/react-router.js +44 -0
- package/dist/{states-Rp8wZ_jH.js → states-IvhjBgna.js} +2 -1
- package/dist/tv-DLbT66dC.js +70 -0
- package/dist/vite.d.ts +27 -0
- package/dist/vite.js +29 -0
- package/fonts.css +10 -0
- package/package.json +47 -5
- package/src/components/accordion/accordion.styles.ts +4 -4
- package/src/components/badge/badge.styles.ts +11 -16
- package/src/components/banner/banner.styles.ts +4 -4
- package/src/components/button/button.styles.ts +3 -1
- package/src/components/calendar/calendar.styles.ts +51 -0
- package/src/components/calendar/calendar.tsx +84 -0
- package/src/components/calendar/index.ts +3 -0
- package/src/components/carousel/carousel.styles.ts +43 -0
- package/src/components/carousel/carousel.tsx +278 -0
- package/src/components/carousel/index.ts +13 -0
- package/src/components/collapsible/collapsible.tsx +66 -0
- package/src/components/collapsible/index.ts +6 -0
- package/src/components/context-menu/context-menu.styles.ts +19 -0
- package/src/components/context-menu/context-menu.tsx +226 -0
- package/src/components/context-menu/index.ts +19 -0
- package/src/components/copy-button/copy-button.tsx +117 -0
- package/src/components/copy-button/index.ts +1 -0
- package/src/components/date-picker/date-picker.styles.ts +42 -0
- package/src/components/date-picker/date-picker.tsx +322 -0
- package/src/components/date-picker/index.ts +8 -0
- package/src/components/dropdown-menu/dropdown-menu.styles.ts +2 -2
- package/src/components/eyebrow/eyebrow.styles.ts +1 -1
- package/src/components/field/field-context.ts +2 -0
- package/src/components/field/field.styles.ts +4 -2
- package/src/components/field/field.tsx +25 -4
- package/src/components/file-upload/file-upload.styles.ts +43 -0
- package/src/components/file-upload/file-upload.tsx +343 -0
- package/src/components/file-upload/index.ts +10 -0
- package/src/components/hover-card/hover-card.tsx +41 -0
- package/src/components/hover-card/index.ts +1 -0
- package/src/components/input-otp/index.ts +10 -0
- package/src/components/input-otp/input-otp.styles.ts +38 -0
- package/src/components/input-otp/input-otp.tsx +116 -0
- package/src/components/link/link.styles.ts +1 -1
- package/src/components/modal/index.ts +2 -0
- package/src/components/modal/modal.styles.ts +20 -0
- package/src/components/modal/modal.tsx +111 -0
- package/src/components/navigation-menu/index.ts +14 -0
- package/src/components/navigation-menu/navigation-menu.styles.ts +48 -0
- package/src/components/navigation-menu/navigation-menu.tsx +208 -0
- package/src/components/number-input/index.ts +2 -0
- package/src/components/number-input/number-input.styles.ts +41 -0
- package/src/components/number-input/number-input.tsx +211 -0
- package/src/components/password-input/index.ts +7 -0
- package/src/components/password-input/password-input.styles.ts +30 -0
- package/src/components/password-input/password-input.tsx +127 -0
- package/src/components/prose/prose.tsx +1 -1
- package/src/components/resizable/index.ts +9 -0
- package/src/components/resizable/resizable.styles.ts +28 -0
- package/src/components/resizable/resizable.tsx +69 -0
- package/src/components/scroll-area/scroll-area.tsx +23 -1
- package/src/components/segmented-control/segmented-control.tsx +17 -2
- package/src/components/sheet/sheet.styles.ts +7 -7
- package/src/components/slider/slider.tsx +9 -2
- package/src/components/stepper/index.ts +2 -0
- package/src/components/stepper/stepper.styles.ts +74 -0
- package/src/components/stepper/stepper.tsx +138 -0
- package/src/components/tag-input/index.ts +2 -0
- package/src/components/tag-input/tag-input.styles.ts +39 -0
- package/src/components/tag-input/tag-input.tsx +198 -0
- package/src/components/text/text.styles.ts +4 -4
- package/src/components/timeline/index.ts +8 -0
- package/src/components/timeline/timeline.styles.ts +56 -0
- package/src/components/timeline/timeline.tsx +91 -0
- package/src/components/toggle/index.ts +9 -0
- package/src/components/toggle/toggle.styles.ts +39 -0
- package/src/components/toggle/toggle.tsx +61 -0
- package/src/components/tree-view/index.ts +2 -0
- package/src/components/tree-view/tree-view.styles.ts +42 -0
- package/src/components/tree-view/tree-view.tsx +274 -0
- package/src/components/visually-hidden/index.ts +1 -0
- package/src/components/visually-hidden/visually-hidden.tsx +10 -0
- package/src/index.ts +20 -0
- package/src/integrations/react-router.tsx +39 -0
- package/src/integrations/vite.test-d.ts +6 -0
- package/src/integrations/vite.test.ts +28 -0
- package/src/integrations/vite.ts +33 -0
- package/src/internal/dev.ts +12 -0
- package/src/patterns/app-shell/app-shell.styles.ts +1 -1
- package/src/patterns/app-shell/navbar.tsx +34 -16
- package/src/patterns/app-shell/sidebar.tsx +7 -2
- package/src/patterns/chart/chart-parts.tsx +179 -0
- package/src/patterns/chart/chart.styles.ts +35 -0
- package/src/patterns/chart/chart.tsx +386 -0
- package/src/patterns/chart/index.ts +13 -0
- package/src/patterns/form/form.tsx +48 -6
- package/src/patterns/form/index.ts +1 -0
- package/src/provider/color-mode-script.ts +28 -0
- package/src/provider/color-mode.tsx +14 -20
- package/src/provider/glyph-context.ts +38 -0
- package/src/provider/glyph-provider.tsx +16 -4
- package/src/provider/index.ts +4 -0
- package/src/provider/theme-scope.tsx +7 -3
- package/styles.css +88 -0
package/dist/chart.js
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { a as themedBorder, s as useComponentConfig, t as tv } from "./tv-DLbT66dC.js";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import * as R from "recharts";
|
|
6
|
+
//#region src/patterns/chart/chart.styles.ts
|
|
7
|
+
const chartStyles = tv({ slots: {
|
|
8
|
+
root: "m-0 grid min-w-0 gap-3",
|
|
9
|
+
caption: "grid gap-0.5",
|
|
10
|
+
title: "text-small font-medium text-foreground",
|
|
11
|
+
description: "text-caption text-muted-foreground",
|
|
12
|
+
plot: "min-w-0 [&_.recharts-surface]:overflow-visible [&_.recharts-text]:fill-muted-foreground",
|
|
13
|
+
legend: "flex flex-wrap items-center gap-x-4 gap-y-1 text-caption text-muted-foreground",
|
|
14
|
+
legendItem: "inline-flex items-center gap-1.5",
|
|
15
|
+
swatch: "size-2.5 shrink-0 rounded-[2px]",
|
|
16
|
+
tooltip: ["grid min-w-36 gap-1.5 rounded-md border-border bg-raised px-3 py-2 text-caption text-foreground shadow-lg", themedBorder],
|
|
17
|
+
tooltipLabel: "font-medium text-foreground",
|
|
18
|
+
tooltipRow: "flex items-center gap-2",
|
|
19
|
+
tooltipName: "flex-1 text-muted-foreground",
|
|
20
|
+
tooltipValue: "font-mono font-medium tabular-nums text-foreground",
|
|
21
|
+
center: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center",
|
|
22
|
+
srOnly: "sr-only"
|
|
23
|
+
} });
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/patterns/chart/chart-parts.tsx
|
|
26
|
+
/** Series without a color use the theme's chart palette, in order. */
|
|
27
|
+
const palette = [
|
|
28
|
+
"chart-1",
|
|
29
|
+
"chart-2",
|
|
30
|
+
"chart-3",
|
|
31
|
+
"chart-4",
|
|
32
|
+
"chart-5"
|
|
33
|
+
];
|
|
34
|
+
function resolveColor(color, index) {
|
|
35
|
+
const value = color ?? palette[index % palette.length];
|
|
36
|
+
return /^[a-z][a-z\d-]*$/.test(value) ? `var(--color-${value})` : value;
|
|
37
|
+
}
|
|
38
|
+
const defaultFormatter = (value) => typeof value === "number" ? value.toLocaleString() : String(value);
|
|
39
|
+
function useChartParts() {
|
|
40
|
+
const [, slots] = useComponentConfig("Chart", {});
|
|
41
|
+
return {
|
|
42
|
+
s: chartStyles(),
|
|
43
|
+
slots
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function ChartLegend({ items }) {
|
|
47
|
+
const { s, slots } = useChartParts();
|
|
48
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
49
|
+
"data-slot": "chart-legend",
|
|
50
|
+
className: s.legend({ class: slots.legend }),
|
|
51
|
+
"aria-hidden": "true",
|
|
52
|
+
children: items.map((item, i) => /* @__PURE__ */ jsxs("li", {
|
|
53
|
+
className: s.legendItem({ class: slots.legendItem }),
|
|
54
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
55
|
+
className: s.swatch({ class: slots.swatch }),
|
|
56
|
+
style: { background: item.color }
|
|
57
|
+
}), item.label]
|
|
58
|
+
}, i))
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function ChartTooltipCard({ active, payload, label, formatter, labelFormatter }) {
|
|
62
|
+
const { s, slots } = useChartParts();
|
|
63
|
+
if (!active || !payload?.length) return null;
|
|
64
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
65
|
+
"data-slot": "chart-tooltip",
|
|
66
|
+
className: s.tooltip({ class: slots.tooltip }),
|
|
67
|
+
children: [label !== void 0 && label !== "" && /* @__PURE__ */ jsx("p", {
|
|
68
|
+
className: s.tooltipLabel({ class: slots.tooltipLabel }),
|
|
69
|
+
children: labelFormatter ? labelFormatter(label) : label
|
|
70
|
+
}), payload.map((item, i) => /* @__PURE__ */ jsxs("div", {
|
|
71
|
+
className: s.tooltipRow({ class: slots.tooltipRow }),
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ jsx("span", {
|
|
74
|
+
className: s.swatch({ class: slots.swatch }),
|
|
75
|
+
style: { background: item.color ?? item.payload?.fill }
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ jsx("span", {
|
|
78
|
+
className: s.tooltipName({ class: slots.tooltipName }),
|
|
79
|
+
children: String(item.name ?? "")
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ jsx("span", {
|
|
82
|
+
className: s.tooltipValue({ class: slots.tooltipValue }),
|
|
83
|
+
children: formatter(Number(item.value))
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
}, i))]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Wraps every chart in a `<figure>` with a caption and a visually hidden data table,
|
|
91
|
+
* so screen-reader users get the numbers the chart shows.
|
|
92
|
+
*/
|
|
93
|
+
function ChartFrame({ title, description, hideTitle, className, legend, table, children }) {
|
|
94
|
+
const { s, slots } = useChartParts();
|
|
95
|
+
const titleId = useId();
|
|
96
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
97
|
+
"data-slot": "chart",
|
|
98
|
+
"aria-labelledby": titleId,
|
|
99
|
+
className: s.root({ class: [slots.root, className] }),
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ jsxs("figcaption", {
|
|
102
|
+
className: hideTitle ? s.srOnly() : s.caption({ class: slots.caption }),
|
|
103
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
104
|
+
id: titleId,
|
|
105
|
+
className: s.title({ class: slots.title }),
|
|
106
|
+
children: title
|
|
107
|
+
}), description && /* @__PURE__ */ jsx("span", {
|
|
108
|
+
className: s.description({ class: slots.description }),
|
|
109
|
+
children: description
|
|
110
|
+
})]
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ jsx("div", {
|
|
113
|
+
className: s.plot({ class: slots.plot }),
|
|
114
|
+
"aria-hidden": "true",
|
|
115
|
+
children
|
|
116
|
+
}),
|
|
117
|
+
legend && legend.length > 1 && /* @__PURE__ */ jsx(ChartLegend, { items: legend }),
|
|
118
|
+
/* @__PURE__ */ jsxs("table", {
|
|
119
|
+
className: s.srOnly(),
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ jsx("caption", { children: title }),
|
|
122
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: table.columns.map((column) => /* @__PURE__ */ jsx("th", {
|
|
123
|
+
scope: "col",
|
|
124
|
+
children: column
|
|
125
|
+
}, column)) }) }),
|
|
126
|
+
/* @__PURE__ */ jsx("tbody", { children: table.rows.map((row, i) => /* @__PURE__ */ jsx("tr", { children: row.map((cell, j) => j === 0 ? /* @__PURE__ */ jsx("th", {
|
|
127
|
+
scope: "row",
|
|
128
|
+
children: cell
|
|
129
|
+
}, j) : /* @__PURE__ */ jsx("td", { children: cell }, j)) }, i)) })
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/patterns/chart/chart.tsx
|
|
137
|
+
const axisTick = {
|
|
138
|
+
fill: "var(--color-muted-foreground)",
|
|
139
|
+
fontSize: 12
|
|
140
|
+
};
|
|
141
|
+
function useCartesian(props) {
|
|
142
|
+
const { data, index, series, title, valueFormatter = defaultFormatter } = props;
|
|
143
|
+
const resolved = series.map((item, i) => ({
|
|
144
|
+
...item,
|
|
145
|
+
label: item.label ?? item.key,
|
|
146
|
+
stroke: resolveColor(item.color, i)
|
|
147
|
+
}));
|
|
148
|
+
return {
|
|
149
|
+
resolved,
|
|
150
|
+
table: {
|
|
151
|
+
columns: [String(index), ...resolved.map((item) => item.label)],
|
|
152
|
+
rows: data.map((row) => [String(row[index]), ...resolved.map((item) => valueFormatter(Number(row[item.key])))])
|
|
153
|
+
},
|
|
154
|
+
legend: props.showLegend ?? series.length > 1 ? resolved.map((item) => ({
|
|
155
|
+
label: item.label,
|
|
156
|
+
color: item.stroke
|
|
157
|
+
})) : void 0,
|
|
158
|
+
valueFormatter,
|
|
159
|
+
title
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function frameProps(props) {
|
|
163
|
+
return {
|
|
164
|
+
title: props.title,
|
|
165
|
+
description: props.description,
|
|
166
|
+
hideTitle: props.hideTitle,
|
|
167
|
+
className: props.className
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function Axes({ index, showGrid = true, showYAxis = true, valueFormatter }) {
|
|
171
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
172
|
+
showGrid && /* @__PURE__ */ jsx(R.CartesianGrid, {
|
|
173
|
+
vertical: false,
|
|
174
|
+
stroke: "var(--color-border)",
|
|
175
|
+
strokeDasharray: "3 3"
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ jsx(R.XAxis, {
|
|
178
|
+
dataKey: index,
|
|
179
|
+
tick: axisTick,
|
|
180
|
+
tickLine: false,
|
|
181
|
+
axisLine: false,
|
|
182
|
+
tickMargin: 8,
|
|
183
|
+
minTickGap: 16
|
|
184
|
+
}),
|
|
185
|
+
showYAxis && /* @__PURE__ */ jsx(R.YAxis, {
|
|
186
|
+
tick: axisTick,
|
|
187
|
+
tickLine: false,
|
|
188
|
+
axisLine: false,
|
|
189
|
+
width: 48,
|
|
190
|
+
tickFormatter: valueFormatter
|
|
191
|
+
})
|
|
192
|
+
] });
|
|
193
|
+
}
|
|
194
|
+
function tooltip(valueFormatter, cursor) {
|
|
195
|
+
return /* @__PURE__ */ jsx(R.Tooltip, {
|
|
196
|
+
cursor,
|
|
197
|
+
content: (p) => /* @__PURE__ */ jsx(ChartTooltipCard, {
|
|
198
|
+
active: p.active,
|
|
199
|
+
payload: p.payload,
|
|
200
|
+
label: p.label,
|
|
201
|
+
formatter: valueFormatter
|
|
202
|
+
})
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/** Trends over time, one line per series. */
|
|
206
|
+
function LineChart(props) {
|
|
207
|
+
const { resolved, table, legend, valueFormatter } = useCartesian(props);
|
|
208
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
209
|
+
...frameProps(props),
|
|
210
|
+
legend,
|
|
211
|
+
table,
|
|
212
|
+
children: /* @__PURE__ */ jsx(R.ResponsiveContainer, {
|
|
213
|
+
width: "100%",
|
|
214
|
+
height: props.height ?? 240,
|
|
215
|
+
children: /* @__PURE__ */ jsxs(R.LineChart, {
|
|
216
|
+
accessibilityLayer: false,
|
|
217
|
+
data: props.data,
|
|
218
|
+
margin: {
|
|
219
|
+
top: 8,
|
|
220
|
+
right: 8,
|
|
221
|
+
bottom: 0,
|
|
222
|
+
left: 0
|
|
223
|
+
},
|
|
224
|
+
children: [
|
|
225
|
+
/* @__PURE__ */ jsx(Axes, {
|
|
226
|
+
index: props.index,
|
|
227
|
+
showGrid: props.showGrid,
|
|
228
|
+
showYAxis: props.showYAxis,
|
|
229
|
+
valueFormatter
|
|
230
|
+
}),
|
|
231
|
+
tooltip(valueFormatter, { stroke: "var(--color-border-strong)" }),
|
|
232
|
+
resolved.map((item) => /* @__PURE__ */ jsx(R.Line, {
|
|
233
|
+
dataKey: item.key,
|
|
234
|
+
name: item.label,
|
|
235
|
+
type: props.curve ?? "monotone",
|
|
236
|
+
stroke: item.stroke,
|
|
237
|
+
strokeWidth: 2,
|
|
238
|
+
dot: false,
|
|
239
|
+
activeDot: {
|
|
240
|
+
r: 4,
|
|
241
|
+
strokeWidth: 0
|
|
242
|
+
},
|
|
243
|
+
isAnimationActive: false
|
|
244
|
+
}, item.key))
|
|
245
|
+
]
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/** Trends with filled areas. `stacked` shows how series add up to a total. */
|
|
251
|
+
function AreaChart(props) {
|
|
252
|
+
const { resolved, table, legend, valueFormatter } = useCartesian(props);
|
|
253
|
+
const id = useId().replace(/:/g, "");
|
|
254
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
255
|
+
...frameProps(props),
|
|
256
|
+
legend,
|
|
257
|
+
table,
|
|
258
|
+
children: /* @__PURE__ */ jsx(R.ResponsiveContainer, {
|
|
259
|
+
width: "100%",
|
|
260
|
+
height: props.height ?? 240,
|
|
261
|
+
children: /* @__PURE__ */ jsxs(R.AreaChart, {
|
|
262
|
+
accessibilityLayer: false,
|
|
263
|
+
data: props.data,
|
|
264
|
+
margin: {
|
|
265
|
+
top: 8,
|
|
266
|
+
right: 8,
|
|
267
|
+
bottom: 0,
|
|
268
|
+
left: 0
|
|
269
|
+
},
|
|
270
|
+
children: [
|
|
271
|
+
/* @__PURE__ */ jsx("defs", { children: resolved.map((item, i) => /* @__PURE__ */ jsxs("linearGradient", {
|
|
272
|
+
id: `${id}-${i}`,
|
|
273
|
+
x1: "0",
|
|
274
|
+
x2: "0",
|
|
275
|
+
y1: "0",
|
|
276
|
+
y2: "1",
|
|
277
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
278
|
+
offset: "0%",
|
|
279
|
+
stopColor: item.stroke,
|
|
280
|
+
stopOpacity: .3
|
|
281
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
282
|
+
offset: "100%",
|
|
283
|
+
stopColor: item.stroke,
|
|
284
|
+
stopOpacity: 0
|
|
285
|
+
})]
|
|
286
|
+
}, item.key)) }),
|
|
287
|
+
/* @__PURE__ */ jsx(Axes, {
|
|
288
|
+
index: props.index,
|
|
289
|
+
showGrid: props.showGrid,
|
|
290
|
+
showYAxis: props.showYAxis,
|
|
291
|
+
valueFormatter
|
|
292
|
+
}),
|
|
293
|
+
tooltip(valueFormatter, { stroke: "var(--color-border-strong)" }),
|
|
294
|
+
resolved.map((item, i) => /* @__PURE__ */ jsx(R.Area, {
|
|
295
|
+
dataKey: item.key,
|
|
296
|
+
name: item.label,
|
|
297
|
+
type: "monotone",
|
|
298
|
+
stroke: item.stroke,
|
|
299
|
+
strokeWidth: 2,
|
|
300
|
+
fill: `url(#${id}-${i})`,
|
|
301
|
+
...props.stacked && { stackId: "stack" },
|
|
302
|
+
isAnimationActive: false
|
|
303
|
+
}, item.key))
|
|
304
|
+
]
|
|
305
|
+
})
|
|
306
|
+
})
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/** Compare values across categories. `stacked` puts series on top of each other. */
|
|
310
|
+
function BarChart(props) {
|
|
311
|
+
const { resolved, table, legend, valueFormatter } = useCartesian(props);
|
|
312
|
+
const radius = props.barRadius ?? 3;
|
|
313
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
314
|
+
...frameProps(props),
|
|
315
|
+
legend,
|
|
316
|
+
table,
|
|
317
|
+
children: /* @__PURE__ */ jsx(R.ResponsiveContainer, {
|
|
318
|
+
width: "100%",
|
|
319
|
+
height: props.height ?? 240,
|
|
320
|
+
children: /* @__PURE__ */ jsxs(R.BarChart, {
|
|
321
|
+
accessibilityLayer: false,
|
|
322
|
+
data: props.data,
|
|
323
|
+
margin: {
|
|
324
|
+
top: 8,
|
|
325
|
+
right: 8,
|
|
326
|
+
bottom: 0,
|
|
327
|
+
left: 0
|
|
328
|
+
},
|
|
329
|
+
children: [
|
|
330
|
+
/* @__PURE__ */ jsx(Axes, {
|
|
331
|
+
index: props.index,
|
|
332
|
+
showGrid: props.showGrid,
|
|
333
|
+
showYAxis: props.showYAxis,
|
|
334
|
+
valueFormatter
|
|
335
|
+
}),
|
|
336
|
+
tooltip(valueFormatter, {
|
|
337
|
+
fill: "var(--color-muted)",
|
|
338
|
+
opacity: .6
|
|
339
|
+
}),
|
|
340
|
+
resolved.map((item, i) => /* @__PURE__ */ jsx(R.Bar, {
|
|
341
|
+
dataKey: item.key,
|
|
342
|
+
name: item.label,
|
|
343
|
+
fill: item.stroke,
|
|
344
|
+
radius: props.stacked && i < resolved.length - 1 ? 0 : [
|
|
345
|
+
radius,
|
|
346
|
+
radius,
|
|
347
|
+
0,
|
|
348
|
+
0
|
|
349
|
+
],
|
|
350
|
+
...props.stacked && { stackId: "stack" },
|
|
351
|
+
isAnimationActive: false
|
|
352
|
+
}, item.key))
|
|
353
|
+
]
|
|
354
|
+
})
|
|
355
|
+
})
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
/** Parts of a whole. Best with five or fewer slices. */
|
|
359
|
+
function DonutChart(props) {
|
|
360
|
+
const { data, category, value, valueFormatter = defaultFormatter, size = 200 } = props;
|
|
361
|
+
const { s, slots } = useChartParts();
|
|
362
|
+
const rows = data.map((row) => row);
|
|
363
|
+
const colors = rows.map((_, i) => resolveColor(props.colors?.[i], i));
|
|
364
|
+
const table = {
|
|
365
|
+
columns: [String(category), String(value)],
|
|
366
|
+
rows: rows.map((row) => [String(row[category]), valueFormatter(Number(row[value]))])
|
|
367
|
+
};
|
|
368
|
+
const legend = props.showLegend ?? true ? rows.map((row, i) => ({
|
|
369
|
+
label: String(row[category]),
|
|
370
|
+
color: colors[i]
|
|
371
|
+
})) : void 0;
|
|
372
|
+
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
373
|
+
title: props.title,
|
|
374
|
+
description: props.description,
|
|
375
|
+
hideTitle: props.hideTitle,
|
|
376
|
+
className: props.className,
|
|
377
|
+
legend,
|
|
378
|
+
table,
|
|
379
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
380
|
+
className: "relative mx-auto",
|
|
381
|
+
style: {
|
|
382
|
+
width: size,
|
|
383
|
+
height: size
|
|
384
|
+
},
|
|
385
|
+
children: [/* @__PURE__ */ jsx(R.ResponsiveContainer, {
|
|
386
|
+
width: "100%",
|
|
387
|
+
height: "100%",
|
|
388
|
+
children: /* @__PURE__ */ jsxs(R.PieChart, {
|
|
389
|
+
accessibilityLayer: false,
|
|
390
|
+
children: [tooltip(valueFormatter, false), /* @__PURE__ */ jsx(R.Pie, {
|
|
391
|
+
rootTabIndex: -1,
|
|
392
|
+
data: rows,
|
|
393
|
+
dataKey: value,
|
|
394
|
+
nameKey: category,
|
|
395
|
+
innerRadius: "68%",
|
|
396
|
+
outerRadius: "100%",
|
|
397
|
+
paddingAngle: 2,
|
|
398
|
+
stroke: "var(--color-surface)",
|
|
399
|
+
strokeWidth: 2,
|
|
400
|
+
isAnimationActive: false,
|
|
401
|
+
children: rows.map((_, i) => /* @__PURE__ */ jsx(R.Cell, { fill: colors[i] }, i))
|
|
402
|
+
})]
|
|
403
|
+
})
|
|
404
|
+
}), props.centerLabel && /* @__PURE__ */ jsx("div", {
|
|
405
|
+
className: s.center({ class: slots.center }),
|
|
406
|
+
children: props.centerLabel
|
|
407
|
+
})]
|
|
408
|
+
})
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/** A tiny trend line without axes, for stat cards and table cells. */
|
|
412
|
+
function Sparkline({ values, title, color, height = 36, area = true, className }) {
|
|
413
|
+
const id = useId().replace(/:/g, "");
|
|
414
|
+
const stroke = resolveColor(color, 0);
|
|
415
|
+
const data = values.map((v, i) => ({
|
|
416
|
+
i,
|
|
417
|
+
v
|
|
418
|
+
}));
|
|
419
|
+
return /* @__PURE__ */ jsx("div", {
|
|
420
|
+
role: "img",
|
|
421
|
+
"aria-label": title,
|
|
422
|
+
"data-slot": "sparkline",
|
|
423
|
+
className,
|
|
424
|
+
style: { height },
|
|
425
|
+
children: /* @__PURE__ */ jsx(R.ResponsiveContainer, {
|
|
426
|
+
width: "100%",
|
|
427
|
+
height: "100%",
|
|
428
|
+
children: /* @__PURE__ */ jsxs(R.AreaChart, {
|
|
429
|
+
accessibilityLayer: false,
|
|
430
|
+
data,
|
|
431
|
+
margin: {
|
|
432
|
+
top: 2,
|
|
433
|
+
right: 2,
|
|
434
|
+
bottom: 2,
|
|
435
|
+
left: 2
|
|
436
|
+
},
|
|
437
|
+
children: [/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
|
|
438
|
+
id,
|
|
439
|
+
x1: "0",
|
|
440
|
+
x2: "0",
|
|
441
|
+
y1: "0",
|
|
442
|
+
y2: "1",
|
|
443
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
444
|
+
offset: "0%",
|
|
445
|
+
stopColor: stroke,
|
|
446
|
+
stopOpacity: area ? .25 : 0
|
|
447
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
448
|
+
offset: "100%",
|
|
449
|
+
stopColor: stroke,
|
|
450
|
+
stopOpacity: 0
|
|
451
|
+
})]
|
|
452
|
+
}) }), /* @__PURE__ */ jsx(R.Area, {
|
|
453
|
+
dataKey: "v",
|
|
454
|
+
type: "monotone",
|
|
455
|
+
stroke,
|
|
456
|
+
strokeWidth: 1.75,
|
|
457
|
+
fill: `url(#${id})`,
|
|
458
|
+
isAnimationActive: false,
|
|
459
|
+
dot: false
|
|
460
|
+
})]
|
|
461
|
+
})
|
|
462
|
+
})
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
466
|
+
export { AreaChart, BarChart, DonutChart, LineChart, Sparkline, chartStyles };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/provider/color-mode-script.ts
|
|
3
|
+
const DARK_QUERY = "(prefers-color-scheme: dark)";
|
|
4
|
+
const DEFAULT_STORAGE_KEY = "glyph-mode";
|
|
5
|
+
/**
|
|
6
|
+
* A tiny inline script that sets `data-mode` on `<html>` before first paint, so dark-mode
|
|
7
|
+
* visitors never see a light flash. Use the same options as `GlyphProvider`.
|
|
8
|
+
*/
|
|
9
|
+
function getColorModeScript({ defaultMode = "system", storageKey = DEFAULT_STORAGE_KEY } = {}) {
|
|
10
|
+
return `(function(){try{var d=${JSON.stringify(defaultMode)},m=null;${storageKey ? `m=localStorage.getItem(${JSON.stringify(storageKey)});` : ""}if(m!=='light'&&m!=='dark'&&m!=='system')m=d;if(m==='system')m=matchMedia('${DARK_QUERY}').matches?'dark':'light';var r=document.documentElement;r.dataset.mode=m;r.style.colorScheme=m}catch(e){}})()`;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { DEFAULT_STORAGE_KEY as n, getColorModeScript as r, DARK_QUERY as t };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ColorMode } from "@glyphui/tokens";
|
|
2
|
+
//#region src/provider/color-mode-script.d.ts
|
|
3
|
+
type ColorModePreference = ColorMode | 'system';
|
|
4
|
+
interface ColorModeOptions {
|
|
5
|
+
/** Used when nothing is stored yet. */
|
|
6
|
+
defaultMode?: ColorModePreference;
|
|
7
|
+
/** localStorage key. Set to `null` to disable persistence. */
|
|
8
|
+
storageKey?: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A tiny inline script that sets `data-mode` on `<html>` before first paint, so dark-mode
|
|
12
|
+
* visitors never see a light flash. Use the same options as `GlyphProvider`.
|
|
13
|
+
*/
|
|
14
|
+
declare function getColorModeScript({ defaultMode, storageKey }?: ColorModeOptions): string;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ColorModePreference as n, getColorModeScript as r, ColorModeOptions as t };
|
package/dist/data-table.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { a as themedBorder, r as focusRing, s as useComponentConfig, t as tv } from "./tv-DLbT66dC.js";
|
|
3
|
+
import { b as SearchIcon, h as ChevronsUpDownIcon, i as IconButton, l as ArrowDownIcon, m as ChevronRightIcon, p as ChevronLeftIcon, r as Button, u as ArrowUpIcon } from "./field-context-7I-cWvvS.js";
|
|
4
|
+
import { a as Table, c as TableCell, d as TableRow, h as Input, l as TableHead, n as ErrorState, o as TableBody, p as Skeleton, t as EmptyState, u as TableHeader, v as Checkbox } from "./states-IvhjBgna.js";
|
|
4
5
|
import { useEffect, useMemo, useState } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { createColumnHelper, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { s as useComponentConfig, t as tv } from "./tv-DLbT66dC.js";
|
|
3
|
+
import { t as FieldContext } from "./field-context-7I-cWvvS.js";
|
|
3
4
|
import { Label } from "radix-ui";
|
|
4
5
|
import { useId, useMemo } from "react";
|
|
5
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -19,10 +20,12 @@ const fieldStyles = tv({
|
|
|
19
20
|
slots: {
|
|
20
21
|
root: "grid gap-1.5",
|
|
21
22
|
label: "",
|
|
22
|
-
|
|
23
|
+
labelRow: "flex items-center justify-between gap-2",
|
|
24
|
+
labelAction: "text-small",
|
|
25
|
+
required: "text-danger-text",
|
|
23
26
|
text: "grid gap-0.5",
|
|
24
27
|
description: "text-small text-faint-foreground",
|
|
25
|
-
error: "text-small font-medium text-danger"
|
|
28
|
+
error: "text-small font-medium text-danger-text"
|
|
26
29
|
},
|
|
27
30
|
variants: { orientation: {
|
|
28
31
|
vertical: {},
|
|
@@ -41,15 +44,17 @@ const fieldStyles = tv({
|
|
|
41
44
|
*/
|
|
42
45
|
function Field(inProps) {
|
|
43
46
|
const [props, slots] = useComponentConfig("Field", inProps);
|
|
44
|
-
const { label, description, error, required = false, disabled = false, controlId, orientation, className, children, ...rest } = props;
|
|
47
|
+
const { label, labelAction, description, error, required = false, disabled = false, controlId, orientation, className, children, ...rest } = props;
|
|
45
48
|
const generated = useId();
|
|
46
49
|
const id = controlId ?? generated;
|
|
47
50
|
const invalid = Boolean(error);
|
|
51
|
+
const labelId = label ? `${id}-label` : void 0;
|
|
48
52
|
const descriptionId = description ? `${id}-description` : void 0;
|
|
49
53
|
const errorId = invalid ? `${id}-error` : void 0;
|
|
50
54
|
const s = fieldStyles({ orientation });
|
|
51
55
|
const context = useMemo(() => ({
|
|
52
56
|
id,
|
|
57
|
+
labelId,
|
|
53
58
|
descriptionId,
|
|
54
59
|
errorId,
|
|
55
60
|
invalid,
|
|
@@ -57,13 +62,15 @@ function Field(inProps) {
|
|
|
57
62
|
disabled
|
|
58
63
|
}), [
|
|
59
64
|
id,
|
|
65
|
+
labelId,
|
|
60
66
|
descriptionId,
|
|
61
67
|
errorId,
|
|
62
68
|
invalid,
|
|
63
69
|
required,
|
|
64
70
|
disabled
|
|
65
71
|
]);
|
|
66
|
-
const
|
|
72
|
+
const labelElement = label ? /* @__PURE__ */ jsxs(Label$1, {
|
|
73
|
+
id: labelId,
|
|
67
74
|
htmlFor: id,
|
|
68
75
|
className: s.label({ class: slots.label }),
|
|
69
76
|
children: [label, required && /* @__PURE__ */ jsx("span", {
|
|
@@ -72,6 +79,15 @@ function Field(inProps) {
|
|
|
72
79
|
children: "*"
|
|
73
80
|
})]
|
|
74
81
|
}) : null;
|
|
82
|
+
const labelNode = labelElement && labelAction ? /* @__PURE__ */ jsxs("div", {
|
|
83
|
+
"data-slot": "field-label-row",
|
|
84
|
+
className: s.labelRow({ class: slots.labelRow }),
|
|
85
|
+
children: [labelElement, /* @__PURE__ */ jsx("span", {
|
|
86
|
+
"data-slot": "field-label-action",
|
|
87
|
+
className: s.labelAction({ class: slots.labelAction }),
|
|
88
|
+
children: labelAction
|
|
89
|
+
})]
|
|
90
|
+
}) : labelElement;
|
|
75
91
|
const messages = /* @__PURE__ */ jsxs(Fragment$1, { children: [description && /* @__PURE__ */ jsx("p", {
|
|
76
92
|
id: descriptionId,
|
|
77
93
|
"data-slot": "field-description",
|
|
@@ -1,40 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { a as themedBorder, o as transition, r as focusRing, s as useComponentConfig, t as tv } from "./tv-DLbT66dC.js";
|
|
3
3
|
import { Slot } from "radix-ui";
|
|
4
4
|
import { Fragment, createContext, useContext } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { createTV } from "tailwind-variants";
|
|
7
|
-
//#region src/provider/glyph-context.ts
|
|
8
|
-
const GlyphContext = createContext(null);
|
|
9
|
-
/** The active theme and app-level settings. Must be used under `GlyphProvider`. */
|
|
10
|
-
function useGlyph() {
|
|
11
|
-
const value = useContext(GlyphContext);
|
|
12
|
-
if (!value) throw new Error("useGlyph must be used inside <GlyphProvider>.");
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
/** The router-aware link component configured on `GlyphProvider`. */
|
|
16
|
-
function useLinkComponent() {
|
|
17
|
-
return useContext(GlyphContext)?.linkComponent ?? "a";
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region src/hooks/use-component-config.ts
|
|
21
|
-
/**
|
|
22
|
-
* Applies the theme's per-component settings (`theme.components[name]`):
|
|
23
|
-
* fills unset variant props from `defaultVariants` and returns the extra slot classes.
|
|
24
|
-
* Every styled component calls this first.
|
|
25
|
-
*/
|
|
26
|
-
function useComponentConfig(name, props) {
|
|
27
|
-
const override = (useContext(GlyphContext)?.theme)?.components[name];
|
|
28
|
-
if (!override) return [props, {}];
|
|
29
|
-
let merged = props;
|
|
30
|
-
const defaults = override.defaultVariants;
|
|
31
|
-
if (defaults) {
|
|
32
|
-
merged = { ...props };
|
|
33
|
-
for (const [key, value] of Object.entries(defaults)) if (merged[key] === void 0) merged[key] = value;
|
|
34
|
-
}
|
|
35
|
-
return [merged, override.className ?? {}];
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
6
|
//#region src/internal/icons.tsx
|
|
39
7
|
function Icon({ children, ...props }) {
|
|
40
8
|
return /* @__PURE__ */ jsx("svg", {
|
|
@@ -123,28 +91,6 @@ const AlertIcon = (p) => /* @__PURE__ */ jsxs(Icon, {
|
|
|
123
91
|
}), /* @__PURE__ */ jsx("path", { d: "M12 8v4M12 16h.01" })]
|
|
124
92
|
});
|
|
125
93
|
//#endregion
|
|
126
|
-
//#region src/utils/styles.ts
|
|
127
|
-
/** Shared class fragments. Kept as literals so Tailwind's scanner picks them up. */
|
|
128
|
-
const focusRing = "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";
|
|
129
|
-
const themedBorder = "border-(length:--glyph-border-width)";
|
|
130
|
-
const transition = "transition-[color,background-color,border-color,box-shadow,transform,opacity] duration-(--glyph-duration-base) ease-standard";
|
|
131
|
-
/** Popover surfaces: Select, Tooltip-like menus. */
|
|
132
|
-
const popover = "z-50 overflow-hidden rounded-[min(var(--radius-md),var(--radius-lg))] border-(length:--glyph-border-width) border-border bg-raised text-foreground shadow-lg animate-pop-in";
|
|
133
|
-
//#endregion
|
|
134
|
-
//#region src/utils/tw-merge-config.ts
|
|
135
|
-
/**
|
|
136
|
-
* Teaches tailwind-merge about Glyph's custom utilities so `cn('text-h1', 'text-small')`
|
|
137
|
-
* keeps only the last size instead of treating `text-h1` as a color.
|
|
138
|
-
*/
|
|
139
|
-
const twMergeConfig = { extend: { theme: {
|
|
140
|
-
text: [...textTokens],
|
|
141
|
-
radius: ["pill"]
|
|
142
|
-
} } };
|
|
143
|
-
//#endregion
|
|
144
|
-
//#region src/utils/tv.ts
|
|
145
|
-
/** `tailwind-variants` preconfigured with Glyph's merge rules. All component styles use this. */
|
|
146
|
-
const tv = createTV({ twMergeConfig });
|
|
147
|
-
//#endregion
|
|
148
94
|
//#region src/components/spinner/spinner.styles.ts
|
|
149
95
|
const spinnerStyles = tv({
|
|
150
96
|
slots: {
|
|
@@ -211,7 +157,7 @@ const buttonStyles = tv({
|
|
|
211
157
|
outline: { base: "border-border bg-surface text-foreground shadow-xs hover:border-border-strong hover:bg-muted" },
|
|
212
158
|
ghost: { base: "text-muted-foreground hover:bg-muted hover:text-foreground" },
|
|
213
159
|
danger: { base: "bg-danger text-danger-foreground shadow-sm hover:bg-danger/88" },
|
|
214
|
-
link: { base: "h-auto px-0 text-primary underline-offset-4 shadow-none hover:underline" }
|
|
160
|
+
link: { base: "h-auto px-0 text-primary-text underline-offset-4 shadow-none hover:underline" }
|
|
215
161
|
},
|
|
216
162
|
size: {
|
|
217
163
|
sm: {
|
|
@@ -318,4 +264,4 @@ function useFieldControl(props) {
|
|
|
318
264
|
};
|
|
319
265
|
}
|
|
320
266
|
//#endregion
|
|
321
|
-
export {
|
|
267
|
+
export { MenuIcon as _, buttonStyles as a, SearchIcon as b, AlertIcon as c, CheckIcon as d, ChevronDownIcon as f, InboxIcon as g, ChevronsUpDownIcon as h, IconButton as i, ArrowDownIcon as l, ChevronRightIcon as m, useFieldControl as n, Spinner as o, ChevronLeftIcon as p, Button as r, spinnerStyles as s, FieldContext as t, ArrowUpIcon as u, MinusIcon as v, XIcon as x, PanelLeftIcon as y };
|