@phcdevworks/spectre-ui 0.0.3 → 0.0.5
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/README.md +10 -1
- package/dist/base.css +5 -5
- package/dist/components.css +98 -3
- package/dist/index.cjs +24 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +8 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -110
- package/dist/index.js.map +1 -1
- package/dist/utilities.css +2 -2
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -24,7 +24,16 @@ npm install @phcdevworks/spectre-ui
|
|
|
24
24
|
|
|
25
25
|
### 1. Import Spectre CSS
|
|
26
26
|
|
|
27
|
-
Import the
|
|
27
|
+
Import the canonical bundle anywhere in your app, layout, or build pipeline.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// Recommended: one-line Spectre UI bundle (tokens + base + components + utilities)
|
|
31
|
+
import "@phcdevworks/spectre-ui/index.css";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`index.css` automatically loads the Spectre Tokens CSS, so you don't need to import `@phcdevworks/spectre-tokens` separately in most apps.
|
|
35
|
+
|
|
36
|
+
**Advanced layer control:** If you prefer to manage the layers individually, you can still import each file directly.
|
|
28
37
|
|
|
29
38
|
```css
|
|
30
39
|
@import "@phcdevworks/spectre-ui/base.css";
|
package/dist/base.css
CHANGED
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
font-family: var(--sp-font-family-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
|
|
25
25
|
font-size: var(--sp-font-md-size, 1rem);
|
|
26
26
|
line-height: var(--sp-font-md-line-height, 1.5);
|
|
27
|
-
color: var(--sp-text-on-page-default
|
|
28
|
-
background-color: var(--sp-surface-page
|
|
27
|
+
color: var(--sp-text-on-page-default);
|
|
28
|
+
background-color: var(--sp-surface-page);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
img,
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
a {
|
|
55
|
-
color: var(--sp-
|
|
55
|
+
color: var(--sp-color-primary, inherit);
|
|
56
56
|
text-decoration: none;
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -61,12 +61,12 @@
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
:focus-visible {
|
|
64
|
-
outline: 2px solid var(--sp-
|
|
64
|
+
outline: 2px solid var(--sp-color-primary, currentColor);
|
|
65
65
|
outline-offset: 2px;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
::selection {
|
|
69
|
-
background-color: var(--sp-
|
|
69
|
+
background-color: var(--sp-color-primary-soft, rgba(79, 70, 229, 0.15));
|
|
70
70
|
color: inherit;
|
|
71
71
|
}
|
|
72
72
|
}
|
package/dist/components.css
CHANGED
|
@@ -87,6 +87,8 @@
|
|
|
87
87
|
font-size: var(--sp-font-md-size, 1rem);
|
|
88
88
|
line-height: 1;
|
|
89
89
|
font-weight: var(--sp-font-md-weight, 500);
|
|
90
|
+
text-decoration: none;
|
|
91
|
+
appearance: none;
|
|
90
92
|
transition:
|
|
91
93
|
background-color var(--sp-duration-fast, 150ms) var(--sp-easing-out, ease),
|
|
92
94
|
color var(--sp-duration-fast, 150ms) var(--sp-easing-out, ease),
|
|
@@ -97,8 +99,25 @@
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
.sp-btn:disabled,
|
|
100
|
-
.sp-btn[aria-disabled="true"]
|
|
102
|
+
.sp-btn[aria-disabled="true"],
|
|
103
|
+
.sp-btn.sp-btn--disabled {
|
|
101
104
|
cursor: not-allowed;
|
|
105
|
+
opacity: var(--sp-opacity-disabled, 0.5);
|
|
106
|
+
pointer-events: none;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.sp-btn--loading {
|
|
110
|
+
pointer-events: none;
|
|
111
|
+
opacity: var(--sp-opacity-loading, 0.7);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.sp-btn--full {
|
|
115
|
+
width: 100%;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.sp-btn--icon {
|
|
119
|
+
padding-inline: var(--sp-space-sm, 0.75rem);
|
|
120
|
+
padding-block: var(--sp-space-3xs, 0.125rem);
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
/* sizes */
|
|
@@ -239,13 +258,39 @@
|
|
|
239
258
|
|
|
240
259
|
/* INPUTS --------------------------------------------------------------- */
|
|
241
260
|
|
|
261
|
+
.sp-input-wrapper {
|
|
262
|
+
display: grid;
|
|
263
|
+
gap: var(--sp-space-4xs, 0.125rem);
|
|
264
|
+
width: 100%;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.sp-label {
|
|
268
|
+
color: var(--sp-component-input-text, var(--sp-text-on-surface-default, var(--sp-form-default-text)));
|
|
269
|
+
font-size: var(--sp-font-sm-size, 0.875rem);
|
|
270
|
+
font-weight: var(--sp-font-sm-weight, 500);
|
|
271
|
+
line-height: var(--sp-font-sm-line-height, 1.25rem);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.sp-helper-text {
|
|
275
|
+
color: var(--sp-text-on-surface-muted);
|
|
276
|
+
font-size: var(--sp-font-xs-size, 0.75rem);
|
|
277
|
+
line-height: var(--sp-font-xs-line-height, 1rem);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.sp-error-message {
|
|
281
|
+
color: var(--sp-color-danger, #dc2626);
|
|
282
|
+
font-size: var(--sp-font-xs-size, 0.75rem);
|
|
283
|
+
line-height: var(--sp-font-xs-line-height, 1rem);
|
|
284
|
+
}
|
|
285
|
+
|
|
242
286
|
.sp-input {
|
|
243
287
|
width: 100%;
|
|
244
288
|
display: block;
|
|
289
|
+
appearance: none;
|
|
245
290
|
padding: var(--sp-space-2xs, 0.25rem) var(--sp-space-md, 1rem);
|
|
246
291
|
border-radius: var(--sp-radius-md, 4px);
|
|
247
292
|
border: 1px solid var(--sp-component-input-border, var(--sp-form-default-border));
|
|
248
|
-
background: var(--sp-component-input-bg, var(--sp-surface-input, var(--sp-form-default-bg)));
|
|
293
|
+
background-color: var(--sp-component-input-bg, var(--sp-surface-input, var(--sp-form-default-bg)));
|
|
249
294
|
color: var(--sp-component-input-text, var(--sp-text-on-surface-default, var(--sp-form-default-text)));
|
|
250
295
|
font-family: var(--sp-font-family-sans, system-ui);
|
|
251
296
|
font-size: var(--sp-font-md-size, 1rem);
|
|
@@ -260,6 +305,28 @@
|
|
|
260
305
|
color: var(--sp-component-input-placeholder, var(--sp-text-on-surface-muted, var(--sp-form-default-placeholder)));
|
|
261
306
|
}
|
|
262
307
|
|
|
308
|
+
.sp-input--sm {
|
|
309
|
+
padding: var(--sp-space-3xs, 0.125rem) var(--sp-space-sm, 0.75rem);
|
|
310
|
+
font-size: var(--sp-font-sm-size, 0.875rem);
|
|
311
|
+
line-height: var(--sp-font-sm-line-height, 1.25rem);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.sp-input--md {
|
|
315
|
+
padding: var(--sp-space-2xs, 0.25rem) var(--sp-space-md, 1rem);
|
|
316
|
+
font-size: var(--sp-font-md-size, 1rem);
|
|
317
|
+
line-height: var(--sp-font-md-line-height, 1.5rem);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.sp-input--lg {
|
|
321
|
+
padding: var(--sp-space-xs, 0.5rem) var(--sp-space-lg, 1.5rem);
|
|
322
|
+
font-size: var(--sp-font-lg-size, 1.125rem);
|
|
323
|
+
line-height: var(--sp-font-lg-line-height, 1.75rem);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.sp-input--full {
|
|
327
|
+
width: 100%;
|
|
328
|
+
}
|
|
329
|
+
|
|
263
330
|
.sp-input:focus,
|
|
264
331
|
.sp-input--focus {
|
|
265
332
|
border-color: var(
|
|
@@ -289,6 +356,7 @@
|
|
|
289
356
|
background-color: var(--sp-component-input-bg-disabled, var(--sp-form-disabled-bg));
|
|
290
357
|
color: var(--sp-component-input-text-disabled, var(--sp-form-disabled-text));
|
|
291
358
|
border-color: var(--sp-component-input-border-disabled, var(--sp-form-disabled-border));
|
|
359
|
+
cursor: not-allowed;
|
|
292
360
|
}
|
|
293
361
|
|
|
294
362
|
.sp-input--disabled,
|
|
@@ -299,7 +367,7 @@
|
|
|
299
367
|
/* CARDS ---------------------------------------------------------------- */
|
|
300
368
|
|
|
301
369
|
.sp-card {
|
|
302
|
-
background: var(--sp-component-card-bg);
|
|
370
|
+
background-color: var(--sp-component-card-bg);
|
|
303
371
|
color: var(--sp-component-card-text);
|
|
304
372
|
border-radius: var(--sp-radius-lg, 8px);
|
|
305
373
|
padding: var(--sp-space-lg, 1.5rem);
|
|
@@ -315,6 +383,11 @@
|
|
|
315
383
|
color: var(--sp-component-card-text-muted);
|
|
316
384
|
}
|
|
317
385
|
|
|
386
|
+
.sp-card h3,
|
|
387
|
+
.sp-card h4 {
|
|
388
|
+
color: var(--sp-component-card-text);
|
|
389
|
+
}
|
|
390
|
+
|
|
318
391
|
.sp-card--elevated {
|
|
319
392
|
box-shadow: var(--sp-component-card-shadow-elevated, var(--sp-shadow-lg));
|
|
320
393
|
}
|
|
@@ -335,4 +408,26 @@
|
|
|
335
408
|
border-color: var(--sp-component-card-ghost-border);
|
|
336
409
|
box-shadow: var(--sp-component-card-shadow-ghost, var(--sp-shadow-none));
|
|
337
410
|
}
|
|
411
|
+
|
|
412
|
+
.sp-card--padded {
|
|
413
|
+
padding: var(--sp-space-xl, 2rem);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.sp-card--full {
|
|
417
|
+
height: 100%;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.sp-card--interactive {
|
|
421
|
+
cursor: pointer;
|
|
422
|
+
transition:
|
|
423
|
+
transform var(--sp-duration-fast, 150ms) var(--sp-easing-out, ease),
|
|
424
|
+
box-shadow var(--sp-duration-fast, 150ms) var(--sp-easing-out, ease);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.sp-card--interactive:hover,
|
|
428
|
+
.sp-card--interactive:focus-visible,
|
|
429
|
+
.sp-card--interactive:focus-within {
|
|
430
|
+
transform: translateY(-1px);
|
|
431
|
+
box-shadow: var(--sp-component-card-shadow-elevated, var(--sp-shadow-lg));
|
|
432
|
+
}
|
|
338
433
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var plugin = require('tailwindcss/plugin');
|
|
4
3
|
var spectreTokens = require('@phcdevworks/spectre-tokens');
|
|
5
4
|
|
|
6
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
-
|
|
8
|
-
var plugin__default = /*#__PURE__*/_interopDefault(plugin);
|
|
9
|
-
|
|
10
5
|
// src/css-constants.ts
|
|
11
6
|
var spectreBaseStylesPath = "@phcdevworks/spectre-ui/dist/base.css";
|
|
12
7
|
var spectreComponentsStylesPath = "@phcdevworks/spectre-ui/dist/components.css";
|
|
@@ -22,125 +17,40 @@ function createSpectreTailwindTheme(options) {
|
|
|
22
17
|
const { tokens, overrides } = options;
|
|
23
18
|
const mergedTokens = {
|
|
24
19
|
...tokens,
|
|
25
|
-
...overrides
|
|
20
|
+
...overrides
|
|
26
21
|
};
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
const colors = {
|
|
23
|
+
page: mergedTokens.surface?.page,
|
|
24
|
+
card: mergedTokens.surface?.card,
|
|
25
|
+
input: mergedTokens.surface?.input,
|
|
26
|
+
text: {
|
|
27
|
+
page: mergedTokens.text?.onPage?.default,
|
|
28
|
+
"page-muted": mergedTokens.text?.onPage?.muted,
|
|
29
|
+
surface: mergedTokens.text?.onSurface?.default,
|
|
30
|
+
"surface-muted": mergedTokens.text?.onSurface?.muted
|
|
31
|
+
},
|
|
32
|
+
primary: mergedTokens.buttons?.primary?.bg ?? mergedTokens.colors?.primary
|
|
36
33
|
};
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
};
|
|
40
|
-
const
|
|
41
|
-
mergedColors.surface ?? {},
|
|
42
|
-
mergedTokens.surface
|
|
43
|
-
);
|
|
44
|
-
if (surfaceColors) {
|
|
45
|
-
themeColors.surface = surfaceColors;
|
|
46
|
-
}
|
|
47
|
-
const textColors = attachSemanticColors(
|
|
48
|
-
mergedColors.text ?? {},
|
|
49
|
-
mergedTokens.text
|
|
50
|
-
);
|
|
51
|
-
if (textColors) {
|
|
52
|
-
themeColors.text = textColors;
|
|
53
|
-
}
|
|
54
|
-
const componentColors = attachSemanticColors(
|
|
55
|
-
mergedColors.component ?? {},
|
|
56
|
-
mergedTokens.component
|
|
57
|
-
);
|
|
58
|
-
if (componentColors) {
|
|
59
|
-
themeColors.component = componentColors;
|
|
60
|
-
}
|
|
34
|
+
const spacing = mergedTokens.spacing ?? {};
|
|
35
|
+
const borderRadius = mergedTokens.radii ?? {};
|
|
36
|
+
const boxShadow = mergedTokens.shadows ?? {};
|
|
37
|
+
const fontFamily = mergedTokens.typography?.families ?? {};
|
|
61
38
|
const theme2 = {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
boxShadow: mergedTokens.shadows ?? {},
|
|
68
|
-
fontFamily: mergedTokens.typography?.families ?? {}
|
|
39
|
+
colors,
|
|
40
|
+
spacing,
|
|
41
|
+
borderRadius,
|
|
42
|
+
boxShadow,
|
|
43
|
+
fontFamily
|
|
69
44
|
};
|
|
70
45
|
return { theme: theme2 };
|
|
71
46
|
}
|
|
72
47
|
|
|
73
48
|
// src/tailwind/preset.ts
|
|
74
|
-
var { theme } = createSpectreTailwindTheme({
|
|
75
|
-
tokens: spectreTokens.tokens
|
|
76
|
-
});
|
|
77
|
-
var resolveTokenValue = (value, fallback) => {
|
|
78
|
-
if (typeof value === "string") {
|
|
79
|
-
return value;
|
|
80
|
-
}
|
|
81
|
-
if (value && typeof value === "object") {
|
|
82
|
-
const maybeDefault = value.default;
|
|
83
|
-
if (typeof maybeDefault === "string") {
|
|
84
|
-
return maybeDefault;
|
|
85
|
-
}
|
|
86
|
-
const firstEntry = Object.values(value).find(
|
|
87
|
-
(entry) => typeof entry === "string"
|
|
88
|
-
);
|
|
89
|
-
if (typeof firstEntry === "string") {
|
|
90
|
-
return firstEntry;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return fallback;
|
|
94
|
-
};
|
|
95
|
-
var semanticUtilities = plugin__default.default(({ addUtilities }) => {
|
|
96
|
-
const tokens = spectreTokens.tokens;
|
|
97
|
-
const neutralScale = tokens?.colors?.neutral ?? {};
|
|
98
|
-
const formDefault = tokens?.forms?.default ?? {};
|
|
99
|
-
const surfaceTokens = tokens?.surface ?? {};
|
|
100
|
-
const textTokens = tokens?.text ?? {};
|
|
101
|
-
const surfacePage = resolveTokenValue(
|
|
102
|
-
surfaceTokens.page,
|
|
103
|
-
neutralScale["50"]
|
|
104
|
-
);
|
|
105
|
-
const surfaceCard = resolveTokenValue(
|
|
106
|
-
surfaceTokens.card,
|
|
107
|
-
formDefault.bg ?? surfacePage ?? neutralScale["50"]
|
|
108
|
-
);
|
|
109
|
-
const surfaceInput = resolveTokenValue(
|
|
110
|
-
surfaceTokens.input,
|
|
111
|
-
formDefault.bg ?? surfaceCard ?? surfacePage
|
|
112
|
-
);
|
|
113
|
-
const textOnPage = resolveTokenValue(
|
|
114
|
-
textTokens?.on?.page ?? textTokens?.onPage,
|
|
115
|
-
neutralScale["900"] ?? formDefault.text
|
|
116
|
-
);
|
|
117
|
-
const textOnSurface = resolveTokenValue(
|
|
118
|
-
textTokens?.on?.surface ?? textTokens?.onSurface,
|
|
119
|
-
formDefault.text ?? textOnPage ?? neutralScale["900"]
|
|
120
|
-
);
|
|
121
|
-
const utilities = {};
|
|
122
|
-
if (surfacePage) {
|
|
123
|
-
utilities[".bg-surface-page"] = { backgroundColor: surfacePage };
|
|
124
|
-
}
|
|
125
|
-
if (surfaceCard) {
|
|
126
|
-
utilities[".bg-surface-card"] = { backgroundColor: surfaceCard };
|
|
127
|
-
}
|
|
128
|
-
if (surfaceInput) {
|
|
129
|
-
utilities[".bg-surface-input"] = { backgroundColor: surfaceInput };
|
|
130
|
-
}
|
|
131
|
-
if (textOnPage) {
|
|
132
|
-
utilities[".text-on-page"] = { color: textOnPage };
|
|
133
|
-
}
|
|
134
|
-
if (textOnSurface) {
|
|
135
|
-
utilities[".text-on-surface"] = { color: textOnSurface };
|
|
136
|
-
}
|
|
137
|
-
addUtilities(utilities);
|
|
138
|
-
});
|
|
49
|
+
var { theme } = createSpectreTailwindTheme({ tokens: spectreTokens.tokens });
|
|
139
50
|
var spectrePreset = {
|
|
140
|
-
// Required for Tailwind's Config type with exactOptionalPropertyTypes
|
|
141
51
|
content: [],
|
|
142
|
-
theme: theme ?? {}
|
|
143
|
-
|
|
52
|
+
theme: theme ?? {}
|
|
53
|
+
// ensure theme is never undefined
|
|
144
54
|
};
|
|
145
55
|
|
|
146
56
|
// src/recipes/button.ts
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/css-constants.ts","../src/tailwind/theme.ts","../src/tailwind/preset.ts","../src/recipes/button.ts","../src/recipes/card.ts","../src/recipes/input.ts"],"names":["theme","spectreTokens","plugin"],"mappings":"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","file":"index.cjs","sourcesContent":["export const spectreBaseStylesPath = \"@phcdevworks/spectre-ui/dist/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/dist/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/dist/utilities.css\";\n\nexport const spectreStyles = {\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from 'tailwindcss';\nimport type { SpectreTokens } from '../tokens';\n\nexport interface SpectreTailwindTheme {\n theme: TailwindConfig['theme'];\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions,\n): SpectreTailwindTheme {\n const { tokens, overrides } = options;\n\n // Shallow merge overrides into tokens\n const mergedTokens: SpectreTokens = {\n ...tokens,\n ...(overrides ?? {}),\n };\n\n const mergedColors = (mergedTokens as any).colors ?? {};\n\n const attachSemanticColors = (\n existing: Record<string, any>,\n semantic: Record<string, any> | undefined,\n ) => {\n if (!semantic || Object.keys(semantic).length === 0) {\n return Object.keys(existing).length > 0 ? existing : undefined;\n }\n\n return {\n ...existing,\n ...semantic,\n };\n };\n\n const themeColors: Record<string, any> = {\n ...mergedColors,\n };\n\n const surfaceColors = attachSemanticColors(\n mergedColors.surface ?? {},\n (mergedTokens as any).surface,\n );\n if (surfaceColors) {\n themeColors.surface = surfaceColors;\n }\n\n const textColors = attachSemanticColors(\n mergedColors.text ?? {},\n (mergedTokens as any).text,\n );\n if (textColors) {\n themeColors.text = textColors;\n }\n\n const componentColors = attachSemanticColors(\n mergedColors.component ?? {},\n (mergedTokens as any).component,\n );\n if (componentColors) {\n themeColors.component = componentColors;\n }\n\n const theme: TailwindConfig['theme'] = {\n // Safely map core token groups into Tailwind theme fields.\n // Use `as any` where necessary to avoid overfitting types right now.\n colors: themeColors,\n spacing: (mergedTokens as any).spacing ?? {},\n borderRadius: (mergedTokens as any).radii ?? {},\n boxShadow: (mergedTokens as any).shadows ?? {},\n fontFamily: (mergedTokens as any).typography?.families ?? {},\n };\n\n return { theme };\n}\n","import type { Config as TailwindConfig } from 'tailwindcss';\nimport plugin from 'tailwindcss/plugin';\nimport { spectreTokens } from '../tokens';\nimport { createSpectreTailwindTheme } from './theme';\n\nconst { theme } = createSpectreTailwindTheme({\n tokens: spectreTokens,\n});\n\nconst resolveTokenValue = (value: unknown, fallback?: string): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n\n if (value && typeof value === 'object') {\n const maybeDefault = (value as Record<string, unknown>).default;\n if (typeof maybeDefault === 'string') {\n return maybeDefault;\n }\n\n const firstEntry = Object.values(value as Record<string, unknown>).find(\n (entry) => typeof entry === 'string',\n );\n if (typeof firstEntry === 'string') {\n return firstEntry;\n }\n }\n\n return fallback;\n};\n\nconst semanticUtilities = plugin(({ addUtilities }) => {\n const tokens = spectreTokens as any;\n const neutralScale = tokens?.colors?.neutral ?? {};\n const formDefault = tokens?.forms?.default ?? {};\n\n const surfaceTokens = tokens?.surface ?? {};\n const textTokens = tokens?.text ?? {};\n\n const surfacePage = resolveTokenValue(\n surfaceTokens.page,\n neutralScale['50'],\n );\n const surfaceCard = resolveTokenValue(\n surfaceTokens.card,\n formDefault.bg ?? surfacePage ?? neutralScale['50'],\n );\n const surfaceInput = resolveTokenValue(\n surfaceTokens.input,\n formDefault.bg ?? surfaceCard ?? surfacePage,\n );\n\n const textOnPage = resolveTokenValue(\n textTokens?.on?.page ?? textTokens?.onPage,\n neutralScale['900'] ?? formDefault.text,\n );\n const textOnSurface = resolveTokenValue(\n textTokens?.on?.surface ?? textTokens?.onSurface,\n formDefault.text ?? textOnPage ?? neutralScale['900'],\n );\n\n const utilities: Record<string, Record<string, string>> = {};\n\n if (surfacePage) {\n utilities['.bg-surface-page'] = { backgroundColor: surfacePage };\n }\n\n if (surfaceCard) {\n utilities['.bg-surface-card'] = { backgroundColor: surfaceCard };\n }\n\n if (surfaceInput) {\n utilities['.bg-surface-input'] = { backgroundColor: surfaceInput };\n }\n\n if (textOnPage) {\n utilities['.text-on-page'] = { color: textOnPage };\n }\n\n if (textOnSurface) {\n utilities['.text-on-surface'] = { color: textOnSurface };\n }\n\n addUtilities(utilities);\n});\n\nexport const spectrePreset: TailwindConfig = {\n // Required for Tailwind's Config type with exactOptionalPropertyTypes\n content: [],\n theme: theme ?? {},\n plugins: [semanticUtilities],\n};\n\nexport const spectreTailwindPreset: TailwindConfig = spectrePreset;\n","export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonTone = 'default' | 'success' | 'warning' | 'danger';\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n tone?: ButtonTone;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\n/**\n * Generate Spectre button classes.\n *\n * Rules:\n * - Base: \"sp-btn\"\n * - Variant: \"sp-btn--primary\" / \"sp-btn--secondary\" / \"sp-btn--ghost\" / \"sp-btn--danger\"\n * - default variant is \"primary\"\n * - Size: \"sp-btn--sm\" / \"sp-btn--md\" / \"sp-btn--lg\"\n * - default size is \"md\"\n * - Tone: \"sp-btn--tone-success\" / \"sp-btn--tone-warning\" / \"sp-btn--tone-danger\"\n * - default tone is \"default\" (no tone class)\n * - fullWidth: add \"sp-btn--full\"\n * - loading: add \"sp-btn--loading\"\n * - disabled: add \"sp-btn--disabled\"\n * - iconOnly: add \"sp-btn--icon\"\n *\n * Must return a single space-joined, trimmed class string.\n */\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = 'primary',\n size = 'md',\n tone = 'default',\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-btn');\n\n // Variant\n const variantMap: Record<ButtonVariant, string> = {\n primary: 'sp-btn--primary',\n secondary: 'sp-btn--secondary',\n ghost: 'sp-btn--ghost',\n danger: 'sp-btn--danger',\n };\n classes.push(variantMap[variant]);\n\n // Size\n const sizeMap: Record<ButtonSize, string> = {\n sm: 'sp-btn--sm',\n md: 'sp-btn--md',\n lg: 'sp-btn--lg',\n };\n classes.push(sizeMap[size]);\n\n // Tone (optional)\n if (tone !== 'default') {\n const toneMap: Record<Exclude<ButtonTone, 'default'>, string> = {\n success: 'sp-btn--tone-success',\n warning: 'sp-btn--tone-warning',\n danger: 'sp-btn--tone-danger',\n };\n classes.push(toneMap[tone as Exclude<ButtonTone, 'default'>]);\n }\n\n // Flags\n if (fullWidth) classes.push('sp-btn--full');\n if (loading) classes.push('sp-btn--loading');\n if (disabled) classes.push('sp-btn--disabled');\n if (iconOnly) classes.push('sp-btn--icon');\n\n // Final class string\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type CardVariant = 'elevated' | 'outline' | 'ghost';\n\nexport interface CardRecipeOptions {\n variant?: CardVariant;\n interactive?: boolean; // hover/focus styles\n padded?: boolean; // apply default padding\n fullHeight?: boolean;\n}\n\n/**\n * Generate Spectre card classes.\n *\n * Rules:\n * - Base class: \"sp-card\"\n * - Variant (default: elevated):\n * - \"sp-card--elevated\"\n * - \"sp-card--outline\"\n * - \"sp-card--ghost\"\n * - interactive: add \"sp-card--interactive\"\n * - padded: add \"sp-card--padded\"\n * - fullHeight: add \"sp-card--full\"\n */\nexport function getCardClasses(opts: CardRecipeOptions = {}): string {\n const {\n variant = 'elevated',\n interactive = false,\n padded = false,\n fullHeight = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-card');\n\n // Variant\n const variantMap: Record<CardVariant, string> = {\n elevated: 'sp-card--elevated',\n outline: 'sp-card--outline',\n ghost: 'sp-card--ghost',\n };\n classes.push(variantMap[variant]);\n\n // Flags\n if (interactive) classes.push('sp-card--interactive');\n if (padded) classes.push('sp-card--padded');\n if (fullHeight) classes.push('sp-card--full');\n\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type InputState = 'default' | 'error' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg';\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\n/**\n * Generate Spectre input classes.\n *\n * Rules:\n * - Base class: \"sp-input\"\n * - State:\n * - \"default\" => no state modifier\n * - \"error\" => \"sp-input--error\"\n * - \"success\" => \"sp-input--success\"\n * - Size (default: md):\n * - \"sp-input--sm\"\n * - \"sp-input--md\"\n * - \"sp-input--lg\"\n * - fullWidth: add \"sp-input--full\"\n */\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const {\n state = 'default',\n size = 'md',\n fullWidth = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-input');\n\n // State\n if (state === 'error') {\n classes.push('sp-input--error');\n } else if (state === 'success') {\n classes.push('sp-input--success');\n }\n\n // Size\n const sizeMap: Record<InputSize, string> = {\n sm: 'sp-input--sm',\n md: 'sp-input--md',\n lg: 'sp-input--lg',\n };\n classes.push(sizeMap[size]);\n\n // Flags\n if (fullWidth) {\n classes.push('sp-input--full');\n }\n\n return classes.filter(Boolean).join(' ').trim();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/css-constants.ts","../src/tailwind/theme.ts","../src/tailwind/preset.ts","../src/recipes/button.ts","../src/recipes/card.ts","../src/recipes/input.ts"],"names":["theme","spectreTokens"],"mappings":"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","file":"index.cjs","sourcesContent":["export const spectreBaseStylesPath = \"@phcdevworks/spectre-ui/dist/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/dist/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/dist/utilities.css\";\n\nexport const spectreStyles = {\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport type { SpectreTokens } from \"../tokens\";\n\nexport interface SpectreTailwindTheme {\n theme: TailwindConfig[\"theme\"];\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions,\n): SpectreTailwindTheme {\n const { tokens, overrides } = options;\n\n // Shallow merge overrides into tokens\n const mergedTokens: SpectreTokens = {\n ...(tokens as SpectreTokens),\n ...(overrides as Partial<SpectreTokens> | undefined),\n };\n\n // Minimal, semantic color mapping\n const colors: Record<string, unknown> = {\n page: mergedTokens.surface?.page,\n card: mergedTokens.surface?.card,\n input: mergedTokens.surface?.input,\n text: {\n page: mergedTokens.text?.onPage?.default,\n \"page-muted\": mergedTokens.text?.onPage?.muted,\n surface: mergedTokens.text?.onSurface?.default,\n \"surface-muted\": mergedTokens.text?.onSurface?.muted,\n },\n primary:\n (mergedTokens as any).buttons?.primary?.bg ??\n (mergedTokens as any).colors?.primary,\n };\n\n const spacing: Record<string, unknown> =\n (mergedTokens as any).spacing ?? {};\n\n const borderRadius: Record<string, unknown> =\n (mergedTokens as any).radii ?? {};\n\n const boxShadow: Record<string, unknown> =\n (mergedTokens as any).shadows ?? {};\n\n const fontFamily: Record<string, unknown> =\n (mergedTokens as any).typography?.families ?? {};\n\n const theme: TailwindConfig[\"theme\"] = {\n colors: colors as any,\n spacing: spacing as any,\n borderRadius: borderRadius as any,\n boxShadow: boxShadow as any,\n fontFamily: fontFamily as any,\n };\n\n return { theme };\n}\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport { spectreTokens } from \"../tokens\";\nimport { createSpectreTailwindTheme } from \"./theme\";\n\nconst { theme } = createSpectreTailwindTheme({ tokens: spectreTokens });\n\nexport const spectrePreset: TailwindConfig = {\n content: [],\n theme: theme ?? {}, // ensure theme is never undefined\n};\n\nexport default spectrePreset;\n","export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonTone = 'default' | 'success' | 'warning' | 'danger';\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n tone?: ButtonTone;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\n/**\n * Generate Spectre button classes.\n *\n * Rules:\n * - Base: \"sp-btn\"\n * - Variant: \"sp-btn--primary\" / \"sp-btn--secondary\" / \"sp-btn--ghost\" / \"sp-btn--danger\"\n * - default variant is \"primary\"\n * - Size: \"sp-btn--sm\" / \"sp-btn--md\" / \"sp-btn--lg\"\n * - default size is \"md\"\n * - Tone: \"sp-btn--tone-success\" / \"sp-btn--tone-warning\" / \"sp-btn--tone-danger\"\n * - default tone is \"default\" (no tone class)\n * - fullWidth: add \"sp-btn--full\"\n * - loading: add \"sp-btn--loading\"\n * - disabled: add \"sp-btn--disabled\"\n * - iconOnly: add \"sp-btn--icon\"\n *\n * Must return a single space-joined, trimmed class string.\n */\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = 'primary',\n size = 'md',\n tone = 'default',\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-btn');\n\n // Variant\n const variantMap: Record<ButtonVariant, string> = {\n primary: 'sp-btn--primary',\n secondary: 'sp-btn--secondary',\n ghost: 'sp-btn--ghost',\n danger: 'sp-btn--danger',\n };\n classes.push(variantMap[variant]);\n\n // Size\n const sizeMap: Record<ButtonSize, string> = {\n sm: 'sp-btn--sm',\n md: 'sp-btn--md',\n lg: 'sp-btn--lg',\n };\n classes.push(sizeMap[size]);\n\n // Tone (optional)\n if (tone !== 'default') {\n const toneMap: Record<Exclude<ButtonTone, 'default'>, string> = {\n success: 'sp-btn--tone-success',\n warning: 'sp-btn--tone-warning',\n danger: 'sp-btn--tone-danger',\n };\n classes.push(toneMap[tone as Exclude<ButtonTone, 'default'>]);\n }\n\n // Flags\n if (fullWidth) classes.push('sp-btn--full');\n if (loading) classes.push('sp-btn--loading');\n if (disabled) classes.push('sp-btn--disabled');\n if (iconOnly) classes.push('sp-btn--icon');\n\n // Final class string\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type CardVariant = 'elevated' | 'outline' | 'ghost';\n\nexport interface CardRecipeOptions {\n variant?: CardVariant;\n interactive?: boolean; // hover/focus styles\n padded?: boolean; // apply default padding\n fullHeight?: boolean;\n}\n\n/**\n * Generate Spectre card classes.\n *\n * Rules:\n * - Base class: \"sp-card\"\n * - Variant (default: elevated):\n * - \"sp-card--elevated\"\n * - \"sp-card--outline\"\n * - \"sp-card--ghost\"\n * - interactive: add \"sp-card--interactive\"\n * - padded: add \"sp-card--padded\"\n * - fullHeight: add \"sp-card--full\"\n */\nexport function getCardClasses(opts: CardRecipeOptions = {}): string {\n const {\n variant = 'elevated',\n interactive = false,\n padded = false,\n fullHeight = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-card');\n\n // Variant\n const variantMap: Record<CardVariant, string> = {\n elevated: 'sp-card--elevated',\n outline: 'sp-card--outline',\n ghost: 'sp-card--ghost',\n };\n classes.push(variantMap[variant]);\n\n // Flags\n if (interactive) classes.push('sp-card--interactive');\n if (padded) classes.push('sp-card--padded');\n if (fullHeight) classes.push('sp-card--full');\n\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type InputState = 'default' | 'error' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg';\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\n/**\n * Generate Spectre input classes.\n *\n * Rules:\n * - Base class: \"sp-input\"\n * - State:\n * - \"default\" => no state modifier\n * - \"error\" => \"sp-input--error\"\n * - \"success\" => \"sp-input--success\"\n * - Size (default: md):\n * - \"sp-input--sm\"\n * - \"sp-input--md\"\n * - \"sp-input--lg\"\n * - fullWidth: add \"sp-input--full\"\n */\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const {\n state = 'default',\n size = 'md',\n fullWidth = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-input');\n\n // State\n if (state === 'error') {\n classes.push('sp-input--error');\n } else if (state === 'success') {\n classes.push('sp-input--success');\n }\n\n // Size\n const sizeMap: Record<InputSize, string> = {\n sm: 'sp-input--sm',\n md: 'sp-input--md',\n lg: 'sp-input--lg',\n };\n classes.push(sizeMap[size]);\n\n // Flags\n if (fullWidth) {\n classes.push('sp-input--full');\n }\n\n return classes.filter(Boolean).join(' ').trim();\n}\n"]}
|
package/dist/index.css
ADDED
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import plugin from 'tailwindcss/plugin';
|
|
2
1
|
import { tokens } from '@phcdevworks/spectre-tokens';
|
|
3
2
|
export { tokens as spectreTokens } from '@phcdevworks/spectre-tokens';
|
|
4
3
|
|
|
@@ -17,125 +16,40 @@ function createSpectreTailwindTheme(options) {
|
|
|
17
16
|
const { tokens, overrides } = options;
|
|
18
17
|
const mergedTokens = {
|
|
19
18
|
...tokens,
|
|
20
|
-
...overrides
|
|
19
|
+
...overrides
|
|
21
20
|
};
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
...mergedColors
|
|
21
|
+
const colors = {
|
|
22
|
+
page: mergedTokens.surface?.page,
|
|
23
|
+
card: mergedTokens.surface?.card,
|
|
24
|
+
input: mergedTokens.surface?.input,
|
|
25
|
+
text: {
|
|
26
|
+
page: mergedTokens.text?.onPage?.default,
|
|
27
|
+
"page-muted": mergedTokens.text?.onPage?.muted,
|
|
28
|
+
surface: mergedTokens.text?.onSurface?.default,
|
|
29
|
+
"surface-muted": mergedTokens.text?.onSurface?.muted
|
|
30
|
+
},
|
|
31
|
+
primary: mergedTokens.buttons?.primary?.bg ?? mergedTokens.colors?.primary
|
|
34
32
|
};
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (surfaceColors) {
|
|
40
|
-
themeColors.surface = surfaceColors;
|
|
41
|
-
}
|
|
42
|
-
const textColors = attachSemanticColors(
|
|
43
|
-
mergedColors.text ?? {},
|
|
44
|
-
mergedTokens.text
|
|
45
|
-
);
|
|
46
|
-
if (textColors) {
|
|
47
|
-
themeColors.text = textColors;
|
|
48
|
-
}
|
|
49
|
-
const componentColors = attachSemanticColors(
|
|
50
|
-
mergedColors.component ?? {},
|
|
51
|
-
mergedTokens.component
|
|
52
|
-
);
|
|
53
|
-
if (componentColors) {
|
|
54
|
-
themeColors.component = componentColors;
|
|
55
|
-
}
|
|
33
|
+
const spacing = mergedTokens.spacing ?? {};
|
|
34
|
+
const borderRadius = mergedTokens.radii ?? {};
|
|
35
|
+
const boxShadow = mergedTokens.shadows ?? {};
|
|
36
|
+
const fontFamily = mergedTokens.typography?.families ?? {};
|
|
56
37
|
const theme2 = {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
boxShadow: mergedTokens.shadows ?? {},
|
|
63
|
-
fontFamily: mergedTokens.typography?.families ?? {}
|
|
38
|
+
colors,
|
|
39
|
+
spacing,
|
|
40
|
+
borderRadius,
|
|
41
|
+
boxShadow,
|
|
42
|
+
fontFamily
|
|
64
43
|
};
|
|
65
44
|
return { theme: theme2 };
|
|
66
45
|
}
|
|
67
46
|
|
|
68
47
|
// src/tailwind/preset.ts
|
|
69
|
-
var { theme } = createSpectreTailwindTheme({
|
|
70
|
-
tokens: tokens
|
|
71
|
-
});
|
|
72
|
-
var resolveTokenValue = (value, fallback) => {
|
|
73
|
-
if (typeof value === "string") {
|
|
74
|
-
return value;
|
|
75
|
-
}
|
|
76
|
-
if (value && typeof value === "object") {
|
|
77
|
-
const maybeDefault = value.default;
|
|
78
|
-
if (typeof maybeDefault === "string") {
|
|
79
|
-
return maybeDefault;
|
|
80
|
-
}
|
|
81
|
-
const firstEntry = Object.values(value).find(
|
|
82
|
-
(entry) => typeof entry === "string"
|
|
83
|
-
);
|
|
84
|
-
if (typeof firstEntry === "string") {
|
|
85
|
-
return firstEntry;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return fallback;
|
|
89
|
-
};
|
|
90
|
-
var semanticUtilities = plugin(({ addUtilities }) => {
|
|
91
|
-
const tokens$1 = tokens;
|
|
92
|
-
const neutralScale = tokens$1?.colors?.neutral ?? {};
|
|
93
|
-
const formDefault = tokens$1?.forms?.default ?? {};
|
|
94
|
-
const surfaceTokens = tokens$1?.surface ?? {};
|
|
95
|
-
const textTokens = tokens$1?.text ?? {};
|
|
96
|
-
const surfacePage = resolveTokenValue(
|
|
97
|
-
surfaceTokens.page,
|
|
98
|
-
neutralScale["50"]
|
|
99
|
-
);
|
|
100
|
-
const surfaceCard = resolveTokenValue(
|
|
101
|
-
surfaceTokens.card,
|
|
102
|
-
formDefault.bg ?? surfacePage ?? neutralScale["50"]
|
|
103
|
-
);
|
|
104
|
-
const surfaceInput = resolveTokenValue(
|
|
105
|
-
surfaceTokens.input,
|
|
106
|
-
formDefault.bg ?? surfaceCard ?? surfacePage
|
|
107
|
-
);
|
|
108
|
-
const textOnPage = resolveTokenValue(
|
|
109
|
-
textTokens?.on?.page ?? textTokens?.onPage,
|
|
110
|
-
neutralScale["900"] ?? formDefault.text
|
|
111
|
-
);
|
|
112
|
-
const textOnSurface = resolveTokenValue(
|
|
113
|
-
textTokens?.on?.surface ?? textTokens?.onSurface,
|
|
114
|
-
formDefault.text ?? textOnPage ?? neutralScale["900"]
|
|
115
|
-
);
|
|
116
|
-
const utilities = {};
|
|
117
|
-
if (surfacePage) {
|
|
118
|
-
utilities[".bg-surface-page"] = { backgroundColor: surfacePage };
|
|
119
|
-
}
|
|
120
|
-
if (surfaceCard) {
|
|
121
|
-
utilities[".bg-surface-card"] = { backgroundColor: surfaceCard };
|
|
122
|
-
}
|
|
123
|
-
if (surfaceInput) {
|
|
124
|
-
utilities[".bg-surface-input"] = { backgroundColor: surfaceInput };
|
|
125
|
-
}
|
|
126
|
-
if (textOnPage) {
|
|
127
|
-
utilities[".text-on-page"] = { color: textOnPage };
|
|
128
|
-
}
|
|
129
|
-
if (textOnSurface) {
|
|
130
|
-
utilities[".text-on-surface"] = { color: textOnSurface };
|
|
131
|
-
}
|
|
132
|
-
addUtilities(utilities);
|
|
133
|
-
});
|
|
48
|
+
var { theme } = createSpectreTailwindTheme({ tokens: tokens });
|
|
134
49
|
var spectrePreset = {
|
|
135
|
-
// Required for Tailwind's Config type with exactOptionalPropertyTypes
|
|
136
50
|
content: [],
|
|
137
|
-
theme: theme ?? {}
|
|
138
|
-
|
|
51
|
+
theme: theme ?? {}
|
|
52
|
+
// ensure theme is never undefined
|
|
139
53
|
};
|
|
140
54
|
|
|
141
55
|
// src/recipes/button.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/css-constants.ts","../src/tailwind/theme.ts","../src/tailwind/preset.ts","../src/recipes/button.ts","../src/recipes/card.ts","../src/recipes/input.ts"],"names":["theme","spectreTokens","tokens"],"mappings":"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","file":"index.js","sourcesContent":["export const spectreBaseStylesPath = \"@phcdevworks/spectre-ui/dist/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/dist/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/dist/utilities.css\";\n\nexport const spectreStyles = {\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from 'tailwindcss';\nimport type { SpectreTokens } from '../tokens';\n\nexport interface SpectreTailwindTheme {\n theme: TailwindConfig['theme'];\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions,\n): SpectreTailwindTheme {\n const { tokens, overrides } = options;\n\n // Shallow merge overrides into tokens\n const mergedTokens: SpectreTokens = {\n ...tokens,\n ...(overrides ?? {}),\n };\n\n const mergedColors = (mergedTokens as any).colors ?? {};\n\n const attachSemanticColors = (\n existing: Record<string, any>,\n semantic: Record<string, any> | undefined,\n ) => {\n if (!semantic || Object.keys(semantic).length === 0) {\n return Object.keys(existing).length > 0 ? existing : undefined;\n }\n\n return {\n ...existing,\n ...semantic,\n };\n };\n\n const themeColors: Record<string, any> = {\n ...mergedColors,\n };\n\n const surfaceColors = attachSemanticColors(\n mergedColors.surface ?? {},\n (mergedTokens as any).surface,\n );\n if (surfaceColors) {\n themeColors.surface = surfaceColors;\n }\n\n const textColors = attachSemanticColors(\n mergedColors.text ?? {},\n (mergedTokens as any).text,\n );\n if (textColors) {\n themeColors.text = textColors;\n }\n\n const componentColors = attachSemanticColors(\n mergedColors.component ?? {},\n (mergedTokens as any).component,\n );\n if (componentColors) {\n themeColors.component = componentColors;\n }\n\n const theme: TailwindConfig['theme'] = {\n // Safely map core token groups into Tailwind theme fields.\n // Use `as any` where necessary to avoid overfitting types right now.\n colors: themeColors,\n spacing: (mergedTokens as any).spacing ?? {},\n borderRadius: (mergedTokens as any).radii ?? {},\n boxShadow: (mergedTokens as any).shadows ?? {},\n fontFamily: (mergedTokens as any).typography?.families ?? {},\n };\n\n return { theme };\n}\n","import type { Config as TailwindConfig } from 'tailwindcss';\nimport plugin from 'tailwindcss/plugin';\nimport { spectreTokens } from '../tokens';\nimport { createSpectreTailwindTheme } from './theme';\n\nconst { theme } = createSpectreTailwindTheme({\n tokens: spectreTokens,\n});\n\nconst resolveTokenValue = (value: unknown, fallback?: string): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n\n if (value && typeof value === 'object') {\n const maybeDefault = (value as Record<string, unknown>).default;\n if (typeof maybeDefault === 'string') {\n return maybeDefault;\n }\n\n const firstEntry = Object.values(value as Record<string, unknown>).find(\n (entry) => typeof entry === 'string',\n );\n if (typeof firstEntry === 'string') {\n return firstEntry;\n }\n }\n\n return fallback;\n};\n\nconst semanticUtilities = plugin(({ addUtilities }) => {\n const tokens = spectreTokens as any;\n const neutralScale = tokens?.colors?.neutral ?? {};\n const formDefault = tokens?.forms?.default ?? {};\n\n const surfaceTokens = tokens?.surface ?? {};\n const textTokens = tokens?.text ?? {};\n\n const surfacePage = resolveTokenValue(\n surfaceTokens.page,\n neutralScale['50'],\n );\n const surfaceCard = resolveTokenValue(\n surfaceTokens.card,\n formDefault.bg ?? surfacePage ?? neutralScale['50'],\n );\n const surfaceInput = resolveTokenValue(\n surfaceTokens.input,\n formDefault.bg ?? surfaceCard ?? surfacePage,\n );\n\n const textOnPage = resolveTokenValue(\n textTokens?.on?.page ?? textTokens?.onPage,\n neutralScale['900'] ?? formDefault.text,\n );\n const textOnSurface = resolveTokenValue(\n textTokens?.on?.surface ?? textTokens?.onSurface,\n formDefault.text ?? textOnPage ?? neutralScale['900'],\n );\n\n const utilities: Record<string, Record<string, string>> = {};\n\n if (surfacePage) {\n utilities['.bg-surface-page'] = { backgroundColor: surfacePage };\n }\n\n if (surfaceCard) {\n utilities['.bg-surface-card'] = { backgroundColor: surfaceCard };\n }\n\n if (surfaceInput) {\n utilities['.bg-surface-input'] = { backgroundColor: surfaceInput };\n }\n\n if (textOnPage) {\n utilities['.text-on-page'] = { color: textOnPage };\n }\n\n if (textOnSurface) {\n utilities['.text-on-surface'] = { color: textOnSurface };\n }\n\n addUtilities(utilities);\n});\n\nexport const spectrePreset: TailwindConfig = {\n // Required for Tailwind's Config type with exactOptionalPropertyTypes\n content: [],\n theme: theme ?? {},\n plugins: [semanticUtilities],\n};\n\nexport const spectreTailwindPreset: TailwindConfig = spectrePreset;\n","export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonTone = 'default' | 'success' | 'warning' | 'danger';\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n tone?: ButtonTone;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\n/**\n * Generate Spectre button classes.\n *\n * Rules:\n * - Base: \"sp-btn\"\n * - Variant: \"sp-btn--primary\" / \"sp-btn--secondary\" / \"sp-btn--ghost\" / \"sp-btn--danger\"\n * - default variant is \"primary\"\n * - Size: \"sp-btn--sm\" / \"sp-btn--md\" / \"sp-btn--lg\"\n * - default size is \"md\"\n * - Tone: \"sp-btn--tone-success\" / \"sp-btn--tone-warning\" / \"sp-btn--tone-danger\"\n * - default tone is \"default\" (no tone class)\n * - fullWidth: add \"sp-btn--full\"\n * - loading: add \"sp-btn--loading\"\n * - disabled: add \"sp-btn--disabled\"\n * - iconOnly: add \"sp-btn--icon\"\n *\n * Must return a single space-joined, trimmed class string.\n */\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = 'primary',\n size = 'md',\n tone = 'default',\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-btn');\n\n // Variant\n const variantMap: Record<ButtonVariant, string> = {\n primary: 'sp-btn--primary',\n secondary: 'sp-btn--secondary',\n ghost: 'sp-btn--ghost',\n danger: 'sp-btn--danger',\n };\n classes.push(variantMap[variant]);\n\n // Size\n const sizeMap: Record<ButtonSize, string> = {\n sm: 'sp-btn--sm',\n md: 'sp-btn--md',\n lg: 'sp-btn--lg',\n };\n classes.push(sizeMap[size]);\n\n // Tone (optional)\n if (tone !== 'default') {\n const toneMap: Record<Exclude<ButtonTone, 'default'>, string> = {\n success: 'sp-btn--tone-success',\n warning: 'sp-btn--tone-warning',\n danger: 'sp-btn--tone-danger',\n };\n classes.push(toneMap[tone as Exclude<ButtonTone, 'default'>]);\n }\n\n // Flags\n if (fullWidth) classes.push('sp-btn--full');\n if (loading) classes.push('sp-btn--loading');\n if (disabled) classes.push('sp-btn--disabled');\n if (iconOnly) classes.push('sp-btn--icon');\n\n // Final class string\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type CardVariant = 'elevated' | 'outline' | 'ghost';\n\nexport interface CardRecipeOptions {\n variant?: CardVariant;\n interactive?: boolean; // hover/focus styles\n padded?: boolean; // apply default padding\n fullHeight?: boolean;\n}\n\n/**\n * Generate Spectre card classes.\n *\n * Rules:\n * - Base class: \"sp-card\"\n * - Variant (default: elevated):\n * - \"sp-card--elevated\"\n * - \"sp-card--outline\"\n * - \"sp-card--ghost\"\n * - interactive: add \"sp-card--interactive\"\n * - padded: add \"sp-card--padded\"\n * - fullHeight: add \"sp-card--full\"\n */\nexport function getCardClasses(opts: CardRecipeOptions = {}): string {\n const {\n variant = 'elevated',\n interactive = false,\n padded = false,\n fullHeight = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-card');\n\n // Variant\n const variantMap: Record<CardVariant, string> = {\n elevated: 'sp-card--elevated',\n outline: 'sp-card--outline',\n ghost: 'sp-card--ghost',\n };\n classes.push(variantMap[variant]);\n\n // Flags\n if (interactive) classes.push('sp-card--interactive');\n if (padded) classes.push('sp-card--padded');\n if (fullHeight) classes.push('sp-card--full');\n\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type InputState = 'default' | 'error' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg';\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\n/**\n * Generate Spectre input classes.\n *\n * Rules:\n * - Base class: \"sp-input\"\n * - State:\n * - \"default\" => no state modifier\n * - \"error\" => \"sp-input--error\"\n * - \"success\" => \"sp-input--success\"\n * - Size (default: md):\n * - \"sp-input--sm\"\n * - \"sp-input--md\"\n * - \"sp-input--lg\"\n * - fullWidth: add \"sp-input--full\"\n */\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const {\n state = 'default',\n size = 'md',\n fullWidth = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-input');\n\n // State\n if (state === 'error') {\n classes.push('sp-input--error');\n } else if (state === 'success') {\n classes.push('sp-input--success');\n }\n\n // Size\n const sizeMap: Record<InputSize, string> = {\n sm: 'sp-input--sm',\n md: 'sp-input--md',\n lg: 'sp-input--lg',\n };\n classes.push(sizeMap[size]);\n\n // Flags\n if (fullWidth) {\n classes.push('sp-input--full');\n }\n\n return classes.filter(Boolean).join(' ').trim();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/css-constants.ts","../src/tailwind/theme.ts","../src/tailwind/preset.ts","../src/recipes/button.ts","../src/recipes/card.ts","../src/recipes/input.ts"],"names":["theme","spectreTokens"],"mappings":"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","file":"index.js","sourcesContent":["export const spectreBaseStylesPath = \"@phcdevworks/spectre-ui/dist/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/dist/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/dist/utilities.css\";\n\nexport const spectreStyles = {\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport type { SpectreTokens } from \"../tokens\";\n\nexport interface SpectreTailwindTheme {\n theme: TailwindConfig[\"theme\"];\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions,\n): SpectreTailwindTheme {\n const { tokens, overrides } = options;\n\n // Shallow merge overrides into tokens\n const mergedTokens: SpectreTokens = {\n ...(tokens as SpectreTokens),\n ...(overrides as Partial<SpectreTokens> | undefined),\n };\n\n // Minimal, semantic color mapping\n const colors: Record<string, unknown> = {\n page: mergedTokens.surface?.page,\n card: mergedTokens.surface?.card,\n input: mergedTokens.surface?.input,\n text: {\n page: mergedTokens.text?.onPage?.default,\n \"page-muted\": mergedTokens.text?.onPage?.muted,\n surface: mergedTokens.text?.onSurface?.default,\n \"surface-muted\": mergedTokens.text?.onSurface?.muted,\n },\n primary:\n (mergedTokens as any).buttons?.primary?.bg ??\n (mergedTokens as any).colors?.primary,\n };\n\n const spacing: Record<string, unknown> =\n (mergedTokens as any).spacing ?? {};\n\n const borderRadius: Record<string, unknown> =\n (mergedTokens as any).radii ?? {};\n\n const boxShadow: Record<string, unknown> =\n (mergedTokens as any).shadows ?? {};\n\n const fontFamily: Record<string, unknown> =\n (mergedTokens as any).typography?.families ?? {};\n\n const theme: TailwindConfig[\"theme\"] = {\n colors: colors as any,\n spacing: spacing as any,\n borderRadius: borderRadius as any,\n boxShadow: boxShadow as any,\n fontFamily: fontFamily as any,\n };\n\n return { theme };\n}\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport { spectreTokens } from \"../tokens\";\nimport { createSpectreTailwindTheme } from \"./theme\";\n\nconst { theme } = createSpectreTailwindTheme({ tokens: spectreTokens });\n\nexport const spectrePreset: TailwindConfig = {\n content: [],\n theme: theme ?? {}, // ensure theme is never undefined\n};\n\nexport default spectrePreset;\n","export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\nexport type ButtonTone = 'default' | 'success' | 'warning' | 'danger';\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n tone?: ButtonTone;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\n/**\n * Generate Spectre button classes.\n *\n * Rules:\n * - Base: \"sp-btn\"\n * - Variant: \"sp-btn--primary\" / \"sp-btn--secondary\" / \"sp-btn--ghost\" / \"sp-btn--danger\"\n * - default variant is \"primary\"\n * - Size: \"sp-btn--sm\" / \"sp-btn--md\" / \"sp-btn--lg\"\n * - default size is \"md\"\n * - Tone: \"sp-btn--tone-success\" / \"sp-btn--tone-warning\" / \"sp-btn--tone-danger\"\n * - default tone is \"default\" (no tone class)\n * - fullWidth: add \"sp-btn--full\"\n * - loading: add \"sp-btn--loading\"\n * - disabled: add \"sp-btn--disabled\"\n * - iconOnly: add \"sp-btn--icon\"\n *\n * Must return a single space-joined, trimmed class string.\n */\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = 'primary',\n size = 'md',\n tone = 'default',\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-btn');\n\n // Variant\n const variantMap: Record<ButtonVariant, string> = {\n primary: 'sp-btn--primary',\n secondary: 'sp-btn--secondary',\n ghost: 'sp-btn--ghost',\n danger: 'sp-btn--danger',\n };\n classes.push(variantMap[variant]);\n\n // Size\n const sizeMap: Record<ButtonSize, string> = {\n sm: 'sp-btn--sm',\n md: 'sp-btn--md',\n lg: 'sp-btn--lg',\n };\n classes.push(sizeMap[size]);\n\n // Tone (optional)\n if (tone !== 'default') {\n const toneMap: Record<Exclude<ButtonTone, 'default'>, string> = {\n success: 'sp-btn--tone-success',\n warning: 'sp-btn--tone-warning',\n danger: 'sp-btn--tone-danger',\n };\n classes.push(toneMap[tone as Exclude<ButtonTone, 'default'>]);\n }\n\n // Flags\n if (fullWidth) classes.push('sp-btn--full');\n if (loading) classes.push('sp-btn--loading');\n if (disabled) classes.push('sp-btn--disabled');\n if (iconOnly) classes.push('sp-btn--icon');\n\n // Final class string\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type CardVariant = 'elevated' | 'outline' | 'ghost';\n\nexport interface CardRecipeOptions {\n variant?: CardVariant;\n interactive?: boolean; // hover/focus styles\n padded?: boolean; // apply default padding\n fullHeight?: boolean;\n}\n\n/**\n * Generate Spectre card classes.\n *\n * Rules:\n * - Base class: \"sp-card\"\n * - Variant (default: elevated):\n * - \"sp-card--elevated\"\n * - \"sp-card--outline\"\n * - \"sp-card--ghost\"\n * - interactive: add \"sp-card--interactive\"\n * - padded: add \"sp-card--padded\"\n * - fullHeight: add \"sp-card--full\"\n */\nexport function getCardClasses(opts: CardRecipeOptions = {}): string {\n const {\n variant = 'elevated',\n interactive = false,\n padded = false,\n fullHeight = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-card');\n\n // Variant\n const variantMap: Record<CardVariant, string> = {\n elevated: 'sp-card--elevated',\n outline: 'sp-card--outline',\n ghost: 'sp-card--ghost',\n };\n classes.push(variantMap[variant]);\n\n // Flags\n if (interactive) classes.push('sp-card--interactive');\n if (padded) classes.push('sp-card--padded');\n if (fullHeight) classes.push('sp-card--full');\n\n return classes.filter(Boolean).join(' ').trim();\n}\n","export type InputState = 'default' | 'error' | 'success';\nexport type InputSize = 'sm' | 'md' | 'lg';\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\n/**\n * Generate Spectre input classes.\n *\n * Rules:\n * - Base class: \"sp-input\"\n * - State:\n * - \"default\" => no state modifier\n * - \"error\" => \"sp-input--error\"\n * - \"success\" => \"sp-input--success\"\n * - Size (default: md):\n * - \"sp-input--sm\"\n * - \"sp-input--md\"\n * - \"sp-input--lg\"\n * - fullWidth: add \"sp-input--full\"\n */\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const {\n state = 'default',\n size = 'md',\n fullWidth = false,\n } = opts;\n\n const classes: string[] = [];\n\n // Base\n classes.push('sp-input');\n\n // State\n if (state === 'error') {\n classes.push('sp-input--error');\n } else if (state === 'success') {\n classes.push('sp-input--success');\n }\n\n // Size\n const sizeMap: Record<InputSize, string> = {\n sm: 'sp-input--sm',\n md: 'sp-input--md',\n lg: 'sp-input--lg',\n };\n classes.push(sizeMap[size]);\n\n // Flags\n if (fullWidth) {\n classes.push('sp-input--full');\n }\n\n return classes.filter(Boolean).join(' ').trim();\n}\n"]}
|
package/dist/utilities.css
CHANGED
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.sp-shadow-soft {
|
|
30
|
-
box-shadow: var(--sp-shadow-md
|
|
30
|
+
box-shadow: var(--sp-shadow-md);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
.sp-shadow-strong {
|
|
34
|
-
box-shadow: var(--sp-shadow-lg
|
|
34
|
+
box-shadow: var(--sp-shadow-lg);
|
|
35
35
|
}
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phcdevworks/spectre-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Framework-agnostic UI layer for the Spectre design system. Provides base CSS, component classes, utilities, and a Tailwind preset powered by @phcdevworks/spectre-tokens.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"phcdevworks",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"import": "./dist/index.js",
|
|
48
48
|
"require": "./dist/index.cjs"
|
|
49
49
|
},
|
|
50
|
+
"./index.css": "./dist/index.css",
|
|
50
51
|
"./base.css": "./dist/base.css",
|
|
51
52
|
"./components.css": "./dist/components.css",
|
|
52
53
|
"./utilities.css": "./dist/utilities.css"
|
|
@@ -60,7 +61,8 @@
|
|
|
60
61
|
"scripts": {
|
|
61
62
|
"build": "tsup --config tsup.config.ts",
|
|
62
63
|
"dev": "tsup --config tsup.config.ts --watch",
|
|
63
|
-
"clean": "rm -rf dist"
|
|
64
|
+
"clean": "rm -rf dist",
|
|
65
|
+
"test": "vitest run"
|
|
64
66
|
},
|
|
65
67
|
"publishConfig": {
|
|
66
68
|
"access": "public"
|
|
@@ -69,13 +71,14 @@
|
|
|
69
71
|
"tailwindcss": "^3.4.0 || ^4.0.0"
|
|
70
72
|
},
|
|
71
73
|
"dependencies": {
|
|
72
|
-
"@phcdevworks/spectre-tokens": "^0.0.
|
|
74
|
+
"@phcdevworks/spectre-tokens": "^0.0.4"
|
|
73
75
|
},
|
|
74
76
|
"devDependencies": {
|
|
75
77
|
"autoprefixer": "^10.4.20",
|
|
76
78
|
"postcss": "^8.4.35",
|
|
77
79
|
"tailwindcss": "^3.4.15",
|
|
78
80
|
"tsup": "^8.5.1",
|
|
79
|
-
"typescript": "^5.9.3"
|
|
81
|
+
"typescript": "^5.9.3",
|
|
82
|
+
"vitest": "^2.1.4"
|
|
80
83
|
}
|
|
81
84
|
}
|