@maracatu/estandarte 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maracatu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Estandarte
2
+
3
+ Estandarte is the **Maracatu** design system: the shared visual language and the
4
+ React primitives every Maracatu frontend builds on. The estandarte is the banner a
5
+ maracatu nation carries, its visual identity, which is exactly what this package is.
6
+
7
+ It is intentionally small. It holds what is genuinely shared across apps:
8
+
9
+ - **Design tokens** (`@maracatu/estandarte/theme.css`): theme-aware surface, text,
10
+ and border tokens that flip with a `.dark` class, plus the brand accent, the chart
11
+ palette, and the radius scale.
12
+ - **Theme**: `ThemeProvider` / `useTheme`, which toggle the `.dark` class and persist
13
+ the choice.
14
+ - **Agnostic primitives**: `Toast` and `ChartRenderer` (BRL-formatted), components
15
+ that carry no app or domain coupling.
16
+
17
+ App- and domain-specific components (chat messages, agent activity, conversation
18
+ menus) stay in the apps that own them. They are not design-system primitives.
19
+
20
+ ## Install
21
+
22
+ ```sh
23
+ npm install @maracatu/estandarte
24
+ ```
25
+
26
+ Peer dependencies: `react` and `react-dom` (18 or 19).
27
+
28
+ ## Use
29
+
30
+ Import the tokens once, in your app's global stylesheet, after Tailwind:
31
+
32
+ ```css
33
+ @import "tailwindcss";
34
+ @import "@maracatu/estandarte/theme.css";
35
+ ```
36
+
37
+ Wrap the app in `ThemeProvider` and build with the components and the token
38
+ utilities:
39
+
40
+ ```tsx
41
+ import { ThemeProvider, Toast, ChartRenderer } from "@maracatu/estandarte";
42
+
43
+ export function App() {
44
+ return (
45
+ <ThemeProvider>
46
+ <div className="min-h-screen bg-canvas text-primary">
47
+ <Toast message="Salvo com sucesso" kind="success" />
48
+ <ChartRenderer config={{ type: "bar", title: "Gastos por mês", data: [/* … */] }} />
49
+ </div>
50
+ </ThemeProvider>
51
+ );
52
+ }
53
+ ```
54
+
55
+ ## Token utilities
56
+
57
+ | Group | Utilities |
58
+ |---|---|
59
+ | Surfaces (theme-aware) | `bg-canvas`, `bg-elevated`, `bg-sidebar`, `bg-subtle` |
60
+ | Text (theme-aware) | `text-primary`, `text-secondary`, `text-muted` |
61
+ | Border (theme-aware) | `border-default` |
62
+ | Accent | `text-accent`, `from-accent-from`, `to-accent-to` |
63
+ | Chart palette | `bg-chart-1` … `bg-chart-6` (and `chartPalette` in JS) |
64
+ | Radius | `rounded-control`, `rounded-card`, `rounded-bubble` |
65
+
66
+ The raw, theme-aware values live in `:root` / `.dark` as `--es-*` custom properties;
67
+ the `@theme` block re-exports them as the utilities above.
68
+
69
+ ## Develop
70
+
71
+ ```sh
72
+ npm install
73
+ npm run build # tsup -> dist (ESM + CJS + .d.ts + theme.css)
74
+ npm run typecheck
75
+ ```
76
+
77
+ ## Scope
78
+
79
+ This is the foundation layer. It is meant to grow by promoting genuinely shared
80
+ pieces out of the apps, never by absorbing app-specific UI. The bar for adding a
81
+ component: it has no app, route, domain, or data coupling, and at least two
82
+ frontends would use it.
package/dist/index.cjs ADDED
@@ -0,0 +1,179 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var react$1 = require('motion/react');
7
+ var lucideReact = require('lucide-react');
8
+ var recharts = require('recharts');
9
+
10
+ // src/theme/theme-context.tsx
11
+ var ThemeContext = react.createContext(void 0);
12
+ function readCookie(key) {
13
+ if (typeof document === "undefined") return null;
14
+ const match = document.cookie.match(new RegExp(`(?:^|; )${key}=(dark|light)`));
15
+ return match?.[1] ?? null;
16
+ }
17
+ function ThemeProvider({
18
+ children,
19
+ defaultTheme = "dark",
20
+ storageKey = "maracatu_theme"
21
+ }) {
22
+ const [theme, setThemeState] = react.useState(() => readCookie(storageKey) ?? defaultTheme);
23
+ react.useEffect(() => {
24
+ document.documentElement.classList.toggle("dark", theme === "dark");
25
+ }, [theme]);
26
+ const persist = react.useCallback(
27
+ (next) => {
28
+ setThemeState(next);
29
+ document.cookie = `${storageKey}=${next};path=/;max-age=${365 * 86400};SameSite=Lax`;
30
+ },
31
+ [storageKey]
32
+ );
33
+ const toggleTheme = react.useCallback(() => {
34
+ persist(theme === "dark" ? "light" : "dark");
35
+ }, [theme, persist]);
36
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme: persist }, children });
37
+ }
38
+ function useTheme() {
39
+ const context = react.useContext(ThemeContext);
40
+ if (context === void 0) {
41
+ throw new Error("useTheme must be used within a ThemeProvider");
42
+ }
43
+ return context;
44
+ }
45
+
46
+ // src/theme/tokens.ts
47
+ var chartPalette = [
48
+ "#10b981",
49
+ "#3b82f6",
50
+ "#f59e0b",
51
+ "#ef4444",
52
+ "#8b5cf6",
53
+ "#ec4899"
54
+ ];
55
+ var accent = {
56
+ base: "#10b981",
57
+ from: "#34d399",
58
+ to: "#22d3ee"
59
+ };
60
+ function Toast({ message, kind = "success" }) {
61
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: message && /* @__PURE__ */ jsxRuntime.jsxs(
62
+ react$1.motion.div,
63
+ {
64
+ initial: { opacity: 0, y: -8 },
65
+ animate: { opacity: 1, y: 0 },
66
+ exit: { opacity: 0, y: -8 },
67
+ transition: { duration: 0.18 },
68
+ role: "status",
69
+ "aria-live": "polite",
70
+ className: "fixed top-3 left-1/2 -translate-x-1/2 z-[100] max-w-[calc(100vw-1.5rem)] sm:max-w-md px-4 py-2.5 text-sm rounded-2xl shadow-lg flex items-start gap-2 " + (kind === "error" ? "bg-red-600 text-white" : "bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900"),
71
+ children: [
72
+ kind === "error" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "w-4 h-4 shrink-0 mt-0.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 shrink-0 mt-0.5" }),
73
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "leading-snug", children: message })
74
+ ]
75
+ },
76
+ message
77
+ ) });
78
+ }
79
+ var DEFAULT_COLORS = [...chartPalette];
80
+ var MESES = {
81
+ Jan: "Janeiro",
82
+ Fev: "Fevereiro",
83
+ Mar: "Mar\xE7o",
84
+ Abr: "Abril",
85
+ Mai: "Maio",
86
+ Jun: "Junho",
87
+ Jul: "Julho",
88
+ Ago: "Agosto",
89
+ Set: "Setembro",
90
+ Out: "Outubro",
91
+ Nov: "Novembro",
92
+ Dez: "Dezembro",
93
+ "1": "Janeiro",
94
+ "2": "Fevereiro",
95
+ "3": "Mar\xE7o",
96
+ "4": "Abril",
97
+ "5": "Maio",
98
+ "6": "Junho",
99
+ "7": "Julho",
100
+ "8": "Agosto",
101
+ "9": "Setembro",
102
+ "10": "Outubro",
103
+ "11": "Novembro",
104
+ "12": "Dezembro"
105
+ };
106
+ function expandMonth(label) {
107
+ return MESES[label] || label;
108
+ }
109
+ function formatBRL(value) {
110
+ return value.toLocaleString("pt-BR", {
111
+ style: "currency",
112
+ currency: "BRL",
113
+ minimumFractionDigits: 2,
114
+ maximumFractionDigits: 2
115
+ });
116
+ }
117
+ function formatYAxis(value) {
118
+ if (value >= 1e6) return `R$ ${(value / 1e6).toLocaleString("pt-BR", { maximumFractionDigits: 1 })}M`;
119
+ if (value >= 1e3) return `R$ ${(value / 1e3).toLocaleString("pt-BR", { maximumFractionDigits: 0 })}k`;
120
+ return `R$ ${value.toLocaleString("pt-BR")}`;
121
+ }
122
+ function CustomTooltip({ active, payload, label }) {
123
+ if (!active || !payload?.length) return null;
124
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg", children: [
125
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: expandMonth(String(label)) }),
126
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: formatBRL(payload[0].value) })
127
+ ] });
128
+ }
129
+ function CustomPieTooltip({ active, payload }) {
130
+ if (!active || !payload?.length) return null;
131
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg", children: [
132
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: payload[0].name }),
133
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: formatBRL(payload[0].value) })
134
+ ] });
135
+ }
136
+ function ChartRendererImpl({ config }) {
137
+ const { type, data, xKey = "name", yKey = "value", title, colors = DEFAULT_COLORS } = config;
138
+ const { theme } = useTheme();
139
+ if (!data || data.length === 0) return null;
140
+ const isDark = theme === "dark";
141
+ const textColor = isDark ? "#a1a1aa" : "#71717a";
142
+ const gridColor = isDark ? "#3f3f46" : "#e4e4e7";
143
+ const chartData = data.map((d) => ({
144
+ ...d,
145
+ [xKey]: expandMonth(String(d[xKey]))
146
+ }));
147
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full my-6 bg-[#f4f4f4] dark:bg-[#2f2f2f] rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 shadow-sm", children: [
148
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-3", children: title }),
149
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-64", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: type === "bar" ? /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: chartData, margin: { top: 10, right: 10, left: 10, bottom: 0 }, children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: gridColor }),
151
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, tick: { fontSize: 10, fill: textColor }, axisLine: false, tickLine: false, angle: -45, textAnchor: "end", height: 50 }),
152
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 11, fill: textColor }, axisLine: false, tickLine: false, tickFormatter: formatYAxis, width: 70 }),
153
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip, {}), cursor: { fill: isDark ? "#3f3f46" : "#e4e4e7" } }),
154
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: yKey, fill: colors[0], radius: [4, 4, 0, 0], isAnimationActive: false })
155
+ ] }) : type === "pie" ? /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { children: [
156
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomPieTooltip, {}) }),
157
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Pie, { data: chartData, dataKey: yKey, nameKey: xKey, cx: "50%", cy: "50%", outerRadius: 80, fill: "#8884d8", isAnimationActive: false, children: chartData.map((_entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: colors[index % colors.length], stroke: isDark ? "#2f2f2f" : "#f4f4f4", strokeWidth: 2 }, `cell-${index}`)) })
158
+ ] }) : type === "line" ? /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: chartData, margin: { top: 10, right: 10, left: 10, bottom: 0 }, children: [
159
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: gridColor }),
160
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, tick: { fontSize: 10, fill: textColor }, axisLine: false, tickLine: false, angle: -45, textAnchor: "end", height: 50 }),
161
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: { fontSize: 11, fill: textColor }, axisLine: false, tickLine: false, tickFormatter: formatYAxis, width: 70 }),
162
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip, {}) }),
163
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Line, { type: "monotone", dataKey: yKey, stroke: colors[0], strokeWidth: 2, dot: { r: 4, fill: colors[0], strokeWidth: 0 }, activeDot: { r: 6, strokeWidth: 0 }, isAnimationActive: false })
164
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-zinc-500", children: "Tipo de gr\xE1fico n\xE3o suportado" }) }) })
165
+ ] });
166
+ }
167
+ var ChartRenderer = react.memo(
168
+ ChartRendererImpl,
169
+ (prev, next) => JSON.stringify(prev.config) === JSON.stringify(next.config)
170
+ );
171
+
172
+ exports.ChartRenderer = ChartRenderer;
173
+ exports.ThemeProvider = ThemeProvider;
174
+ exports.Toast = Toast;
175
+ exports.accent = accent;
176
+ exports.chartPalette = chartPalette;
177
+ exports.useTheme = useTheme;
178
+ //# sourceMappingURL=index.cjs.map
179
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/theme-context.tsx","../src/theme/tokens.ts","../src/components/toast.tsx","../src/components/chart-renderer.tsx"],"names":["createContext","useState","useEffect","useCallback","jsx","useContext","AnimatePresence","jsxs","motion","AlertTriangle","Check","ResponsiveContainer","BarChart","CartesianGrid","XAxis","YAxis","Tooltip","Bar","PieChart","Pie","Cell","LineChart","Line","memo"],"mappings":"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","file":"index.cjs","sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useCallback, useEffect } from \"react\";\n\nexport type Theme = \"dark\" | \"light\";\n\ntype ThemeContextType = {\n theme: Theme;\n toggleTheme: () => void;\n setTheme: (theme: Theme) => void;\n};\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\n\nexport type ThemeProviderProps = {\n children: React.ReactNode;\n /** Theme used before any stored preference is found. Defaults to \"dark\". */\n defaultTheme?: Theme;\n /** Cookie name the preference is persisted under. Defaults to \"maracatu_theme\". */\n storageKey?: string;\n};\n\nfunction readCookie(key: string): Theme | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(new RegExp(`(?:^|; )${key}=(dark|light)`));\n return (match?.[1] as Theme) ?? null;\n}\n\n/**\n * Provides the active theme and toggles a `dark` class on <html> so the\n * Estandarte tokens (theme.css) flip. Persists the choice to a cookie so it\n * survives reloads and is readable server-side.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"dark\",\n storageKey = \"maracatu_theme\",\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<Theme>(() => readCookie(storageKey) ?? defaultTheme);\n\n useEffect(() => {\n document.documentElement.classList.toggle(\"dark\", theme === \"dark\");\n }, [theme]);\n\n const persist = useCallback(\n (next: Theme) => {\n setThemeState(next);\n document.cookie = `${storageKey}=${next};path=/;max-age=${365 * 86400};SameSite=Lax`;\n },\n [storageKey],\n );\n\n const toggleTheme = useCallback(() => {\n persist(theme === \"dark\" ? \"light\" : \"dark\");\n }, [theme, persist]);\n\n return (\n <ThemeContext.Provider value={{ theme, toggleTheme, setTheme: persist }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (context === undefined) {\n throw new Error(\"useTheme must be used within a ThemeProvider\");\n }\n return context;\n}\n","// JS mirrors of the design tokens, for places that need the raw values\n// (e.g. Recharts, which takes colors as props, not classes).\n\n/** Brand chart palette, in order. Matches `--color-chart-*` in theme.css. */\nexport const chartPalette = [\n \"#10b981\",\n \"#3b82f6\",\n \"#f59e0b\",\n \"#ef4444\",\n \"#8b5cf6\",\n \"#ec4899\",\n] as const;\n\n/** Brand accent (emerald-500) and the avatar gradient stops. */\nexport const accent = {\n base: \"#10b981\",\n from: \"#34d399\",\n to: \"#22d3ee\",\n} as const;\n","\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { AlertTriangle, Check } from \"lucide-react\";\n\nexport type ToastProps = {\n message: string | null;\n kind?: \"success\" | \"error\";\n};\n\n/**\n * Single inline toast pinned to the top of the viewport. Animated in and out;\n * the message string is the source of truth — pass null to dismiss. The caller\n * owns the dismiss timer (typically 3-4s).\n */\nexport function Toast({ message, kind = \"success\" }: ToastProps) {\n return (\n <AnimatePresence>\n {message && (\n <motion.div\n key={message}\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.18 }}\n role=\"status\"\n aria-live=\"polite\"\n className={\n \"fixed top-3 left-1/2 -translate-x-1/2 z-[100] max-w-[calc(100vw-1.5rem)] sm:max-w-md px-4 py-2.5 text-sm rounded-2xl shadow-lg flex items-start gap-2 \" +\n (kind === \"error\"\n ? \"bg-red-600 text-white\"\n : \"bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900\")\n }\n >\n {kind === \"error\" ? (\n <AlertTriangle className=\"w-4 h-4 shrink-0 mt-0.5\" />\n ) : (\n <Check className=\"w-4 h-4 shrink-0 mt-0.5\" />\n )}\n <span className=\"leading-snug\">{message}</span>\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n","\"use client\";\n\nimport { memo } from \"react\";\nimport {\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n PieChart,\n Pie,\n Cell,\n LineChart,\n Line,\n} from \"recharts\";\nimport { useTheme } from \"../theme/theme-context\";\nimport { chartPalette } from \"../theme/tokens\";\n\nexport type ChartConfig = {\n type: \"bar\" | \"pie\" | \"line\";\n data: any[];\n xKey?: string;\n yKey?: string;\n title?: string;\n colors?: string[];\n};\n\nexport type ChartRendererProps = {\n config: ChartConfig;\n};\n\nconst DEFAULT_COLORS = [...chartPalette];\n\nconst MESES: Record<string, string> = {\n Jan: \"Janeiro\", Fev: \"Fevereiro\", Mar: \"Março\", Abr: \"Abril\",\n Mai: \"Maio\", Jun: \"Junho\", Jul: \"Julho\", Ago: \"Agosto\",\n Set: \"Setembro\", Out: \"Outubro\", Nov: \"Novembro\", Dez: \"Dezembro\",\n \"1\": \"Janeiro\", \"2\": \"Fevereiro\", \"3\": \"Março\", \"4\": \"Abril\",\n \"5\": \"Maio\", \"6\": \"Junho\", \"7\": \"Julho\", \"8\": \"Agosto\",\n \"9\": \"Setembro\", \"10\": \"Outubro\", \"11\": \"Novembro\", \"12\": \"Dezembro\",\n};\n\nfunction expandMonth(label: string): string {\n return MESES[label] || label;\n}\n\nfunction formatBRL(value: number): string {\n return value.toLocaleString(\"pt-BR\", {\n style: \"currency\",\n currency: \"BRL\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\nfunction formatYAxis(value: number): string {\n if (value >= 1_000_000) return `R$ ${(value / 1_000_000).toLocaleString(\"pt-BR\", { maximumFractionDigits: 1 })}M`;\n if (value >= 1_000) return `R$ ${(value / 1_000).toLocaleString(\"pt-BR\", { maximumFractionDigits: 0 })}k`;\n return `R$ ${value.toLocaleString(\"pt-BR\")}`;\n}\n\nfunction CustomTooltip({ active, payload, label }: any) {\n if (!active || !payload?.length) return null;\n return (\n <div className=\"bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg\">\n <p className=\"font-medium\">{expandMonth(String(label))}</p>\n <p>{formatBRL(payload[0].value)}</p>\n </div>\n );\n}\n\nfunction CustomPieTooltip({ active, payload }: any) {\n if (!active || !payload?.length) return null;\n return (\n <div className=\"bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg\">\n <p className=\"font-medium\">{payload[0].name}</p>\n <p>{formatBRL(payload[0].value)}</p>\n </div>\n );\n}\n\nfunction ChartRendererImpl({ config }: ChartRendererProps) {\n const { type, data, xKey = \"name\", yKey = \"value\", title, colors = DEFAULT_COLORS } = config;\n const { theme } = useTheme();\n\n if (!data || data.length === 0) return null;\n\n const isDark = theme === \"dark\";\n const textColor = isDark ? \"#a1a1aa\" : \"#71717a\";\n const gridColor = isDark ? \"#3f3f46\" : \"#e4e4e7\";\n\n const chartData = data.map((d) => ({\n ...d,\n [xKey]: expandMonth(String(d[xKey])),\n }));\n\n return (\n <div className=\"w-full my-6 bg-[#f4f4f4] dark:bg-[#2f2f2f] rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 shadow-sm\">\n {title && <p className=\"text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-3\">{title}</p>}\n <div className=\"w-full h-64\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {type === \"bar\" ? (\n <BarChart data={chartData} margin={{ top: 10, right: 10, left: 10, bottom: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" vertical={false} stroke={gridColor} />\n <XAxis dataKey={xKey} tick={{ fontSize: 10, fill: textColor }} axisLine={false} tickLine={false} angle={-45} textAnchor=\"end\" height={50} />\n <YAxis tick={{ fontSize: 11, fill: textColor }} axisLine={false} tickLine={false} tickFormatter={formatYAxis} width={70} />\n <Tooltip content={<CustomTooltip />} cursor={{ fill: isDark ? \"#3f3f46\" : \"#e4e4e7\" }} />\n <Bar dataKey={yKey} fill={colors[0]} radius={[4, 4, 0, 0]} isAnimationActive={false} />\n </BarChart>\n ) : type === \"pie\" ? (\n <PieChart>\n <Tooltip content={<CustomPieTooltip />} />\n <Pie data={chartData} dataKey={yKey} nameKey={xKey} cx=\"50%\" cy=\"50%\" outerRadius={80} fill=\"#8884d8\" isAnimationActive={false}>\n {chartData.map((_entry: any, index: number) => (\n <Cell key={`cell-${index}`} fill={colors[index % colors.length]} stroke={isDark ? \"#2f2f2f\" : \"#f4f4f4\"} strokeWidth={2} />\n ))}\n </Pie>\n </PieChart>\n ) : type === \"line\" ? (\n <LineChart data={chartData} margin={{ top: 10, right: 10, left: 10, bottom: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" vertical={false} stroke={gridColor} />\n <XAxis dataKey={xKey} tick={{ fontSize: 10, fill: textColor }} axisLine={false} tickLine={false} angle={-45} textAnchor=\"end\" height={50} />\n <YAxis tick={{ fontSize: 11, fill: textColor }} axisLine={false} tickLine={false} tickFormatter={formatYAxis} width={70} />\n <Tooltip content={<CustomTooltip />} />\n <Line type=\"monotone\" dataKey={yKey} stroke={colors[0]} strokeWidth={2} dot={{ r: 4, fill: colors[0], strokeWidth: 0 }} activeDot={{ r: 6, strokeWidth: 0 }} isAnimationActive={false} />\n </LineChart>\n ) : (\n <div className=\"flex items-center justify-center h-full text-zinc-500\">Tipo de gráfico não suportado</div>\n )}\n </ResponsiveContainer>\n </div>\n </div>\n );\n}\n\nexport const ChartRenderer = memo(\n ChartRendererImpl,\n (prev, next) => JSON.stringify(prev.config) === JSON.stringify(next.config),\n);\n"]}
@@ -0,0 +1,59 @@
1
+ import * as react from 'react';
2
+ import react__default from 'react';
3
+
4
+ type Theme = "dark" | "light";
5
+ type ThemeContextType = {
6
+ theme: Theme;
7
+ toggleTheme: () => void;
8
+ setTheme: (theme: Theme) => void;
9
+ };
10
+ type ThemeProviderProps = {
11
+ children: react__default.ReactNode;
12
+ /** Theme used before any stored preference is found. Defaults to "dark". */
13
+ defaultTheme?: Theme;
14
+ /** Cookie name the preference is persisted under. Defaults to "maracatu_theme". */
15
+ storageKey?: string;
16
+ };
17
+ /**
18
+ * Provides the active theme and toggles a `dark` class on <html> so the
19
+ * Estandarte tokens (theme.css) flip. Persists the choice to a cookie so it
20
+ * survives reloads and is readable server-side.
21
+ */
22
+ declare function ThemeProvider({ children, defaultTheme, storageKey, }: ThemeProviderProps): react__default.JSX.Element;
23
+ declare function useTheme(): ThemeContextType;
24
+
25
+ /** Brand chart palette, in order. Matches `--color-chart-*` in theme.css. */
26
+ declare const chartPalette: readonly ["#10b981", "#3b82f6", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
27
+ /** Brand accent (emerald-500) and the avatar gradient stops. */
28
+ declare const accent: {
29
+ readonly base: "#10b981";
30
+ readonly from: "#34d399";
31
+ readonly to: "#22d3ee";
32
+ };
33
+
34
+ type ToastProps = {
35
+ message: string | null;
36
+ kind?: "success" | "error";
37
+ };
38
+ /**
39
+ * Single inline toast pinned to the top of the viewport. Animated in and out;
40
+ * the message string is the source of truth — pass null to dismiss. The caller
41
+ * owns the dismiss timer (typically 3-4s).
42
+ */
43
+ declare function Toast({ message, kind }: ToastProps): react.JSX.Element;
44
+
45
+ type ChartConfig = {
46
+ type: "bar" | "pie" | "line";
47
+ data: any[];
48
+ xKey?: string;
49
+ yKey?: string;
50
+ title?: string;
51
+ colors?: string[];
52
+ };
53
+ type ChartRendererProps = {
54
+ config: ChartConfig;
55
+ };
56
+ declare function ChartRendererImpl({ config }: ChartRendererProps): react.JSX.Element | null;
57
+ declare const ChartRenderer: react.MemoExoticComponent<typeof ChartRendererImpl>;
58
+
59
+ export { type ChartConfig, ChartRenderer, type ChartRendererProps, type Theme, ThemeProvider, type ThemeProviderProps, Toast, type ToastProps, accent, chartPalette, useTheme };
@@ -0,0 +1,59 @@
1
+ import * as react from 'react';
2
+ import react__default from 'react';
3
+
4
+ type Theme = "dark" | "light";
5
+ type ThemeContextType = {
6
+ theme: Theme;
7
+ toggleTheme: () => void;
8
+ setTheme: (theme: Theme) => void;
9
+ };
10
+ type ThemeProviderProps = {
11
+ children: react__default.ReactNode;
12
+ /** Theme used before any stored preference is found. Defaults to "dark". */
13
+ defaultTheme?: Theme;
14
+ /** Cookie name the preference is persisted under. Defaults to "maracatu_theme". */
15
+ storageKey?: string;
16
+ };
17
+ /**
18
+ * Provides the active theme and toggles a `dark` class on <html> so the
19
+ * Estandarte tokens (theme.css) flip. Persists the choice to a cookie so it
20
+ * survives reloads and is readable server-side.
21
+ */
22
+ declare function ThemeProvider({ children, defaultTheme, storageKey, }: ThemeProviderProps): react__default.JSX.Element;
23
+ declare function useTheme(): ThemeContextType;
24
+
25
+ /** Brand chart palette, in order. Matches `--color-chart-*` in theme.css. */
26
+ declare const chartPalette: readonly ["#10b981", "#3b82f6", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
27
+ /** Brand accent (emerald-500) and the avatar gradient stops. */
28
+ declare const accent: {
29
+ readonly base: "#10b981";
30
+ readonly from: "#34d399";
31
+ readonly to: "#22d3ee";
32
+ };
33
+
34
+ type ToastProps = {
35
+ message: string | null;
36
+ kind?: "success" | "error";
37
+ };
38
+ /**
39
+ * Single inline toast pinned to the top of the viewport. Animated in and out;
40
+ * the message string is the source of truth — pass null to dismiss. The caller
41
+ * owns the dismiss timer (typically 3-4s).
42
+ */
43
+ declare function Toast({ message, kind }: ToastProps): react.JSX.Element;
44
+
45
+ type ChartConfig = {
46
+ type: "bar" | "pie" | "line";
47
+ data: any[];
48
+ xKey?: string;
49
+ yKey?: string;
50
+ title?: string;
51
+ colors?: string[];
52
+ };
53
+ type ChartRendererProps = {
54
+ config: ChartConfig;
55
+ };
56
+ declare function ChartRendererImpl({ config }: ChartRendererProps): react.JSX.Element | null;
57
+ declare const ChartRenderer: react.MemoExoticComponent<typeof ChartRendererImpl>;
58
+
59
+ export { type ChartConfig, ChartRenderer, type ChartRendererProps, type Theme, ThemeProvider, type ThemeProviderProps, Toast, type ToastProps, accent, chartPalette, useTheme };
package/dist/index.js ADDED
@@ -0,0 +1,172 @@
1
+ "use client";
2
+ import { createContext, memo, useContext, useState, useEffect, useCallback } from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import { AnimatePresence, motion } from 'motion/react';
5
+ import { AlertTriangle, Check } from 'lucide-react';
6
+ import { ResponsiveContainer, BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar, PieChart, Pie, Cell, LineChart, Line } from 'recharts';
7
+
8
+ // src/theme/theme-context.tsx
9
+ var ThemeContext = createContext(void 0);
10
+ function readCookie(key) {
11
+ if (typeof document === "undefined") return null;
12
+ const match = document.cookie.match(new RegExp(`(?:^|; )${key}=(dark|light)`));
13
+ return match?.[1] ?? null;
14
+ }
15
+ function ThemeProvider({
16
+ children,
17
+ defaultTheme = "dark",
18
+ storageKey = "maracatu_theme"
19
+ }) {
20
+ const [theme, setThemeState] = useState(() => readCookie(storageKey) ?? defaultTheme);
21
+ useEffect(() => {
22
+ document.documentElement.classList.toggle("dark", theme === "dark");
23
+ }, [theme]);
24
+ const persist = useCallback(
25
+ (next) => {
26
+ setThemeState(next);
27
+ document.cookie = `${storageKey}=${next};path=/;max-age=${365 * 86400};SameSite=Lax`;
28
+ },
29
+ [storageKey]
30
+ );
31
+ const toggleTheme = useCallback(() => {
32
+ persist(theme === "dark" ? "light" : "dark");
33
+ }, [theme, persist]);
34
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme: persist }, children });
35
+ }
36
+ function useTheme() {
37
+ const context = useContext(ThemeContext);
38
+ if (context === void 0) {
39
+ throw new Error("useTheme must be used within a ThemeProvider");
40
+ }
41
+ return context;
42
+ }
43
+
44
+ // src/theme/tokens.ts
45
+ var chartPalette = [
46
+ "#10b981",
47
+ "#3b82f6",
48
+ "#f59e0b",
49
+ "#ef4444",
50
+ "#8b5cf6",
51
+ "#ec4899"
52
+ ];
53
+ var accent = {
54
+ base: "#10b981",
55
+ from: "#34d399",
56
+ to: "#22d3ee"
57
+ };
58
+ function Toast({ message, kind = "success" }) {
59
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: message && /* @__PURE__ */ jsxs(
60
+ motion.div,
61
+ {
62
+ initial: { opacity: 0, y: -8 },
63
+ animate: { opacity: 1, y: 0 },
64
+ exit: { opacity: 0, y: -8 },
65
+ transition: { duration: 0.18 },
66
+ role: "status",
67
+ "aria-live": "polite",
68
+ className: "fixed top-3 left-1/2 -translate-x-1/2 z-[100] max-w-[calc(100vw-1.5rem)] sm:max-w-md px-4 py-2.5 text-sm rounded-2xl shadow-lg flex items-start gap-2 " + (kind === "error" ? "bg-red-600 text-white" : "bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900"),
69
+ children: [
70
+ kind === "error" ? /* @__PURE__ */ jsx(AlertTriangle, { className: "w-4 h-4 shrink-0 mt-0.5" }) : /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 shrink-0 mt-0.5" }),
71
+ /* @__PURE__ */ jsx("span", { className: "leading-snug", children: message })
72
+ ]
73
+ },
74
+ message
75
+ ) });
76
+ }
77
+ var DEFAULT_COLORS = [...chartPalette];
78
+ var MESES = {
79
+ Jan: "Janeiro",
80
+ Fev: "Fevereiro",
81
+ Mar: "Mar\xE7o",
82
+ Abr: "Abril",
83
+ Mai: "Maio",
84
+ Jun: "Junho",
85
+ Jul: "Julho",
86
+ Ago: "Agosto",
87
+ Set: "Setembro",
88
+ Out: "Outubro",
89
+ Nov: "Novembro",
90
+ Dez: "Dezembro",
91
+ "1": "Janeiro",
92
+ "2": "Fevereiro",
93
+ "3": "Mar\xE7o",
94
+ "4": "Abril",
95
+ "5": "Maio",
96
+ "6": "Junho",
97
+ "7": "Julho",
98
+ "8": "Agosto",
99
+ "9": "Setembro",
100
+ "10": "Outubro",
101
+ "11": "Novembro",
102
+ "12": "Dezembro"
103
+ };
104
+ function expandMonth(label) {
105
+ return MESES[label] || label;
106
+ }
107
+ function formatBRL(value) {
108
+ return value.toLocaleString("pt-BR", {
109
+ style: "currency",
110
+ currency: "BRL",
111
+ minimumFractionDigits: 2,
112
+ maximumFractionDigits: 2
113
+ });
114
+ }
115
+ function formatYAxis(value) {
116
+ if (value >= 1e6) return `R$ ${(value / 1e6).toLocaleString("pt-BR", { maximumFractionDigits: 1 })}M`;
117
+ if (value >= 1e3) return `R$ ${(value / 1e3).toLocaleString("pt-BR", { maximumFractionDigits: 0 })}k`;
118
+ return `R$ ${value.toLocaleString("pt-BR")}`;
119
+ }
120
+ function CustomTooltip({ active, payload, label }) {
121
+ if (!active || !payload?.length) return null;
122
+ return /* @__PURE__ */ jsxs("div", { className: "bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg", children: [
123
+ /* @__PURE__ */ jsx("p", { className: "font-medium", children: expandMonth(String(label)) }),
124
+ /* @__PURE__ */ jsx("p", { children: formatBRL(payload[0].value) })
125
+ ] });
126
+ }
127
+ function CustomPieTooltip({ active, payload }) {
128
+ if (!active || !payload?.length) return null;
129
+ return /* @__PURE__ */ jsxs("div", { className: "bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg", children: [
130
+ /* @__PURE__ */ jsx("p", { className: "font-medium", children: payload[0].name }),
131
+ /* @__PURE__ */ jsx("p", { children: formatBRL(payload[0].value) })
132
+ ] });
133
+ }
134
+ function ChartRendererImpl({ config }) {
135
+ const { type, data, xKey = "name", yKey = "value", title, colors = DEFAULT_COLORS } = config;
136
+ const { theme } = useTheme();
137
+ if (!data || data.length === 0) return null;
138
+ const isDark = theme === "dark";
139
+ const textColor = isDark ? "#a1a1aa" : "#71717a";
140
+ const gridColor = isDark ? "#3f3f46" : "#e4e4e7";
141
+ const chartData = data.map((d) => ({
142
+ ...d,
143
+ [xKey]: expandMonth(String(d[xKey]))
144
+ }));
145
+ return /* @__PURE__ */ jsxs("div", { className: "w-full my-6 bg-[#f4f4f4] dark:bg-[#2f2f2f] rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 shadow-sm", children: [
146
+ title && /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-3", children: title }),
147
+ /* @__PURE__ */ jsx("div", { className: "w-full h-64", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: type === "bar" ? /* @__PURE__ */ jsxs(BarChart, { data: chartData, margin: { top: 10, right: 10, left: 10, bottom: 0 }, children: [
148
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: gridColor }),
149
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, tick: { fontSize: 10, fill: textColor }, axisLine: false, tickLine: false, angle: -45, textAnchor: "end", height: 50 }),
150
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 11, fill: textColor }, axisLine: false, tickLine: false, tickFormatter: formatYAxis, width: 70 }),
151
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { fill: isDark ? "#3f3f46" : "#e4e4e7" } }),
152
+ /* @__PURE__ */ jsx(Bar, { dataKey: yKey, fill: colors[0], radius: [4, 4, 0, 0], isAnimationActive: false })
153
+ ] }) : type === "pie" ? /* @__PURE__ */ jsxs(PieChart, { children: [
154
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomPieTooltip, {}) }),
155
+ /* @__PURE__ */ jsx(Pie, { data: chartData, dataKey: yKey, nameKey: xKey, cx: "50%", cy: "50%", outerRadius: 80, fill: "#8884d8", isAnimationActive: false, children: chartData.map((_entry, index) => /* @__PURE__ */ jsx(Cell, { fill: colors[index % colors.length], stroke: isDark ? "#2f2f2f" : "#f4f4f4", strokeWidth: 2 }, `cell-${index}`)) })
156
+ ] }) : type === "line" ? /* @__PURE__ */ jsxs(LineChart, { data: chartData, margin: { top: 10, right: 10, left: 10, bottom: 0 }, children: [
157
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: gridColor }),
158
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, tick: { fontSize: 10, fill: textColor }, axisLine: false, tickLine: false, angle: -45, textAnchor: "end", height: 50 }),
159
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 11, fill: textColor }, axisLine: false, tickLine: false, tickFormatter: formatYAxis, width: 70 }),
160
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}) }),
161
+ /* @__PURE__ */ jsx(Line, { type: "monotone", dataKey: yKey, stroke: colors[0], strokeWidth: 2, dot: { r: 4, fill: colors[0], strokeWidth: 0 }, activeDot: { r: 6, strokeWidth: 0 }, isAnimationActive: false })
162
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-zinc-500", children: "Tipo de gr\xE1fico n\xE3o suportado" }) }) })
163
+ ] });
164
+ }
165
+ var ChartRenderer = memo(
166
+ ChartRendererImpl,
167
+ (prev, next) => JSON.stringify(prev.config) === JSON.stringify(next.config)
168
+ );
169
+
170
+ export { ChartRenderer, ThemeProvider, Toast, accent, chartPalette, useTheme };
171
+ //# sourceMappingURL=index.js.map
172
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/theme-context.tsx","../src/theme/tokens.ts","../src/components/toast.tsx","../src/components/chart-renderer.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useCallback, useEffect } from \"react\";\n\nexport type Theme = \"dark\" | \"light\";\n\ntype ThemeContextType = {\n theme: Theme;\n toggleTheme: () => void;\n setTheme: (theme: Theme) => void;\n};\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\n\nexport type ThemeProviderProps = {\n children: React.ReactNode;\n /** Theme used before any stored preference is found. Defaults to \"dark\". */\n defaultTheme?: Theme;\n /** Cookie name the preference is persisted under. Defaults to \"maracatu_theme\". */\n storageKey?: string;\n};\n\nfunction readCookie(key: string): Theme | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(new RegExp(`(?:^|; )${key}=(dark|light)`));\n return (match?.[1] as Theme) ?? null;\n}\n\n/**\n * Provides the active theme and toggles a `dark` class on <html> so the\n * Estandarte tokens (theme.css) flip. Persists the choice to a cookie so it\n * survives reloads and is readable server-side.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"dark\",\n storageKey = \"maracatu_theme\",\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<Theme>(() => readCookie(storageKey) ?? defaultTheme);\n\n useEffect(() => {\n document.documentElement.classList.toggle(\"dark\", theme === \"dark\");\n }, [theme]);\n\n const persist = useCallback(\n (next: Theme) => {\n setThemeState(next);\n document.cookie = `${storageKey}=${next};path=/;max-age=${365 * 86400};SameSite=Lax`;\n },\n [storageKey],\n );\n\n const toggleTheme = useCallback(() => {\n persist(theme === \"dark\" ? \"light\" : \"dark\");\n }, [theme, persist]);\n\n return (\n <ThemeContext.Provider value={{ theme, toggleTheme, setTheme: persist }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (context === undefined) {\n throw new Error(\"useTheme must be used within a ThemeProvider\");\n }\n return context;\n}\n","// JS mirrors of the design tokens, for places that need the raw values\n// (e.g. Recharts, which takes colors as props, not classes).\n\n/** Brand chart palette, in order. Matches `--color-chart-*` in theme.css. */\nexport const chartPalette = [\n \"#10b981\",\n \"#3b82f6\",\n \"#f59e0b\",\n \"#ef4444\",\n \"#8b5cf6\",\n \"#ec4899\",\n] as const;\n\n/** Brand accent (emerald-500) and the avatar gradient stops. */\nexport const accent = {\n base: \"#10b981\",\n from: \"#34d399\",\n to: \"#22d3ee\",\n} as const;\n","\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { AlertTriangle, Check } from \"lucide-react\";\n\nexport type ToastProps = {\n message: string | null;\n kind?: \"success\" | \"error\";\n};\n\n/**\n * Single inline toast pinned to the top of the viewport. Animated in and out;\n * the message string is the source of truth — pass null to dismiss. The caller\n * owns the dismiss timer (typically 3-4s).\n */\nexport function Toast({ message, kind = \"success\" }: ToastProps) {\n return (\n <AnimatePresence>\n {message && (\n <motion.div\n key={message}\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.18 }}\n role=\"status\"\n aria-live=\"polite\"\n className={\n \"fixed top-3 left-1/2 -translate-x-1/2 z-[100] max-w-[calc(100vw-1.5rem)] sm:max-w-md px-4 py-2.5 text-sm rounded-2xl shadow-lg flex items-start gap-2 \" +\n (kind === \"error\"\n ? \"bg-red-600 text-white\"\n : \"bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900\")\n }\n >\n {kind === \"error\" ? (\n <AlertTriangle className=\"w-4 h-4 shrink-0 mt-0.5\" />\n ) : (\n <Check className=\"w-4 h-4 shrink-0 mt-0.5\" />\n )}\n <span className=\"leading-snug\">{message}</span>\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n","\"use client\";\n\nimport { memo } from \"react\";\nimport {\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n PieChart,\n Pie,\n Cell,\n LineChart,\n Line,\n} from \"recharts\";\nimport { useTheme } from \"../theme/theme-context\";\nimport { chartPalette } from \"../theme/tokens\";\n\nexport type ChartConfig = {\n type: \"bar\" | \"pie\" | \"line\";\n data: any[];\n xKey?: string;\n yKey?: string;\n title?: string;\n colors?: string[];\n};\n\nexport type ChartRendererProps = {\n config: ChartConfig;\n};\n\nconst DEFAULT_COLORS = [...chartPalette];\n\nconst MESES: Record<string, string> = {\n Jan: \"Janeiro\", Fev: \"Fevereiro\", Mar: \"Março\", Abr: \"Abril\",\n Mai: \"Maio\", Jun: \"Junho\", Jul: \"Julho\", Ago: \"Agosto\",\n Set: \"Setembro\", Out: \"Outubro\", Nov: \"Novembro\", Dez: \"Dezembro\",\n \"1\": \"Janeiro\", \"2\": \"Fevereiro\", \"3\": \"Março\", \"4\": \"Abril\",\n \"5\": \"Maio\", \"6\": \"Junho\", \"7\": \"Julho\", \"8\": \"Agosto\",\n \"9\": \"Setembro\", \"10\": \"Outubro\", \"11\": \"Novembro\", \"12\": \"Dezembro\",\n};\n\nfunction expandMonth(label: string): string {\n return MESES[label] || label;\n}\n\nfunction formatBRL(value: number): string {\n return value.toLocaleString(\"pt-BR\", {\n style: \"currency\",\n currency: \"BRL\",\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\nfunction formatYAxis(value: number): string {\n if (value >= 1_000_000) return `R$ ${(value / 1_000_000).toLocaleString(\"pt-BR\", { maximumFractionDigits: 1 })}M`;\n if (value >= 1_000) return `R$ ${(value / 1_000).toLocaleString(\"pt-BR\", { maximumFractionDigits: 0 })}k`;\n return `R$ ${value.toLocaleString(\"pt-BR\")}`;\n}\n\nfunction CustomTooltip({ active, payload, label }: any) {\n if (!active || !payload?.length) return null;\n return (\n <div className=\"bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg\">\n <p className=\"font-medium\">{expandMonth(String(label))}</p>\n <p>{formatBRL(payload[0].value)}</p>\n </div>\n );\n}\n\nfunction CustomPieTooltip({ active, payload }: any) {\n if (!active || !payload?.length) return null;\n return (\n <div className=\"bg-zinc-900 dark:bg-zinc-100 text-zinc-100 dark:text-zinc-900 px-3 py-2 rounded-lg text-sm shadow-lg\">\n <p className=\"font-medium\">{payload[0].name}</p>\n <p>{formatBRL(payload[0].value)}</p>\n </div>\n );\n}\n\nfunction ChartRendererImpl({ config }: ChartRendererProps) {\n const { type, data, xKey = \"name\", yKey = \"value\", title, colors = DEFAULT_COLORS } = config;\n const { theme } = useTheme();\n\n if (!data || data.length === 0) return null;\n\n const isDark = theme === \"dark\";\n const textColor = isDark ? \"#a1a1aa\" : \"#71717a\";\n const gridColor = isDark ? \"#3f3f46\" : \"#e4e4e7\";\n\n const chartData = data.map((d) => ({\n ...d,\n [xKey]: expandMonth(String(d[xKey])),\n }));\n\n return (\n <div className=\"w-full my-6 bg-[#f4f4f4] dark:bg-[#2f2f2f] rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 shadow-sm\">\n {title && <p className=\"text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-3\">{title}</p>}\n <div className=\"w-full h-64\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {type === \"bar\" ? (\n <BarChart data={chartData} margin={{ top: 10, right: 10, left: 10, bottom: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" vertical={false} stroke={gridColor} />\n <XAxis dataKey={xKey} tick={{ fontSize: 10, fill: textColor }} axisLine={false} tickLine={false} angle={-45} textAnchor=\"end\" height={50} />\n <YAxis tick={{ fontSize: 11, fill: textColor }} axisLine={false} tickLine={false} tickFormatter={formatYAxis} width={70} />\n <Tooltip content={<CustomTooltip />} cursor={{ fill: isDark ? \"#3f3f46\" : \"#e4e4e7\" }} />\n <Bar dataKey={yKey} fill={colors[0]} radius={[4, 4, 0, 0]} isAnimationActive={false} />\n </BarChart>\n ) : type === \"pie\" ? (\n <PieChart>\n <Tooltip content={<CustomPieTooltip />} />\n <Pie data={chartData} dataKey={yKey} nameKey={xKey} cx=\"50%\" cy=\"50%\" outerRadius={80} fill=\"#8884d8\" isAnimationActive={false}>\n {chartData.map((_entry: any, index: number) => (\n <Cell key={`cell-${index}`} fill={colors[index % colors.length]} stroke={isDark ? \"#2f2f2f\" : \"#f4f4f4\"} strokeWidth={2} />\n ))}\n </Pie>\n </PieChart>\n ) : type === \"line\" ? (\n <LineChart data={chartData} margin={{ top: 10, right: 10, left: 10, bottom: 0 }}>\n <CartesianGrid strokeDasharray=\"3 3\" vertical={false} stroke={gridColor} />\n <XAxis dataKey={xKey} tick={{ fontSize: 10, fill: textColor }} axisLine={false} tickLine={false} angle={-45} textAnchor=\"end\" height={50} />\n <YAxis tick={{ fontSize: 11, fill: textColor }} axisLine={false} tickLine={false} tickFormatter={formatYAxis} width={70} />\n <Tooltip content={<CustomTooltip />} />\n <Line type=\"monotone\" dataKey={yKey} stroke={colors[0]} strokeWidth={2} dot={{ r: 4, fill: colors[0], strokeWidth: 0 }} activeDot={{ r: 6, strokeWidth: 0 }} isAnimationActive={false} />\n </LineChart>\n ) : (\n <div className=\"flex items-center justify-center h-full text-zinc-500\">Tipo de gráfico não suportado</div>\n )}\n </ResponsiveContainer>\n </div>\n </div>\n );\n}\n\nexport const ChartRenderer = memo(\n ChartRendererImpl,\n (prev, next) => JSON.stringify(prev.config) === JSON.stringify(next.config),\n);\n"]}
package/dist/theme.css ADDED
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Estandarte — the Maracatu design tokens.
3
+ *
4
+ * Import this once in an app's global stylesheet, after Tailwind:
5
+ * @import "tailwindcss";
6
+ * @import "@maracatu/estandarte/theme.css";
7
+ *
8
+ * It provides:
9
+ * - theme-aware surface/text/border tokens that flip with the `.dark` class
10
+ * (ThemeProvider toggles it), exposed as Tailwind utilities:
11
+ * bg-canvas / bg-elevated / bg-sidebar / bg-subtle
12
+ * text-primary / text-secondary / text-muted
13
+ * border-default
14
+ * - brand accent + the chart palette (chart-1..chart-6)
15
+ * - the radius scale (rounded-control / rounded-card / rounded-bubble)
16
+ *
17
+ * Values are the ones audited from the shipped product, promoted to named
18
+ * tokens so every Maracatu frontend shares one visual language.
19
+ */
20
+
21
+ @custom-variant dark (&:where(.dark, .dark *));
22
+
23
+ /* Raw, theme-aware values. These are the single source of truth; the @theme
24
+ block below only re-exports them as Tailwind utilities. */
25
+ :root {
26
+ --es-canvas: #ffffff;
27
+ --es-elevated: #f4f4f4;
28
+ --es-sidebar: #f9f9f9;
29
+ --es-subtle: #f9f9f9;
30
+
31
+ --es-text-primary: #18181b; /* zinc-900 */
32
+ --es-text-secondary: #71717a; /* zinc-500 */
33
+ --es-text-muted: #a1a1aa; /* zinc-400 */
34
+
35
+ --es-border: #e4e4e7; /* zinc-200 */
36
+ }
37
+
38
+ .dark {
39
+ --es-canvas: #212121;
40
+ --es-elevated: #2f2f2f;
41
+ --es-sidebar: #171717;
42
+ --es-subtle: #171717;
43
+
44
+ --es-text-primary: #f4f4f4; /* zinc-100 */
45
+ --es-text-secondary: #a1a1aa; /* zinc-400 */
46
+ --es-text-muted: #71717a; /* zinc-500 */
47
+
48
+ --es-border: #27272a; /* zinc-800 */
49
+ }
50
+
51
+ @theme inline {
52
+ /* Semantic, theme-aware surfaces + text (resolve to the vars above). */
53
+ --color-canvas: var(--es-canvas);
54
+ --color-elevated: var(--es-elevated);
55
+ --color-sidebar: var(--es-sidebar);
56
+ --color-subtle: var(--es-subtle);
57
+
58
+ --color-primary: var(--es-text-primary);
59
+ --color-secondary: var(--es-text-secondary);
60
+ --color-muted: var(--es-text-muted);
61
+
62
+ --color-default: var(--es-border);
63
+ }
64
+
65
+ @theme {
66
+ /* Brand accent. */
67
+ --color-accent: #10b981; /* emerald-500 */
68
+ --color-accent-from: #34d399; /* emerald-400 */
69
+ --color-accent-to: #22d3ee; /* cyan-400 */
70
+
71
+ /* Chart palette (matches the product's DEFAULT_COLORS). */
72
+ --color-chart-1: #10b981;
73
+ --color-chart-2: #3b82f6;
74
+ --color-chart-3: #f59e0b;
75
+ --color-chart-4: #ef4444;
76
+ --color-chart-5: #8b5cf6;
77
+ --color-chart-6: #ec4899;
78
+
79
+ /* Radius scale. */
80
+ --radius-control: 0.75rem; /* inputs, menu items */
81
+ --radius-card: 1rem; /* cards, panels */
82
+ --radius-bubble: 1.5rem; /* chat bubbles */
83
+ }
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@maracatu/estandarte",
3
+ "version": "0.1.0",
4
+ "description": "Estandarte — the Maracatu design system: tokens, theme, and shared React primitives.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "homepage": "https://github.com/maracatu-org/estandarte#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/maracatu-org/estandarte.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/maracatu-org/estandarte/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "sideEffects": [
19
+ "**/*.css"
20
+ ],
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js",
28
+ "require": "./dist/index.cjs"
29
+ },
30
+ "./theme.css": "./dist/theme.css"
31
+ },
32
+ "main": "./dist/index.cjs",
33
+ "module": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsup --watch",
38
+ "typecheck": "tsc --noEmit",
39
+ "prepublishOnly": "npm run build"
40
+ },
41
+ "peerDependencies": {
42
+ "react": "^18.0.0 || ^19.0.0",
43
+ "react-dom": "^18.0.0 || ^19.0.0"
44
+ },
45
+ "dependencies": {
46
+ "lucide-react": "^0.546.0",
47
+ "motion": "^12.38.0",
48
+ "recharts": "^2.12.0"
49
+ },
50
+ "devDependencies": {
51
+ "@tailwindcss/postcss": "^4.3.1",
52
+ "@types/react": "^19.0.0",
53
+ "@types/react-dom": "^19.0.0",
54
+ "postcss": "^8.5.15",
55
+ "react": "^19.0.0",
56
+ "react-dom": "^19.0.0",
57
+ "tailwindcss": "^4.3.1",
58
+ "tsup": "^8.0.0",
59
+ "typescript": "^5.7.0"
60
+ }
61
+ }