@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 +12 -0
- package/README.md +58 -0
- package/dist/index.cjs +281 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +257 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
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"]}
|
package/dist/index.d.cts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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
|
+
}
|