@giddaa-housing/ui 1.1.0 → 2.0.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.
Files changed (47) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/giddaa.css +12 -2
  3. package/dist/badge.js +1 -1
  4. package/dist/bullet-chart.d.ts +8 -4
  5. package/dist/bullet-chart.js +10 -6
  6. package/dist/button.js +1 -1
  7. package/dist/card.js +1 -1
  8. package/dist/chart.d.ts +33 -5
  9. package/dist/chart.js +210 -13
  10. package/dist/checkbox.js +1 -1
  11. package/dist/data-table.d.ts +7 -3
  12. package/dist/data-table.js +8 -5
  13. package/dist/dialog-nesting.d.ts +9 -0
  14. package/dist/dialog-nesting.js +27 -0
  15. package/dist/dialog.js +9 -5
  16. package/dist/file-upload.d.ts +43 -0
  17. package/dist/file-upload.js +154 -0
  18. package/dist/funnel-chart.d.ts +11 -7
  19. package/dist/funnel-chart.js +11 -8
  20. package/dist/input-group.js +1 -1
  21. package/dist/input-otp.d.ts +23 -0
  22. package/dist/input-otp.js +56 -0
  23. package/dist/input.js +1 -1
  24. package/dist/line-chart.d.ts +113 -41
  25. package/dist/line-chart.js +217 -30
  26. package/dist/list-item.d.ts +22 -0
  27. package/dist/list-item.js +84 -0
  28. package/dist/number-input.js +20 -17
  29. package/dist/pie-chart.d.ts +83 -52
  30. package/dist/pie-chart.js +85 -43
  31. package/dist/purchase-option-card.d.ts +79 -0
  32. package/dist/purchase-option-card.js +176 -0
  33. package/dist/radio-group.js +1 -1
  34. package/dist/select.js +1 -1
  35. package/dist/sheet.d.ts +4 -2
  36. package/dist/sheet.js +22 -11
  37. package/dist/sparkline.d.ts +28 -15
  38. package/dist/sparkline.js +131 -37
  39. package/dist/styles.css +831 -119
  40. package/dist/switch.js +1 -1
  41. package/dist/table.js +6 -2
  42. package/dist/tabs.d.ts +21 -5
  43. package/dist/tabs.js +55 -12
  44. package/dist/textarea.js +1 -1
  45. package/dist/tree-map.d.ts +14 -14
  46. package/dist/tree-map.js +14 -15
  47. package/package.json +17 -1
package/dist/chart.d.ts CHANGED
@@ -31,6 +31,33 @@ declare function ChartTitle({ className, size, ...props }: React.ComponentProps<
31
31
  declare function ChartDescription({ className, size, ...props }: React.ComponentProps<"p"> & {
32
32
  size?: ComponentSize;
33
33
  }): React.JSX.Element;
34
+ type ChartMetricLayout = "stacked" | "inline";
35
+ declare function ChartMetric({ className, layout, size, ...props }: React.ComponentProps<"div"> & {
36
+ layout?: ChartMetricLayout;
37
+ size?: ComponentSize;
38
+ }): React.JSX.Element;
39
+ declare function ChartValue({ className, size, ...props }: React.ComponentProps<"p"> & {
40
+ size?: ComponentSize;
41
+ }): React.JSX.Element;
42
+ type ChartTrendDirection = "up" | "down";
43
+ type ChartTrendOrientation = "horizontal" | "vertical";
44
+ declare function ChartTrend({ className, direction, orientation, size, ...props }: React.ComponentProps<"p"> & {
45
+ direction?: ChartTrendDirection;
46
+ orientation?: ChartTrendOrientation;
47
+ size?: ComponentSize;
48
+ }): React.JSX.Element;
49
+ declare function ChartTrendChip({ children, className, direction: directionProp, showIcon, size: sizeProp, ...props }: React.ComponentProps<"span"> & {
50
+ direction?: ChartTrendDirection;
51
+ showIcon?: boolean;
52
+ size?: ComponentSize;
53
+ }): React.JSX.Element;
54
+ declare function ChartTrendValue({ className, size: sizeProp, ...props }: React.ComponentProps<"span"> & {
55
+ size?: ComponentSize;
56
+ }): React.JSX.Element;
57
+ declare function ChartTrendCaption({ className, size: sizeProp, ...props }: React.ComponentProps<"span"> & {
58
+ size?: ComponentSize;
59
+ }): React.JSX.Element;
60
+ declare function ChartFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
34
61
  declare function ChartContainer({ id, className, children, config, initialDimension, ...props }: React.ComponentProps<"div"> & {
35
62
  config: ChartConfig;
36
63
  children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
@@ -93,11 +120,12 @@ type CartesianAxisLayout = {
93
120
  * or axis lines, a size-scaled tick font, and a reserved value-axis width) that
94
121
  * every bar and line chart would otherwise repeat per axis. Spread the result
95
122
  * onto the recharts axis, then add the chart-specific props (`dataKey`,
96
- * `domain`, `ticks`, a `width`/`type` override, …):
123
+ * `domain`, `ticks`, a `width`/`type` override, …). Chart modules build their
124
+ * per-size axis wrappers (`BarChartXAxis`, `LineChartXAxis`, …) on top of this:
97
125
  *
98
- * const chart = useBarChartLayout();
99
- * <XAxis dataKey="month" {...chart.xAxis} />
100
- * <YAxis domain={[0, 120]} {...chart.yAxis} />
126
+ * const axes = cartesianAxisProps({ tickMargin: 8, tickFontSize: 11, yAxisWidth: 32 });
127
+ * <XAxis dataKey="month" {...axes.xAxis} />
128
+ * <YAxis domain={[0, 120]} {...axes.yAxis} />
101
129
  */
102
130
  declare function cartesianAxisProps(layout: CartesianAxisLayout): {
103
131
  readonly xAxis: {
@@ -118,4 +146,4 @@ declare function cartesianAxisProps(layout: CartesianAxisLayout): {
118
146
  };
119
147
  };
120
148
  //#endregion
121
- export { type CartesianAxisLayout, ChartCard, ChartConfig, ChartContainer, ChartDescription, ChartHeader, ChartLegend, ChartLegendContent, ChartStyle, ChartTitle, ChartTooltip, ChartTooltipContent, ChartValueType, cartesianAxisProps };
149
+ export { type CartesianAxisLayout, ChartCard, ChartConfig, ChartContainer, ChartDescription, ChartFooter, ChartHeader, ChartLegend, ChartLegendContent, ChartMetric, type ChartMetricLayout, ChartStyle, ChartTitle, ChartTooltip, ChartTooltipContent, ChartTrend, ChartTrendCaption, ChartTrendChip, type ChartTrendDirection, type ChartTrendOrientation, ChartTrendValue, ChartValue, ChartValueType, cartesianAxisProps };
package/dist/chart.js CHANGED
@@ -1,18 +1,19 @@
1
1
  "use client";
2
2
  import { t as cn } from "./cn-BI_4DMBf.js";
3
3
  import { SizeProvider, useComponentSize } from "./size-context.js";
4
+ import { ArrowDown, ArrowUp } from "lucide-react";
4
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
6
  import { cva } from "class-variance-authority";
6
7
  import * as React from "react";
7
8
  import * as RechartsPrimitive from "recharts";
8
9
  //#region src/chart.tsx
9
10
  /**
10
- * Markers use `--color-surface-brand` as a placeholder. Giddaa has no
11
- * categorical chart palette yetadd `chart-1`…`chart-N` tokens and bind each
12
- * series (its legend marker and tooltip dot) to its own colour once they exist.
13
- * Until then any series without an explicit colour paints brand-green.
11
+ * Fallback colour for a legend marker or tooltip dot when a series resolves no
12
+ * colour of its ownit defaults to the first categorical slot (`chart-1`).
13
+ * A series almost always carries its own colour (set by the chart's `color`
14
+ * prop or `ChartConfig`), so this is only hit by an unconfigured series.
14
15
  */
15
- const SERIES_COLOR_PLACEHOLDER = "var(--color-surface-brand)";
16
+ const SERIES_COLOR_FALLBACK = "var(--color-chart-1)";
16
17
  function formatChartValue(value, type) {
17
18
  if (Array.isArray(value)) return value.join(", ");
18
19
  if (typeof value !== "number") return value == null ? "" : String(value);
@@ -52,6 +53,19 @@ function useChart() {
52
53
  * </ChartHeader>
53
54
  * <ChartContainer config={config}>{/* recharts plot *\/}</ChartContainer>
54
55
  * </ChartCard>
56
+ *
57
+ * // Single-metric chart tile
58
+ * <ChartCard size="md">
59
+ * <ChartTitle>Properties sold</ChartTitle>
60
+ * <ChartMetric>
61
+ * <ChartValue>1.28k</ChartValue>
62
+ * <ChartTrend direction="up">
63
+ * <ChartTrendChip><ChartTrendValue>12.5%</ChartTrendValue></ChartTrendChip>
64
+ * <ChartTrendCaption>vs last month</ChartTrendCaption>
65
+ * </ChartTrend>
66
+ * </ChartMetric>
67
+ * <ChartFooter>{/* sparkline *\/}</ChartFooter>
68
+ * </ChartCard>
55
69
  */
56
70
  const chartCardVariants = cva("flex w-full min-w-0 flex-col rounded-2xl border border-line-subtle bg-surface-raised text-fg-primary shadow-1", {
57
71
  variants: { size: {
@@ -112,6 +126,188 @@ function ChartDescription({ className, size, ...props }) {
112
126
  ...props
113
127
  });
114
128
  }
129
+ const chartMetricVariants = cva("min-w-0", {
130
+ variants: {
131
+ layout: {
132
+ stacked: "flex flex-col items-start",
133
+ inline: "flex flex-wrap items-center"
134
+ },
135
+ size: {
136
+ sm: "gap-1.5",
137
+ md: "gap-2",
138
+ lg: "gap-3"
139
+ }
140
+ },
141
+ defaultVariants: {
142
+ layout: "stacked",
143
+ size: "md"
144
+ }
145
+ });
146
+ function ChartMetric({ className, layout = "stacked", size, ...props }) {
147
+ const resolvedSize = useComponentSize(size);
148
+ return /* @__PURE__ */ jsx("div", {
149
+ "data-slot": "chart-metric",
150
+ "data-layout": layout,
151
+ className: cn(chartMetricVariants({
152
+ layout,
153
+ size: resolvedSize
154
+ }), className),
155
+ ...props
156
+ });
157
+ }
158
+ const chartValueVariants = cva("min-w-0 font-extrabold leading-none tracking-[-0.02em] text-fg-primary tabular-nums", {
159
+ variants: { size: {
160
+ sm: "text-[2.25rem]",
161
+ md: "text-[3rem]",
162
+ lg: "text-[3.875rem]"
163
+ } },
164
+ defaultVariants: { size: "md" }
165
+ });
166
+ function ChartValue({ className, size, ...props }) {
167
+ const resolvedSize = useComponentSize(size);
168
+ return /* @__PURE__ */ jsx("p", {
169
+ "data-slot": "chart-value",
170
+ className: cn(chartValueVariants({ size: resolvedSize }), className),
171
+ ...props
172
+ });
173
+ }
174
+ const ChartTrendContext = React.createContext(null);
175
+ function useChartTrend({ direction, size } = {}) {
176
+ const context = React.useContext(ChartTrendContext);
177
+ return {
178
+ direction: direction ?? context?.direction ?? "up",
179
+ size: size ?? context?.size ?? "md"
180
+ };
181
+ }
182
+ const chartTrendVariants = cva("min-w-0", {
183
+ variants: {
184
+ orientation: {
185
+ horizontal: "flex flex-wrap items-center gap-2",
186
+ vertical: "flex flex-col items-start"
187
+ },
188
+ size: {
189
+ sm: "",
190
+ md: "",
191
+ lg: ""
192
+ }
193
+ },
194
+ compoundVariants: [
195
+ {
196
+ orientation: "vertical",
197
+ size: "sm",
198
+ className: "gap-0.5"
199
+ },
200
+ {
201
+ orientation: "vertical",
202
+ size: "md",
203
+ className: "gap-1"
204
+ },
205
+ {
206
+ orientation: "vertical",
207
+ size: "lg",
208
+ className: "gap-1"
209
+ }
210
+ ],
211
+ defaultVariants: {
212
+ orientation: "horizontal",
213
+ size: "md"
214
+ }
215
+ });
216
+ function ChartTrend({ className, direction = "up", orientation = "horizontal", size, ...props }) {
217
+ const resolvedSize = useComponentSize(size);
218
+ return /* @__PURE__ */ jsx(ChartTrendContext.Provider, {
219
+ value: {
220
+ direction,
221
+ size: resolvedSize
222
+ },
223
+ children: /* @__PURE__ */ jsx("p", {
224
+ "data-slot": "chart-trend",
225
+ "data-direction": direction,
226
+ "data-orientation": orientation,
227
+ className: cn(chartTrendVariants({
228
+ orientation,
229
+ size: resolvedSize
230
+ }), className),
231
+ ...props
232
+ })
233
+ });
234
+ }
235
+ const chartTrendChipVariants = cva("inline-flex shrink-0 items-center rounded-full font-semibold leading-none", {
236
+ variants: {
237
+ direction: {
238
+ up: "bg-surface-brand-subtle text-status-success",
239
+ down: "bg-surface-danger-subtle text-status-danger"
240
+ },
241
+ size: {
242
+ sm: "gap-1 px-2 py-0.5 [&>svg]:size-2.5",
243
+ md: "gap-1 px-[9px] py-1 [&>svg]:size-3",
244
+ lg: "gap-1 px-2.5 py-1.5 [&>svg]:size-3.5"
245
+ }
246
+ },
247
+ defaultVariants: {
248
+ direction: "up",
249
+ size: "md"
250
+ }
251
+ });
252
+ function ChartTrendChip({ children, className, direction: directionProp, showIcon = true, size: sizeProp, ...props }) {
253
+ const { direction, size } = useChartTrend({
254
+ direction: directionProp,
255
+ size: sizeProp
256
+ });
257
+ const Icon = direction === "down" ? ArrowDown : ArrowUp;
258
+ return /* @__PURE__ */ jsxs("span", {
259
+ "data-slot": "chart-trend-chip",
260
+ "data-direction": direction,
261
+ className: cn(chartTrendChipVariants({
262
+ direction,
263
+ size
264
+ }), className),
265
+ ...props,
266
+ children: [showIcon ? /* @__PURE__ */ jsx(Icon, {
267
+ "aria-hidden": "true",
268
+ className: "shrink-0"
269
+ }) : null, children]
270
+ });
271
+ }
272
+ const chartTrendValueVariants = cva("font-semibold leading-none text-current", {
273
+ variants: { size: {
274
+ sm: "text-[11px]",
275
+ md: "text-[13px]",
276
+ lg: "text-[15px]"
277
+ } },
278
+ defaultVariants: { size: "md" }
279
+ });
280
+ function ChartTrendValue({ className, size: sizeProp, ...props }) {
281
+ const { size } = useChartTrend({ size: sizeProp });
282
+ return /* @__PURE__ */ jsx("span", {
283
+ "data-slot": "chart-trend-value",
284
+ className: cn(chartTrendValueVariants({ size }), className),
285
+ ...props
286
+ });
287
+ }
288
+ const chartTrendCaptionVariants = cva("min-w-0 truncate font-normal leading-none text-fg-secondary", {
289
+ variants: { size: {
290
+ sm: "text-[11px]",
291
+ md: "text-xs",
292
+ lg: "text-[13px]"
293
+ } },
294
+ defaultVariants: { size: "md" }
295
+ });
296
+ function ChartTrendCaption({ className, size: sizeProp, ...props }) {
297
+ const { size } = useChartTrend({ size: sizeProp });
298
+ return /* @__PURE__ */ jsx("span", {
299
+ "data-slot": "chart-trend-caption",
300
+ className: cn(chartTrendCaptionVariants({ size }), className),
301
+ ...props
302
+ });
303
+ }
304
+ function ChartFooter({ className, ...props }) {
305
+ return /* @__PURE__ */ jsx("div", {
306
+ "data-slot": "chart-footer",
307
+ className: cn("mt-auto flex min-h-0 w-full flex-1 flex-col items-start justify-end", className),
308
+ ...props
309
+ });
310
+ }
115
311
  function ChartContainer({ id, className, children, config, initialDimension = INITIAL_DIMENSION, ...props }) {
116
312
  const uniqueId = React.useId();
117
313
  const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
@@ -120,7 +316,7 @@ function ChartContainer({ id, className, children, config, initialDimension = IN
120
316
  children: /* @__PURE__ */ jsxs("div", {
121
317
  "data-slot": "chart",
122
318
  "data-chart": chartId,
123
- className: cn("flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden", className),
319
+ className: cn("flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-fg-caption-placeholder [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-line [&_.recharts-curve.recharts-tooltip-cursor]:stroke-line [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-line [&_.recharts-radial-bar-background-sector]:fill-surface-raised [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-surface-raised [&_.recharts-reference-line_[stroke='#ccc']]:stroke-line [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden", className),
124
320
  ...props,
125
321
  children: [/* @__PURE__ */ jsx(ChartStyle, {
126
322
  id: chartId,
@@ -195,7 +391,7 @@ function ChartTooltipContent({ active, payload, className, hideIndicator = false
195
391
  const [item] = payload.filter((entry) => entry.type !== "none");
196
392
  if (!item) return null;
197
393
  const itemConfig = getPayloadConfigFromPayload(config, item, `${nameKey ?? item.name ?? item.dataKey ?? "value"}`);
198
- const dotColor = color ?? item.payload?.fill ?? item.color ?? SERIES_COLOR_PLACEHOLDER;
394
+ const dotColor = color ?? item.payload?.fill ?? item.color ?? SERIES_COLOR_FALLBACK;
199
395
  const metricLabel = itemConfig?.label ?? item.name;
200
396
  const heroValue = formatter ? formatter(item.value, item.name ?? "", item, 0, item.payload) : formatChartValue(item.value, valueType);
201
397
  const periodCaption = labelFormatter ? labelFormatter(label, payload) : (typeof label === "string" ? config[label]?.label : null) ?? label;
@@ -307,7 +503,7 @@ function ChartLegendContent({ className, hideIcon = false, payload, verticalAlig
307
503
  const itemKey = `${item.dataKey ?? item.value ?? index}`;
308
504
  const itemConfig = getPayloadConfigFromPayload(config, item, key);
309
505
  const inactive = (inactiveSet?.has(key) ?? false) || Boolean(item.inactive);
310
- const markerColor = inactive ? "var(--color-fg-caption-placeholder)" : item.color ?? SERIES_COLOR_PLACEHOLDER;
506
+ const markerColor = inactive ? "var(--color-fg-caption-placeholder)" : item.color ?? SERIES_COLOR_FALLBACK;
311
507
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : /* @__PURE__ */ jsx("span", {
312
508
  "aria-hidden": "true",
313
509
  className: cn(chartLegendMarkerSizeVariants({
@@ -343,11 +539,12 @@ function ChartLegendContent({ className, hideIcon = false, payload, verticalAlig
343
539
  * or axis lines, a size-scaled tick font, and a reserved value-axis width) that
344
540
  * every bar and line chart would otherwise repeat per axis. Spread the result
345
541
  * onto the recharts axis, then add the chart-specific props (`dataKey`,
346
- * `domain`, `ticks`, a `width`/`type` override, …):
542
+ * `domain`, `ticks`, a `width`/`type` override, …). Chart modules build their
543
+ * per-size axis wrappers (`BarChartXAxis`, `LineChartXAxis`, …) on top of this:
347
544
  *
348
- * const chart = useBarChartLayout();
349
- * <XAxis dataKey="month" {...chart.xAxis} />
350
- * <YAxis domain={[0, 120]} {...chart.yAxis} />
545
+ * const axes = cartesianAxisProps({ tickMargin: 8, tickFontSize: 11, yAxisWidth: 32 });
546
+ * <XAxis dataKey="month" {...axes.xAxis} />
547
+ * <YAxis domain={[0, 120]} {...axes.yAxis} />
351
548
  */
352
549
  function cartesianAxisProps(layout) {
353
550
  const tick = { fontSize: layout.tickFontSize };
@@ -375,4 +572,4 @@ function getPayloadConfigFromPayload(config, payload, key) {
375
572
  return configLabelKey in config ? config[configLabelKey] : config[key];
376
573
  }
377
574
  //#endregion
378
- export { ChartCard, ChartContainer, ChartDescription, ChartHeader, ChartLegend, ChartLegendContent, ChartStyle, ChartTitle, ChartTooltip, ChartTooltipContent, cartesianAxisProps };
575
+ export { ChartCard, ChartContainer, ChartDescription, ChartFooter, ChartHeader, ChartLegend, ChartLegendContent, ChartMetric, ChartStyle, ChartTitle, ChartTooltip, ChartTooltipContent, ChartTrend, ChartTrendCaption, ChartTrendChip, ChartTrendValue, ChartValue, cartesianAxisProps };
package/dist/checkbox.js CHANGED
@@ -7,7 +7,7 @@ import { cva } from "class-variance-authority";
7
7
  import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox";
8
8
  import { CheckboxGroup } from "@base-ui/react/checkbox-group";
9
9
  //#region src/checkbox.tsx
10
- const checkboxVariants = cva("peer group/checkbox relative flex shrink-0 items-center justify-center rounded-sm border bg-canvas text-transparent outline-none transition-[background-color,border-color,box-shadow,color] after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-line-focus focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-focus)] aria-invalid:border-line-danger aria-invalid:ring-3 aria-invalid:ring-destructive/20 border-line data-unchecked:hover:border-line-focus data-unchecked:hover:bg-surface-brand-subtle data-checked:border-action-primary data-checked:bg-action-primary data-checked:text-fg-on-brand data-disabled:cursor-not-allowed data-disabled:border-line-subtle data-disabled:bg-surface data-disabled:text-fg-caption-placeholder size-5 [--checkbox-icon-size:0.75rem] group-data-[size=sm]/field:size-4 group-data-[size=sm]/field:[--checkbox-icon-size:0.625rem] group-data-[size=md]/field:size-5 group-data-[size=md]/field:[--checkbox-icon-size:0.75rem] group-data-[size=lg]/field:size-6 group-data-[size=lg]/field:[--checkbox-icon-size:0.875rem]", { variants: { size: {
10
+ const checkboxVariants = cva("peer group/checkbox relative flex shrink-0 items-center justify-center rounded-sm border bg-canvas text-transparent outline-none transition-[background-color,border-color,box-shadow,color] after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-line-focus focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-focus)] aria-invalid:border-line-danger aria-invalid:ring-3 aria-invalid:ring-line-danger/20 aria-invalid:focus-visible:border-line-danger aria-invalid:focus-visible:shadow-[0px_0px_0px_2px_var(--color-line-danger)] border-line data-unchecked:hover:border-line-focus data-unchecked:hover:bg-surface-brand-subtle data-checked:border-action-primary data-checked:bg-action-primary data-checked:text-fg-on-brand data-disabled:cursor-not-allowed data-disabled:border-line-subtle data-disabled:bg-surface data-disabled:text-fg-caption-placeholder size-5 [--checkbox-icon-size:0.75rem] group-data-[size=sm]/field:size-4 group-data-[size=sm]/field:[--checkbox-icon-size:0.625rem] group-data-[size=md]/field:size-5 group-data-[size=md]/field:[--checkbox-icon-size:0.75rem] group-data-[size=lg]/field:size-6 group-data-[size=lg]/field:[--checkbox-icon-size:0.875rem]", { variants: { size: {
11
11
  sm: "size-4 [--checkbox-icon-size:0.625rem]",
12
12
  md: "size-5 [--checkbox-icon-size:0.75rem]",
13
13
  lg: "size-6 [--checkbox-icon-size:0.875rem]"
@@ -58,6 +58,8 @@ type DataTableFilterProps = Omit<FilterProps, "children"> & {
58
58
  popoverFooterProps?: React.ComponentProps<typeof PopoverFooter>;
59
59
  popoverHeaderProps?: React.ComponentProps<typeof PopoverHeader>;
60
60
  resetButtonProps?: FilterResetButtonProps;
61
+ /** Size of the default trigger button. Mirrors `Button`'s sizes. */
62
+ size?: React.ComponentProps<typeof Button>["size"];
61
63
  title?: React.ReactNode;
62
64
  trigger?: React.ReactElement;
63
65
  triggerButtonProps?: Omit<React.ComponentProps<typeof Button>, "children">;
@@ -65,7 +67,7 @@ type DataTableFilterProps = Omit<FilterProps, "children"> & {
65
67
  triggerHideCountWhenZero?: boolean;
66
68
  triggerLabel?: React.ReactNode;
67
69
  };
68
- declare function DataTableFilter({ applyButtonProps, children, closeOnApply, closeOnReset, contentProps, defaultJoin, defaultOpen, defaultValue, fields, footer, onApply, onOpenChange, open, popoverBodyProps, popoverContentProps, popoverFooterProps, popoverHeaderProps, resetButtonProps, title, trigger, triggerButtonProps, triggerCountClassName, triggerHideCountWhenZero, triggerLabel }: DataTableFilterProps): React.JSX.Element;
70
+ declare function DataTableFilter({ applyButtonProps, children, closeOnApply, closeOnReset, contentProps, defaultJoin, defaultOpen, defaultValue, fields, footer, onApply, onOpenChange, open, popoverBodyProps, popoverContentProps, popoverFooterProps, popoverHeaderProps, resetButtonProps, size, title, trigger, triggerButtonProps, triggerCountClassName, triggerHideCountWhenZero, triggerLabel }: DataTableFilterProps): React.JSX.Element;
69
71
  type DataTableTableProps<TData> = Omit<React.ComponentProps<typeof Table$1>, "children"> & {
70
72
  emptyState?: React.ReactNode;
71
73
  interactiveColumnIds?: string[];
@@ -74,7 +76,7 @@ type DataTableTableProps<TData> = Omit<React.ComponentProps<typeof Table$1>, "ch
74
76
  onRowClick?: (row: Row<TData>) => void;
75
77
  table?: Table<TData>;
76
78
  };
77
- declare function DataTable<TData>({ containerClassName, emptyState, interactiveColumnIds, isLoading: isLoadingProp, loadingRowCount, onRowClick: onRowClickProp, table: tableProp, ...props }: DataTableTableProps<TData>): string | number | bigint | true | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined>;
79
+ declare function DataTable<TData>({ className, containerClassName, emptyState, interactiveColumnIds, isLoading: isLoadingProp, loadingRowCount, onRowClick: onRowClickProp, table: tableProp, ...props }: DataTableTableProps<TData>): string | number | bigint | true | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined>;
78
80
  type DataTableCardGridProps<TData> = React.ComponentProps<"div"> & {
79
81
  actionsColumnId?: string;
80
82
  badgeColumnId?: string;
@@ -151,9 +153,11 @@ type DataTablePageSizeSelectProps<TData> = {
151
153
  /** Current page size. Overrides the table's pagination state when set. */
152
154
  pageSize?: number;
153
155
  pageSizeOptions?: number[];
156
+ /** Size of the trigger button. Mirrors `Button`'s sizes. */
157
+ size?: React.ComponentProps<typeof Button>["size"];
154
158
  table?: Table<TData>;
155
159
  };
156
- declare function DataTablePageSizeSelect<TData>({ className, label, onPageSizeChange, pageSize: pageSizeProp, pageSizeOptions, table: tableProp }: DataTablePageSizeSelectProps<TData>): React.JSX.Element;
160
+ declare function DataTablePageSizeSelect<TData>({ className, label, onPageSizeChange, pageSize: pageSizeProp, pageSizeOptions, size, table: tableProp }: DataTablePageSizeSelectProps<TData>): React.JSX.Element;
157
161
  type DataTableEmptyStateProps = {
158
162
  action?: React.ReactNode;
159
163
  description?: React.ReactNode;
@@ -141,7 +141,7 @@ function DataTableToolbar({ className, ...props }) {
141
141
  ...props
142
142
  });
143
143
  }
144
- function DataTableFilter({ applyButtonProps, children, closeOnApply = true, closeOnReset = true, contentProps, defaultJoin, defaultOpen = false, defaultValue, fields, footer, onApply, onOpenChange, open, popoverBodyProps, popoverContentProps, popoverFooterProps, popoverHeaderProps, resetButtonProps, title = "Filter", trigger, triggerButtonProps, triggerCountClassName, triggerHideCountWhenZero, triggerLabel = "Filters" }) {
144
+ function DataTableFilter({ applyButtonProps, children, closeOnApply = true, closeOnReset = true, contentProps, defaultJoin, defaultOpen = false, defaultValue, fields, footer, onApply, onOpenChange, open, popoverBodyProps, popoverContentProps, popoverFooterProps, popoverHeaderProps, resetButtonProps, size = "md", title = "Filter", trigger, triggerButtonProps, triggerCountClassName, triggerHideCountWhenZero, triggerLabel = "Filters" }) {
145
145
  const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
146
146
  const isOpenControlled = open !== void 0;
147
147
  const resolvedOpen = open ?? internalOpen;
@@ -169,7 +169,7 @@ function DataTableFilter({ applyButtonProps, children, closeOnApply = true, clos
169
169
  hideCountWhenZero: triggerHideCountWhenZero,
170
170
  children: /* @__PURE__ */ jsx(PopoverTrigger, { render: trigger ?? /* @__PURE__ */ jsxs(Button, {
171
171
  className: cn("group", triggerButtonClassName),
172
- size: "sm",
172
+ size,
173
173
  variant: "tertiary-outline",
174
174
  ...resolvedTriggerButtonProps,
175
175
  children: [
@@ -218,7 +218,7 @@ function DataTableFilter({ applyButtonProps, children, closeOnApply = true, clos
218
218
  })
219
219
  });
220
220
  }
221
- function DataTable({ containerClassName, emptyState, interactiveColumnIds = [ACTIONS_COLUMN_ID, ROW_SELECT_COLUMN_ID], isLoading: isLoadingProp, loadingRowCount = DEFAULT_SKELETON_ROW_COUNT, onRowClick: onRowClickProp, table: tableProp, ...props }) {
221
+ function DataTable({ className, containerClassName, emptyState, interactiveColumnIds = [ACTIONS_COLUMN_ID, ROW_SELECT_COLUMN_ID], isLoading: isLoadingProp, loadingRowCount = DEFAULT_SKELETON_ROW_COUNT, onRowClick: onRowClickProp, table: tableProp, ...props }) {
222
222
  const context = useOptionalDataTableContext();
223
223
  const table = tableProp ?? context?.table;
224
224
  const isLoading = isLoadingProp ?? context?.isLoading;
@@ -229,6 +229,7 @@ function DataTable({ containerClassName, emptyState, interactiveColumnIds = [ACT
229
229
  const skeletonRows = Array.from({ length: loadingRowCount }, (_, index) => index);
230
230
  if (isEmpty && emptyState) return emptyState;
231
231
  return /* @__PURE__ */ jsxs(Table$1, {
232
+ className: cn("table-fixed", className),
232
233
  containerClassName: cn("max-h-[68vh] overflow-y-auto", containerClassName),
233
234
  style: { width: table.getTotalSize() },
234
235
  ...props,
@@ -624,7 +625,7 @@ function range(start, end) {
624
625
  if (length <= 0) return [];
625
626
  return Array.from({ length }, (_, index) => start + index);
626
627
  }
627
- function DataTablePageSizeSelect({ className, label = (pageSize) => `Showing ${pageSize} entries`, onPageSizeChange, pageSize: pageSizeProp, pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS, table: tableProp }) {
628
+ function DataTablePageSizeSelect({ className, label = (pageSize) => `Showing ${pageSize} entries`, onPageSizeChange, pageSize: pageSizeProp, pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS, size = "md", table: tableProp }) {
628
629
  const context = useOptionalDataTableContext();
629
630
  const table = tableProp ?? context?.table;
630
631
  if (!(pageSizeProp !== void 0) && !table) throw new Error("DataTablePageSizeSelect requires either a table (prop or DataTable context) or the controlled `pageSize` prop.");
@@ -635,14 +636,16 @@ function DataTablePageSizeSelect({ className, label = (pageSize) => `Showing ${p
635
636
  if (onPageSizeChange) onPageSizeChange(nextPageSize);
636
637
  else table?.setPageSize(nextPageSize);
637
638
  };
639
+ const selectSize = size === "sm" || size === "md" || size === "lg" ? size : void 0;
638
640
  return /* @__PURE__ */ jsxs(Select, {
639
641
  value: pageSize.toString(),
640
642
  onValueChange: handleValueChange,
641
- size: "sm",
643
+ size: selectSize,
642
644
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
643
645
  unstyled: true,
644
646
  render: /* @__PURE__ */ jsx(Button, {
645
647
  variant: "tertiary-outline",
648
+ size,
646
649
  className
647
650
  }),
648
651
  children: /* @__PURE__ */ jsx(SelectValue, { children: () => label(pageSize) })
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/dialog-nesting.d.ts
3
+ declare function DialogNestingProvider({ children }: {
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
6
+ /** Depth of the current dialog (1 = top-level, 2+ = nested). */
7
+ declare function useDialogNestingDepth(): number;
8
+ //#endregion
9
+ export { DialogNestingProvider, useDialogNestingDepth };
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ //#region src/dialog-nesting.tsx
5
+ /**
6
+ * Tracks how deep a Dialog/Sheet is nested. Sheet and Dialog share the same
7
+ * Base UI primitive, so they share this one context too — a Dialog opened
8
+ * inside a Sheet (or vice-versa) counts as nested.
9
+ *
10
+ * Depth is 0 outside any dialog, 1 for a top-level dialog, 2+ for nested ones.
11
+ * Overlays use `depth > 1` to render lighter (so the parent shows through),
12
+ * while the base overlay keeps the full page-hiding dim.
13
+ */
14
+ const DialogNestingContext = createContext(0);
15
+ function DialogNestingProvider({ children }) {
16
+ const depth = useContext(DialogNestingContext);
17
+ return /* @__PURE__ */ jsx(DialogNestingContext.Provider, {
18
+ value: depth + 1,
19
+ children
20
+ });
21
+ }
22
+ /** Depth of the current dialog (1 = top-level, 2+ = nested). */
23
+ function useDialogNestingDepth() {
24
+ return useContext(DialogNestingContext);
25
+ }
26
+ //#endregion
27
+ export { DialogNestingProvider, useDialogNestingDepth };
package/dist/dialog.js CHANGED
@@ -2,16 +2,17 @@
2
2
  import { t as cn } from "./cn-BI_4DMBf.js";
3
3
  import { SizeProvider, useComponentSize } from "./size-context.js";
4
4
  import { Button } from "./button.js";
5
+ import { DialogNestingProvider, useDialogNestingDepth } from "./dialog-nesting.js";
5
6
  import { XIcon } from "lucide-react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  import { cva } from "class-variance-authority";
8
9
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
9
10
  //#region src/dialog.tsx
10
11
  function Dialog({ ...props }) {
11
- return /* @__PURE__ */ jsx(Dialog$1.Root, {
12
+ return /* @__PURE__ */ jsx(DialogNestingProvider, { children: /* @__PURE__ */ jsx(Dialog$1.Root, {
12
13
  "data-slot": "dialog",
13
14
  ...props
14
- });
15
+ }) });
15
16
  }
16
17
  function DialogTrigger({ ...props }) {
17
18
  return /* @__PURE__ */ jsx(Dialog$1.Trigger, {
@@ -32,13 +33,16 @@ function DialogClose({ ...props }) {
32
33
  });
33
34
  }
34
35
  function DialogOverlay({ className, ...props }) {
36
+ const nested = useDialogNestingDepth() > 1;
35
37
  return /* @__PURE__ */ jsx(Dialog$1.Backdrop, {
38
+ forceRender: true,
36
39
  "data-slot": "dialog-overlay",
37
- className: cn("fixed inset-0 z-50 bg-black/55 transition-opacity duration-150 data-closed:opacity-0 data-open:opacity-100 supports-backdrop-filter:backdrop-blur-xl", className),
40
+ "data-nested": nested || void 0,
41
+ className: cn("fixed inset-0 z-50 transition-opacity duration-150 data-closed:opacity-0 data-open:opacity-100", nested ? "bg-black/25" : "bg-black/55 supports-backdrop-filter:backdrop-blur-xl", className),
38
42
  ...props
39
43
  });
40
44
  }
41
- const dialogContentVariants = cva("group/dialog-content fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-5rem)] w-full max-w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-visible rounded-2xl border border-line-subtle bg-surface-overlay bg-clip-padding p-(--dialog-padding) text-fg-primary shadow-(--elevation-e2-shadow) outline-none [--dialog-padding:1.25rem] transition-[opacity,transform] duration-200 ease-in-out data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", {
45
+ const dialogContentVariants = cva("group/dialog-content fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-5rem)] w-full max-w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-visible rounded-2xl border border-line-subtle bg-surface-overlay bg-clip-padding p-(--dialog-padding) text-fg-primary shadow-(--elevation-e2-shadow) outline-none [--dialog-padding:1.25rem] transition-[opacity,transform] duration-200 ease-in-out data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 origin-center data-[nested-dialog-open]:scale-[0.96]", {
42
46
  variants: { size: {
43
47
  sm: "sm:w-90 sm:[--dialog-padding:1.5rem]",
44
48
  md: "sm:w-105 sm:[--dialog-padding:1.5rem]",
@@ -78,7 +82,7 @@ function DialogContent({ className, children, size, showCloseButton = true, ...p
78
82
  "data-slot": "dialog-close",
79
83
  render: /* @__PURE__ */ jsxs(Button, {
80
84
  variant: "tertiary",
81
- className: "absolute -top-10 right-0 z-10",
85
+ className: "absolute -top-10 right-0 z-10 group-data-[nested-dialog-open]/dialog-content:hidden",
82
86
  size: "icon-sm",
83
87
  children: [/* @__PURE__ */ jsx(XIcon, {}), /* @__PURE__ */ jsx("span", {
84
88
  className: "sr-only",
@@ -0,0 +1,43 @@
1
+ import { CircularProgressProps, ProgressProps } from "./progress.js";
2
+ import { ComponentProps, ReactNode } from "react";
3
+ //#region src/file-upload.d.ts
4
+ type FileUploadState = "pending" | "uploading" | "complete" | "error";
5
+ type FileUploadContextValue = {
6
+ state: FileUploadState;
7
+ value: number;
8
+ };
9
+ declare function useFileUpload(): FileUploadContextValue;
10
+ type FileUploadProps = ComponentProps<"div"> & {
11
+ state?: FileUploadState;
12
+ value: number;
13
+ };
14
+ declare function FileUpload({ className, state, value, "aria-busy": ariaBusy, ...props }: FileUploadProps): import("react").JSX.Element;
15
+ declare function FileUploadPreview({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
16
+ declare function FileUploadImage({ className, alt, ...props }: ComponentProps<"img">): import("react").JSX.Element;
17
+ declare function FileUploadOverlay({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
18
+ declare function FileUploadPreviewAction({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
19
+ declare function FileUploadIcon({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
20
+ declare function FileUploadContent({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
21
+ declare function FileUploadHeader({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
22
+ declare function FileUploadName({ className, ...props }: ComponentProps<"p">): import("react").JSX.Element;
23
+ declare function FileUploadMeta({ className, ...props }: ComponentProps<"p">): import("react").JSX.Element;
24
+ type FileUploadStatusProps = Omit<ComponentProps<"output">, "children"> & {
25
+ children?: ReactNode | ((context: FileUploadContextValue) => ReactNode);
26
+ pendingLabel?: ReactNode;
27
+ uploadingLabel?: ReactNode;
28
+ completeLabel?: ReactNode;
29
+ errorLabel?: ReactNode;
30
+ };
31
+ declare function FileUploadStatus({ className, children, pendingLabel, uploadingLabel, completeLabel, errorLabel, ...props }: FileUploadStatusProps): import("react").JSX.Element;
32
+ type FileUploadProgressProps = Omit<ProgressProps, "value"> & {
33
+ showValue?: boolean;
34
+ };
35
+ declare function FileUploadProgress({ className, children, showValue, "aria-label": ariaLabel, ...props }: FileUploadProgressProps): import("react").JSX.Element;
36
+ type FileUploadCircularProgressProps = Omit<CircularProgressProps, "value">;
37
+ declare function FileUploadCircularProgress({ className, labelOverlay, "aria-label": ariaLabel, ...props }: FileUploadCircularProgressProps): import("react").JSX.Element;
38
+ type FileUploadCancelProps = ComponentProps<"button"> & {
39
+ variant?: "ghost" | "surface";
40
+ };
41
+ declare function FileUploadCancel({ className, type, children, variant, "aria-label": ariaLabel, ...props }: FileUploadCancelProps): import("react").JSX.Element;
42
+ //#endregion
43
+ export { FileUpload, FileUploadCancel, type FileUploadCancelProps, FileUploadCircularProgress, type FileUploadCircularProgressProps, FileUploadContent, type FileUploadContextValue, FileUploadHeader, FileUploadIcon, FileUploadImage, FileUploadMeta, FileUploadName, FileUploadOverlay, FileUploadPreview, FileUploadPreviewAction, FileUploadProgress, type FileUploadProgressProps, type FileUploadProps, type FileUploadState, FileUploadStatus, type FileUploadStatusProps, useFileUpload };