@surf-kit/theme 0.1.1

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,12 @@
1
+ Copyright (c) 2026 surf-kit contributors
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted.
5
+
6
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
8
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
9
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
11
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
12
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @surf-kit/theme
2
+
3
+ > Theme provider and Tailwind preset for surf-kit — light, dark, and brand color modes
4
+
5
+ Part of the [surf-kit](https://github.com/barney-w/surf-kit) design system.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @surf-kit/theme @surf-kit/tokens
11
+ ```
12
+
13
+ ## Quick Example
14
+
15
+ ```tsx
16
+ import { ThemeProvider, useColorMode } from '@surf-kit/theme';
17
+ import '@surf-kit/tokens/css';
18
+ import '@surf-kit/tokens/css/dark';
19
+
20
+ function App() {
21
+ return (
22
+ <ThemeProvider defaultColorMode="system">
23
+ <MyApp />
24
+ </ThemeProvider>
25
+ );
26
+ }
27
+
28
+ function MyApp() {
29
+ const { colorMode, setColorMode } = useColorMode();
30
+ return <button onClick={() => setColorMode('dark')}>Current: {colorMode}</button>;
31
+ }
32
+ ```
33
+
34
+ ## What's Included
35
+
36
+ - **ThemeProvider** — wraps your app, manages color mode state
37
+ - **useTheme** — access the current theme object
38
+ - **useColorMode** — read and set the active color mode (`light` | `dark` | `brand`)
39
+ - **createTheme** — build a custom theme configuration
40
+ - **surfKitPreset** — Tailwind CSS v4 preset with all surf-kit design tokens
41
+
42
+ ## Color Modes
43
+
44
+ | Mode | Description |
45
+ |------|-------------|
46
+ | `light` | Default light theme |
47
+ | `dark` | Dark theme |
48
+ | `brand` | Teal and gold brand theme |
49
+ | `system` | Auto-detects `light` or `dark` from OS preference |
50
+
51
+ ## Docs
52
+
53
+ - [Storybook](https://barney-w.github.io/surf-kit/storybook)
54
+ - [Contributing](https://github.com/barney-w/surf-kit/blob/main/CONTRIBUTING.md)
55
+
56
+ ## License
57
+
58
+ [0BSD](./LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,281 @@
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/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ThemeProvider: () => ThemeProvider,
24
+ createTheme: () => createTheme,
25
+ surfKitPreset: () => surfKitPreset,
26
+ useColorMode: () => useColorMode,
27
+ useTheme: () => useTheme
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/ThemeProvider.tsx
32
+ var import_react = require("react");
33
+ var import_jsx_runtime = require("react/jsx-runtime");
34
+ var DEFAULT_THEME = {
35
+ name: "default",
36
+ cssVars: {}
37
+ };
38
+ var ThemeContext = (0, import_react.createContext)(null);
39
+ function getSystemPreference() {
40
+ if (typeof window === "undefined") return "light";
41
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
42
+ }
43
+ function ThemeProvider({
44
+ colorMode: colorModeProp = "system",
45
+ theme = DEFAULT_THEME,
46
+ children
47
+ }) {
48
+ const [preference, setPreference] = (0, import_react.useState)(colorModeProp);
49
+ const [systemPref, setSystemPref] = (0, import_react.useState)(getSystemPreference);
50
+ const wrapperRef = (0, import_react.useRef)(null);
51
+ (0, import_react.useEffect)(() => {
52
+ setPreference(colorModeProp);
53
+ }, [colorModeProp]);
54
+ (0, import_react.useEffect)(() => {
55
+ if (typeof window === "undefined") return;
56
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
57
+ const handler = (e) => {
58
+ setSystemPref(e.matches ? "dark" : "light");
59
+ };
60
+ mql.addEventListener("change", handler);
61
+ return () => mql.removeEventListener("change", handler);
62
+ }, []);
63
+ const resolvedMode = preference === "system" ? systemPref : preference;
64
+ (0, import_react.useEffect)(() => {
65
+ const el = wrapperRef.current;
66
+ if (!el) return;
67
+ el.setAttribute("data-color-mode", resolvedMode);
68
+ el.setAttribute("data-theme", theme.name);
69
+ for (const [key, value] of Object.entries(theme.cssVars)) {
70
+ const varName = key.startsWith("--") ? key : `--surf-${key}`;
71
+ el.style.setProperty(varName, value);
72
+ }
73
+ }, [resolvedMode, theme]);
74
+ const setColorMode = (0, import_react.useCallback)((mode) => {
75
+ setPreference(mode);
76
+ }, []);
77
+ const contextValue = (0, import_react.useMemo)(
78
+ () => ({
79
+ theme,
80
+ colorMode: resolvedMode,
81
+ colorModePreference: preference,
82
+ setColorMode
83
+ }),
84
+ [theme, resolvedMode, preference, setColorMode]
85
+ );
86
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: wrapperRef, "data-color-mode": resolvedMode, "data-theme": theme.name, children }) });
87
+ }
88
+
89
+ // src/useTheme.ts
90
+ var import_react2 = require("react");
91
+ function useTheme() {
92
+ const context = (0, import_react2.useContext)(ThemeContext);
93
+ if (context === null) {
94
+ throw new Error(
95
+ "useTheme() must be used within a <ThemeProvider>. Wrap your component tree with <ThemeProvider> from @surf-kit/theme."
96
+ );
97
+ }
98
+ return context;
99
+ }
100
+
101
+ // src/useColorMode.ts
102
+ var import_react3 = require("react");
103
+ function getSystemPreference2() {
104
+ if (typeof window === "undefined") return "light";
105
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
106
+ }
107
+ function useColorMode() {
108
+ const { colorMode, setColorMode } = useTheme();
109
+ const [systemPreference, setSystemPreference] = (0, import_react3.useState)(
110
+ getSystemPreference2
111
+ );
112
+ (0, import_react3.useEffect)(() => {
113
+ if (typeof window === "undefined") return;
114
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
115
+ const handler = (e) => {
116
+ setSystemPreference(e.matches ? "dark" : "light");
117
+ };
118
+ mql.addEventListener("change", handler);
119
+ return () => mql.removeEventListener("change", handler);
120
+ }, []);
121
+ const toggleColorMode = (0, import_react3.useCallback)(() => {
122
+ setColorMode(colorMode === "light" ? "dark" : "light");
123
+ }, [colorMode, setColorMode]);
124
+ return {
125
+ colorMode,
126
+ setColorMode,
127
+ toggleColorMode,
128
+ systemPreference
129
+ };
130
+ }
131
+
132
+ // src/createTheme.ts
133
+ function createTheme(config) {
134
+ const cssVars = {};
135
+ if (config.overrides) {
136
+ for (const [key, value] of Object.entries(config.overrides)) {
137
+ const varName = key.startsWith("--") ? key : `--surf-${key}`;
138
+ cssVars[varName] = value;
139
+ }
140
+ }
141
+ return {
142
+ name: config.name,
143
+ cssVars
144
+ };
145
+ }
146
+
147
+ // src/tailwind-preset.ts
148
+ var surfKitPreset = {
149
+ theme: {
150
+ extend: {
151
+ colors: {
152
+ surface: "var(--surf-color-bg-surface)",
153
+ "surface-raised": "var(--surf-color-bg-surface-raised)",
154
+ "surface-sunken": "var(--surf-color-bg-surface-sunken)",
155
+ canvas: "var(--surf-color-bg-canvas)",
156
+ "text-primary": "var(--surf-color-text-primary)",
157
+ "text-secondary": "var(--surf-color-text-secondary)",
158
+ "text-muted": "var(--surf-color-text-muted)",
159
+ accent: {
160
+ DEFAULT: "var(--surf-color-accent-primary)",
161
+ hover: "var(--surf-color-accent-primary-hover)",
162
+ active: "var(--surf-color-accent-primary-active)",
163
+ subtle: "var(--surf-color-accent-primary-subtle)",
164
+ subtlest: "var(--surf-color-accent-primary-subtlest)"
165
+ },
166
+ border: {
167
+ DEFAULT: "var(--surf-color-border-default)",
168
+ strong: "var(--surf-color-border-strong)",
169
+ interactive: "var(--surf-color-border-interactive)"
170
+ },
171
+ status: {
172
+ success: "var(--surf-color-status-success)",
173
+ "success-subtle": "var(--surf-color-status-success-subtle)",
174
+ warning: "var(--surf-color-status-warning)",
175
+ "warning-subtle": "var(--surf-color-status-warning-subtle)",
176
+ error: "var(--surf-color-status-error)",
177
+ "error-subtle": "var(--surf-color-status-error-subtle)",
178
+ info: "var(--surf-color-status-info)"
179
+ },
180
+ confidence: {
181
+ high: "var(--surf-confidence-high-text)",
182
+ "high-bg": "var(--surf-confidence-high-bg)",
183
+ medium: "var(--surf-confidence-medium-text)",
184
+ "medium-bg": "var(--surf-confidence-medium-bg)",
185
+ low: "var(--surf-confidence-low-text)",
186
+ "low-bg": "var(--surf-confidence-low-bg)"
187
+ },
188
+ verification: {
189
+ passed: "var(--surf-verification-passed-icon)",
190
+ flagged: "var(--surf-verification-flagged-icon)",
191
+ failed: "var(--surf-verification-failed-icon)"
192
+ },
193
+ agent: {
194
+ coordinator: "var(--surf-agent-coordinator-accent)",
195
+ hr: "var(--surf-agent-hr-accent)",
196
+ it: "var(--surf-agent-it-accent)",
197
+ governance: "var(--surf-agent-governance-accent)",
198
+ finance: "var(--surf-agent-finance-accent)",
199
+ facilities: "var(--surf-agent-facilities-accent)"
200
+ },
201
+ brand: {
202
+ dark: "#041F26",
203
+ "dark-panel": "#0A3642",
204
+ blue: "#0091A5",
205
+ cyan: "#38BDD0",
206
+ gold: "#E1B989",
207
+ "gold-light": "#F3D79C",
208
+ cream: "#F1F0E3",
209
+ "cream-warm": "#F0E8B6",
210
+ charcoal: "#414142",
211
+ watermelon: "#E81152"
212
+ }
213
+ },
214
+ spacing: {
215
+ "surf-1": "var(--surf-spacing-1)",
216
+ "surf-2": "var(--surf-spacing-2)",
217
+ "surf-3": "var(--surf-spacing-3)",
218
+ "surf-4": "var(--surf-spacing-4)",
219
+ "surf-6": "var(--surf-spacing-6)",
220
+ "surf-8": "var(--surf-spacing-8)"
221
+ },
222
+ borderRadius: {
223
+ "surf-sm": "var(--surf-radius-sm)",
224
+ "surf-md": "var(--surf-radius-md)",
225
+ "surf-lg": "var(--surf-radius-lg)",
226
+ "surf-xl": "var(--surf-radius-xl)",
227
+ "surf-full": "var(--surf-radius-full)"
228
+ },
229
+ fontFamily: {
230
+ "surf-sans": "var(--surf-font-family-sans)",
231
+ "surf-mono": "var(--surf-font-family-mono)",
232
+ "surf-display": "var(--surf-font-family-display)"
233
+ },
234
+ boxShadow: {
235
+ "surf-sm": "var(--surf-shadow-sm)",
236
+ "surf-md": "var(--surf-shadow-md)",
237
+ "surf-lg": "var(--surf-shadow-lg)",
238
+ "glow": "0 0 20px rgba(225,185,137,0.4)",
239
+ "glow-strong": "0 0 30px rgba(225,185,137,0.6), 0 0 60px rgba(225,185,137,0.3)",
240
+ "glow-cyan": "0 0 15px rgba(56,189,208,0.5)",
241
+ "glow-watermelon": "0 0 15px rgba(232,17,82,0.5)",
242
+ "card": "0 4px 24px rgba(4,31,38,0.8)"
243
+ },
244
+ backdropBlur: {
245
+ "glass": "12px"
246
+ },
247
+ keyframes: {
248
+ blink: {
249
+ "0%, 50%": { opacity: "1" },
250
+ "51%, 100%": { opacity: "0" }
251
+ },
252
+ fadeSlideIn: {
253
+ from: { opacity: "0", transform: "translateY(12px)" },
254
+ to: { opacity: "1", transform: "translateY(0)" }
255
+ },
256
+ pulseGlow: {
257
+ "0%, 100%": { boxShadow: "0 0 20px rgba(225,185,137,0.2)" },
258
+ "50%": { boxShadow: "0 0 40px rgba(225,185,137,0.4)" }
259
+ },
260
+ "brand-spin": {
261
+ to: { transform: "rotate(360deg)" }
262
+ }
263
+ },
264
+ animation: {
265
+ blink: "blink 1s step-end infinite",
266
+ fadeSlideIn: "fadeSlideIn 0.4s ease-out both",
267
+ pulseGlow: "pulseGlow 2s ease-in-out infinite",
268
+ "brand-spin": "brand-spin 1.2s linear infinite"
269
+ }
270
+ }
271
+ }
272
+ };
273
+ // Annotate the CommonJS export names for ESM import in node:
274
+ 0 && (module.exports = {
275
+ ThemeProvider,
276
+ createTheme,
277
+ surfKitPreset,
278
+ useColorMode,
279
+ useTheme
280
+ });
281
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/ThemeProvider.tsx","../src/useTheme.ts","../src/useColorMode.ts","../src/createTheme.ts","../src/tailwind-preset.ts"],"sourcesContent":["export { ThemeProvider } from './ThemeProvider'\nexport { useTheme } from './useTheme'\nexport { useColorMode } from './useColorMode'\nexport { createTheme } from './createTheme'\nexport { surfKitPreset } from './tailwind-preset'\nexport type { Theme, ThemeConfig, ColorMode } from './types'\n","import React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport type {\n ColorMode,\n ColorModePreference,\n Theme,\n ThemeContextValue,\n} from './types'\n\nconst DEFAULT_THEME: Theme = {\n name: 'default',\n cssVars: {},\n}\n\nexport const ThemeContext = createContext<ThemeContextValue | null>(null)\n\nfunction getSystemPreference(): ColorMode {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\nexport interface ThemeProviderProps {\n /** Color mode preference. Defaults to 'system'. */\n colorMode?: ColorModePreference\n /** Theme object (from createTheme). Defaults to the built-in default theme. */\n theme?: Theme\n children: React.ReactNode\n}\n\nexport function ThemeProvider({\n colorMode: colorModeProp = 'system',\n theme = DEFAULT_THEME,\n children,\n}: ThemeProviderProps) {\n const [preference, setPreference] =\n useState<ColorModePreference>(colorModeProp)\n const [systemPref, setSystemPref] = useState<ColorMode>(getSystemPreference)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Sync prop changes into state\n useEffect(() => {\n setPreference(colorModeProp)\n }, [colorModeProp])\n\n // Listen for OS color-scheme changes\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mql = window.matchMedia('(prefers-color-scheme: dark)')\n const handler = (e: MediaQueryListEvent) => {\n setSystemPref(e.matches ? 'dark' : 'light')\n }\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n }, [])\n\n const resolvedMode: ColorMode =\n preference === 'system' ? systemPref : (preference as ColorMode)\n\n // Apply data attributes and CSS variable overrides to wrapper div\n useEffect(() => {\n const el = wrapperRef.current\n if (!el) return\n\n el.setAttribute('data-color-mode', resolvedMode)\n el.setAttribute('data-theme', theme.name)\n\n // Apply any CSS variable overrides from the theme\n for (const [key, value] of Object.entries(theme.cssVars)) {\n const varName = key.startsWith('--') ? key : `--surf-${key}`\n el.style.setProperty(varName, value)\n }\n }, [resolvedMode, theme])\n\n const setColorMode = useCallback((mode: ColorModePreference) => {\n setPreference(mode)\n }, [])\n\n const contextValue = useMemo<ThemeContextValue>(\n () => ({\n theme,\n colorMode: resolvedMode,\n colorModePreference: preference,\n setColorMode,\n }),\n [theme, resolvedMode, preference, setColorMode],\n )\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <div ref={wrapperRef} data-color-mode={resolvedMode as string} data-theme={theme.name}>\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { useContext } from 'react'\nimport { ThemeContext } from './ThemeProvider'\nimport type { ThemeContextValue } from './types'\n\n/**\n * Returns the current theme and color mode from ThemeProvider.\n *\n * Must be called within a <ThemeProvider>.\n */\nexport function useTheme(): ThemeContextValue {\n const context = useContext(ThemeContext)\n if (context === null) {\n throw new Error(\n 'useTheme() must be used within a <ThemeProvider>. ' +\n 'Wrap your component tree with <ThemeProvider> from @surf-kit/theme.',\n )\n }\n return context\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport { useTheme } from './useTheme'\nimport type { ColorMode, ColorModePreference } from './types'\n\nfunction getSystemPreference(): ColorMode {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\nexport interface UseColorModeReturn {\n /** Resolved color mode ('light' | 'dark') */\n colorMode: ColorMode\n /** Update the color mode preference */\n setColorMode: (mode: ColorModePreference) => void\n /** Toggle between light and dark (ignores 'system') */\n toggleColorMode: () => void\n /** The OS-level color scheme preference */\n systemPreference: ColorMode\n}\n\n/**\n * Provides color mode controls. Must be called within a <ThemeProvider>.\n */\nexport function useColorMode(): UseColorModeReturn {\n const { colorMode, setColorMode } = useTheme()\n const [systemPreference, setSystemPreference] = useState<ColorMode>(\n getSystemPreference,\n )\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mql = window.matchMedia('(prefers-color-scheme: dark)')\n const handler = (e: MediaQueryListEvent) => {\n setSystemPreference(e.matches ? 'dark' : 'light')\n }\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n }, [])\n\n const toggleColorMode = useCallback(() => {\n setColorMode(colorMode === 'light' ? 'dark' : 'light')\n }, [colorMode, setColorMode])\n\n return {\n colorMode,\n setColorMode,\n toggleColorMode,\n systemPreference,\n }\n}\n","import type { Theme, ThemeConfig } from './types'\n\n/**\n * Creates a Theme object from configuration.\n *\n * The returned Theme can be passed to <ThemeProvider theme={myTheme}>.\n * Override CSS custom properties by providing an `overrides` map keyed\n * by token name (without the `--surf-` prefix).\n */\nexport function createTheme(config: ThemeConfig): Theme {\n const cssVars: Record<string, string> = {}\n\n if (config.overrides) {\n for (const [key, value] of Object.entries(config.overrides)) {\n // Store with the full custom-property name\n const varName = key.startsWith('--') ? key : `--surf-${key}`\n cssVars[varName] = value\n }\n }\n\n return {\n name: config.name,\n cssVars,\n }\n}\n","import type { Config } from 'tailwindcss'\n\nexport const surfKitPreset: Partial<Config> = {\n theme: {\n extend: {\n colors: {\n surface: 'var(--surf-color-bg-surface)',\n 'surface-raised': 'var(--surf-color-bg-surface-raised)',\n 'surface-sunken': 'var(--surf-color-bg-surface-sunken)',\n canvas: 'var(--surf-color-bg-canvas)',\n 'text-primary': 'var(--surf-color-text-primary)',\n 'text-secondary': 'var(--surf-color-text-secondary)',\n 'text-muted': 'var(--surf-color-text-muted)',\n accent: {\n DEFAULT: 'var(--surf-color-accent-primary)',\n hover: 'var(--surf-color-accent-primary-hover)',\n active: 'var(--surf-color-accent-primary-active)',\n subtle: 'var(--surf-color-accent-primary-subtle)',\n subtlest: 'var(--surf-color-accent-primary-subtlest)',\n },\n border: {\n DEFAULT: 'var(--surf-color-border-default)',\n strong: 'var(--surf-color-border-strong)',\n interactive: 'var(--surf-color-border-interactive)',\n },\n status: {\n success: 'var(--surf-color-status-success)',\n 'success-subtle': 'var(--surf-color-status-success-subtle)',\n warning: 'var(--surf-color-status-warning)',\n 'warning-subtle': 'var(--surf-color-status-warning-subtle)',\n error: 'var(--surf-color-status-error)',\n 'error-subtle': 'var(--surf-color-status-error-subtle)',\n info: 'var(--surf-color-status-info)',\n },\n confidence: {\n high: 'var(--surf-confidence-high-text)',\n 'high-bg': 'var(--surf-confidence-high-bg)',\n medium: 'var(--surf-confidence-medium-text)',\n 'medium-bg': 'var(--surf-confidence-medium-bg)',\n low: 'var(--surf-confidence-low-text)',\n 'low-bg': 'var(--surf-confidence-low-bg)',\n },\n verification: {\n passed: 'var(--surf-verification-passed-icon)',\n flagged: 'var(--surf-verification-flagged-icon)',\n failed: 'var(--surf-verification-failed-icon)',\n },\n agent: {\n coordinator: 'var(--surf-agent-coordinator-accent)',\n hr: 'var(--surf-agent-hr-accent)',\n it: 'var(--surf-agent-it-accent)',\n governance: 'var(--surf-agent-governance-accent)',\n finance: 'var(--surf-agent-finance-accent)',\n facilities: 'var(--surf-agent-facilities-accent)',\n },\n brand: {\n dark: '#041F26',\n 'dark-panel': '#0A3642',\n blue: '#0091A5',\n cyan: '#38BDD0',\n gold: '#E1B989',\n 'gold-light': '#F3D79C',\n cream: '#F1F0E3',\n 'cream-warm': '#F0E8B6',\n charcoal: '#414142',\n watermelon: '#E81152',\n },\n },\n spacing: {\n 'surf-1': 'var(--surf-spacing-1)',\n 'surf-2': 'var(--surf-spacing-2)',\n 'surf-3': 'var(--surf-spacing-3)',\n 'surf-4': 'var(--surf-spacing-4)',\n 'surf-6': 'var(--surf-spacing-6)',\n 'surf-8': 'var(--surf-spacing-8)',\n },\n borderRadius: {\n 'surf-sm': 'var(--surf-radius-sm)',\n 'surf-md': 'var(--surf-radius-md)',\n 'surf-lg': 'var(--surf-radius-lg)',\n 'surf-xl': 'var(--surf-radius-xl)',\n 'surf-full': 'var(--surf-radius-full)',\n },\n fontFamily: {\n 'surf-sans': 'var(--surf-font-family-sans)',\n 'surf-mono': 'var(--surf-font-family-mono)',\n 'surf-display': 'var(--surf-font-family-display)',\n },\n boxShadow: {\n 'surf-sm': 'var(--surf-shadow-sm)',\n 'surf-md': 'var(--surf-shadow-md)',\n 'surf-lg': 'var(--surf-shadow-lg)',\n 'glow': '0 0 20px rgba(225,185,137,0.4)',\n 'glow-strong': '0 0 30px rgba(225,185,137,0.6), 0 0 60px rgba(225,185,137,0.3)',\n 'glow-cyan': '0 0 15px rgba(56,189,208,0.5)',\n 'glow-watermelon': '0 0 15px rgba(232,17,82,0.5)',\n 'card': '0 4px 24px rgba(4,31,38,0.8)',\n },\n backdropBlur: {\n 'glass': '12px',\n },\n keyframes: {\n blink: {\n '0%, 50%': { opacity: '1' },\n '51%, 100%': { opacity: '0' },\n },\n fadeSlideIn: {\n from: { opacity: '0', transform: 'translateY(12px)' },\n to: { opacity: '1', transform: 'translateY(0)' },\n },\n pulseGlow: {\n '0%, 100%': { boxShadow: '0 0 20px rgba(225,185,137,0.2)' },\n '50%': { boxShadow: '0 0 40px rgba(225,185,137,0.4)' },\n },\n 'brand-spin': {\n to: { transform: 'rotate(360deg)' },\n },\n },\n animation: {\n blink: 'blink 1s step-end infinite',\n fadeSlideIn: 'fadeSlideIn 0.4s ease-out both',\n pulseGlow: 'pulseGlow 2s ease-in-out infinite',\n 'brand-spin': 'brand-spin 1.2s linear infinite',\n },\n },\n },\n}\n"],"mappings":"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","names":["import_react","import_react","getSystemPreference"]}
@@ -0,0 +1,77 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { Config } from 'tailwindcss';
4
+
5
+ /** Resolved color mode applied to the DOM */
6
+ type ColorMode = 'light' | 'dark' | 'brand';
7
+ /** User-facing color mode preference (includes 'system') */
8
+ type ColorModePreference = ColorMode | 'system';
9
+ /** Theme configuration input for createTheme */
10
+ interface ThemeConfig {
11
+ /** Unique theme name */
12
+ name: string;
13
+ /** Optional CSS variable overrides keyed by variable name (without --surf- prefix) */
14
+ overrides?: Record<string, string>;
15
+ }
16
+ /** Resolved theme object */
17
+ interface Theme {
18
+ /** Unique theme name */
19
+ name: string;
20
+ /** CSS variable overrides to apply */
21
+ cssVars: Record<string, string>;
22
+ }
23
+ /** Shape of the ThemeContext value */
24
+ interface ThemeContextValue {
25
+ /** The active theme */
26
+ theme: Theme;
27
+ /** The resolved color mode ('light' | 'dark') */
28
+ colorMode: ColorMode;
29
+ /** The user's color mode preference ('light' | 'dark' | 'system') */
30
+ colorModePreference: ColorModePreference;
31
+ /** Update the color mode preference */
32
+ setColorMode: (mode: ColorModePreference) => void;
33
+ }
34
+
35
+ interface ThemeProviderProps {
36
+ /** Color mode preference. Defaults to 'system'. */
37
+ colorMode?: ColorModePreference;
38
+ /** Theme object (from createTheme). Defaults to the built-in default theme. */
39
+ theme?: Theme;
40
+ children: React.ReactNode;
41
+ }
42
+ declare function ThemeProvider({ colorMode: colorModeProp, theme, children, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
43
+
44
+ /**
45
+ * Returns the current theme and color mode from ThemeProvider.
46
+ *
47
+ * Must be called within a <ThemeProvider>.
48
+ */
49
+ declare function useTheme(): ThemeContextValue;
50
+
51
+ interface UseColorModeReturn {
52
+ /** Resolved color mode ('light' | 'dark') */
53
+ colorMode: ColorMode;
54
+ /** Update the color mode preference */
55
+ setColorMode: (mode: ColorModePreference) => void;
56
+ /** Toggle between light and dark (ignores 'system') */
57
+ toggleColorMode: () => void;
58
+ /** The OS-level color scheme preference */
59
+ systemPreference: ColorMode;
60
+ }
61
+ /**
62
+ * Provides color mode controls. Must be called within a <ThemeProvider>.
63
+ */
64
+ declare function useColorMode(): UseColorModeReturn;
65
+
66
+ /**
67
+ * Creates a Theme object from configuration.
68
+ *
69
+ * The returned Theme can be passed to <ThemeProvider theme={myTheme}>.
70
+ * Override CSS custom properties by providing an `overrides` map keyed
71
+ * by token name (without the `--surf-` prefix).
72
+ */
73
+ declare function createTheme(config: ThemeConfig): Theme;
74
+
75
+ declare const surfKitPreset: Partial<Config>;
76
+
77
+ export { type ColorMode, type Theme, type ThemeConfig, ThemeProvider, createTheme, surfKitPreset, useColorMode, useTheme };
@@ -0,0 +1,77 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { Config } from 'tailwindcss';
4
+
5
+ /** Resolved color mode applied to the DOM */
6
+ type ColorMode = 'light' | 'dark' | 'brand';
7
+ /** User-facing color mode preference (includes 'system') */
8
+ type ColorModePreference = ColorMode | 'system';
9
+ /** Theme configuration input for createTheme */
10
+ interface ThemeConfig {
11
+ /** Unique theme name */
12
+ name: string;
13
+ /** Optional CSS variable overrides keyed by variable name (without --surf- prefix) */
14
+ overrides?: Record<string, string>;
15
+ }
16
+ /** Resolved theme object */
17
+ interface Theme {
18
+ /** Unique theme name */
19
+ name: string;
20
+ /** CSS variable overrides to apply */
21
+ cssVars: Record<string, string>;
22
+ }
23
+ /** Shape of the ThemeContext value */
24
+ interface ThemeContextValue {
25
+ /** The active theme */
26
+ theme: Theme;
27
+ /** The resolved color mode ('light' | 'dark') */
28
+ colorMode: ColorMode;
29
+ /** The user's color mode preference ('light' | 'dark' | 'system') */
30
+ colorModePreference: ColorModePreference;
31
+ /** Update the color mode preference */
32
+ setColorMode: (mode: ColorModePreference) => void;
33
+ }
34
+
35
+ interface ThemeProviderProps {
36
+ /** Color mode preference. Defaults to 'system'. */
37
+ colorMode?: ColorModePreference;
38
+ /** Theme object (from createTheme). Defaults to the built-in default theme. */
39
+ theme?: Theme;
40
+ children: React.ReactNode;
41
+ }
42
+ declare function ThemeProvider({ colorMode: colorModeProp, theme, children, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
43
+
44
+ /**
45
+ * Returns the current theme and color mode from ThemeProvider.
46
+ *
47
+ * Must be called within a <ThemeProvider>.
48
+ */
49
+ declare function useTheme(): ThemeContextValue;
50
+
51
+ interface UseColorModeReturn {
52
+ /** Resolved color mode ('light' | 'dark') */
53
+ colorMode: ColorMode;
54
+ /** Update the color mode preference */
55
+ setColorMode: (mode: ColorModePreference) => void;
56
+ /** Toggle between light and dark (ignores 'system') */
57
+ toggleColorMode: () => void;
58
+ /** The OS-level color scheme preference */
59
+ systemPreference: ColorMode;
60
+ }
61
+ /**
62
+ * Provides color mode controls. Must be called within a <ThemeProvider>.
63
+ */
64
+ declare function useColorMode(): UseColorModeReturn;
65
+
66
+ /**
67
+ * Creates a Theme object from configuration.
68
+ *
69
+ * The returned Theme can be passed to <ThemeProvider theme={myTheme}>.
70
+ * Override CSS custom properties by providing an `overrides` map keyed
71
+ * by token name (without the `--surf-` prefix).
72
+ */
73
+ declare function createTheme(config: ThemeConfig): Theme;
74
+
75
+ declare const surfKitPreset: Partial<Config>;
76
+
77
+ export { type ColorMode, type Theme, type ThemeConfig, ThemeProvider, createTheme, surfKitPreset, useColorMode, useTheme };
package/dist/index.js ADDED
@@ -0,0 +1,257 @@
1
+ // src/ThemeProvider.tsx
2
+ import {
3
+ createContext,
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState
9
+ } from "react";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var DEFAULT_THEME = {
12
+ name: "default",
13
+ cssVars: {}
14
+ };
15
+ var ThemeContext = createContext(null);
16
+ function getSystemPreference() {
17
+ if (typeof window === "undefined") return "light";
18
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
19
+ }
20
+ function ThemeProvider({
21
+ colorMode: colorModeProp = "system",
22
+ theme = DEFAULT_THEME,
23
+ children
24
+ }) {
25
+ const [preference, setPreference] = useState(colorModeProp);
26
+ const [systemPref, setSystemPref] = useState(getSystemPreference);
27
+ const wrapperRef = useRef(null);
28
+ useEffect(() => {
29
+ setPreference(colorModeProp);
30
+ }, [colorModeProp]);
31
+ useEffect(() => {
32
+ if (typeof window === "undefined") return;
33
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
34
+ const handler = (e) => {
35
+ setSystemPref(e.matches ? "dark" : "light");
36
+ };
37
+ mql.addEventListener("change", handler);
38
+ return () => mql.removeEventListener("change", handler);
39
+ }, []);
40
+ const resolvedMode = preference === "system" ? systemPref : preference;
41
+ useEffect(() => {
42
+ const el = wrapperRef.current;
43
+ if (!el) return;
44
+ el.setAttribute("data-color-mode", resolvedMode);
45
+ el.setAttribute("data-theme", theme.name);
46
+ for (const [key, value] of Object.entries(theme.cssVars)) {
47
+ const varName = key.startsWith("--") ? key : `--surf-${key}`;
48
+ el.style.setProperty(varName, value);
49
+ }
50
+ }, [resolvedMode, theme]);
51
+ const setColorMode = useCallback((mode) => {
52
+ setPreference(mode);
53
+ }, []);
54
+ const contextValue = useMemo(
55
+ () => ({
56
+ theme,
57
+ colorMode: resolvedMode,
58
+ colorModePreference: preference,
59
+ setColorMode
60
+ }),
61
+ [theme, resolvedMode, preference, setColorMode]
62
+ );
63
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { ref: wrapperRef, "data-color-mode": resolvedMode, "data-theme": theme.name, children }) });
64
+ }
65
+
66
+ // src/useTheme.ts
67
+ import { useContext } from "react";
68
+ function useTheme() {
69
+ const context = useContext(ThemeContext);
70
+ if (context === null) {
71
+ throw new Error(
72
+ "useTheme() must be used within a <ThemeProvider>. Wrap your component tree with <ThemeProvider> from @surf-kit/theme."
73
+ );
74
+ }
75
+ return context;
76
+ }
77
+
78
+ // src/useColorMode.ts
79
+ import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
80
+ function getSystemPreference2() {
81
+ if (typeof window === "undefined") return "light";
82
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
83
+ }
84
+ function useColorMode() {
85
+ const { colorMode, setColorMode } = useTheme();
86
+ const [systemPreference, setSystemPreference] = useState2(
87
+ getSystemPreference2
88
+ );
89
+ useEffect2(() => {
90
+ if (typeof window === "undefined") return;
91
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
92
+ const handler = (e) => {
93
+ setSystemPreference(e.matches ? "dark" : "light");
94
+ };
95
+ mql.addEventListener("change", handler);
96
+ return () => mql.removeEventListener("change", handler);
97
+ }, []);
98
+ const toggleColorMode = useCallback2(() => {
99
+ setColorMode(colorMode === "light" ? "dark" : "light");
100
+ }, [colorMode, setColorMode]);
101
+ return {
102
+ colorMode,
103
+ setColorMode,
104
+ toggleColorMode,
105
+ systemPreference
106
+ };
107
+ }
108
+
109
+ // src/createTheme.ts
110
+ function createTheme(config) {
111
+ const cssVars = {};
112
+ if (config.overrides) {
113
+ for (const [key, value] of Object.entries(config.overrides)) {
114
+ const varName = key.startsWith("--") ? key : `--surf-${key}`;
115
+ cssVars[varName] = value;
116
+ }
117
+ }
118
+ return {
119
+ name: config.name,
120
+ cssVars
121
+ };
122
+ }
123
+
124
+ // src/tailwind-preset.ts
125
+ var surfKitPreset = {
126
+ theme: {
127
+ extend: {
128
+ colors: {
129
+ surface: "var(--surf-color-bg-surface)",
130
+ "surface-raised": "var(--surf-color-bg-surface-raised)",
131
+ "surface-sunken": "var(--surf-color-bg-surface-sunken)",
132
+ canvas: "var(--surf-color-bg-canvas)",
133
+ "text-primary": "var(--surf-color-text-primary)",
134
+ "text-secondary": "var(--surf-color-text-secondary)",
135
+ "text-muted": "var(--surf-color-text-muted)",
136
+ accent: {
137
+ DEFAULT: "var(--surf-color-accent-primary)",
138
+ hover: "var(--surf-color-accent-primary-hover)",
139
+ active: "var(--surf-color-accent-primary-active)",
140
+ subtle: "var(--surf-color-accent-primary-subtle)",
141
+ subtlest: "var(--surf-color-accent-primary-subtlest)"
142
+ },
143
+ border: {
144
+ DEFAULT: "var(--surf-color-border-default)",
145
+ strong: "var(--surf-color-border-strong)",
146
+ interactive: "var(--surf-color-border-interactive)"
147
+ },
148
+ status: {
149
+ success: "var(--surf-color-status-success)",
150
+ "success-subtle": "var(--surf-color-status-success-subtle)",
151
+ warning: "var(--surf-color-status-warning)",
152
+ "warning-subtle": "var(--surf-color-status-warning-subtle)",
153
+ error: "var(--surf-color-status-error)",
154
+ "error-subtle": "var(--surf-color-status-error-subtle)",
155
+ info: "var(--surf-color-status-info)"
156
+ },
157
+ confidence: {
158
+ high: "var(--surf-confidence-high-text)",
159
+ "high-bg": "var(--surf-confidence-high-bg)",
160
+ medium: "var(--surf-confidence-medium-text)",
161
+ "medium-bg": "var(--surf-confidence-medium-bg)",
162
+ low: "var(--surf-confidence-low-text)",
163
+ "low-bg": "var(--surf-confidence-low-bg)"
164
+ },
165
+ verification: {
166
+ passed: "var(--surf-verification-passed-icon)",
167
+ flagged: "var(--surf-verification-flagged-icon)",
168
+ failed: "var(--surf-verification-failed-icon)"
169
+ },
170
+ agent: {
171
+ coordinator: "var(--surf-agent-coordinator-accent)",
172
+ hr: "var(--surf-agent-hr-accent)",
173
+ it: "var(--surf-agent-it-accent)",
174
+ governance: "var(--surf-agent-governance-accent)",
175
+ finance: "var(--surf-agent-finance-accent)",
176
+ facilities: "var(--surf-agent-facilities-accent)"
177
+ },
178
+ brand: {
179
+ dark: "#041F26",
180
+ "dark-panel": "#0A3642",
181
+ blue: "#0091A5",
182
+ cyan: "#38BDD0",
183
+ gold: "#E1B989",
184
+ "gold-light": "#F3D79C",
185
+ cream: "#F1F0E3",
186
+ "cream-warm": "#F0E8B6",
187
+ charcoal: "#414142",
188
+ watermelon: "#E81152"
189
+ }
190
+ },
191
+ spacing: {
192
+ "surf-1": "var(--surf-spacing-1)",
193
+ "surf-2": "var(--surf-spacing-2)",
194
+ "surf-3": "var(--surf-spacing-3)",
195
+ "surf-4": "var(--surf-spacing-4)",
196
+ "surf-6": "var(--surf-spacing-6)",
197
+ "surf-8": "var(--surf-spacing-8)"
198
+ },
199
+ borderRadius: {
200
+ "surf-sm": "var(--surf-radius-sm)",
201
+ "surf-md": "var(--surf-radius-md)",
202
+ "surf-lg": "var(--surf-radius-lg)",
203
+ "surf-xl": "var(--surf-radius-xl)",
204
+ "surf-full": "var(--surf-radius-full)"
205
+ },
206
+ fontFamily: {
207
+ "surf-sans": "var(--surf-font-family-sans)",
208
+ "surf-mono": "var(--surf-font-family-mono)",
209
+ "surf-display": "var(--surf-font-family-display)"
210
+ },
211
+ boxShadow: {
212
+ "surf-sm": "var(--surf-shadow-sm)",
213
+ "surf-md": "var(--surf-shadow-md)",
214
+ "surf-lg": "var(--surf-shadow-lg)",
215
+ "glow": "0 0 20px rgba(225,185,137,0.4)",
216
+ "glow-strong": "0 0 30px rgba(225,185,137,0.6), 0 0 60px rgba(225,185,137,0.3)",
217
+ "glow-cyan": "0 0 15px rgba(56,189,208,0.5)",
218
+ "glow-watermelon": "0 0 15px rgba(232,17,82,0.5)",
219
+ "card": "0 4px 24px rgba(4,31,38,0.8)"
220
+ },
221
+ backdropBlur: {
222
+ "glass": "12px"
223
+ },
224
+ keyframes: {
225
+ blink: {
226
+ "0%, 50%": { opacity: "1" },
227
+ "51%, 100%": { opacity: "0" }
228
+ },
229
+ fadeSlideIn: {
230
+ from: { opacity: "0", transform: "translateY(12px)" },
231
+ to: { opacity: "1", transform: "translateY(0)" }
232
+ },
233
+ pulseGlow: {
234
+ "0%, 100%": { boxShadow: "0 0 20px rgba(225,185,137,0.2)" },
235
+ "50%": { boxShadow: "0 0 40px rgba(225,185,137,0.4)" }
236
+ },
237
+ "brand-spin": {
238
+ to: { transform: "rotate(360deg)" }
239
+ }
240
+ },
241
+ animation: {
242
+ blink: "blink 1s step-end infinite",
243
+ fadeSlideIn: "fadeSlideIn 0.4s ease-out both",
244
+ pulseGlow: "pulseGlow 2s ease-in-out infinite",
245
+ "brand-spin": "brand-spin 1.2s linear infinite"
246
+ }
247
+ }
248
+ }
249
+ };
250
+ export {
251
+ ThemeProvider,
252
+ createTheme,
253
+ surfKitPreset,
254
+ useColorMode,
255
+ useTheme
256
+ };
257
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ThemeProvider.tsx","../src/useTheme.ts","../src/useColorMode.ts","../src/createTheme.ts","../src/tailwind-preset.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport type {\n ColorMode,\n ColorModePreference,\n Theme,\n ThemeContextValue,\n} from './types'\n\nconst DEFAULT_THEME: Theme = {\n name: 'default',\n cssVars: {},\n}\n\nexport const ThemeContext = createContext<ThemeContextValue | null>(null)\n\nfunction getSystemPreference(): ColorMode {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\nexport interface ThemeProviderProps {\n /** Color mode preference. Defaults to 'system'. */\n colorMode?: ColorModePreference\n /** Theme object (from createTheme). Defaults to the built-in default theme. */\n theme?: Theme\n children: React.ReactNode\n}\n\nexport function ThemeProvider({\n colorMode: colorModeProp = 'system',\n theme = DEFAULT_THEME,\n children,\n}: ThemeProviderProps) {\n const [preference, setPreference] =\n useState<ColorModePreference>(colorModeProp)\n const [systemPref, setSystemPref] = useState<ColorMode>(getSystemPreference)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Sync prop changes into state\n useEffect(() => {\n setPreference(colorModeProp)\n }, [colorModeProp])\n\n // Listen for OS color-scheme changes\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mql = window.matchMedia('(prefers-color-scheme: dark)')\n const handler = (e: MediaQueryListEvent) => {\n setSystemPref(e.matches ? 'dark' : 'light')\n }\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n }, [])\n\n const resolvedMode: ColorMode =\n preference === 'system' ? systemPref : (preference as ColorMode)\n\n // Apply data attributes and CSS variable overrides to wrapper div\n useEffect(() => {\n const el = wrapperRef.current\n if (!el) return\n\n el.setAttribute('data-color-mode', resolvedMode)\n el.setAttribute('data-theme', theme.name)\n\n // Apply any CSS variable overrides from the theme\n for (const [key, value] of Object.entries(theme.cssVars)) {\n const varName = key.startsWith('--') ? key : `--surf-${key}`\n el.style.setProperty(varName, value)\n }\n }, [resolvedMode, theme])\n\n const setColorMode = useCallback((mode: ColorModePreference) => {\n setPreference(mode)\n }, [])\n\n const contextValue = useMemo<ThemeContextValue>(\n () => ({\n theme,\n colorMode: resolvedMode,\n colorModePreference: preference,\n setColorMode,\n }),\n [theme, resolvedMode, preference, setColorMode],\n )\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <div ref={wrapperRef} data-color-mode={resolvedMode as string} data-theme={theme.name}>\n {children}\n </div>\n </ThemeContext.Provider>\n )\n}\n","import { useContext } from 'react'\nimport { ThemeContext } from './ThemeProvider'\nimport type { ThemeContextValue } from './types'\n\n/**\n * Returns the current theme and color mode from ThemeProvider.\n *\n * Must be called within a <ThemeProvider>.\n */\nexport function useTheme(): ThemeContextValue {\n const context = useContext(ThemeContext)\n if (context === null) {\n throw new Error(\n 'useTheme() must be used within a <ThemeProvider>. ' +\n 'Wrap your component tree with <ThemeProvider> from @surf-kit/theme.',\n )\n }\n return context\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport { useTheme } from './useTheme'\nimport type { ColorMode, ColorModePreference } from './types'\n\nfunction getSystemPreference(): ColorMode {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\nexport interface UseColorModeReturn {\n /** Resolved color mode ('light' | 'dark') */\n colorMode: ColorMode\n /** Update the color mode preference */\n setColorMode: (mode: ColorModePreference) => void\n /** Toggle between light and dark (ignores 'system') */\n toggleColorMode: () => void\n /** The OS-level color scheme preference */\n systemPreference: ColorMode\n}\n\n/**\n * Provides color mode controls. Must be called within a <ThemeProvider>.\n */\nexport function useColorMode(): UseColorModeReturn {\n const { colorMode, setColorMode } = useTheme()\n const [systemPreference, setSystemPreference] = useState<ColorMode>(\n getSystemPreference,\n )\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mql = window.matchMedia('(prefers-color-scheme: dark)')\n const handler = (e: MediaQueryListEvent) => {\n setSystemPreference(e.matches ? 'dark' : 'light')\n }\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n }, [])\n\n const toggleColorMode = useCallback(() => {\n setColorMode(colorMode === 'light' ? 'dark' : 'light')\n }, [colorMode, setColorMode])\n\n return {\n colorMode,\n setColorMode,\n toggleColorMode,\n systemPreference,\n }\n}\n","import type { Theme, ThemeConfig } from './types'\n\n/**\n * Creates a Theme object from configuration.\n *\n * The returned Theme can be passed to <ThemeProvider theme={myTheme}>.\n * Override CSS custom properties by providing an `overrides` map keyed\n * by token name (without the `--surf-` prefix).\n */\nexport function createTheme(config: ThemeConfig): Theme {\n const cssVars: Record<string, string> = {}\n\n if (config.overrides) {\n for (const [key, value] of Object.entries(config.overrides)) {\n // Store with the full custom-property name\n const varName = key.startsWith('--') ? key : `--surf-${key}`\n cssVars[varName] = value\n }\n }\n\n return {\n name: config.name,\n cssVars,\n }\n}\n","import type { Config } from 'tailwindcss'\n\nexport const surfKitPreset: Partial<Config> = {\n theme: {\n extend: {\n colors: {\n surface: 'var(--surf-color-bg-surface)',\n 'surface-raised': 'var(--surf-color-bg-surface-raised)',\n 'surface-sunken': 'var(--surf-color-bg-surface-sunken)',\n canvas: 'var(--surf-color-bg-canvas)',\n 'text-primary': 'var(--surf-color-text-primary)',\n 'text-secondary': 'var(--surf-color-text-secondary)',\n 'text-muted': 'var(--surf-color-text-muted)',\n accent: {\n DEFAULT: 'var(--surf-color-accent-primary)',\n hover: 'var(--surf-color-accent-primary-hover)',\n active: 'var(--surf-color-accent-primary-active)',\n subtle: 'var(--surf-color-accent-primary-subtle)',\n subtlest: 'var(--surf-color-accent-primary-subtlest)',\n },\n border: {\n DEFAULT: 'var(--surf-color-border-default)',\n strong: 'var(--surf-color-border-strong)',\n interactive: 'var(--surf-color-border-interactive)',\n },\n status: {\n success: 'var(--surf-color-status-success)',\n 'success-subtle': 'var(--surf-color-status-success-subtle)',\n warning: 'var(--surf-color-status-warning)',\n 'warning-subtle': 'var(--surf-color-status-warning-subtle)',\n error: 'var(--surf-color-status-error)',\n 'error-subtle': 'var(--surf-color-status-error-subtle)',\n info: 'var(--surf-color-status-info)',\n },\n confidence: {\n high: 'var(--surf-confidence-high-text)',\n 'high-bg': 'var(--surf-confidence-high-bg)',\n medium: 'var(--surf-confidence-medium-text)',\n 'medium-bg': 'var(--surf-confidence-medium-bg)',\n low: 'var(--surf-confidence-low-text)',\n 'low-bg': 'var(--surf-confidence-low-bg)',\n },\n verification: {\n passed: 'var(--surf-verification-passed-icon)',\n flagged: 'var(--surf-verification-flagged-icon)',\n failed: 'var(--surf-verification-failed-icon)',\n },\n agent: {\n coordinator: 'var(--surf-agent-coordinator-accent)',\n hr: 'var(--surf-agent-hr-accent)',\n it: 'var(--surf-agent-it-accent)',\n governance: 'var(--surf-agent-governance-accent)',\n finance: 'var(--surf-agent-finance-accent)',\n facilities: 'var(--surf-agent-facilities-accent)',\n },\n brand: {\n dark: '#041F26',\n 'dark-panel': '#0A3642',\n blue: '#0091A5',\n cyan: '#38BDD0',\n gold: '#E1B989',\n 'gold-light': '#F3D79C',\n cream: '#F1F0E3',\n 'cream-warm': '#F0E8B6',\n charcoal: '#414142',\n watermelon: '#E81152',\n },\n },\n spacing: {\n 'surf-1': 'var(--surf-spacing-1)',\n 'surf-2': 'var(--surf-spacing-2)',\n 'surf-3': 'var(--surf-spacing-3)',\n 'surf-4': 'var(--surf-spacing-4)',\n 'surf-6': 'var(--surf-spacing-6)',\n 'surf-8': 'var(--surf-spacing-8)',\n },\n borderRadius: {\n 'surf-sm': 'var(--surf-radius-sm)',\n 'surf-md': 'var(--surf-radius-md)',\n 'surf-lg': 'var(--surf-radius-lg)',\n 'surf-xl': 'var(--surf-radius-xl)',\n 'surf-full': 'var(--surf-radius-full)',\n },\n fontFamily: {\n 'surf-sans': 'var(--surf-font-family-sans)',\n 'surf-mono': 'var(--surf-font-family-mono)',\n 'surf-display': 'var(--surf-font-family-display)',\n },\n boxShadow: {\n 'surf-sm': 'var(--surf-shadow-sm)',\n 'surf-md': 'var(--surf-shadow-md)',\n 'surf-lg': 'var(--surf-shadow-lg)',\n 'glow': '0 0 20px rgba(225,185,137,0.4)',\n 'glow-strong': '0 0 30px rgba(225,185,137,0.6), 0 0 60px rgba(225,185,137,0.3)',\n 'glow-cyan': '0 0 15px rgba(56,189,208,0.5)',\n 'glow-watermelon': '0 0 15px rgba(232,17,82,0.5)',\n 'card': '0 4px 24px rgba(4,31,38,0.8)',\n },\n backdropBlur: {\n 'glass': '12px',\n },\n keyframes: {\n blink: {\n '0%, 50%': { opacity: '1' },\n '51%, 100%': { opacity: '0' },\n },\n fadeSlideIn: {\n from: { opacity: '0', transform: 'translateY(12px)' },\n to: { opacity: '1', transform: 'translateY(0)' },\n },\n pulseGlow: {\n '0%, 100%': { boxShadow: '0 0 20px rgba(225,185,137,0.2)' },\n '50%': { boxShadow: '0 0 40px rgba(225,185,137,0.4)' },\n },\n 'brand-spin': {\n to: { transform: 'rotate(360deg)' },\n },\n },\n animation: {\n blink: 'blink 1s step-end infinite',\n fadeSlideIn: 'fadeSlideIn 0.4s ease-out both',\n pulseGlow: 'pulseGlow 2s ease-in-out infinite',\n 'brand-spin': 'brand-spin 1.2s linear infinite',\n },\n },\n },\n}\n"],"mappings":"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","names":["useCallback","useEffect","useState","getSystemPreference","useState","useEffect","useCallback"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@surf-kit/theme",
3
+ "version": "0.1.1",
4
+ "description": "Theme provider and Tailwind preset for surf-kit — light, dark, and brand color modes",
5
+ "keywords": [
6
+ "react",
7
+ "theme",
8
+ "tailwind",
9
+ "color-mode",
10
+ "dark-mode",
11
+ "design-system"
12
+ ],
13
+ "license": "0BSD",
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/barney-w/surf-kit.git",
22
+ "directory": "packages/theme"
23
+ },
24
+ "homepage": "https://github.com/barney-w/surf-kit#readme",
25
+ "bugs": {
26
+ "url": "https://github.com/barney-w/surf-kit/issues"
27
+ },
28
+ "type": "module",
29
+ "main": "dist/index.js",
30
+ "types": "dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js",
35
+ "require": "./dist/index.cjs"
36
+ }
37
+ },
38
+ "dependencies": {
39
+ "@surf-kit/tokens": "0.1.1"
40
+ },
41
+ "devDependencies": {
42
+ "react": "^18.3.0",
43
+ "@types/react": "^18.3.0",
44
+ "tsup": "^8.0.0",
45
+ "typescript": "^5.5.0",
46
+ "@surf-kit/tsconfig": "0.1.0"
47
+ },
48
+ "peerDependencies": {
49
+ "react": ">=18",
50
+ "tailwindcss": ">=4"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "tailwindcss": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsup",
62
+ "dev": "tsup --watch",
63
+ "typecheck": "tsc --noEmit"
64
+ }
65
+ }