@franco_roura/module-01 0.0.0-stage → 1.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 (222) hide show
  1. package/LICENSE-APACHE +202 -0
  2. package/LICENSE-MIT +21 -0
  3. package/README.md +64 -2
  4. package/dist/charts.d.ts +3 -0
  5. package/dist/charts.js +3 -0
  6. package/dist/components/alert-dialog.d.ts +19 -0
  7. package/dist/components/alert-dialog.js +101 -0
  8. package/dist/components/alert-dialog.js.map +1 -0
  9. package/dist/components/amount.d.ts +24 -0
  10. package/dist/components/amount.js +27 -0
  11. package/dist/components/amount.js.map +1 -0
  12. package/dist/components/appearance-pickers.d.ts +9 -0
  13. package/dist/components/appearance-pickers.js +65 -0
  14. package/dist/components/appearance-pickers.js.map +1 -0
  15. package/dist/components/badge.d.ts +10 -0
  16. package/dist/components/badge.js +28 -0
  17. package/dist/components/badge.js.map +1 -0
  18. package/dist/components/budget-meter.d.ts +18 -0
  19. package/dist/components/budget-meter.js +38 -0
  20. package/dist/components/budget-meter.js.map +1 -0
  21. package/dist/components/button.d.ts +13 -0
  22. package/dist/components/button.js +54 -0
  23. package/dist/components/button.js.map +1 -0
  24. package/dist/components/calendar.d.ts +7 -0
  25. package/dist/components/calendar.js +52 -0
  26. package/dist/components/calendar.js.map +1 -0
  27. package/dist/components/category-icon.d.ts +33 -0
  28. package/dist/components/category-icon.js +49 -0
  29. package/dist/components/category-icon.js.map +1 -0
  30. package/dist/components/chart.d.ts +44 -0
  31. package/dist/components/chart.js +147 -0
  32. package/dist/components/chart.js.map +1 -0
  33. package/dist/components/charts.d.ts +52 -0
  34. package/dist/components/charts.js +482 -0
  35. package/dist/components/charts.js.map +1 -0
  36. package/dist/components/checkbox.d.ts +5 -0
  37. package/dist/components/checkbox.js +21 -0
  38. package/dist/components/checkbox.js.map +1 -0
  39. package/dist/components/combobox.d.ts +32 -0
  40. package/dist/components/combobox.js +100 -0
  41. package/dist/components/combobox.js.map +1 -0
  42. package/dist/components/command.d.ts +19 -0
  43. package/dist/components/command.js +86 -0
  44. package/dist/components/command.js.map +1 -0
  45. package/dist/components/cta-banner.d.ts +14 -0
  46. package/dist/components/cta-banner.js +39 -0
  47. package/dist/components/cta-banner.js.map +1 -0
  48. package/dist/components/date-picker.d.ts +19 -0
  49. package/dist/components/date-picker.js +107 -0
  50. package/dist/components/date-picker.js.map +1 -0
  51. package/dist/components/dialog.d.ts +18 -0
  52. package/dist/components/dialog.js +99 -0
  53. package/dist/components/dialog.js.map +1 -0
  54. package/dist/components/dropdown-menu.d.ts +26 -0
  55. package/dist/components/dropdown-menu.js +123 -0
  56. package/dist/components/dropdown-menu.js.map +1 -0
  57. package/dist/components/field.d.ts +30 -0
  58. package/dist/components/field.js +53 -0
  59. package/dist/components/field.js.map +1 -0
  60. package/dist/components/footer.d.ts +18 -0
  61. package/dist/components/footer.js +40 -0
  62. package/dist/components/footer.js.map +1 -0
  63. package/dist/components/fx-converter.d.ts +22 -0
  64. package/dist/components/fx-converter.js +91 -0
  65. package/dist/components/fx-converter.js.map +1 -0
  66. package/dist/components/hero.d.ts +28 -0
  67. package/dist/components/hero.js +83 -0
  68. package/dist/components/hero.js.map +1 -0
  69. package/dist/components/hud.d.ts +41 -0
  70. package/dist/components/hud.js +108 -0
  71. package/dist/components/hud.js.map +1 -0
  72. package/dist/components/input.d.ts +4 -0
  73. package/dist/components/input.js +14 -0
  74. package/dist/components/input.js.map +1 -0
  75. package/dist/components/label.d.ts +5 -0
  76. package/dist/components/label.js +15 -0
  77. package/dist/components/label.js.map +1 -0
  78. package/dist/components/media-card.d.ts +29 -0
  79. package/dist/components/media-card.js +80 -0
  80. package/dist/components/media-card.js.map +1 -0
  81. package/dist/components/money-input.d.ts +10 -0
  82. package/dist/components/money-input.js +30 -0
  83. package/dist/components/money-input.js.map +1 -0
  84. package/dist/components/multi-combobox.d.ts +27 -0
  85. package/dist/components/multi-combobox.js +101 -0
  86. package/dist/components/multi-combobox.js.map +1 -0
  87. package/dist/components/nav-bar.d.ts +21 -0
  88. package/dist/components/nav-bar.js +44 -0
  89. package/dist/components/nav-bar.js.map +1 -0
  90. package/dist/components/panel.d.ts +27 -0
  91. package/dist/components/panel.js +49 -0
  92. package/dist/components/panel.js.map +1 -0
  93. package/dist/components/popover.d.ts +11 -0
  94. package/dist/components/popover.js +56 -0
  95. package/dist/components/popover.js.map +1 -0
  96. package/dist/components/select.d.ts +16 -0
  97. package/dist/components/select.js +128 -0
  98. package/dist/components/select.js.map +1 -0
  99. package/dist/components/separator.d.ts +5 -0
  100. package/dist/components/separator.js +17 -0
  101. package/dist/components/separator.js.map +1 -0
  102. package/dist/components/sheet.d.ts +15 -0
  103. package/dist/components/sheet.js +87 -0
  104. package/dist/components/sheet.js.map +1 -0
  105. package/dist/components/skeleton.d.ts +3 -0
  106. package/dist/components/skeleton.js +13 -0
  107. package/dist/components/skeleton.js.map +1 -0
  108. package/dist/components/sonner.d.ts +5 -0
  109. package/dist/components/sonner.js +44 -0
  110. package/dist/components/sonner.js.map +1 -0
  111. package/dist/components/spec-readout.d.ts +11 -0
  112. package/dist/components/spec-readout.js +25 -0
  113. package/dist/components/spec-readout.js.map +1 -0
  114. package/dist/components/split-flap.d.ts +12 -0
  115. package/dist/components/split-flap.js +77 -0
  116. package/dist/components/split-flap.js.map +1 -0
  117. package/dist/components/tabs.d.ts +12 -0
  118. package/dist/components/tabs.js +47 -0
  119. package/dist/components/tabs.js.map +1 -0
  120. package/dist/components/tag.d.ts +16 -0
  121. package/dist/components/tag.js +26 -0
  122. package/dist/components/tag.js.map +1 -0
  123. package/dist/components/terminal.d.ts +10 -0
  124. package/dist/components/terminal.js +20 -0
  125. package/dist/components/terminal.js.map +1 -0
  126. package/dist/components/textarea.d.ts +4 -0
  127. package/dist/components/textarea.js +13 -0
  128. package/dist/components/textarea.js.map +1 -0
  129. package/dist/components/timeline-entry.d.ts +26 -0
  130. package/dist/components/timeline-entry.js +63 -0
  131. package/dist/components/timeline-entry.js.map +1 -0
  132. package/dist/components/toggle-group.d.ts +10 -0
  133. package/dist/components/toggle-group.js +49 -0
  134. package/dist/components/toggle-group.js.map +1 -0
  135. package/dist/components/toggle.d.ts +10 -0
  136. package/dist/components/toggle.js +37 -0
  137. package/dist/components/toggle.js.map +1 -0
  138. package/dist/components/tooltip.d.ts +8 -0
  139. package/dist/components/tooltip.js +36 -0
  140. package/dist/components/tooltip.js.map +1 -0
  141. package/dist/finance.d.ts +10 -0
  142. package/dist/finance.js +10 -0
  143. package/dist/index.d.ts +33 -0
  144. package/dist/index.js +33 -0
  145. package/dist/lib/category-icons.d.ts +80 -0
  146. package/dist/lib/category-icons.js +102 -0
  147. package/dist/lib/category-icons.js.map +1 -0
  148. package/dist/lib/fault.d.ts +7 -0
  149. package/dist/lib/fault.js +28 -0
  150. package/dist/lib/fault.js.map +1 -0
  151. package/dist/lib/form-flow.d.ts +15 -0
  152. package/dist/lib/form-flow.js +50 -0
  153. package/dist/lib/form-flow.js.map +1 -0
  154. package/dist/lib/fx.d.ts +39 -0
  155. package/dist/lib/fx.js +98 -0
  156. package/dist/lib/fx.js.map +1 -0
  157. package/dist/lib/money.d.ts +19 -0
  158. package/dist/lib/money.js +55 -0
  159. package/dist/lib/money.js.map +1 -0
  160. package/dist/lib/use-media-query.d.ts +3 -0
  161. package/dist/lib/use-media-query.js +15 -0
  162. package/dist/lib/use-media-query.js.map +1 -0
  163. package/dist/lib/utils.d.ts +3 -0
  164. package/dist/lib/utils.js +26 -0
  165. package/dist/lib/utils.js.map +1 -0
  166. package/dist/site.d.ts +10 -0
  167. package/dist/site.js +10 -0
  168. package/dist/styles.css +2 -0
  169. package/dist/theme.css +391 -0
  170. package/dist/tokens.css +181 -0
  171. package/guidelines/AlertDialog.md +9 -0
  172. package/guidelines/Amount.md +10 -0
  173. package/guidelines/AppearancePickers.md +8 -0
  174. package/guidelines/Badge.md +11 -0
  175. package/guidelines/BudgetMeter.md +11 -0
  176. package/guidelines/Button.md +16 -0
  177. package/guidelines/Calendar.md +8 -0
  178. package/guidelines/CategoryIcon.md +10 -0
  179. package/guidelines/Charts.md +12 -0
  180. package/guidelines/Checkbox.md +8 -0
  181. package/guidelines/Combobox.md +18 -0
  182. package/guidelines/Command.md +8 -0
  183. package/guidelines/Crosshair.md +7 -0
  184. package/guidelines/CtaBanner.md +8 -0
  185. package/guidelines/DatePicker.md +11 -0
  186. package/guidelines/Dialog.md +9 -0
  187. package/guidelines/DropdownMenu.md +9 -0
  188. package/guidelines/Field.md +22 -0
  189. package/guidelines/Footer.md +7 -0
  190. package/guidelines/FxConverter.md +12 -0
  191. package/guidelines/GlassPanel.md +8 -0
  192. package/guidelines/Grill.md +7 -0
  193. package/guidelines/Hero.md +9 -0
  194. package/guidelines/HudLabel.md +8 -0
  195. package/guidelines/Input.md +9 -0
  196. package/guidelines/Label.md +7 -0
  197. package/guidelines/MediaCard.md +8 -0
  198. package/guidelines/MoneyInput.md +10 -0
  199. package/guidelines/MultiCombobox.md +11 -0
  200. package/guidelines/NavBar.md +10 -0
  201. package/guidelines/Panel.md +10 -0
  202. package/guidelines/Popover.md +8 -0
  203. package/guidelines/README.md +100 -0
  204. package/guidelines/SectionHeader.md +9 -0
  205. package/guidelines/Select.md +9 -0
  206. package/guidelines/Separator.md +8 -0
  207. package/guidelines/Sheet.md +9 -0
  208. package/guidelines/Skeleton.md +8 -0
  209. package/guidelines/SpecReadout.md +7 -0
  210. package/guidelines/SplitFlap.md +9 -0
  211. package/guidelines/StatusLed.md +8 -0
  212. package/guidelines/Tabs.md +9 -0
  213. package/guidelines/Tag.md +9 -0
  214. package/guidelines/Terminal.md +7 -0
  215. package/guidelines/Textarea.md +8 -0
  216. package/guidelines/TickRuler.md +8 -0
  217. package/guidelines/TimelineEntry.md +8 -0
  218. package/guidelines/Toaster.md +9 -0
  219. package/guidelines/Toggle.md +9 -0
  220. package/guidelines/Tooltip.md +8 -0
  221. package/package.json +103 -4
  222. package/tokens/tokens.json +739 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Budget progress: a sunken track filled to the share spent (signal while within budget,
3
+ * danger once over), with a thin "today" tick at the share of the period that has passed.
4
+ * Pair it with the figures in text; the fill color is never the only cue.
5
+ */
6
+ export declare function BudgetMeter({ spent, budget, elapsed, label, size, className }: {
7
+ /** Minor units spent so far. */
8
+ spent: bigint;
9
+ /** Budgeted minor units (> 0). */
10
+ budget: bigint;
11
+ /** Share of the period that has passed, 0–1; omit to hide the today tick. */
12
+ elapsed?: number;
13
+ /** Accessible name, e.g. "Food budget". */
14
+ label: string;
15
+ size?: "sm" | "md";
16
+ className?: string;
17
+ }): import("react").JSX.Element;
18
+ //# sourceMappingURL=budget-meter.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ // src/components/budget-meter.tsx
4
+ /**
5
+ * Budget progress: a sunken track filled to the share spent (signal while within budget,
6
+ * danger once over), with a thin "today" tick at the share of the period that has passed.
7
+ * Pair it with the figures in text; the fill color is never the only cue.
8
+ */
9
+ function BudgetMeter({ spent, budget, elapsed, label, size = "md", className }) {
10
+ const share = budget > 0n ? Number(spent * 10000n / budget) / 1e4 : 0;
11
+ const over = spent > budget;
12
+ const fill = Math.min(Math.max(share, 0), 1);
13
+ return /* @__PURE__ */ jsxs("div", {
14
+ role: "meter",
15
+ "aria-label": label,
16
+ "aria-valuemin": 0,
17
+ "aria-valuemax": 100,
18
+ "aria-valuenow": Math.round(share * 100),
19
+ "aria-valuetext": `${Math.round(share * 100)}% spent`,
20
+ "data-over": over || void 0,
21
+ className: cn("relative", size === "md" ? "py-1.5" : "py-1", className),
22
+ children: [/* @__PURE__ */ jsx("div", {
23
+ className: cn("overflow-hidden rounded-full bg-shell-recess shadow-press", size === "md" ? "h-3" : "h-2"),
24
+ children: /* @__PURE__ */ jsx("div", {
25
+ className: cn("h-full rounded-full", over ? "bg-danger" : "bg-signal"),
26
+ style: { width: `${fill * 100}%` }
27
+ })
28
+ }), elapsed !== void 0 && elapsed > 0 && elapsed < 1 && /* @__PURE__ */ jsx("div", {
29
+ "aria-hidden": true,
30
+ className: "absolute inset-y-0 w-px bg-ink",
31
+ style: { left: `${elapsed * 100}%` },
32
+ children: /* @__PURE__ */ jsx("span", { className: "absolute -top-0.5 left-1/2 size-1.5 -translate-x-1/2 rotate-45 bg-ink" })
33
+ })]
34
+ });
35
+ }
36
+ export { BudgetMeter };
37
+
38
+ //# sourceMappingURL=budget-meter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-meter.js","names":[],"sources":["../../src/components/budget-meter.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\n\n/**\n * Budget progress: a sunken track filled to the share spent (signal while within budget,\n * danger once over), with a thin \"today\" tick at the share of the period that has passed.\n * Pair it with the figures in text; the fill color is never the only cue.\n */\nexport function BudgetMeter({\n spent,\n budget,\n elapsed,\n label,\n size = \"md\",\n className,\n}: {\n /** Minor units spent so far. */\n spent: bigint;\n /** Budgeted minor units (> 0). */\n budget: bigint;\n /** Share of the period that has passed, 0–1; omit to hide the today tick. */\n elapsed?: number;\n /** Accessible name, e.g. \"Food budget\". */\n label: string;\n size?: \"sm\" | \"md\";\n className?: string;\n}) {\n const share = budget > 0n ? Number((spent * 10000n) / budget) / 10000 : 0;\n const over = spent > budget;\n const fill = Math.min(Math.max(share, 0), 1);\n return (\n <div\n role=\"meter\"\n aria-label={label}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(share * 100)}\n aria-valuetext={`${Math.round(share * 100)}% spent`}\n data-over={over || undefined}\n className={cn(\"relative\", size === \"md\" ? \"py-1.5\" : \"py-1\", className)}\n >\n <div\n className={cn(\n \"overflow-hidden rounded-full bg-shell-recess shadow-press\",\n size === \"md\" ? \"h-3\" : \"h-2\",\n )}\n >\n <div\n className={cn(\"h-full rounded-full\", over ? \"bg-danger\" : \"bg-signal\")}\n style={{ width: `${fill * 100}%` }}\n />\n </div>\n {elapsed !== undefined && elapsed > 0 && elapsed < 1 && (\n <div\n aria-hidden\n className=\"absolute inset-y-0 w-px bg-ink\"\n style={{ left: `${elapsed * 100}%` }}\n >\n <span className=\"absolute -top-0.5 left-1/2 size-1.5 -translate-x-1/2 rotate-45 bg-ink\" />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,YAAY,EAC1B,OACA,QACA,SACA,OACA,OAAO,MACP,aAYC;CACD,MAAM,QAAQ,SAAS,KAAK,OAAQ,QAAQ,SAAU,MAAM,IAAI,MAAQ;CACxE,MAAM,OAAO,QAAQ;CACrB,MAAM,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC;CAC3C,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,iBAAe;EACf,iBAAe;EACf,iBAAe,KAAK,MAAM,QAAQ,GAAG;EACrC,kBAAgB,GAAG,KAAK,MAAM,QAAQ,GAAG,EAAE;EAC3C,aAAW,QAAQ,KAAA;EACnB,WAAW,GAAG,YAAY,SAAS,OAAO,WAAW,QAAQ,SAAS;EARxE,UAAA,CAUE,oBAAC,OAAD;GACE,WAAW,GACT,6DACA,SAAS,OAAO,QAAQ,KAC1B;GAEA,UAAA,oBAAC,OAAD;IACE,WAAW,GAAG,uBAAuB,OAAO,cAAc,WAAW;IACrE,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,GAAG;GAClC,CAAA;EACE,CAAA,GACJ,YAAY,KAAA,KAAa,UAAU,KAAK,UAAU,KACjD,oBAAC,OAAD;GACE,eAAA;GACA,WAAU;GACV,OAAO,EAAE,MAAM,GAAG,UAAU,IAAI,GAAG;GAEnC,UAAA,oBAAC,QAAD,EAAM,WAAU,wEAAyE,CAAA;EACtF,CAAA,CAEJ;;AAET"}
@@ -0,0 +1,13 @@
1
+ import { VariantProps } from "class-variance-authority";
2
+ import * as React from "react";
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "bracket" | "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
5
+ size?: "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ declare function Button({ className, variant, size, asChild, arrow, children, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
8
+ asChild?: boolean;
9
+ /** Appends a mono → after the label. Ignored with `asChild`; put the arrow in the child. */
10
+ arrow?: boolean;
11
+ }): React.JSX.Element;
12
+ export { Button, buttonVariants };
13
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { cva } from "class-variance-authority";
3
+ import { Slot } from "radix-ui";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ // src/components/button.tsx
6
+ const buttonVariants = cva("inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 rounded-full font-sans text-label whitespace-nowrap transition-[background-color,box-shadow,transform] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/60 disabled:pointer-events-none disabled:opacity-50 aria-invalid:ring-[3px] aria-invalid:ring-destructive/30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
7
+ variants: {
8
+ variant: {
9
+ default: "bg-signal text-ink shadow-mold hover:bg-[color-mix(in_srgb,var(--color-signal)_88%,white)] active:shadow-press active:translate-y-px",
10
+ destructive: "bg-danger text-shell shadow-mold hover:bg-[color-mix(in_srgb,var(--color-danger)_90%,black)] active:shadow-press active:translate-y-px",
11
+ outline: "border border-seam bg-shell text-ink shadow-mold hover:bg-shell-recess active:shadow-press",
12
+ secondary: "bg-shell text-ink shadow-mold hover:bg-shell-recess active:shadow-press active:translate-y-px",
13
+ ghost: "text-ink hover:bg-shell-recess active:shadow-press",
14
+ link: "rounded-none px-0 text-signal-ink underline-offset-4 hover:underline",
15
+ bracket: "h-auto min-h-control-height gap-1 px-2 text-ink before:font-mono before:text-signal-ink before:content-['['] after:font-mono after:text-signal-ink after:content-[']'] hover:text-signal-ink"
16
+ },
17
+ size: {
18
+ default: "h-control-height px-5 has-[>svg]:px-4",
19
+ xs: "h-7 gap-1 px-3 text-body-sm [&_svg:not([class*='size-'])]:size-3",
20
+ sm: "h-9 gap-1.5 px-4 has-[>svg]:px-3",
21
+ lg: "h-12 px-7 has-[>svg]:px-5",
22
+ icon: "size-control-height",
23
+ "icon-xs": "size-7 [&_svg:not([class*='size-'])]:size-3",
24
+ "icon-sm": "size-9",
25
+ "icon-lg": "size-12"
26
+ }
27
+ },
28
+ defaultVariants: {
29
+ variant: "default",
30
+ size: "default"
31
+ }
32
+ });
33
+ function Button({ className, variant = "default", size = "default", asChild = false, arrow = false, children, ...props }) {
34
+ const Comp = asChild ? Slot.Root : "button";
35
+ return /* @__PURE__ */ jsx(Comp, {
36
+ "data-slot": "button",
37
+ "data-variant": variant,
38
+ "data-size": size,
39
+ className: cn(buttonVariants({
40
+ variant,
41
+ size,
42
+ className
43
+ })),
44
+ ...props,
45
+ children: asChild || !arrow ? children : /* @__PURE__ */ jsxs(Fragment, { children: [children, /* @__PURE__ */ jsx("span", {
46
+ "aria-hidden": true,
47
+ className: "font-mono",
48
+ children: "→"
49
+ })] })
50
+ });
51
+ }
52
+ export { Button, buttonVariants };
53
+
54
+ //# sourceMappingURL=button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\n\n// Module/01: everything you press is a molded stadium. Signal orange carries ink text, never white.\nconst buttonVariants = cva(\n \"inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 rounded-full font-sans text-label whitespace-nowrap transition-[background-color,box-shadow,transform] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/60 disabled:pointer-events-none disabled:opacity-50 aria-invalid:ring-[3px] aria-invalid:ring-destructive/30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-signal text-ink shadow-mold hover:bg-[color-mix(in_srgb,var(--color-signal)_88%,white)] active:shadow-press active:translate-y-px\",\n destructive:\n \"bg-danger text-shell shadow-mold hover:bg-[color-mix(in_srgb,var(--color-danger)_90%,black)] active:shadow-press active:translate-y-px\",\n outline:\n \"border border-seam bg-shell text-ink shadow-mold hover:bg-shell-recess active:shadow-press\",\n secondary:\n \"bg-shell text-ink shadow-mold hover:bg-shell-recess active:shadow-press active:translate-y-px\",\n ghost: \"text-ink hover:bg-shell-recess active:shadow-press\",\n link: \"rounded-none px-0 text-signal-ink underline-offset-4 hover:underline\",\n // [ Label ] in mono brackets: footer and card links on a site.\n bracket:\n \"h-auto min-h-control-height gap-1 px-2 text-ink before:font-mono before:text-signal-ink before:content-['['] after:font-mono after:text-signal-ink after:content-[']'] hover:text-signal-ink\",\n },\n size: {\n default: \"h-control-height px-5 has-[>svg]:px-4\",\n xs: \"h-7 gap-1 px-3 text-body-sm [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-9 gap-1.5 px-4 has-[>svg]:px-3\",\n lg: \"h-12 px-7 has-[>svg]:px-5\",\n icon: \"size-control-height\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-9\",\n \"icon-lg\": \"size-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n arrow = false,\n children,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n /** Appends a mono → after the label. Ignored with `asChild`; put the arrow in the child. */\n arrow?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"button\";\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n >\n {asChild || !arrow ? (\n children\n ) : (\n <>\n {children}\n <span aria-hidden className=\"font-mono\">\n →\n </span>\n </>\n )}\n </Comp>\n );\n}\n\nexport { Button, buttonVariants };\n"],"mappings":";;;;;AAMA,MAAM,iBAAiB,IACrB,ybACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,aACE;GACF,SACE;GACF,WACE;GACF,OAAO;GACP,MAAM;GAEN,SACE;EACJ;EACA,MAAM;GACJ,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,WAAW;GACX,WAAW;GACX,WAAW;EACb;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;AACF,CACF;AAEA,SAAS,OAAO,EACd,WACA,UAAU,WACV,OAAO,WACP,UAAU,OACV,QAAQ,OACR,UACA,GAAG,SAMA;CACH,MAAM,OAAO,UAAU,KAAK,OAAO;CAEnC,OACE,oBAAC,MAAD;EACE,aAAU;EACV,gBAAc;EACd,aAAW;EACX,WAAW,GAAG,eAAe;GAAE;GAAS;GAAM;EAAU,CAAC,CAAC;EAC1D,GAAI;EAEH,UAAA,WAAW,CAAC,QACX,WAEA,qBAAA,UAAA,EAAA,UAAA,CACG,UACD,oBAAC,QAAD;GAAM,eAAA;GAAY,WAAU;GAAY,UAAA;EAElC,CAAA,CACN,EAAA,CAAA;CAEA,CAAA;AAEV"}
@@ -0,0 +1,7 @@
1
+ import { DayPickerProps } from "react-day-picker";
2
+ /**
3
+ * Module/01 month calendar: HUD caption, mono weekday microprint, stadium days. The selected
4
+ * day is a signal part with ink text; today carries a signal-ink ring.
5
+ */
6
+ export declare function Calendar({ className, classNames, showOutsideDays, weekStartsOn, ...props }: DayPickerProps): import("react").JSX.Element;
7
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { cn } from "../lib/utils.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { ChevronLeft, ChevronRight } from "lucide-react";
5
+ import { DayPicker } from "react-day-picker";
6
+ // src/components/calendar.tsx
7
+ function CalendarChevron({ orientation, className }) {
8
+ return /* @__PURE__ */ jsx(orientation === "left" ? ChevronLeft : ChevronRight, {
9
+ className: cn("size-4", className),
10
+ strokeWidth: 1.25
11
+ });
12
+ }
13
+ const navButton = "inline-flex size-9 cursor-pointer items-center justify-center rounded-full bg-shell text-ink shadow-mold outline-none hover:bg-shell-recess focus-visible:ring-[3px] focus-visible:ring-ring/60 active:shadow-press disabled:pointer-events-none disabled:opacity-40";
14
+ /**
15
+ * Module/01 month calendar: HUD caption, mono weekday microprint, stadium days. The selected
16
+ * day is a signal part with ink text; today carries a signal-ink ring.
17
+ */
18
+ function Calendar({ className, classNames, showOutsideDays = true, weekStartsOn = 1, ...props }) {
19
+ return /* @__PURE__ */ jsx(DayPicker, {
20
+ showOutsideDays,
21
+ weekStartsOn,
22
+ className: cn("select-none", className),
23
+ classNames: {
24
+ root: "relative",
25
+ months: "relative flex flex-col",
26
+ month: "flex flex-col gap-2",
27
+ month_caption: "flex h-9 items-center pl-1",
28
+ caption_label: "hud text-ink",
29
+ nav: "absolute top-0 right-0 z-10 flex items-center gap-1.5",
30
+ button_previous: navButton,
31
+ button_next: navButton,
32
+ month_grid: "border-collapse",
33
+ weekdays: "",
34
+ weekday: "hud-sm h-8 w-10 text-center font-normal text-ink-soft",
35
+ weeks: "",
36
+ week: "",
37
+ day: "p-0.5 text-center",
38
+ day_button: "tabular mx-auto flex size-9 cursor-pointer items-center justify-center rounded-full text-body-sm text-ink outline-none transition-[background-color,box-shadow] hover:bg-shell-recess focus-visible:ring-[3px] focus-visible:ring-ring/60",
39
+ selected: "[&>button]:bg-signal [&>button]:font-bold [&>button]:text-ink [&>button]:shadow-mold [&>button]:hover:bg-signal",
40
+ today: "[&>button]:font-bold [&>button]:text-signal-ink [&>button]:ring-1 [&>button]:ring-signal-ink",
41
+ outside: "[&>button]:text-hud-mark",
42
+ disabled: "[&>button]:pointer-events-none [&>button]:opacity-40",
43
+ hidden: "invisible",
44
+ ...classNames
45
+ },
46
+ components: { Chevron: CalendarChevron },
47
+ ...props
48
+ });
49
+ }
50
+ export { Calendar };
51
+
52
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","names":[],"sources":["../../src/components/calendar.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../lib/utils\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { type ChevronProps, DayPicker, type DayPickerProps } from \"react-day-picker\";\n\nfunction CalendarChevron({ orientation, className }: ChevronProps) {\n const Icon = orientation === \"left\" ? ChevronLeft : ChevronRight;\n return <Icon className={cn(\"size-4\", className)} strokeWidth={1.25} />;\n}\n\nconst navButton =\n \"inline-flex size-9 cursor-pointer items-center justify-center rounded-full bg-shell text-ink shadow-mold outline-none hover:bg-shell-recess focus-visible:ring-[3px] focus-visible:ring-ring/60 active:shadow-press disabled:pointer-events-none disabled:opacity-40\";\n\n/**\n * Module/01 month calendar: HUD caption, mono weekday microprint, stadium days. The selected\n * day is a signal part with ink text; today carries a signal-ink ring.\n */\nexport function Calendar({\n className,\n classNames,\n showOutsideDays = true,\n weekStartsOn = 1,\n ...props\n}: DayPickerProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n weekStartsOn={weekStartsOn}\n className={cn(\"select-none\", className)}\n classNames={{\n root: \"relative\",\n months: \"relative flex flex-col\",\n month: \"flex flex-col gap-2\",\n month_caption: \"flex h-9 items-center pl-1\",\n caption_label: \"hud text-ink\",\n nav: \"absolute top-0 right-0 z-10 flex items-center gap-1.5\",\n button_previous: navButton,\n button_next: navButton,\n month_grid: \"border-collapse\",\n weekdays: \"\",\n weekday: \"hud-sm h-8 w-10 text-center font-normal text-ink-soft\",\n weeks: \"\",\n week: \"\",\n day: \"p-0.5 text-center\",\n day_button:\n \"tabular mx-auto flex size-9 cursor-pointer items-center justify-center rounded-full text-body-sm text-ink outline-none transition-[background-color,box-shadow] hover:bg-shell-recess focus-visible:ring-[3px] focus-visible:ring-ring/60\",\n selected:\n \"[&>button]:bg-signal [&>button]:font-bold [&>button]:text-ink [&>button]:shadow-mold [&>button]:hover:bg-signal\",\n today:\n \"[&>button]:font-bold [&>button]:text-signal-ink [&>button]:ring-1 [&>button]:ring-signal-ink\",\n outside: \"[&>button]:text-hud-mark\",\n disabled: \"[&>button]:pointer-events-none [&>button]:opacity-40\",\n hidden: \"invisible\",\n ...classNames,\n }}\n components={{ Chevron: CalendarChevron }}\n {...props}\n />\n );\n}\n"],"mappings":";;;;;;AAMA,SAAS,gBAAgB,EAAE,aAAa,aAA2B;CAEjE,OAAO,oBADM,gBAAgB,SAAS,cAAc,cAC7C;EAAM,WAAW,GAAG,UAAU,SAAS;EAAG,aAAa;CAAO,CAAA;AACvE;AAEA,MAAM,YACJ;;;;;AAMF,SAAgB,SAAS,EACvB,WACA,YACA,kBAAkB,MAClB,eAAe,GACf,GAAG,SACc;CACjB,OACE,oBAAC,WAAD;EACmB;EACH;EACd,WAAW,GAAG,eAAe,SAAS;EACtC,YAAY;GACV,MAAM;GACN,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,KAAK;GACL,iBAAiB;GACjB,aAAa;GACb,YAAY;GACZ,UAAU;GACV,SAAS;GACT,OAAO;GACP,MAAM;GACN,KAAK;GACL,YACE;GACF,UACE;GACF,OACE;GACF,SAAS;GACT,UAAU;GACV,QAAQ;GACR,GAAG;EACL;EACA,YAAY,EAAE,SAAS,gBAAgB;EACvC,GAAI;CACL,CAAA;AAEL"}
@@ -0,0 +1,33 @@
1
+ declare const sizes: {
2
+ sm: {
3
+ box: string;
4
+ icon: string;
5
+ };
6
+ md: {
7
+ box: string;
8
+ icon: string;
9
+ };
10
+ lg: {
11
+ box: string;
12
+ icon: string;
13
+ };
14
+ };
15
+ /**
16
+ * A category's Lucide glyph in ink on a palette-colored disc. For transfers pass
17
+ * icon="arrow-left-right" and color="cat-slate".
18
+ */
19
+ export declare function CategoryIcon({ icon, color, size, label, className }: {
20
+ icon: string;
21
+ color: string;
22
+ size?: keyof typeof sizes;
23
+ /** Accessible name; omit when the category name is shown next to it. */
24
+ label?: string;
25
+ className?: string;
26
+ }): import("react").JSX.Element;
27
+ /** Small colored dot for labels and legends. */
28
+ export declare function ColorDot({ color, className }: {
29
+ color: string;
30
+ className?: string;
31
+ }): import("react").JSX.Element;
32
+ export {};
33
+ //# sourceMappingURL=category-icon.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { categoryColorVar, categoryIcon } from "../lib/category-icons.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ // src/components/category-icon.tsx
5
+ const sizes = {
6
+ sm: {
7
+ box: "size-7",
8
+ icon: "size-3.5"
9
+ },
10
+ md: {
11
+ box: "size-9",
12
+ icon: "size-4.5"
13
+ },
14
+ lg: {
15
+ box: "size-12",
16
+ icon: "size-6"
17
+ }
18
+ };
19
+ /**
20
+ * A category's Lucide glyph in ink on a palette-colored disc. For transfers pass
21
+ * icon="arrow-left-right" and color="cat-slate".
22
+ */
23
+ function CategoryIcon({ icon, color, size = "md", label, className }) {
24
+ const Icon = categoryIcon(icon);
25
+ const s = sizes[size];
26
+ return /* @__PURE__ */ jsx("span", {
27
+ ...label ? {
28
+ role: "img",
29
+ "aria-label": label
30
+ } : { "aria-hidden": true },
31
+ className: cn("inline-flex shrink-0 items-center justify-center rounded-full text-ink shadow-[inset_0_1px_0_rgba(255,255,255,0.45),inset_0_-2px_0_rgba(28,30,33,0.08)]", s.box, className),
32
+ style: { background: categoryColorVar(color) },
33
+ children: /* @__PURE__ */ jsx(Icon, {
34
+ className: s.icon,
35
+ strokeWidth: 1.25
36
+ })
37
+ });
38
+ }
39
+ /** Small colored dot for labels and legends. */
40
+ function ColorDot({ color, className }) {
41
+ return /* @__PURE__ */ jsx("span", {
42
+ "aria-hidden": true,
43
+ className: cn("inline-block size-2.5 shrink-0 rounded-full", className),
44
+ style: { background: categoryColorVar(color) }
45
+ });
46
+ }
47
+ export { CategoryIcon, ColorDot };
48
+
49
+ //# sourceMappingURL=category-icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"category-icon.js","names":[],"sources":["../../src/components/category-icon.tsx"],"sourcesContent":["import { categoryColorVar, categoryIcon } from \"../lib/category-icons\";\nimport { cn } from \"../lib/utils\";\n\nconst sizes = {\n sm: { box: \"size-7\", icon: \"size-3.5\" },\n md: { box: \"size-9\", icon: \"size-4.5\" },\n lg: { box: \"size-12\", icon: \"size-6\" },\n};\n\n/**\n * A category's Lucide glyph in ink on a palette-colored disc. For transfers pass\n * icon=\"arrow-left-right\" and color=\"cat-slate\".\n */\nexport function CategoryIcon({\n icon,\n color,\n size = \"md\",\n label,\n className,\n}: {\n icon: string;\n color: string;\n size?: keyof typeof sizes;\n /** Accessible name; omit when the category name is shown next to it. */\n label?: string;\n className?: string;\n}) {\n const Icon = categoryIcon(icon);\n const s = sizes[size];\n // Named image when labelled; otherwise decorative (the category name sits next to it).\n const a11y = label\n ? { role: \"img\" as const, \"aria-label\": label }\n : { \"aria-hidden\": true as const };\n return (\n <span\n {...a11y}\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-full text-ink shadow-[inset_0_1px_0_rgba(255,255,255,0.45),inset_0_-2px_0_rgba(28,30,33,0.08)]\",\n s.box,\n className,\n )}\n style={{ background: categoryColorVar(color) }}\n >\n <Icon className={s.icon} strokeWidth={1.25} />\n </span>\n );\n}\n\n/** Small colored dot for labels and legends. */\nexport function ColorDot({ color, className }: { color: string; className?: string }) {\n return (\n <span\n aria-hidden\n className={cn(\"inline-block size-2.5 shrink-0 rounded-full\", className)}\n style={{ background: categoryColorVar(color) }}\n />\n );\n}\n"],"mappings":";;;;AAGA,MAAM,QAAQ;CACZ,IAAI;EAAE,KAAK;EAAU,MAAM;CAAW;CACtC,IAAI;EAAE,KAAK;EAAU,MAAM;CAAW;CACtC,IAAI;EAAE,KAAK;EAAW,MAAM;CAAS;AACvC;;;;;AAMA,SAAgB,aAAa,EAC3B,MACA,OACA,OAAO,MACP,OACA,aAQC;CACD,MAAM,OAAO,aAAa,IAAI;CAC9B,MAAM,IAAI,MAAM;CAKhB,OACE,oBAAC,QAAD;EACE,GALS,QACT;GAAE,MAAM;GAAgB,cAAc;EAAM,IAC5C,EAAE,eAAe,KAAc;EAI/B,WAAW,GACT,2JACA,EAAE,KACF,SACF;EACA,OAAO,EAAE,YAAY,iBAAiB,KAAK,EAAE;EAE7C,UAAA,oBAAC,MAAD;GAAM,WAAW,EAAE;GAAM,aAAa;EAAO,CAAA;CACzC,CAAA;AAEV;;AAGA,SAAgB,SAAS,EAAE,OAAO,aAAoD;CACpF,OACE,oBAAC,QAAD;EACE,eAAA;EACA,WAAW,GAAG,+CAA+C,SAAS;EACtE,OAAO,EAAE,YAAY,iBAAiB,KAAK,EAAE;CAC9C,CAAA;AAEL"}
@@ -0,0 +1,44 @@
1
+ import * as React from "react";
2
+ import * as RechartsPrimitive from "recharts";
3
+ import { TooltipValueType } from "recharts";
4
+ declare const THEMES: {
5
+ readonly light: "";
6
+ };
7
+ type TooltipNameType = number | string;
8
+ export type ChartConfig = Record<string, {
9
+ label?: React.ReactNode;
10
+ icon?: React.ComponentType;
11
+ } & ({
12
+ color?: string;
13
+ theme?: never;
14
+ } | {
15
+ color?: never;
16
+ theme: Record<keyof typeof THEMES, string>;
17
+ })>;
18
+ declare function ChartContainer({ id, className, children, config, initialDimension, ...props }: React.ComponentProps<"div"> & {
19
+ config: ChartConfig;
20
+ children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
21
+ initialDimension?: {
22
+ width: number;
23
+ height: number;
24
+ };
25
+ }): React.JSX.Element;
26
+ declare const ChartStyle: ({ id, config }: {
27
+ id: string;
28
+ config: ChartConfig;
29
+ }) => React.JSX.Element | null;
30
+ declare const ChartTooltip: typeof RechartsPrimitive.Tooltip;
31
+ declare function ChartTooltipContent({ active, payload, className, indicator, hideLabel, hideIndicator, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> & React.ComponentProps<"div"> & {
32
+ hideLabel?: boolean;
33
+ hideIndicator?: boolean;
34
+ indicator?: "line" | "dot" | "dashed";
35
+ nameKey?: string;
36
+ labelKey?: string;
37
+ } & Omit<RechartsPrimitive.DefaultTooltipContentProps<TooltipValueType, TooltipNameType>, "accessibilityLayer">): React.JSX.Element | null;
38
+ declare const ChartLegend: React.MemoExoticComponent<(outsideProps: RechartsPrimitive.LegendProps) => React.ReactPortal | null>;
39
+ declare function ChartLegendContent({ className, hideIcon, payload, verticalAlign, nameKey }: React.ComponentProps<"div"> & {
40
+ hideIcon?: boolean;
41
+ nameKey?: string;
42
+ } & RechartsPrimitive.DefaultLegendContentProps): React.JSX.Element | null;
43
+ export { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };
44
+ //# sourceMappingURL=chart.d.ts.map
@@ -0,0 +1,147 @@
1
+ "use client";
2
+ import { cn } from "../lib/utils.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import * as React from "react";
5
+ import * as RechartsPrimitive from "recharts";
6
+ // src/components/chart.tsx
7
+ const THEMES = { light: "" };
8
+ const INITIAL_DIMENSION = {
9
+ width: 320,
10
+ height: 200
11
+ };
12
+ const ChartContext = React.createContext(null);
13
+ function useChart() {
14
+ const context = React.useContext(ChartContext);
15
+ if (!context) throw new Error("useChart must be used within a <ChartContainer />");
16
+ return context;
17
+ }
18
+ function ChartContainer({ id, className, children, config, initialDimension = INITIAL_DIMENSION, ...props }) {
19
+ const uniqueId = React.useId();
20
+ const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
21
+ return /* @__PURE__ */ jsx(ChartContext.Provider, {
22
+ value: { config },
23
+ children: /* @__PURE__ */ jsxs("div", {
24
+ "data-slot": "chart",
25
+ "data-chart": chartId,
26
+ 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),
27
+ ...props,
28
+ children: [/* @__PURE__ */ jsx(ChartStyle, {
29
+ id: chartId,
30
+ config
31
+ }), /* @__PURE__ */ jsx(RechartsPrimitive.ResponsiveContainer, {
32
+ initialDimension,
33
+ children
34
+ })]
35
+ })
36
+ });
37
+ }
38
+ const ChartStyle = ({ id, config }) => {
39
+ const colorConfig = Object.entries(config).filter(([, config]) => config.theme ?? config.color);
40
+ if (!colorConfig.length) return null;
41
+ return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: Object.entries(THEMES).map(([theme, prefix]) => `
42
+ ${prefix} [data-chart=${id}] {
43
+ ${colorConfig.map(([key, itemConfig]) => {
44
+ const color = itemConfig.theme?.[theme] ?? itemConfig.color;
45
+ return color ? ` --color-${key}: ${color};` : null;
46
+ }).join("\n")}
47
+ }
48
+ `).join("\n") } });
49
+ };
50
+ const ChartTooltip = RechartsPrimitive.Tooltip;
51
+ function ChartTooltipContent({ active, payload, className, indicator = "dot", hideLabel = false, hideIndicator = false, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey }) {
52
+ const { config } = useChart();
53
+ const tooltipLabel = React.useMemo(() => {
54
+ if (hideLabel || !payload?.length) return null;
55
+ const [item] = payload;
56
+ const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`;
57
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
58
+ const value = !labelKey && typeof label === "string" ? config[label]?.label ?? label : itemConfig?.label;
59
+ if (labelFormatter) return /* @__PURE__ */ jsx("div", {
60
+ className: cn("font-medium", labelClassName),
61
+ children: labelFormatter(value, payload)
62
+ });
63
+ if (!value) return null;
64
+ return /* @__PURE__ */ jsx("div", {
65
+ className: cn("font-medium", labelClassName),
66
+ children: value
67
+ });
68
+ }, [
69
+ label,
70
+ labelFormatter,
71
+ payload,
72
+ hideLabel,
73
+ labelClassName,
74
+ config,
75
+ labelKey
76
+ ]);
77
+ if (!active || !payload?.length) return null;
78
+ const nestLabel = payload.length === 1 && indicator !== "dot";
79
+ return /* @__PURE__ */ jsxs("div", {
80
+ className: cn("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-float", className),
81
+ children: [!nestLabel ? tooltipLabel : null, /* @__PURE__ */ jsx("div", {
82
+ className: "grid gap-1.5",
83
+ children: payload.filter((item) => item.type !== "none").map((item, index) => {
84
+ const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
85
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
86
+ const indicatorColor = color ?? item.payload?.fill ?? item.color;
87
+ return /* @__PURE__ */ jsx("div", {
88
+ className: cn("flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center"),
89
+ children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */ jsxs(Fragment, { children: [itemConfig?.icon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsx("div", {
90
+ className: cn("shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)", {
91
+ "h-2.5 w-2.5": indicator === "dot",
92
+ "w-1": indicator === "line",
93
+ "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
94
+ "my-0.5": nestLabel && indicator === "dashed"
95
+ }),
96
+ style: {
97
+ "--color-bg": indicatorColor,
98
+ "--color-border": indicatorColor
99
+ }
100
+ }), /* @__PURE__ */ jsxs("div", {
101
+ className: cn("flex flex-1 justify-between leading-none", nestLabel ? "items-end" : "items-center"),
102
+ children: [/* @__PURE__ */ jsxs("div", {
103
+ className: "grid gap-1.5",
104
+ children: [nestLabel ? tooltipLabel : null, /* @__PURE__ */ jsx("span", {
105
+ className: "text-muted-foreground",
106
+ children: itemConfig?.label ?? item.name
107
+ })]
108
+ }), item.value != null && /* @__PURE__ */ jsx("span", {
109
+ className: "font-mono font-medium text-foreground tabular-nums",
110
+ children: typeof item.value === "number" ? item.value.toLocaleString() : String(item.value)
111
+ })]
112
+ })] })
113
+ }, index);
114
+ })
115
+ })]
116
+ });
117
+ }
118
+ const ChartLegend = RechartsPrimitive.Legend;
119
+ function ChartLegendContent({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }) {
120
+ const { config } = useChart();
121
+ if (!payload?.length) return null;
122
+ return /* @__PURE__ */ jsx("div", {
123
+ className: cn("flex items-center justify-center gap-4", verticalAlign === "top" ? "pb-3" : "pt-3", className),
124
+ children: payload.filter((item) => item.type !== "none").map((item, index) => {
125
+ const key = `${nameKey ?? item.dataKey ?? "value"}`;
126
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
127
+ return /* @__PURE__ */ jsxs("div", {
128
+ className: cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"),
129
+ children: [itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : /* @__PURE__ */ jsx("div", {
130
+ className: "h-2 w-2 shrink-0 rounded-[2px]",
131
+ style: { backgroundColor: item.color }
132
+ }), itemConfig?.label]
133
+ }, index);
134
+ })
135
+ });
136
+ }
137
+ function getPayloadConfigFromPayload(config, payload, key) {
138
+ if (typeof payload !== "object" || payload === null) return;
139
+ const payloadPayload = "payload" in payload && typeof payload.payload === "object" && payload.payload !== null ? payload.payload : void 0;
140
+ let configLabelKey = key;
141
+ if (key in payload && typeof payload[key] === "string") configLabelKey = payload[key];
142
+ else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === "string") configLabelKey = payloadPayload[key];
143
+ return configLabelKey in config ? config[configLabelKey] : config[key];
144
+ }
145
+ export { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };
146
+
147
+ //# sourceMappingURL=chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.js","names":[],"sources":["../../src/components/chart.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../lib/utils\";\nimport * as React from \"react\";\nimport type { TooltipValueType } from \"recharts\";\nimport * as RechartsPrimitive from \"recharts\";\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\" } as const;\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const;\ntype TooltipNameType = number | string;\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n )\n>;\n\ntype ChartContextProps = {\n config: ChartConfig;\n};\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n\n if (!context) {\n throw new Error(\"useChart must be used within a <ChartContainer />\");\n }\n\n return context;\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig;\n children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>[\"children\"];\n initialDimension?: {\n width: number;\n height: number;\n };\n}) {\n const uniqueId = React.useId();\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"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\",\n className,\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer initialDimension={initialDimension}>\n {children}\n </RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(([, config]) => config.theme ?? config.color);\n\n if (!colorConfig.length) {\n return null;\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .join(\"\\n\")}\n}\n`,\n )\n .join(\"\\n\"),\n }}\n />\n );\n};\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: \"line\" | \"dot\" | \"dashed\";\n nameKey?: string;\n labelKey?: string;\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<TooltipValueType, TooltipNameType>,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null;\n }\n\n const [item] = payload;\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value =\n !labelKey && typeof label === \"string\" ? (config[label]?.label ?? label) : itemConfig?.label;\n\n if (labelFormatter) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>{labelFormatter(value, payload)}</div>\n );\n }\n\n if (!value) {\n return null;\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>;\n }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);\n\n if (!active || !payload?.length) {\n return null;\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n return (\n <div\n className={cn(\n \"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-float\",\n className,\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const indicatorColor = color ?? item.payload?.fill ?? item.color;\n\n return (\n <div\n key={index}\n className={cn(\n \"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\",\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\n indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n },\n )}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\",\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">\n {itemConfig?.label ?? item.name}\n </span>\n </div>\n {item.value != null && (\n <span className=\"font-mono font-medium text-foreground tabular-nums\">\n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean;\n nameKey?: string;\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className,\n )}\n >\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={index}\n className={cn(\n \"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\",\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: item.color,\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined;\n }\n\n const payloadPayload =\n \"payload\" in payload && typeof payload.payload === \"object\" && payload.payload !== null\n ? payload.payload\n : undefined;\n\n let configLabelKey: string = key;\n\n if (key in payload && typeof payload[key as keyof typeof payload] === \"string\") {\n configLabelKey = payload[key as keyof typeof payload] as string;\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key];\n}\n\nexport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n ChartTooltip,\n ChartTooltipContent,\n};\n"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ type Money = {
2
+ currency: string;
3
+ minorUnits: number;
4
+ };
5
+ export type BalancePoint = {
6
+ label: string;
7
+ tooltipLabel: string;
8
+ balance: bigint;
9
+ };
10
+ /** One series over time: the balance line with a soft area and a crosshair tooltip. */
11
+ export declare function BalanceChart({ points, money, className }: {
12
+ points: BalancePoint[];
13
+ money: Money;
14
+ className?: string;
15
+ }): import("react").JSX.Element;
16
+ export type FlowPoint = {
17
+ label: string;
18
+ tooltipLabel: string;
19
+ income: bigint;
20
+ expense: bigint;
21
+ };
22
+ /**
23
+ * Income above the baseline, expenses below it, per bucket. With `only`, a single series (no
24
+ * legend: the panel title names it).
25
+ */
26
+ export declare function FlowChart({ points, money, only, className }: {
27
+ points: FlowPoint[];
28
+ money: Money;
29
+ only?: "income" | "expense";
30
+ className?: string;
31
+ }): import("react").JSX.Element;
32
+ export type DonutSlice = {
33
+ key: string;
34
+ label: string;
35
+ color: string;
36
+ amount: bigint;
37
+ /** Category icon for the slice's callout. Charts without icons get color dots. */
38
+ icon?: string;
39
+ };
40
+ /**
41
+ * Shares of a total, clockwise from 12 o'clock. Up to 7 slices plus "Other". Each slice of 2% or
42
+ * more gets a callout outside the ring (its icon and share), so it reads without the legend; the
43
+ * caller still shows the ranked list beside it.
44
+ */
45
+ export declare function DonutChart({ slices, money, centerLabel, className }: {
46
+ slices: DonutSlice[];
47
+ money: Money;
48
+ centerLabel: string;
49
+ className?: string;
50
+ }): import("react").JSX.Element;
51
+ export {};
52
+ //# sourceMappingURL=charts.d.ts.map