@suzumiyaaoba/mdxr 0.1.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/LICENSE +21 -0
- package/README.md +56 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2902 -0
- package/dist/components.d.mts +791 -0
- package/dist/components.mjs +2 -0
- package/dist/config-SI9IyFiC.mjs +184 -0
- package/dist/doc-context-CEqzMYKv.d.mts +568 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.mjs +4 -0
- package/dist/ui-GKFD0mx5.mjs +15986 -0
- package/package.json +131 -0
- package/skill/SKILL.md +49 -0
- package/skill/references/components/charts.md +172 -0
- package/skill/references/components/document.md +98 -0
- package/skill/references/components/forms.md +35 -0
- package/skill/references/components/investigation.md +198 -0
- package/skill/references/components/layout.md +68 -0
- package/skill/references/components/output.md +158 -0
- package/skill/references/components/planning.md +155 -0
- package/skill/references/components/reports.md +252 -0
- package/skill/references/components/shadcn.md +19 -0
- package/skill/references/components.md +186 -0
- package/skill/references/extending.md +48 -0
- package/src/ask-sheet.ts +40 -0
- package/src/assets/css.ts +392 -0
- package/src/assets/scripts.ts +78 -0
- package/src/catalog.ts +287 -0
- package/src/cli.ts +178 -0
- package/src/client/doc-events.ts +1108 -0
- package/src/client/entry.ts +27 -0
- package/src/client-js.ts +47 -0
- package/src/component-map.ts +47 -0
- package/src/components/ui/accordion.tsx +77 -0
- package/src/components/ui/alert-dialog.tsx +185 -0
- package/src/components/ui/alert.tsx +76 -0
- package/src/components/ui/aspect-ratio.tsx +22 -0
- package/src/components/ui/attachment.tsx +208 -0
- package/src/components/ui/avatar.tsx +106 -0
- package/src/components/ui/badge.tsx +52 -0
- package/src/components/ui/breadcrumb.tsx +121 -0
- package/src/components/ui/bubble.tsx +128 -0
- package/src/components/ui/button-group.tsx +88 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/calendar.tsx +226 -0
- package/src/components/ui/card.tsx +102 -0
- package/src/components/ui/carousel.tsx +246 -0
- package/src/components/ui/chart.tsx +379 -0
- package/src/components/ui/checkbox.tsx +27 -0
- package/src/components/ui/collapsible.tsx +19 -0
- package/src/components/ui/combobox.tsx +298 -0
- package/src/components/ui/command.tsx +193 -0
- package/src/components/ui/context-menu.tsx +271 -0
- package/src/components/ui/dialog.tsx +159 -0
- package/src/components/ui/direction.tsx +4 -0
- package/src/components/ui/drawer.tsx +227 -0
- package/src/components/ui/dropdown-menu.tsx +269 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +237 -0
- package/src/components/ui/fieldset.tsx +32 -0
- package/src/components/ui/frame.tsx +87 -0
- package/src/components/ui/hover-card.tsx +50 -0
- package/src/components/ui/input-group.tsx +159 -0
- package/src/components/ui/input-otp.tsx +83 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/item.tsx +202 -0
- package/src/components/ui/kbd.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/marker.tsx +71 -0
- package/src/components/ui/menubar.tsx +284 -0
- package/src/components/ui/message-scroller.tsx +128 -0
- package/src/components/ui/message.tsx +91 -0
- package/src/components/ui/meter.tsx +80 -0
- package/src/components/ui/native-select.tsx +64 -0
- package/src/components/ui/navigation-menu.tsx +170 -0
- package/src/components/ui/pagination.tsx +133 -0
- package/src/components/ui/popover.tsx +87 -0
- package/src/components/ui/progress.tsx +82 -0
- package/src/components/ui/questionnaire.tsx +328 -0
- package/src/components/ui/radio-group.tsx +35 -0
- package/src/components/ui/resizable.tsx +49 -0
- package/src/components/ui/scroll-area.tsx +50 -0
- package/src/components/ui/select.tsx +201 -0
- package/src/components/ui/separator.tsx +22 -0
- package/src/components/ui/sheet.tsx +135 -0
- package/src/components/ui/sidebar.tsx +730 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +51 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +113 -0
- package/src/components/ui/tabs.tsx +82 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/toast.tsx +229 -0
- package/src/components/ui/toggle-group.tsx +87 -0
- package/src/components/ui/toggle.tsx +43 -0
- package/src/components/ui/tooltip.tsx +65 -0
- package/src/components.ts +78 -0
- package/src/config.ts +56 -0
- package/src/define.ts +122 -0
- package/src/doc-context.ts +20 -0
- package/src/editor.ts +94 -0
- package/src/format-error.ts +78 -0
- package/src/guards.ts +84 -0
- package/src/hooks/use-mobile.ts +21 -0
- package/src/html.ts +91 -0
- package/src/hydrate/export-index.ts +232 -0
- package/src/hydrate/import-scan.ts +169 -0
- package/src/hydrate/plugins.ts +118 -0
- package/src/hydrate/runtime-module.ts +145 -0
- package/src/hydrate-runtime.ts +67 -0
- package/src/hydrate.ts +147 -0
- package/src/index.ts +16 -0
- package/src/init.ts +57 -0
- package/src/langs.ts +148 -0
- package/src/lines.ts +53 -0
- package/src/load-user-module.ts +191 -0
- package/src/mdx.ts +248 -0
- package/src/paths.ts +36 -0
- package/src/rehype/shiki.ts +533 -0
- package/src/remark/alerts.ts +53 -0
- package/src/remark/ast.ts +96 -0
- package/src/remark/callouts.ts +25 -0
- package/src/remark/code-file.ts +85 -0
- package/src/remark/code-meta.ts +21 -0
- package/src/remark/directives.ts +170 -0
- package/src/remark/file-paths.ts +64 -0
- package/src/remark/headings.ts +131 -0
- package/src/remark/no-js.ts +40 -0
- package/src/render.ts +337 -0
- package/src/serve.ts +322 -0
- package/src/styles/globals.css +134 -0
- package/src/styles/shadcn.css +641 -0
- package/src/tailwind.ts +119 -0
- package/src/ui/approvals.tsx +76 -0
- package/src/ui/ask-question.tsx +386 -0
- package/src/ui/ask.tsx +206 -0
- package/src/ui/attrs.ts +51 -0
- package/src/ui/audit.tsx +139 -0
- package/src/ui/bar-chart.tsx +334 -0
- package/src/ui/benchmarks.tsx +143 -0
- package/src/ui/bits.tsx +537 -0
- package/src/ui/board.tsx +173 -0
- package/src/ui/bridge.tsx +207 -0
- package/src/ui/bumps.tsx +178 -0
- package/src/ui/callout.tsx +106 -0
- package/src/ui/changes.tsx +89 -0
- package/src/ui/chart-bits.tsx +52 -0
- package/src/ui/chart.ts +577 -0
- package/src/ui/checks.tsx +203 -0
- package/src/ui/child-index.tsx +44 -0
- package/src/ui/children.ts +43 -0
- package/src/ui/chips.tsx +49 -0
- package/src/ui/cmd.tsx +27 -0
- package/src/ui/columns.tsx +31 -0
- package/src/ui/comments.tsx +544 -0
- package/src/ui/compare.tsx +67 -0
- package/src/ui/decision.tsx +79 -0
- package/src/ui/deps.tsx +78 -0
- package/src/ui/details.tsx +43 -0
- package/src/ui/diff-parse.ts +307 -0
- package/src/ui/diff.tsx +458 -0
- package/src/ui/diffstat.tsx +58 -0
- package/src/ui/due.tsx +65 -0
- package/src/ui/effort.tsx +29 -0
- package/src/ui/endpoints.tsx +118 -0
- package/src/ui/envvars.tsx +96 -0
- package/src/ui/figure.tsx +37 -0
- package/src/ui/file-icon.ts +1020 -0
- package/src/ui/file-link.ts +32 -0
- package/src/ui/file-ref.tsx +39 -0
- package/src/ui/files.tsx +112 -0
- package/src/ui/findings.tsx +85 -0
- package/src/ui/flow.tsx +73 -0
- package/src/ui/funnel.tsx +121 -0
- package/src/ui/gantt.tsx +443 -0
- package/src/ui/gauges.tsx +135 -0
- package/src/ui/glossary.tsx +29 -0
- package/src/ui/graph-layout.ts +149 -0
- package/src/ui/graph-specs.tsx +102 -0
- package/src/ui/graph.tsx +278 -0
- package/src/ui/grid.tsx +119 -0
- package/src/ui/hypothesis.tsx +94 -0
- package/src/ui/icon.tsx +80 -0
- package/src/ui/incident.tsx +130 -0
- package/src/ui/index.ts +342 -0
- package/src/ui/ins-del.tsx +41 -0
- package/src/ui/json.tsx +190 -0
- package/src/ui/layout.ts +9 -0
- package/src/ui/line-chart.tsx +251 -0
- package/src/ui/matrix.tsx +208 -0
- package/src/ui/meta.tsx +73 -0
- package/src/ui/option.tsx +64 -0
- package/src/ui/owner.tsx +40 -0
- package/src/ui/packages.tsx +104 -0
- package/src/ui/pathway.tsx +96 -0
- package/src/ui/phase.tsx +41 -0
- package/src/ui/pie-chart.tsx +170 -0
- package/src/ui/plan.tsx +77 -0
- package/src/ui/pre.tsx +175 -0
- package/src/ui/priority.tsx +51 -0
- package/src/ui/props.tsx +77 -0
- package/src/ui/quadrant.tsx +172 -0
- package/src/ui/radar.tsx +200 -0
- package/src/ui/ref.tsx +160 -0
- package/src/ui/release.tsx +178 -0
- package/src/ui/req.tsx +42 -0
- package/src/ui/review.tsx +133 -0
- package/src/ui/risk.tsx +67 -0
- package/src/ui/sankey.tsx +287 -0
- package/src/ui/scatter.tsx +237 -0
- package/src/ui/schema.tsx +113 -0
- package/src/ui/score.tsx +105 -0
- package/src/ui/search.tsx +120 -0
- package/src/ui/series.tsx +38 -0
- package/src/ui/severity.tsx +69 -0
- package/src/ui/shadcn.tsx +216 -0
- package/src/ui/spark.tsx +86 -0
- package/src/ui/stack.tsx +57 -0
- package/src/ui/stats.tsx +63 -0
- package/src/ui/status-badge.tsx +66 -0
- package/src/ui/statuspage.tsx +238 -0
- package/src/ui/steps.tsx +74 -0
- package/src/ui/summary.tsx +41 -0
- package/src/ui/symbol-ref.tsx +73 -0
- package/src/ui/terminal.tsx +117 -0
- package/src/ui/tests.tsx +218 -0
- package/src/ui/timeline.tsx +63 -0
- package/src/ui/toc.tsx +56 -0
- package/src/ui/tones.ts +187 -0
- package/src/ui/trace.tsx +69 -0
- package/src/ui/tree.tsx +281 -0
- package/src/ui/treemap.tsx +128 -0
- package/src/ui/venn.tsx +258 -0
- package/src/ui/verdict.tsx +78 -0
- package/src/ui/waterfall.tsx +142 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as RechartsPrimitive from "recharts";
|
|
4
|
+
import type { TooltipValueType } from "recharts";
|
|
5
|
+
|
|
6
|
+
// Format: { THEME_NAME: CSS_SELECTOR }
|
|
7
|
+
const THEMES = { dark: ".dark", light: "" } as const;
|
|
8
|
+
|
|
9
|
+
const INITIAL_DIMENSION = { height: 200, width: 320 } as const;
|
|
10
|
+
type TooltipNameType = number | string;
|
|
11
|
+
|
|
12
|
+
export type ChartConfig = Record<
|
|
13
|
+
string,
|
|
14
|
+
{
|
|
15
|
+
label?: React.ReactNode;
|
|
16
|
+
icon?: React.ComponentType;
|
|
17
|
+
} & (
|
|
18
|
+
| { color?: string; theme?: never }
|
|
19
|
+
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
|
20
|
+
)
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
interface ChartContextProps {
|
|
24
|
+
config: ChartConfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ChartContext = React.createContext<ChartContextProps | null>(null);
|
|
28
|
+
|
|
29
|
+
function useChart() {
|
|
30
|
+
const context = React.useContext(ChartContext);
|
|
31
|
+
|
|
32
|
+
if (!context) {
|
|
33
|
+
throw new Error("useChart must be used within a <ChartContainer />");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return context;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ChartContainer({
|
|
40
|
+
id,
|
|
41
|
+
className,
|
|
42
|
+
children,
|
|
43
|
+
config,
|
|
44
|
+
initialDimension = INITIAL_DIMENSION,
|
|
45
|
+
...props
|
|
46
|
+
}: React.ComponentProps<"div"> & {
|
|
47
|
+
config: ChartConfig;
|
|
48
|
+
children: React.ComponentProps<
|
|
49
|
+
typeof RechartsPrimitive.ResponsiveContainer
|
|
50
|
+
>["children"];
|
|
51
|
+
initialDimension?: {
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
};
|
|
55
|
+
}) {
|
|
56
|
+
const uniqueId = React.useId();
|
|
57
|
+
const chartId = `chart-${id ?? uniqueId.replaceAll(":", "")}`;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<ChartContext.Provider value={{ config }}>
|
|
61
|
+
<div
|
|
62
|
+
data-slot="chart"
|
|
63
|
+
data-chart={chartId}
|
|
64
|
+
className={cn(
|
|
65
|
+
"[&_.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-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 flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
>
|
|
70
|
+
<ChartStyle id={chartId} config={config} />
|
|
71
|
+
<RechartsPrimitive.ResponsiveContainer
|
|
72
|
+
initialDimension={initialDimension}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</RechartsPrimitive.ResponsiveContainer>
|
|
76
|
+
</div>
|
|
77
|
+
</ChartContext.Provider>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Interpolated values land inside a <style> element — `<`/`>`/`&` must never
|
|
82
|
+
// survive (`</style>` breaks out of the element at the HTML level, regardless
|
|
83
|
+
// of CSS string quoting), and idents can't contain quotes/braces either.
|
|
84
|
+
const cssIdent = (s: string): string => s.replaceAll(/[^\w-]/gu, "");
|
|
85
|
+
const cssValue = (s: string): string => s.replaceAll(/[<>&'"\\{};]/gu, "");
|
|
86
|
+
|
|
87
|
+
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|
88
|
+
const colorConfig = Object.entries(config).filter(
|
|
89
|
+
([, config]) => config.theme ?? config.color
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (!colorConfig.length) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<style
|
|
98
|
+
dangerouslySetInnerHTML={{
|
|
99
|
+
__html: Object.entries(THEMES)
|
|
100
|
+
.map(
|
|
101
|
+
([theme, prefix]) => `
|
|
102
|
+
${prefix} [data-chart="${cssValue(id)}"] {
|
|
103
|
+
${colorConfig
|
|
104
|
+
.map(([key, itemConfig]) => {
|
|
105
|
+
const color =
|
|
106
|
+
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??
|
|
107
|
+
itemConfig.color;
|
|
108
|
+
return color ? ` --color-${cssIdent(key)}: ${cssValue(color)};` : null;
|
|
109
|
+
})
|
|
110
|
+
.join("\n")}
|
|
111
|
+
}
|
|
112
|
+
`
|
|
113
|
+
)
|
|
114
|
+
.join("\n"),
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const ChartTooltip = RechartsPrimitive.Tooltip;
|
|
121
|
+
|
|
122
|
+
function ChartTooltipContent({
|
|
123
|
+
active,
|
|
124
|
+
payload,
|
|
125
|
+
className,
|
|
126
|
+
indicator = "dot",
|
|
127
|
+
hideLabel = false,
|
|
128
|
+
hideIndicator = false,
|
|
129
|
+
label,
|
|
130
|
+
labelFormatter,
|
|
131
|
+
labelClassName,
|
|
132
|
+
formatter,
|
|
133
|
+
color,
|
|
134
|
+
nameKey,
|
|
135
|
+
labelKey,
|
|
136
|
+
}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
|
137
|
+
React.ComponentProps<"div"> & {
|
|
138
|
+
hideLabel?: boolean;
|
|
139
|
+
hideIndicator?: boolean;
|
|
140
|
+
indicator?: "line" | "dot" | "dashed";
|
|
141
|
+
nameKey?: string;
|
|
142
|
+
labelKey?: string;
|
|
143
|
+
} & Omit<
|
|
144
|
+
RechartsPrimitive.DefaultTooltipContentProps<
|
|
145
|
+
TooltipValueType,
|
|
146
|
+
TooltipNameType
|
|
147
|
+
>,
|
|
148
|
+
"accessibilityLayer"
|
|
149
|
+
>) {
|
|
150
|
+
const { config } = useChart();
|
|
151
|
+
|
|
152
|
+
const tooltipLabel = React.useMemo(() => {
|
|
153
|
+
if (hideLabel || !payload?.length) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const [item] = payload;
|
|
158
|
+
const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`;
|
|
159
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
160
|
+
const value =
|
|
161
|
+
!labelKey && typeof label === "string"
|
|
162
|
+
? (config[label]?.label ?? label)
|
|
163
|
+
: itemConfig?.label;
|
|
164
|
+
|
|
165
|
+
if (labelFormatter) {
|
|
166
|
+
return (
|
|
167
|
+
<div className={cn("font-medium", labelClassName)}>
|
|
168
|
+
{labelFormatter(value, payload)}
|
|
169
|
+
</div>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!value) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return <div className={cn("font-medium", labelClassName)}>{value}</div>;
|
|
178
|
+
}, [
|
|
179
|
+
label,
|
|
180
|
+
labelFormatter,
|
|
181
|
+
payload,
|
|
182
|
+
hideLabel,
|
|
183
|
+
labelClassName,
|
|
184
|
+
config,
|
|
185
|
+
labelKey,
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
if (!active || !payload?.length) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<div
|
|
196
|
+
className={cn(
|
|
197
|
+
"border-border/50 bg-background grid min-w-32 items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
|
|
198
|
+
className
|
|
199
|
+
)}
|
|
200
|
+
>
|
|
201
|
+
{nestLabel ? null : tooltipLabel}
|
|
202
|
+
<div className="grid gap-1.5">
|
|
203
|
+
{payload
|
|
204
|
+
.filter((item) => item.type !== "none")
|
|
205
|
+
.map((item, index) => {
|
|
206
|
+
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
|
|
207
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
208
|
+
const indicatorColor = color ?? item.payload?.fill ?? item.color;
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<div
|
|
212
|
+
key={index}
|
|
213
|
+
className={cn(
|
|
214
|
+
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
|
|
215
|
+
indicator === "dot" && "items-center"
|
|
216
|
+
)}
|
|
217
|
+
>
|
|
218
|
+
{formatter && item?.value !== undefined && item.name ? (
|
|
219
|
+
formatter(item.value, item.name, item, index, item.payload)
|
|
220
|
+
) : (
|
|
221
|
+
<>
|
|
222
|
+
{itemConfig?.icon ? (
|
|
223
|
+
<itemConfig.icon />
|
|
224
|
+
) : (
|
|
225
|
+
!hideIndicator && (
|
|
226
|
+
<div
|
|
227
|
+
className={cn(
|
|
228
|
+
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
|
|
229
|
+
{
|
|
230
|
+
"h-2.5 w-2.5": indicator === "dot",
|
|
231
|
+
"my-0.5": nestLabel && indicator === "dashed",
|
|
232
|
+
"w-0 border-[1.5px] border-dashed bg-transparent":
|
|
233
|
+
indicator === "dashed",
|
|
234
|
+
"w-1": indicator === "line",
|
|
235
|
+
}
|
|
236
|
+
)}
|
|
237
|
+
style={
|
|
238
|
+
{
|
|
239
|
+
"--color-bg": indicatorColor,
|
|
240
|
+
"--color-border": indicatorColor,
|
|
241
|
+
} as React.CSSProperties
|
|
242
|
+
}
|
|
243
|
+
/>
|
|
244
|
+
)
|
|
245
|
+
)}
|
|
246
|
+
<div
|
|
247
|
+
className={cn(
|
|
248
|
+
"flex flex-1 justify-between leading-none",
|
|
249
|
+
nestLabel ? "items-end" : "items-center"
|
|
250
|
+
)}
|
|
251
|
+
>
|
|
252
|
+
<div className="grid gap-1.5">
|
|
253
|
+
{nestLabel ? tooltipLabel : null}
|
|
254
|
+
<span className="text-muted-foreground">
|
|
255
|
+
{itemConfig?.label ?? item.name}
|
|
256
|
+
</span>
|
|
257
|
+
</div>
|
|
258
|
+
{item.value != null && (
|
|
259
|
+
<span className="text-foreground font-mono font-medium tabular-nums">
|
|
260
|
+
{typeof item.value === "number"
|
|
261
|
+
? item.value.toLocaleString()
|
|
262
|
+
: String(item.value)}
|
|
263
|
+
</span>
|
|
264
|
+
)}
|
|
265
|
+
</div>
|
|
266
|
+
</>
|
|
267
|
+
)}
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
})}
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const ChartLegend = RechartsPrimitive.Legend;
|
|
277
|
+
|
|
278
|
+
function ChartLegendContent({
|
|
279
|
+
className,
|
|
280
|
+
hideIcon = false,
|
|
281
|
+
payload,
|
|
282
|
+
verticalAlign = "bottom",
|
|
283
|
+
nameKey,
|
|
284
|
+
}: React.ComponentProps<"div"> & {
|
|
285
|
+
hideIcon?: boolean;
|
|
286
|
+
nameKey?: string;
|
|
287
|
+
} & RechartsPrimitive.DefaultLegendContentProps) {
|
|
288
|
+
const { config } = useChart();
|
|
289
|
+
|
|
290
|
+
if (!payload?.length) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return (
|
|
295
|
+
<div
|
|
296
|
+
className={cn(
|
|
297
|
+
"flex items-center justify-center gap-4",
|
|
298
|
+
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
299
|
+
className
|
|
300
|
+
)}
|
|
301
|
+
>
|
|
302
|
+
{payload
|
|
303
|
+
.filter((item) => item.type !== "none")
|
|
304
|
+
.map((item, index) => {
|
|
305
|
+
const key = `${nameKey ?? item.dataKey ?? "value"}`;
|
|
306
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
307
|
+
|
|
308
|
+
return (
|
|
309
|
+
<div
|
|
310
|
+
key={index}
|
|
311
|
+
className={cn(
|
|
312
|
+
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"
|
|
313
|
+
)}
|
|
314
|
+
>
|
|
315
|
+
{itemConfig?.icon && !hideIcon ? (
|
|
316
|
+
<itemConfig.icon />
|
|
317
|
+
) : (
|
|
318
|
+
<div
|
|
319
|
+
className="h-2 w-2 shrink-0 rounded-[2px]"
|
|
320
|
+
style={{
|
|
321
|
+
backgroundColor: item.color,
|
|
322
|
+
}}
|
|
323
|
+
/>
|
|
324
|
+
)}
|
|
325
|
+
{itemConfig?.label}
|
|
326
|
+
</div>
|
|
327
|
+
);
|
|
328
|
+
})}
|
|
329
|
+
</div>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function getPayloadConfigFromPayload(
|
|
334
|
+
config: ChartConfig,
|
|
335
|
+
payload: unknown,
|
|
336
|
+
key: string
|
|
337
|
+
) {
|
|
338
|
+
if (typeof payload !== "object" || payload === null) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const payloadPayload =
|
|
343
|
+
"payload" in payload &&
|
|
344
|
+
typeof payload.payload === "object" &&
|
|
345
|
+
payload.payload !== null
|
|
346
|
+
? payload.payload
|
|
347
|
+
: undefined;
|
|
348
|
+
|
|
349
|
+
let configLabelKey: string = key;
|
|
350
|
+
|
|
351
|
+
// hasOwn, not `in`: prototype members ("toString", "constructor") are not
|
|
352
|
+
// data — `config["toString"]` would hand React a function to render.
|
|
353
|
+
if (
|
|
354
|
+
Object.hasOwn(payload, key) &&
|
|
355
|
+
typeof payload[key as keyof typeof payload] === "string"
|
|
356
|
+
) {
|
|
357
|
+
configLabelKey = payload[key as keyof typeof payload];
|
|
358
|
+
} else if (
|
|
359
|
+
payloadPayload &&
|
|
360
|
+
Object.hasOwn(payloadPayload, key) &&
|
|
361
|
+
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
|
|
362
|
+
) {
|
|
363
|
+
configLabelKey = payloadPayload[key as keyof typeof payloadPayload];
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const fallback = Object.hasOwn(config, key) ? config[key] : undefined;
|
|
367
|
+
return Object.hasOwn(config, configLabelKey)
|
|
368
|
+
? config[configLabelKey]
|
|
369
|
+
: fallback;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export {
|
|
373
|
+
ChartContainer,
|
|
374
|
+
ChartTooltip,
|
|
375
|
+
ChartTooltipContent,
|
|
376
|
+
ChartLegend,
|
|
377
|
+
ChartLegendContent,
|
|
378
|
+
ChartStyle,
|
|
379
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
import { CheckIcon } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<CheckboxPrimitive.Root
|
|
10
|
+
data-slot="checkbox"
|
|
11
|
+
className={cn(
|
|
12
|
+
"peer border-input group-has-[:focus-visible]/field-label:not-data-checked:border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3",
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<CheckboxPrimitive.Indicator
|
|
18
|
+
data-slot="checkbox-indicator"
|
|
19
|
+
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
|
20
|
+
>
|
|
21
|
+
<CheckIcon />
|
|
22
|
+
</CheckboxPrimitive.Indicator>
|
|
23
|
+
</CheckboxPrimitive.Root>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { Checkbox };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
|
|
2
|
+
|
|
3
|
+
function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
|
|
4
|
+
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|