@olympusoss/canvas 2.20.1 → 4.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 (208) hide show
  1. package/package.json +41 -177
  2. package/src/cn.ts +3 -0
  3. package/src/index.ts +12 -603
  4. package/src/theme.ts +41 -0
  5. package/src/tokens.ts +11 -0
  6. package/styles/base.css +17 -0
  7. package/styles/canvas.css +69 -52
  8. package/styles/components/alert.css +66 -0
  9. package/styles/components/app-shell.css +46 -0
  10. package/styles/components/avatar.css +15 -0
  11. package/styles/components/badge.css +83 -0
  12. package/styles/components/breadcrumb.css +35 -0
  13. package/styles/components/button-group.css +23 -0
  14. package/styles/components/button.css +107 -0
  15. package/styles/components/calendar.css +73 -0
  16. package/styles/components/card.css +58 -0
  17. package/styles/components/checkbox.css +55 -0
  18. package/styles/components/code-block.css +18 -0
  19. package/styles/components/combobox.css +75 -0
  20. package/styles/components/command.css +94 -0
  21. package/styles/components/data-table.css +142 -0
  22. package/styles/components/dialog.css +72 -0
  23. package/styles/components/dropdown.css +54 -0
  24. package/styles/components/empty-state.css +17 -0
  25. package/styles/components/field.css +27 -0
  26. package/styles/components/filter-panel.css +58 -0
  27. package/styles/components/form.css +27 -0
  28. package/styles/components/icon.css +8 -0
  29. package/styles/components/input-group.css +45 -0
  30. package/styles/components/input.css +56 -0
  31. package/styles/components/kbd.css +15 -0
  32. package/styles/components/page-header.css +52 -0
  33. package/styles/components/pagination.css +48 -0
  34. package/styles/components/popover.css +14 -0
  35. package/styles/components/radio.css +28 -0
  36. package/styles/components/row-menu.css +69 -0
  37. package/styles/components/section-card.css +49 -0
  38. package/styles/components/select.css +57 -0
  39. package/styles/components/separator.css +32 -0
  40. package/styles/components/sheet.css +70 -0
  41. package/styles/components/sidebar.css +146 -0
  42. package/styles/components/skeleton.css +32 -0
  43. package/styles/components/spinner.css +26 -0
  44. package/styles/components/stat-card.css +71 -0
  45. package/styles/components/stepper.css +63 -0
  46. package/styles/components/switch.css +45 -0
  47. package/styles/components/tabs.css +40 -0
  48. package/styles/components/textarea.css +31 -0
  49. package/styles/components/toast.css +95 -0
  50. package/styles/components/tooltip.css +53 -0
  51. package/styles/components/topbar.css +24 -0
  52. package/styles/components/typography.css +105 -0
  53. package/styles/patterns/backdrops.css +35 -0
  54. package/styles/patterns/density.css +66 -0
  55. package/styles/patterns/focus.css +38 -0
  56. package/styles/patterns/glass.css +85 -0
  57. package/styles/patterns/high-contrast.css +70 -0
  58. package/styles/patterns/reduced-motion.css +12 -0
  59. package/styles/patterns/scrollbar.css +10 -0
  60. package/styles/reset.css +89 -0
  61. package/styles/tokens/colors.css +106 -0
  62. package/styles/tokens/motion.css +33 -0
  63. package/styles/tokens/radius.css +10 -0
  64. package/styles/tokens/shadows.css +35 -0
  65. package/styles/tokens/spacing.css +19 -0
  66. package/styles/tokens/typography.css +6 -0
  67. package/styles/tokens/z-index.css +12 -0
  68. package/tsconfig.json +20 -21
  69. package/README.md +0 -60
  70. package/src/components/atoms/README.md +0 -11
  71. package/src/components/atoms/aspect-ratio.tsx +0 -32
  72. package/src/components/atoms/avatar.tsx +0 -98
  73. package/src/components/atoms/badge.tsx +0 -44
  74. package/src/components/atoms/brand-mark.tsx +0 -74
  75. package/src/components/atoms/button.tsx +0 -105
  76. package/src/components/atoms/checkbox.tsx +0 -63
  77. package/src/components/atoms/flex-box.tsx +0 -105
  78. package/src/components/atoms/icon.tsx +0 -34
  79. package/src/components/atoms/input.tsx +0 -92
  80. package/src/components/atoms/label.tsx +0 -41
  81. package/src/components/atoms/logo.tsx +0 -89
  82. package/src/components/atoms/progress.tsx +0 -55
  83. package/src/components/atoms/radio-group.tsx +0 -122
  84. package/src/components/atoms/scroll-area.tsx +0 -106
  85. package/src/components/atoms/section.tsx +0 -48
  86. package/src/components/atoms/separator.tsx +0 -45
  87. package/src/components/atoms/skeleton.tsx +0 -17
  88. package/src/components/atoms/slider.tsx +0 -93
  89. package/src/components/atoms/spinner.tsx +0 -47
  90. package/src/components/atoms/switch.tsx +0 -60
  91. package/src/components/atoms/textarea.tsx +0 -78
  92. package/src/components/atoms/toggle.tsx +0 -80
  93. package/src/components/charts/activity-heatmap.tsx +0 -186
  94. package/src/components/charts/axes.tsx +0 -21
  95. package/src/components/charts/chart-container.tsx +0 -254
  96. package/src/components/charts/chart-legend.tsx +0 -67
  97. package/src/components/charts/chart-tooltip.tsx +0 -161
  98. package/src/components/charts/chart-types.tsx +0 -49
  99. package/src/components/charts/containers.tsx +0 -11
  100. package/src/components/charts/data.tsx +0 -16
  101. package/src/components/charts/details.tsx +0 -25
  102. package/src/components/charts/dot-pulse.tsx +0 -61
  103. package/src/components/charts/gauge.tsx +0 -106
  104. package/src/components/charts/grids.tsx +0 -8
  105. package/src/components/charts/index.ts +0 -62
  106. package/src/components/charts/labeled-bar-list.tsx +0 -85
  107. package/src/components/charts/metric-breakdown.tsx +0 -316
  108. package/src/components/charts/references.tsx +0 -8
  109. package/src/components/charts/service-health-list.tsx +0 -85
  110. package/src/components/charts/sparkline-area.tsx +0 -80
  111. package/src/components/charts/sparkline.tsx +0 -52
  112. package/src/components/charts/stacked-bar.tsx +0 -104
  113. package/src/components/charts/text.tsx +0 -10
  114. package/src/components/charts/world-heat-map-inner.tsx +0 -317
  115. package/src/components/charts/world-heat-map.tsx +0 -184
  116. package/src/components/molecules/README.md +0 -12
  117. package/src/components/molecules/action-bar.tsx +0 -73
  118. package/src/components/molecules/activity-item.tsx +0 -74
  119. package/src/components/molecules/alert.tsx +0 -86
  120. package/src/components/molecules/animated-background.tsx +0 -92
  121. package/src/components/molecules/auth-shell.tsx +0 -95
  122. package/src/components/molecules/brand-lockup.tsx +0 -48
  123. package/src/components/molecules/breadcrumb.tsx +0 -157
  124. package/src/components/molecules/button-group.tsx +0 -104
  125. package/src/components/molecules/calendar.tsx +0 -217
  126. package/src/components/molecules/card.tsx +0 -102
  127. package/src/components/molecules/client-brand.tsx +0 -95
  128. package/src/components/molecules/code-block.tsx +0 -86
  129. package/src/components/molecules/countdown-button.tsx +0 -92
  130. package/src/components/molecules/empty-state.tsx +0 -56
  131. package/src/components/molecules/error-state.tsx +0 -42
  132. package/src/components/molecules/field-display.tsx +0 -35
  133. package/src/components/molecules/input-otp.tsx +0 -74
  134. package/src/components/molecules/launcher-card.tsx +0 -152
  135. package/src/components/molecules/loading-state.tsx +0 -36
  136. package/src/components/molecules/notification-item.tsx +0 -67
  137. package/src/components/molecules/notification-list.tsx +0 -45
  138. package/src/components/molecules/number-badge.tsx +0 -53
  139. package/src/components/molecules/or-separator.tsx +0 -38
  140. package/src/components/molecules/page-header.tsx +0 -88
  141. package/src/components/molecules/page-tabs.tsx +0 -94
  142. package/src/components/molecules/pagination.tsx +0 -150
  143. package/src/components/molecules/password-input.tsx +0 -83
  144. package/src/components/molecules/password-strength-meter.tsx +0 -104
  145. package/src/components/molecules/phone-input.tsx +0 -200
  146. package/src/components/molecules/search-bar.tsx +0 -64
  147. package/src/components/molecules/secret-field.tsx +0 -158
  148. package/src/components/molecules/section-card.tsx +0 -91
  149. package/src/components/molecules/social-buttons.tsx +0 -165
  150. package/src/components/molecules/stat-card.tsx +0 -100
  151. package/src/components/molecules/status-badge.tsx +0 -42
  152. package/src/components/molecules/stepper.tsx +0 -96
  153. package/src/components/molecules/table.tsx +0 -157
  154. package/src/components/molecules/terminal.tsx +0 -74
  155. package/src/components/molecules/toggle-group.tsx +0 -145
  156. package/src/components/molecules/tooltip.tsx +0 -155
  157. package/src/components/molecules/user-avatar-chip.tsx +0 -71
  158. package/src/components/organisms/README.md +0 -14
  159. package/src/components/organisms/accordion.tsx +0 -154
  160. package/src/components/organisms/alert-dialog.tsx +0 -277
  161. package/src/components/organisms/carousel.tsx +0 -244
  162. package/src/components/organisms/collapsible.tsx +0 -69
  163. package/src/components/organisms/command.tsx +0 -144
  164. package/src/components/organisms/context-menu.tsx +0 -339
  165. package/src/components/organisms/dashboard-grid.tsx +0 -369
  166. package/src/components/organisms/data-table.tsx +0 -330
  167. package/src/components/organisms/dialog.tsx +0 -312
  168. package/src/components/organisms/drawer.tsx +0 -123
  169. package/src/components/organisms/dropdown-menu.tsx +0 -440
  170. package/src/components/organisms/editors/code-editor.tsx +0 -144
  171. package/src/components/organisms/editors/index.ts +0 -4
  172. package/src/components/organisms/editors/markdown-editor.tsx +0 -153
  173. package/src/components/organisms/editors/markdown-renderer.ts +0 -27
  174. package/src/components/organisms/editors/prose-canvas-classes.ts +0 -45
  175. package/src/components/organisms/editors/rich-text-editor.tsx +0 -126
  176. package/src/components/organisms/editors/toolbar/md-toolbar.tsx +0 -129
  177. package/src/components/organisms/editors/toolbar/rte-toolbar.tsx +0 -211
  178. package/src/components/organisms/editors/toolbar/toolbar-shell.tsx +0 -45
  179. package/src/components/organisms/editors/use-codemirror-theme.ts +0 -61
  180. package/src/components/organisms/error-boundary.tsx +0 -61
  181. package/src/components/organisms/form.tsx +0 -174
  182. package/src/components/organisms/hover-card.tsx +0 -115
  183. package/src/components/organisms/menubar.tsx +0 -498
  184. package/src/components/organisms/navbar.tsx +0 -104
  185. package/src/components/organisms/navigation-menu.tsx +0 -235
  186. package/src/components/organisms/popover.tsx +0 -149
  187. package/src/components/organisms/resizable.tsx +0 -58
  188. package/src/components/organisms/schema-form.tsx +0 -232
  189. package/src/components/organisms/select.tsx +0 -309
  190. package/src/components/organisms/sheet.tsx +0 -265
  191. package/src/components/organisms/sidebar.tsx +0 -1040
  192. package/src/components/organisms/sonner.tsx +0 -96
  193. package/src/components/organisms/tabs.tsx +0 -133
  194. package/src/components/organisms/theme-provider.tsx +0 -101
  195. package/src/hooks/use-mobile.tsx +0 -19
  196. package/src/lib/portal-container.tsx +0 -35
  197. package/src/lib/utils.ts +0 -6
  198. package/src/native.ts +0 -23
  199. package/src/tokens/colors.ts +0 -91
  200. package/src/tokens/index.ts +0 -3
  201. package/src/tokens/spacing.ts +0 -55
  202. package/src/tokens/typography.ts +0 -27
  203. package/styles/dashboard-grid.css +0 -47
  204. package/styles/fonts/Roboto-VariableFont_wdth_wght.ttf +0 -0
  205. package/styles/glass.css +0 -171
  206. package/styles/leaflet.css +0 -13
  207. package/styles/tokens.css +0 -317
  208. package/tailwind.config.ts +0 -70
@@ -1,161 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import * as RechartsPrimitive from "recharts";
5
-
6
- import { cn } from "../../lib/utils";
7
- import { getPayloadConfigFromPayload, useChart } from "./chart-container";
8
-
9
- const ChartTooltip = RechartsPrimitive.Tooltip;
10
-
11
- const ChartTooltipContent = React.forwardRef<
12
- HTMLDivElement,
13
- React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
14
- React.ComponentProps<"div"> & {
15
- hideLabel?: boolean;
16
- hideIndicator?: boolean;
17
- indicator?: "line" | "dot" | "dashed";
18
- nameKey?: string;
19
- labelKey?: string;
20
- }
21
- >(
22
- (
23
- {
24
- active,
25
- payload,
26
- className,
27
- indicator = "dot",
28
- hideLabel = false,
29
- hideIndicator = false,
30
- label,
31
- labelFormatter,
32
- labelClassName,
33
- formatter,
34
- color,
35
- nameKey,
36
- labelKey,
37
- },
38
- ref,
39
- ) => {
40
- const { config } = useChart();
41
-
42
- const tooltipLabel = React.useMemo(() => {
43
- if (hideLabel || !payload?.length) {
44
- return null;
45
- }
46
-
47
- const [item] = payload;
48
- /* c8 ignore next -- the || chain prefers labelKey when set; the remaining fallbacks are recharts-internal edge cases */
49
- const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
50
- const itemConfig = getPayloadConfigFromPayload(config, item, key);
51
- const value =
52
- !labelKey && typeof label === "string"
53
- ? config[label as keyof typeof config]?.label || label
54
- : itemConfig?.label;
55
-
56
- if (labelFormatter) {
57
- return (
58
- <div className={cn("font-medium", labelClassName)}>{labelFormatter(value, payload)}</div>
59
- );
60
- }
61
-
62
- /* c8 ignore next 3 -- defensive fallback: value is always truthy when this branch is reached in practice */
63
- if (!value) {
64
- return null;
65
- }
66
-
67
- return <div className={cn("font-medium", labelClassName)}>{value}</div>;
68
- }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
69
-
70
- if (!active || !payload?.length) {
71
- return null;
72
- }
73
-
74
- const nestLabel = payload.length === 1 && indicator !== "dot";
75
-
76
- return (
77
- <div
78
- ref={ref}
79
- className={cn(
80
- "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
81
- className,
82
- )}
83
- >
84
- {!nestLabel ? tooltipLabel : null}
85
- <div className="grid gap-1.5">
86
- {payload
87
- .filter((item) => item.type !== "none")
88
- .map((item, index) => {
89
- /* c8 ignore next -- prefers nameKey when provided; remaining fallbacks are recharts-internal edge cases */
90
- const key = `${nameKey || item.name || item.dataKey || "value"}`;
91
- const itemConfig = getPayloadConfigFromPayload(config, item, key);
92
- /* c8 ignore next -- defers to explicit color prop; remaining fallbacks cover recharts-internal edge cases */
93
- const indicatorColor = color || item.payload.fill || item.color;
94
-
95
- return (
96
- <div
97
- key={item.dataKey}
98
- className={cn(
99
- "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
100
- indicator === "dot" && "items-center",
101
- )}
102
- >
103
- {formatter && item?.value !== undefined && item.name ? (
104
- formatter(item.value, item.name, item, index, item.payload)
105
- ) : (
106
- <>
107
- {itemConfig?.icon ? (
108
- <itemConfig.icon />
109
- ) : (
110
- !hideIndicator && (
111
- <div
112
- className={cn(
113
- "shrink-0 rounded-[2px] border-[var(--color-border)] bg-[var(--color-bg)]",
114
- {
115
- "h-2.5 w-2.5": indicator === "dot",
116
- "w-1": indicator === "line",
117
- "w-0 border-[1.5px] border-dashed bg-transparent":
118
- indicator === "dashed",
119
- "my-0.5": nestLabel && indicator === "dashed",
120
- },
121
- )}
122
- style={
123
- {
124
- "--color-bg": indicatorColor,
125
- "--color-border": indicatorColor,
126
- } as React.CSSProperties
127
- }
128
- />
129
- )
130
- )}
131
- <div
132
- className={cn(
133
- "flex flex-1 justify-between leading-none",
134
- nestLabel ? "items-end" : "items-center",
135
- )}
136
- >
137
- <div className="grid gap-1.5">
138
- {nestLabel ? tooltipLabel : null}
139
- <span className="text-muted-foreground">
140
- {itemConfig?.label || item.name}
141
- </span>
142
- </div>
143
- {item.value && (
144
- <span className="font-mono font-medium tabular-nums text-foreground">
145
- {item.value.toLocaleString()}
146
- </span>
147
- )}
148
- </div>
149
- </>
150
- )}
151
- </div>
152
- );
153
- })}
154
- </div>
155
- </div>
156
- );
157
- },
158
- );
159
- ChartTooltipContent.displayName = "ChartTooltip";
160
-
161
- export { ChartTooltip, ChartTooltipContent };
@@ -1,49 +0,0 @@
1
- "use client";
2
-
3
- import type * as React from "react";
4
- import * as RechartsPrimitive from "recharts";
5
-
6
- /**
7
- * Chart-type wrappers. Each wraps a Recharts top-level chart component with
8
- * sensible default `margin` so axis labels don't clip. Children pass through
9
- * UNWRAPPED — Recharts uses `findAllByType` on its direct children to detect
10
- * `<Line>` / `<XAxis>` / `<CartesianGrid>` etc., so any extra wrapper element
11
- * (Context.Provider, fragment-only-on-render, etc.) breaks chart rendering.
12
- *
13
- * The auto-palette context is established by `<ChartContainer>` instead, so
14
- * data primitives still cycle through `--chart-N` colours when no fill /
15
- * stroke is supplied.
16
- *
17
- * Margin defaults are merged with any user-supplied margin (user wins on
18
- * conflict). Everything else is straight pass-through.
19
- */
20
-
21
- const DEFAULT_MARGIN = { top: 12, right: 12, bottom: 4, left: 0 } as const;
22
-
23
- function withDefaults<P extends { children?: React.ReactNode; margin?: object }>(
24
- Comp: React.ComponentType<P>,
25
- ): React.FC<P> {
26
- const Wrapped = ({ children, margin, ...rest }: P) => {
27
- const merged = { ...DEFAULT_MARGIN, ...(margin ?? {}) };
28
- const props = { ...rest, margin: merged } as any;
29
- return <Comp {...props}>{children}</Comp>;
30
- };
31
- /* c8 ignore next -- defensive: every recharts top-level chart component ships with a `displayName`; the `?? Comp.name ?? "Anonymous"` fallback chain only fires for hand-rolled non-recharts wrappers */
32
- Wrapped.displayName = `Chart(${(Comp as { displayName?: string }).displayName ?? Comp.name ?? "Anonymous"})`;
33
- return Wrapped;
34
- }
35
-
36
- export const LineChart = withDefaults(RechartsPrimitive.LineChart);
37
- export const BarChart = withDefaults(RechartsPrimitive.BarChart);
38
- export const AreaChart = withDefaults(RechartsPrimitive.AreaChart);
39
- export const ComposedChart = withDefaults(RechartsPrimitive.ComposedChart);
40
- export const PieChart = withDefaults(RechartsPrimitive.PieChart);
41
- export const ScatterChart = withDefaults(RechartsPrimitive.ScatterChart);
42
- export const RadarChart = withDefaults(RechartsPrimitive.RadarChart);
43
- export const RadialBarChart = withDefaults(RechartsPrimitive.RadialBarChart);
44
- export const FunnelChart = withDefaults(RechartsPrimitive.FunnelChart);
45
- export const SunburstChart = withDefaults(RechartsPrimitive.SunburstChart);
46
-
47
- // Treemap and Sankey have a different children shape — pure pass-throughs.
48
- export const Treemap = RechartsPrimitive.Treemap;
49
- export const Sankey = RechartsPrimitive.Sankey;
@@ -1,11 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Container-level Recharts primitives. Pure pass-throughs.
5
- * `ResponsiveContainer` is also re-rendered internally by `<ChartContainer>`,
6
- * but consumers might want to use it directly for non-canvas-themed charts.
7
- *
8
- * NOTE: re-exported via `export { … }` (not `export const = …`) so TypeScript
9
- * doesn't have to name internal Recharts prop types in the d.ts emit.
10
- */
11
- export { Brush, Layer, ResponsiveContainer, Surface } from "recharts";
@@ -1,16 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Data-primitive re-exports. These are direct pass-throughs of the Recharts
5
- * primitives — wrapping them in our own function components breaks Recharts'
6
- * `findAllByType` introspection (it looks for `child.type === Bar` etc., and
7
- * a wrapper's `type` is our function, not Bar). The earlier wrapped version
8
- * crashed Recharts with "Cannot read properties of undefined (reading
9
- * 'yAxisId')" because the chart-type couldn't find our axes / data.
10
- *
11
- * Auto-palette cycling happens inside `<ChartContainer>` via a deep
12
- * `React.cloneElement` walk that injects `fill`/`stroke` defaults when the
13
- * consumer didn't supply one. The wrapped types remain the real Recharts
14
- * classes, so axis detection / chart-type child resolution keep working.
15
- */
16
- export { Area, Bar, Funnel, Line, Pie, Radar, RadialBar, Scatter } from "recharts";
@@ -1,25 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Detail-level Recharts primitives. Pure pass-throughs — no theming
5
- * opportunity, but re-exported here so consumers can import the entire
6
- * Recharts surface from canvas.
7
- *
8
- * `Cell` and `Customized` are aliased to `ChartCell` / `ChartCustomized` to
9
- * avoid likely future collisions with canvas-domain primitives.
10
- *
11
- * Re-exported via `export { … }` (not `export const = …`) so TypeScript
12
- * doesn't have to name internal Recharts prop types in the d.ts emit.
13
- */
14
- export {
15
- Cell as ChartCell,
16
- Cross,
17
- Curve,
18
- Customized as ChartCustomized,
19
- Dot,
20
- ErrorBar,
21
- Polygon,
22
- Rectangle,
23
- Sector,
24
- Trapezoid,
25
- } from "recharts";
@@ -1,61 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface DotPulseProps extends React.HTMLAttributes<HTMLDivElement> {
6
- /** Number of active (pulsing) dots. Clamped to `[0, total]`. */
7
- count: number;
8
- /** Total number of dots rendered. Default `5`. */
9
- total?: number;
10
- /**
11
- * CSS variable name (without leading `--`) used for active dot fill.
12
- * Default `chart-1`. The variable should resolve to an HSL triplet.
13
- */
14
- colorVar?: string;
15
- }
16
-
17
- /**
18
- * Pure-CSS severity indicator: a row of small circles where the first `count`
19
- * dots pulse with color and the rest are muted. Designed for `<StatCard>`
20
- * slots where no time-series data exists (e.g. lockout counts).
21
- */
22
- export const DotPulse = React.forwardRef<HTMLDivElement, DotPulseProps>(
23
- ({ count, total = 5, colorVar = "chart-1", className, ...props }, ref) => {
24
- const active = Math.max(0, Math.min(total, count));
25
- const color = `hsl(var(--${colorVar}))`;
26
-
27
- return (
28
- <div
29
- ref={ref}
30
- className={cn("flex items-center gap-2", className)}
31
- role="presentation"
32
- {...props}
33
- >
34
- {Array.from({ length: total }, (_, i) => {
35
- const isActive = i < active;
36
- return (
37
- <span
38
- key={i}
39
- className={cn("inline-block size-2 rounded-full", !isActive && "bg-muted")}
40
- style={
41
- isActive
42
- ? {
43
- background: color,
44
- animation: `canvas-dot-pulse 1.5s ease-in-out infinite`,
45
- animationDelay: `${i * 0.15}s`,
46
- }
47
- : undefined
48
- }
49
- aria-hidden
50
- />
51
- );
52
- })}
53
- <style>{`@keyframes canvas-dot-pulse {
54
- 0%, 100% { transform: scale(1); opacity: 1; }
55
- 50% { transform: scale(1.4); opacity: 0.5; }
56
- }`}</style>
57
- </div>
58
- );
59
- },
60
- );
61
- DotPulse.displayName = "DotPulse";
@@ -1,106 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface GaugeProps extends React.HTMLAttributes<HTMLDivElement> {
6
- /** Percentage to fill (0–100). Values outside the range are clamped. */
7
- value: number;
8
- /** Pixel size (width = height). Default `160`. */
9
- size?: number;
10
- /** Pixel stroke width of the ring. Default `14`. */
11
- strokeWidth?: number;
12
- /**
13
- * CSS variable name (without leading `--`) used for the filled arc. Default
14
- * `chart-1`.
15
- */
16
- colorVar?: string;
17
- /**
18
- * Center value text. Defaults to `"{value}%"`. Pass a custom node to render
19
- * something richer (e.g. a unit label).
20
- */
21
- valueLabel?: React.ReactNode;
22
- /** Small label rendered below the centre value. Optional. */
23
- caption?: React.ReactNode;
24
- /** Accessible label describing the gauge. Default `"Gauge"`. */
25
- "aria-label"?: string;
26
- }
27
-
28
- /**
29
- * Single-arc circular gauge with a centered value. Useful for adoption
30
- * percentages, health scores, completion ratios, and similar 0–100 metrics.
31
- * Renders a complete background ring plus a filled arc; the arc is animated
32
- * via `transition-[stroke-dashoffset]` so consumers get smooth updates when
33
- * `value` changes.
34
- */
35
- export const Gauge = React.forwardRef<HTMLDivElement, GaugeProps>(
36
- (
37
- {
38
- value,
39
- size = 160,
40
- strokeWidth = 14,
41
- colorVar = "chart-1",
42
- valueLabel,
43
- caption,
44
- className,
45
- "aria-label": ariaLabel = "Gauge",
46
- ...props
47
- },
48
- ref,
49
- ) => {
50
- const clamped = Math.max(0, Math.min(100, value));
51
- const r = (size - strokeWidth) / 2;
52
- const cx = size / 2;
53
- const c = 2 * Math.PI * r;
54
- const offset = c - (clamped / 100) * c;
55
- const display = valueLabel ?? `${Math.round(clamped)}%`;
56
- return (
57
- <div
58
- ref={ref}
59
- role="meter"
60
- aria-label={ariaLabel}
61
- aria-valuenow={Math.round(clamped)}
62
- aria-valuemin={0}
63
- aria-valuemax={100}
64
- className={cn("relative inline-flex flex-col items-center", className)}
65
- style={{ width: size, height: caption ? "auto" : size }}
66
- {...props}
67
- >
68
- <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} aria-hidden>
69
- <circle
70
- cx={cx}
71
- cy={cx}
72
- r={r}
73
- fill="none"
74
- stroke="hsl(var(--muted))"
75
- strokeWidth={strokeWidth}
76
- />
77
- <circle
78
- cx={cx}
79
- cy={cx}
80
- r={r}
81
- fill="none"
82
- stroke={`hsl(var(--${colorVar}))`}
83
- strokeWidth={strokeWidth}
84
- strokeDasharray={c}
85
- strokeDashoffset={offset}
86
- strokeLinecap="round"
87
- transform={`rotate(-90 ${cx} ${cx})`}
88
- className="transition-[stroke-dashoffset] duration-500"
89
- />
90
- </svg>
91
- <div
92
- className="pointer-events-none absolute inset-x-0 flex flex-col items-center justify-center"
93
- style={{ top: 0, height: size }}
94
- >
95
- <span className="font-mono text-3xl font-bold tabular-nums">{display}</span>
96
- {caption && (
97
- <span className="mt-1 text-[11px] uppercase tracking-[0.04em] text-muted-foreground">
98
- {caption}
99
- </span>
100
- )}
101
- </div>
102
- </div>
103
- );
104
- },
105
- );
106
- Gauge.displayName = "Gauge";
@@ -1,8 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Grid re-exports — pure pass-throughs. Theming via CSS in `<ChartContainer>`
5
- * (`[&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50` etc.).
6
- * Wrapping breaks Recharts' child-by-type detection.
7
- */
8
- export { CartesianGrid, PolarGrid } from "recharts";
@@ -1,62 +0,0 @@
1
- // Container + style emitter (canvas-specific)
2
-
3
- // Chrome — canvas-token defaults
4
- export {
5
- CartesianAxis,
6
- PolarAngleAxis,
7
- PolarRadiusAxis,
8
- XAxis,
9
- YAxis,
10
- ZAxis,
11
- } from "./axes";
12
- export {
13
- type ChartConfig,
14
- ChartContainer,
15
- ChartStyle,
16
- useChart,
17
- } from "./chart-container";
18
- export { ChartLegend, ChartLegendContent } from "./chart-legend";
19
- export { ChartTooltip, ChartTooltipContent } from "./chart-tooltip";
20
- // Chart-type wrappers (`margin` defaults; auto-palette runs in ChartContainer)
21
- export {
22
- AreaChart,
23
- BarChart,
24
- ComposedChart,
25
- FunnelChart,
26
- LineChart,
27
- PieChart,
28
- RadarChart,
29
- RadialBarChart,
30
- Sankey,
31
- ScatterChart,
32
- SunburstChart,
33
- Treemap,
34
- } from "./chart-types";
35
- // Container-level — pure pass-through
36
- export { Brush, Layer, ResponsiveContainer, Surface } from "./containers";
37
- // Data primitives (auto-cycle palette)
38
- export { Area, Bar, Funnel, Line, Pie, Radar, RadialBar, Scatter } from "./data";
39
- // Detail primitives — pure pass-through
40
- export {
41
- ChartCell,
42
- ChartCustomized,
43
- Cross,
44
- Curve,
45
- Dot,
46
- ErrorBar,
47
- Polygon,
48
- Rectangle,
49
- Sector,
50
- Trapezoid,
51
- } from "./details";
52
- export { CartesianGrid, PolarGrid } from "./grids";
53
- export { ReferenceArea, ReferenceDot, ReferenceLine } from "./references";
54
- // Text + labels (Label aliased to avoid collision with canvas form Label)
55
- export { ChartLabel, LabelList, Text } from "./text";
56
-
57
- // Geographic — Leaflet-based heat-map (peer-optional `leaflet` + `react-leaflet`)
58
- export {
59
- WorldHeatMap,
60
- type WorldHeatMapPoint,
61
- type WorldHeatMapProps,
62
- } from "./world-heat-map";
@@ -1,85 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- export interface LabeledBarListItem {
6
- /** Row label. Used as the React key. */
7
- label: React.ReactNode;
8
- /** Numeric value rendered in the right cap; bar fill scales against the max. */
9
- value: number;
10
- /** Optional leading element — e.g. a flag, avatar, or `<Icon />`. */
11
- leading?: React.ReactNode;
12
- }
13
-
14
- export interface LabeledBarListProps extends React.HTMLAttributes<HTMLDivElement> {
15
- /** Rows rendered top-to-bottom. */
16
- items: LabeledBarListItem[];
17
- /**
18
- * CSS variable name (without leading `--`) used for the bar fill. Default
19
- * `chart-1`.
20
- */
21
- colorVar?: string;
22
- /** Format the value rendered to the right of each label. Default `toLocaleString`. */
23
- valueFormatter?: (value: number) => string;
24
- /** Pixel height of the row's bar track. Default `4`. */
25
- barHeight?: number;
26
- /** Caption rendered below the list. */
27
- caption?: React.ReactNode;
28
- }
29
-
30
- /**
31
- * Vertical list of labeled rows with a horizontal progress bar per row. Useful
32
- * for "top regions", "schema usage", "provider connections" — anywhere a small
33
- * set of named values needs proportional comparison without a full chart.
34
- */
35
- export const LabeledBarList = React.forwardRef<HTMLDivElement, LabeledBarListProps>(
36
- (
37
- {
38
- items,
39
- colorVar = "chart-1",
40
- valueFormatter = (v) => v.toLocaleString(),
41
- barHeight = 4,
42
- caption,
43
- className,
44
- ...props
45
- },
46
- ref,
47
- ) => {
48
- const max = Math.max(1, ...items.map((it) => it.value));
49
- return (
50
- <div ref={ref} className={cn("w-full", className)} {...props}>
51
- <ul className="flex flex-col gap-2.5">
52
- {items.map((item, i) => {
53
- const pct = Math.max(0, Math.min(100, (item.value / max) * 100));
54
- return (
55
- <li key={`${i}-${item.value}`} className="flex flex-col gap-1.5">
56
- <div className="flex items-center gap-2 text-[13px]">
57
- {item.leading && <span className="shrink-0">{item.leading}</span>}
58
- <span className="flex-1 truncate">{item.label}</span>
59
- <span className="font-mono text-xs text-muted-foreground tabular-nums">
60
- {valueFormatter(item.value)}
61
- </span>
62
- </div>
63
- <div
64
- className="overflow-hidden rounded-full bg-muted"
65
- style={{ height: barHeight }}
66
- aria-hidden
67
- >
68
- <div
69
- className="h-full rounded-full"
70
- style={{
71
- width: `${pct}%`,
72
- background: `hsl(var(--${colorVar}))`,
73
- }}
74
- />
75
- </div>
76
- </li>
77
- );
78
- })}
79
- </ul>
80
- {caption && <p className="mt-3 text-xs text-muted-foreground">{caption}</p>}
81
- </div>
82
- );
83
- },
84
- );
85
- LabeledBarList.displayName = "LabeledBarList";