@web-my-money/tokens 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.
@@ -0,0 +1,61 @@
1
+ import * as React from 'react';
2
+ import { c as FontSizeName, e as ThemeName } from './font-size-runtime-DlvZXy2n.js';
3
+
4
+ /**
5
+ * @web-my-money/tokens/react — versioned React theme helpers.
6
+ * Wraps the framework-agnostic runtime (theme-runtime.ts) so every app shares one
7
+ * theme vocabulary: light / dark / wmm (default dark, persisted as `wmm-theme`).
8
+ *
9
+ * import { ThemeProvider, ThemeToggle, useTheme } from "@web-my-money/tokens/react";
10
+ *
11
+ * React is an OPTIONAL peer — the core tokens package stays framework-agnostic;
12
+ * React is only pulled in if you import this subpath.
13
+ */
14
+
15
+ interface ThemeCtx {
16
+ theme: ThemeName;
17
+ setTheme: (t: ThemeName) => void;
18
+ themes: readonly ThemeName[];
19
+ }
20
+ declare function ThemeProvider({ children }: {
21
+ children: React.ReactNode;
22
+ }): React.JSX.Element;
23
+ declare function useTheme(): ThemeCtx;
24
+ /** Minimal segmented theme switcher styled from token CSS vars. */
25
+ declare function ThemeToggle({ className }: {
26
+ className?: string;
27
+ }): React.JSX.Element;
28
+ /** Persisted 3-step text-size preference, synced with whatever `fontSizeBootScript` already applied. */
29
+ declare function useFontSizePreference(): [FontSizeName, (size: FontSizeName) => void];
30
+ /**
31
+ * Three "A" buttons that scale the whole UI via `html.font-*` classes. Modeled
32
+ * directly on wmm-finance-hr's real FontSizeToggle. Uses inline `style` with
33
+ * token CSS vars (not Tailwind utility classes) — same reasoning as
34
+ * `ThemeToggle` above: `tokens` ships no rendered-JSX Tailwind classes, so
35
+ * consuming apps never need a `@source` directive for this package.
36
+ */
37
+ declare function FontSizeToggle({ className }: {
38
+ className?: string;
39
+ }): React.JSX.Element;
40
+ declare const BREAKPOINTS: {
41
+ readonly sm: 640;
42
+ readonly md: 768;
43
+ readonly lg: 1024;
44
+ readonly xl: 1280;
45
+ readonly "2xl": 1536;
46
+ };
47
+ type Breakpoint = keyof typeof BREAKPOINTS;
48
+ /**
49
+ * SSR-safe media query hook — `false` on the server and on first client render
50
+ * (avoids hydration mismatch), then updates after mount. Prefer CSS (`md:flex`)
51
+ * for pure styling; reach for this only when a component needs the boolean in
52
+ * JS (e.g. choosing AppShell's drawer vs. static sidebar, swapping a chart's
53
+ * orientation, rendering a Sheet on mobile vs. a Dialog on desktop).
54
+ *
55
+ * const isMobile = !useBreakpoint("md"); // true below 768px
56
+ */
57
+ declare function useMediaQuery(query: string): boolean;
58
+ /** True once the viewport is at or above the named breakpoint. SSR-safe (see useMediaQuery). */
59
+ declare function useBreakpoint(bp: Breakpoint): boolean;
60
+
61
+ export { type Breakpoint, FontSizeToggle, ThemeProvider, ThemeToggle, useBreakpoint, useFontSizePreference, useMediaQuery, useTheme };
package/dist/react.js ADDED
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/react.tsx
32
+ var react_exports = {};
33
+ __export(react_exports, {
34
+ FontSizeToggle: () => FontSizeToggle,
35
+ ThemeProvider: () => ThemeProvider,
36
+ ThemeToggle: () => ThemeToggle,
37
+ useBreakpoint: () => useBreakpoint,
38
+ useFontSizePreference: () => useFontSizePreference,
39
+ useMediaQuery: () => useMediaQuery,
40
+ useTheme: () => useTheme
41
+ });
42
+ module.exports = __toCommonJS(react_exports);
43
+ var React = __toESM(require("react"));
44
+
45
+ // src/theme-runtime.ts
46
+ var THEMES = ["light", "dark", "wmm"];
47
+ var DEFAULT_THEME = "dark";
48
+ var THEME_STORAGE_KEY = "wmm-theme";
49
+ function isThemeName(v) {
50
+ return typeof v === "string" && THEMES.includes(v);
51
+ }
52
+ var themeBootScript = `(function(){try{var t=localStorage.getItem('${THEME_STORAGE_KEY}');if(t==='light'||t==='dark'||t==='wmm'){document.documentElement.setAttribute('data-theme',t);}}catch(e){}})();`;
53
+ function getStoredTheme() {
54
+ if (typeof window === "undefined") return null;
55
+ try {
56
+ const t = window.localStorage.getItem(THEME_STORAGE_KEY);
57
+ return isThemeName(t) ? t : null;
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+ function applyTheme(name) {
63
+ if (typeof document !== "undefined") {
64
+ document.documentElement.setAttribute("data-theme", name);
65
+ }
66
+ try {
67
+ window.localStorage.setItem(THEME_STORAGE_KEY, name);
68
+ } catch {
69
+ }
70
+ }
71
+
72
+ // src/font-size-runtime.ts
73
+ var FONT_SIZES = ["md", "lg", "xl"];
74
+ var DEFAULT_FONT_SIZE = "md";
75
+ var FONT_SIZE_STORAGE_KEY = "wmm-font-size";
76
+ var fontSizeBootScript = `(function(){try{var f=localStorage.getItem('${FONT_SIZE_STORAGE_KEY}');if(f==='md'||f==='lg'||f==='xl'){document.documentElement.classList.add('font-'+f);}}catch(e){}})();`;
77
+ function applyFontSize(name) {
78
+ if (typeof document !== "undefined") {
79
+ const d = document.documentElement;
80
+ for (const s of FONT_SIZES) d.classList.remove(`font-${s}`);
81
+ d.classList.add(`font-${name}`);
82
+ }
83
+ try {
84
+ window.localStorage.setItem(FONT_SIZE_STORAGE_KEY, name);
85
+ } catch {
86
+ }
87
+ }
88
+
89
+ // src/react.tsx
90
+ var import_jsx_runtime = require("react/jsx-runtime");
91
+ var Ctx = React.createContext(null);
92
+ function ThemeProvider({ children }) {
93
+ const [theme, setThemeState] = React.useState(DEFAULT_THEME);
94
+ React.useEffect(() => {
95
+ setThemeState(getStoredTheme() ?? DEFAULT_THEME);
96
+ }, []);
97
+ const setTheme = React.useCallback((t) => {
98
+ applyTheme(t);
99
+ setThemeState(t);
100
+ }, []);
101
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ctx.Provider, { value: { theme, setTheme, themes: THEMES }, children });
102
+ }
103
+ function useTheme() {
104
+ const ctx = React.useContext(Ctx);
105
+ if (!ctx) throw new Error("useTheme must be used within <ThemeProvider>");
106
+ return ctx;
107
+ }
108
+ var LABELS = { light: "Light", dark: "Dark", wmm: "WMM" };
109
+ function ThemeToggle({ className }) {
110
+ const { theme, setTheme, themes } = useTheme();
111
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
+ "div",
113
+ {
114
+ role: "radiogroup",
115
+ "aria-label": "Theme",
116
+ className,
117
+ style: { display: "inline-flex", gap: 4 },
118
+ children: themes.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
119
+ "button",
120
+ {
121
+ role: "radio",
122
+ "aria-checked": theme === t,
123
+ onClick: () => setTheme(t),
124
+ style: {
125
+ borderRadius: 6,
126
+ padding: "4px 10px",
127
+ fontSize: 14,
128
+ cursor: "pointer",
129
+ background: theme === t ? "var(--primary)" : "transparent",
130
+ color: theme === t ? "var(--primary-foreground)" : "var(--muted-foreground)",
131
+ border: "1px solid var(--border)"
132
+ },
133
+ children: LABELS[t] ?? t
134
+ },
135
+ t
136
+ ))
137
+ }
138
+ );
139
+ }
140
+ var fontSizeListeners = /* @__PURE__ */ new Set();
141
+ function getFontSizeSnapshot() {
142
+ if (typeof document === "undefined") return DEFAULT_FONT_SIZE;
143
+ const classList = document.documentElement.classList;
144
+ for (const s of FONT_SIZES) if (classList.contains(`font-${s}`)) return s;
145
+ return DEFAULT_FONT_SIZE;
146
+ }
147
+ function subscribeFontSize(cb) {
148
+ fontSizeListeners.add(cb);
149
+ return () => {
150
+ fontSizeListeners.delete(cb);
151
+ };
152
+ }
153
+ function useFontSizePreference() {
154
+ const size = React.useSyncExternalStore(subscribeFontSize, getFontSizeSnapshot, () => DEFAULT_FONT_SIZE);
155
+ const setSize = React.useCallback((next) => {
156
+ applyFontSize(next);
157
+ fontSizeListeners.forEach((l) => l());
158
+ }, []);
159
+ return [size, setSize];
160
+ }
161
+ var FONT_SIZE_TITLES = {
162
+ md: "Normal text (14px)",
163
+ lg: "Comfortable text (16px)",
164
+ xl: "Large text (18px)"
165
+ };
166
+ var FONT_SIZE_LABEL_PX = { md: 11, lg: 13, xl: 15 };
167
+ function FontSizeToggle({ className }) {
168
+ const [size, setSize] = useFontSizePreference();
169
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
170
+ "div",
171
+ {
172
+ role: "group",
173
+ "aria-label": "Text size",
174
+ className,
175
+ style: { display: "inline-flex", gap: 2 },
176
+ children: FONT_SIZES.map((s) => {
177
+ const active = size === s;
178
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
+ "button",
180
+ {
181
+ type: "button",
182
+ onClick: () => setSize(s),
183
+ title: FONT_SIZE_TITLES[s],
184
+ "aria-label": FONT_SIZE_TITLES[s],
185
+ "aria-pressed": active,
186
+ style: {
187
+ display: "inline-flex",
188
+ alignItems: "center",
189
+ justifyContent: "center",
190
+ borderRadius: 6,
191
+ padding: "4px 8px",
192
+ fontSize: FONT_SIZE_LABEL_PX[s],
193
+ fontWeight: 700,
194
+ fontFamily: "ui-monospace, monospace",
195
+ cursor: "pointer",
196
+ background: active ? "var(--primary-dim, color-mix(in srgb, var(--primary) 10%, transparent))" : "transparent",
197
+ color: active ? "var(--primary)" : "var(--muted-foreground, var(--muted))",
198
+ border: `1px solid ${active ? "var(--primary)" : "transparent"}`
199
+ },
200
+ children: "A"
201
+ },
202
+ s
203
+ );
204
+ })
205
+ }
206
+ );
207
+ }
208
+ var BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280, "2xl": 1536 };
209
+ function useMediaQuery(query) {
210
+ const [matches, setMatches] = React.useState(false);
211
+ React.useEffect(() => {
212
+ const mql = window.matchMedia(query);
213
+ setMatches(mql.matches);
214
+ const onChange = () => setMatches(mql.matches);
215
+ mql.addEventListener("change", onChange);
216
+ return () => mql.removeEventListener("change", onChange);
217
+ }, [query]);
218
+ return matches;
219
+ }
220
+ function useBreakpoint(bp) {
221
+ return useMediaQuery(`(min-width: ${BREAKPOINTS[bp]}px)`);
222
+ }
223
+ // Annotate the CommonJS export names for ESM import in node:
224
+ 0 && (module.exports = {
225
+ FontSizeToggle,
226
+ ThemeProvider,
227
+ ThemeToggle,
228
+ useBreakpoint,
229
+ useFontSizePreference,
230
+ useMediaQuery,
231
+ useTheme
232
+ });
package/dist/react.mjs ADDED
@@ -0,0 +1,155 @@
1
+ "use client";
2
+ import {
3
+ DEFAULT_FONT_SIZE,
4
+ DEFAULT_THEME,
5
+ FONT_SIZES,
6
+ THEMES,
7
+ applyFontSize,
8
+ applyTheme,
9
+ getStoredTheme
10
+ } from "./chunk-2IXFKPNU.mjs";
11
+
12
+ // src/react.tsx
13
+ import * as React from "react";
14
+ import { jsx } from "react/jsx-runtime";
15
+ var Ctx = React.createContext(null);
16
+ function ThemeProvider({ children }) {
17
+ const [theme, setThemeState] = React.useState(DEFAULT_THEME);
18
+ React.useEffect(() => {
19
+ setThemeState(getStoredTheme() ?? DEFAULT_THEME);
20
+ }, []);
21
+ const setTheme = React.useCallback((t) => {
22
+ applyTheme(t);
23
+ setThemeState(t);
24
+ }, []);
25
+ return /* @__PURE__ */ jsx(Ctx.Provider, { value: { theme, setTheme, themes: THEMES }, children });
26
+ }
27
+ function useTheme() {
28
+ const ctx = React.useContext(Ctx);
29
+ if (!ctx) throw new Error("useTheme must be used within <ThemeProvider>");
30
+ return ctx;
31
+ }
32
+ var LABELS = { light: "Light", dark: "Dark", wmm: "WMM" };
33
+ function ThemeToggle({ className }) {
34
+ const { theme, setTheme, themes } = useTheme();
35
+ return /* @__PURE__ */ jsx(
36
+ "div",
37
+ {
38
+ role: "radiogroup",
39
+ "aria-label": "Theme",
40
+ className,
41
+ style: { display: "inline-flex", gap: 4 },
42
+ children: themes.map((t) => /* @__PURE__ */ jsx(
43
+ "button",
44
+ {
45
+ role: "radio",
46
+ "aria-checked": theme === t,
47
+ onClick: () => setTheme(t),
48
+ style: {
49
+ borderRadius: 6,
50
+ padding: "4px 10px",
51
+ fontSize: 14,
52
+ cursor: "pointer",
53
+ background: theme === t ? "var(--primary)" : "transparent",
54
+ color: theme === t ? "var(--primary-foreground)" : "var(--muted-foreground)",
55
+ border: "1px solid var(--border)"
56
+ },
57
+ children: LABELS[t] ?? t
58
+ },
59
+ t
60
+ ))
61
+ }
62
+ );
63
+ }
64
+ var fontSizeListeners = /* @__PURE__ */ new Set();
65
+ function getFontSizeSnapshot() {
66
+ if (typeof document === "undefined") return DEFAULT_FONT_SIZE;
67
+ const classList = document.documentElement.classList;
68
+ for (const s of FONT_SIZES) if (classList.contains(`font-${s}`)) return s;
69
+ return DEFAULT_FONT_SIZE;
70
+ }
71
+ function subscribeFontSize(cb) {
72
+ fontSizeListeners.add(cb);
73
+ return () => {
74
+ fontSizeListeners.delete(cb);
75
+ };
76
+ }
77
+ function useFontSizePreference() {
78
+ const size = React.useSyncExternalStore(subscribeFontSize, getFontSizeSnapshot, () => DEFAULT_FONT_SIZE);
79
+ const setSize = React.useCallback((next) => {
80
+ applyFontSize(next);
81
+ fontSizeListeners.forEach((l) => l());
82
+ }, []);
83
+ return [size, setSize];
84
+ }
85
+ var FONT_SIZE_TITLES = {
86
+ md: "Normal text (14px)",
87
+ lg: "Comfortable text (16px)",
88
+ xl: "Large text (18px)"
89
+ };
90
+ var FONT_SIZE_LABEL_PX = { md: 11, lg: 13, xl: 15 };
91
+ function FontSizeToggle({ className }) {
92
+ const [size, setSize] = useFontSizePreference();
93
+ return /* @__PURE__ */ jsx(
94
+ "div",
95
+ {
96
+ role: "group",
97
+ "aria-label": "Text size",
98
+ className,
99
+ style: { display: "inline-flex", gap: 2 },
100
+ children: FONT_SIZES.map((s) => {
101
+ const active = size === s;
102
+ return /* @__PURE__ */ jsx(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ onClick: () => setSize(s),
107
+ title: FONT_SIZE_TITLES[s],
108
+ "aria-label": FONT_SIZE_TITLES[s],
109
+ "aria-pressed": active,
110
+ style: {
111
+ display: "inline-flex",
112
+ alignItems: "center",
113
+ justifyContent: "center",
114
+ borderRadius: 6,
115
+ padding: "4px 8px",
116
+ fontSize: FONT_SIZE_LABEL_PX[s],
117
+ fontWeight: 700,
118
+ fontFamily: "ui-monospace, monospace",
119
+ cursor: "pointer",
120
+ background: active ? "var(--primary-dim, color-mix(in srgb, var(--primary) 10%, transparent))" : "transparent",
121
+ color: active ? "var(--primary)" : "var(--muted-foreground, var(--muted))",
122
+ border: `1px solid ${active ? "var(--primary)" : "transparent"}`
123
+ },
124
+ children: "A"
125
+ },
126
+ s
127
+ );
128
+ })
129
+ }
130
+ );
131
+ }
132
+ var BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280, "2xl": 1536 };
133
+ function useMediaQuery(query) {
134
+ const [matches, setMatches] = React.useState(false);
135
+ React.useEffect(() => {
136
+ const mql = window.matchMedia(query);
137
+ setMatches(mql.matches);
138
+ const onChange = () => setMatches(mql.matches);
139
+ mql.addEventListener("change", onChange);
140
+ return () => mql.removeEventListener("change", onChange);
141
+ }, [query]);
142
+ return matches;
143
+ }
144
+ function useBreakpoint(bp) {
145
+ return useMediaQuery(`(min-width: ${BREAKPOINTS[bp]}px)`);
146
+ }
147
+ export {
148
+ FontSizeToggle,
149
+ ThemeProvider,
150
+ ThemeToggle,
151
+ useBreakpoint,
152
+ useFontSizePreference,
153
+ useMediaQuery,
154
+ useTheme
155
+ };
@@ -0,0 +1,14 @@
1
+ import { Config } from 'tailwindcss';
2
+
3
+ /**
4
+ * Shared Tailwind preset — import in any app's tailwind.config.ts:
5
+ *
6
+ * import { wmmPreset } from "@web-my-money/tokens/tailwind-preset";
7
+ * export default { presets: [wmmPreset], ... };
8
+ *
9
+ * Includes all design tokens: colors, typography, spacing, shadows, animations.
10
+ */
11
+
12
+ declare const wmmPreset: Partial<Config>;
13
+
14
+ export { wmmPreset };
@@ -0,0 +1,14 @@
1
+ import { Config } from 'tailwindcss';
2
+
3
+ /**
4
+ * Shared Tailwind preset — import in any app's tailwind.config.ts:
5
+ *
6
+ * import { wmmPreset } from "@web-my-money/tokens/tailwind-preset";
7
+ * export default { presets: [wmmPreset], ... };
8
+ *
9
+ * Includes all design tokens: colors, typography, spacing, shadows, animations.
10
+ */
11
+
12
+ declare const wmmPreset: Partial<Config>;
13
+
14
+ export { wmmPreset };
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/tailwind-preset.ts
21
+ var tailwind_preset_exports = {};
22
+ __export(tailwind_preset_exports, {
23
+ wmmPreset: () => wmmPreset
24
+ });
25
+ module.exports = __toCommonJS(tailwind_preset_exports);
26
+
27
+ // src/typography.ts
28
+ var fontFamily = {
29
+ /** Body text — Inter or system sans */
30
+ sans: [
31
+ "var(--font-inter)",
32
+ "ui-sans-serif",
33
+ "system-ui",
34
+ "-apple-system",
35
+ "BlinkMacSystemFont",
36
+ "Segoe UI",
37
+ "Roboto",
38
+ "Helvetica Neue",
39
+ "Arial",
40
+ "sans-serif"
41
+ ],
42
+ /** Display / hero headings — Satoshi */
43
+ display: [
44
+ "Satoshi",
45
+ "ui-sans-serif",
46
+ "system-ui",
47
+ "-apple-system",
48
+ "sans-serif"
49
+ ],
50
+ /** Labels, badges, section headers — Space Grotesk */
51
+ label: [
52
+ "var(--font-space-grotesk)",
53
+ "ui-sans-serif",
54
+ "system-ui",
55
+ "sans-serif"
56
+ ],
57
+ /** Code blocks */
58
+ mono: [
59
+ "var(--font-geist-mono)",
60
+ "ui-monospace",
61
+ "SFMono-Regular",
62
+ "Menlo",
63
+ "Monaco",
64
+ "Consolas",
65
+ "monospace"
66
+ ]
67
+ };
68
+
69
+ // src/shadows.ts
70
+ var boxShadow = {
71
+ /** Subtle teal glow for CTAs */
72
+ glow: "0 0 30px rgba(0, 196, 180, 0.15)",
73
+ /** Strong teal glow on hover */
74
+ glowStrong: "0 0 40px rgba(0, 196, 180, 0.4)",
75
+ /** Deep panel shadow with inset highlight (glassmorphism) */
76
+ panel: "0 24px 80px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255,255,255,0.08)",
77
+ /** Glass panel shadow */
78
+ glass: "0 28px 90px rgba(0, 0, 0, 0.38), 0 0 36px rgba(0, 196, 180, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.06)"
79
+ };
80
+
81
+ // src/animations.ts
82
+ var keyframes = {
83
+ marquee: {
84
+ "0%": { transform: "translate3d(0, 0, 0)" },
85
+ "100%": { transform: "translate3d(-50%, 0, 0)" }
86
+ },
87
+ "marquee-reverse": {
88
+ "0%": { transform: "translate3d(-50%, 0, 0)" },
89
+ "100%": { transform: "translate3d(0, 0, 0)" }
90
+ },
91
+ shimmer: {
92
+ "0%": { transform: "translate3d(-150%, 0, 0)" },
93
+ "100%": { transform: "translate3d(150%, 0, 0)" }
94
+ },
95
+ float: {
96
+ "0%, 100%": { transform: "translate3d(0, 0, 0)" },
97
+ "50%": { transform: "translate3d(0, -12px, 0)" }
98
+ },
99
+ pulseGlow: {
100
+ "0%, 100%": { boxShadow: "0 0 0 rgba(0, 196, 180, 0.0)" },
101
+ "50%": { boxShadow: "0 0 36px rgba(0, 196, 180, 0.18)" }
102
+ }
103
+ };
104
+ var animation = {
105
+ marquee: "marquee 28s linear infinite",
106
+ "marquee-slow": "marquee 42s linear infinite",
107
+ "marquee-reverse": "marquee-reverse 32s linear infinite",
108
+ shimmer: "shimmer 4.2s linear infinite",
109
+ float: "float 8s ease-in-out infinite",
110
+ "pulse-glow": "pulseGlow 5s ease-in-out infinite"
111
+ };
112
+
113
+ // src/gradients.ts
114
+ var backgroundImage = {
115
+ /** CTA gradient: navy → aqua (production brand) */
116
+ "cta-gradient": "linear-gradient(135deg, #1f2d56, #8fccb6)",
117
+ /** Grid pattern overlay for hero backgrounds */
118
+ "hero-grid": "linear-gradient(to right, rgba(255,255,255,0.04) 1px, transparent 1px), linear-gradient(to bottom, rgba(255,255,255,0.04) 1px, transparent 1px)"
119
+ };
120
+
121
+ // src/spacing.ts
122
+ var container = {
123
+ center: true,
124
+ padding: {
125
+ DEFAULT: "1.25rem",
126
+ sm: "1.5rem",
127
+ lg: "2rem",
128
+ xl: "2.5rem",
129
+ "2xl": "3rem"
130
+ },
131
+ screens: {
132
+ "2xl": "1320px"
133
+ }
134
+ };
135
+
136
+ // src/tailwind-preset.ts
137
+ var wmmPreset = {
138
+ darkMode: ["class"],
139
+ theme: {
140
+ container,
141
+ extend: {
142
+ colors: {
143
+ background: "var(--background)",
144
+ foreground: "var(--foreground)",
145
+ card: {
146
+ DEFAULT: "var(--card)",
147
+ foreground: "var(--card-foreground)"
148
+ },
149
+ popover: {
150
+ DEFAULT: "var(--popover)",
151
+ foreground: "var(--popover-foreground)"
152
+ },
153
+ primary: {
154
+ DEFAULT: "var(--primary)",
155
+ foreground: "var(--primary-foreground)"
156
+ },
157
+ secondary: {
158
+ DEFAULT: "var(--secondary)",
159
+ foreground: "var(--secondary-foreground)"
160
+ },
161
+ muted: {
162
+ DEFAULT: "var(--muted)",
163
+ foreground: "var(--muted-foreground)"
164
+ },
165
+ accent: {
166
+ DEFAULT: "var(--accent)",
167
+ foreground: "var(--accent-foreground)"
168
+ },
169
+ destructive: "var(--destructive)",
170
+ border: "var(--border)",
171
+ input: "var(--input)",
172
+ ring: "var(--ring)",
173
+ // Brand accents (from theme CSS — available when WMM theme is loaded)
174
+ teal: "var(--teal, #8fccb6)",
175
+ violet: "var(--violet, #869ce2)",
176
+ // Sidebar
177
+ sidebar: {
178
+ DEFAULT: "var(--sidebar)",
179
+ foreground: "var(--sidebar-foreground)",
180
+ primary: "var(--sidebar-primary)",
181
+ "primary-foreground": "var(--sidebar-primary-foreground)",
182
+ accent: "var(--sidebar-accent)",
183
+ "accent-foreground": "var(--sidebar-accent-foreground)",
184
+ border: "var(--sidebar-border)",
185
+ ring: "var(--sidebar-ring)"
186
+ },
187
+ // Charts
188
+ chart: {
189
+ 1: "var(--chart-1)",
190
+ 2: "var(--chart-2)",
191
+ 3: "var(--chart-3)",
192
+ 4: "var(--chart-4)",
193
+ 5: "var(--chart-5)"
194
+ }
195
+ },
196
+ fontFamily: {
197
+ // spread the `as const` token tuples → mutable string[] (Tailwind's Config type)
198
+ sans: [...fontFamily.sans],
199
+ display: [...fontFamily.display],
200
+ label: [...fontFamily.label],
201
+ mono: [...fontFamily.mono]
202
+ },
203
+ backgroundImage,
204
+ boxShadow,
205
+ keyframes,
206
+ animation,
207
+ borderRadius: {
208
+ sm: "calc(var(--radius) * 0.6)",
209
+ md: "calc(var(--radius) * 0.8)",
210
+ lg: "var(--radius)",
211
+ xl: "calc(var(--radius) * 1.4)",
212
+ "2xl": "calc(var(--radius) * 1.8)",
213
+ "3xl": "calc(var(--radius) * 2.2)",
214
+ "4xl": "calc(var(--radius) * 2.6)"
215
+ },
216
+ backdropBlur: {
217
+ xs: "4px"
218
+ }
219
+ }
220
+ }
221
+ };
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ wmmPreset
225
+ });