@phcdevworks/spectre-ui 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -11
- package/dist/base.css +5 -11
- package/dist/components.css +53 -50
- package/dist/index.cjs +38 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +8 -0
- package/dist/index.d.cts +19 -61
- package/dist/index.d.ts +19 -61
- package/dist/index.js +35 -60
- package/dist/index.js.map +1 -1
- package/dist/utilities.css +2 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Framework-agnostic styling layer that powers Spectre Blocks, Spectre Astro, Spectre 11ty, and every Spectre integration.
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> 🤝 **[Contributing Guide](CONTRIBUTING.md)** | 📝 **[Changelog](CHANGELOG.md)**
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
@@ -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";
|
|
@@ -48,6 +57,31 @@ export default {
|
|
|
48
57
|
|
|
49
58
|
Works with Tailwind 3.x and 4.x through the classic config API.
|
|
50
59
|
|
|
60
|
+
Need a plain theme object without presets? Generate it from the first-party tokens.
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
// tailwind.config.ts
|
|
64
|
+
import {
|
|
65
|
+
createSpectreTailwindTheme,
|
|
66
|
+
spectreTokens,
|
|
67
|
+
} from "@phcdevworks/spectre-ui";
|
|
68
|
+
|
|
69
|
+
const { theme } = createSpectreTailwindTheme({
|
|
70
|
+
tokens: spectreTokens,
|
|
71
|
+
overrides: {
|
|
72
|
+
spacing: {
|
|
73
|
+
...spectreTokens.spacing,
|
|
74
|
+
gutter: "1.125rem",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export default {
|
|
80
|
+
content: ["./src/**/*.{js,ts,jsx,tsx,astro}"],
|
|
81
|
+
theme,
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
51
85
|
### 3. Use Spectre recipes
|
|
52
86
|
|
|
53
87
|
Recipes wrap Spectre's class combinations so every framework composes styles consistently.
|
|
@@ -86,9 +120,10 @@ getButtonClasses({ variant: "primary" }); // CTA baseline
|
|
|
86
120
|
getButtonClasses({ variant: "secondary" }); // Outlined
|
|
87
121
|
getButtonClasses({ variant: "ghost" }); // Low-emphasis
|
|
88
122
|
getButtonClasses({ variant: "danger" }); // Destructive
|
|
123
|
+
getButtonClasses({ variant: "success" }); // Positive actions
|
|
89
124
|
```
|
|
90
125
|
|
|
91
|
-
Each variant ships with full state coverage: `default`, `hover`, `active`, `disabled
|
|
126
|
+
Each variant ships with full state coverage: `default`, `hover`, `active`, `disabled`.
|
|
92
127
|
|
|
93
128
|
```css
|
|
94
129
|
.cta-button {
|
|
@@ -111,8 +146,7 @@ getInputClasses({ state: "success" });
|
|
|
111
146
|
```css
|
|
112
147
|
.input:focus {
|
|
113
148
|
border-color: var(--sp-component-input-border-focus);
|
|
114
|
-
outline: var(--sp-focus-ring-width) var(--sp-focus-ring-style)
|
|
115
|
-
var(--sp-component-input-ring-focus);
|
|
149
|
+
outline: var(--sp-focus-ring-width) var(--sp-focus-ring-style) var(--sp-component-input-ring-focus);
|
|
116
150
|
}
|
|
117
151
|
.input.error {
|
|
118
152
|
border-color: var(--sp-component-input-border-error);
|
|
@@ -208,10 +242,10 @@ import {
|
|
|
208
242
|
|
|
209
243
|
## Repository Layout
|
|
210
244
|
|
|
211
|
-
| Folder | Responsibility
|
|
212
|
-
| ------------- |
|
|
213
|
-
| `src/` | TypeScript source: recipes, Tailwind preset, token re-exports, CSS constants.
|
|
214
|
-
| `src/styles/` | Raw CSS files (`base.css`, `components.css`, `utilities.css`) copied to `dist/` during build.
|
|
245
|
+
| Folder | Responsibility |
|
|
246
|
+
| ------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
247
|
+
| `src/` | TypeScript source: recipes, Tailwind preset, token re-exports, CSS constants. |
|
|
248
|
+
| `src/styles/` | Raw CSS files (`base.css`, `components.css`, `utilities.css`) copied to `dist/` during build. |
|
|
215
249
|
| `dist/` | Generated artifacts: `index.js`, `index.cjs`, `index.d.ts`, and CSS files. Regenerated via `npm run build`. |
|
|
216
250
|
|
|
217
251
|
Designers update tokens in `@phcdevworks/spectre-tokens`. Engineering evolves recipes, presets, and CSS in this package.
|
|
@@ -243,7 +277,9 @@ import type {
|
|
|
243
277
|
SpectreTokens,
|
|
244
278
|
SpectreTailwindTheme,
|
|
245
279
|
ButtonVariant,
|
|
280
|
+
ButtonSize,
|
|
246
281
|
InputState,
|
|
282
|
+
InputSize,
|
|
247
283
|
CardVariant,
|
|
248
284
|
ButtonRecipeOptions,
|
|
249
285
|
CardRecipeOptions,
|
|
@@ -259,8 +295,6 @@ import type {
|
|
|
259
295
|
- **Spectre Astro** – Astro integration
|
|
260
296
|
- **Spectre 11ty** – Eleventy integration
|
|
261
297
|
|
|
262
|
-
For the project's future direction, see the **[Roadmap](https://github.com/phcdevworks/spectre-ui/blob/main/ROADMAP.md)**.
|
|
263
|
-
|
|
264
298
|
## Contributing
|
|
265
299
|
|
|
266
300
|
Issues and pull requests are welcome. If you are proposing style or recipe changes, update `src/` and include regenerated builds.
|
package/dist/base.css
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
@layer base {
|
|
2
2
|
|
|
3
|
-
:root {
|
|
4
|
-
--sp-surface-page: var(--sp-color-neutral-50, #f8fafc);
|
|
5
|
-
--sp-surface-card: #ffffff;
|
|
6
|
-
--sp-surface-input: var(--sp-form-default-bg, #ffffff);
|
|
7
|
-
--sp-surface-overlay: rgba(15, 23, 42, var(--sp-opacity-overlay, 0.5));
|
|
8
|
-
}
|
|
9
|
-
|
|
10
3
|
*,
|
|
11
4
|
*::before,
|
|
12
5
|
*::after {
|
|
@@ -52,7 +45,7 @@
|
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
a {
|
|
55
|
-
color: var(--sp-color-
|
|
48
|
+
color: var(--sp-color-brand-600, inherit);
|
|
56
49
|
text-decoration: none;
|
|
57
50
|
}
|
|
58
51
|
|
|
@@ -61,12 +54,13 @@
|
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
:focus-visible {
|
|
64
|
-
outline: 2px solid var(--sp-color-primary,
|
|
65
|
-
|
|
57
|
+
outline: var(--sp-focus-ring-width, 2px) solid var(--sp-color-focus-primary,
|
|
58
|
+
var(--sp-color-brand-600, currentColor));
|
|
59
|
+
outline-offset: var(--sp-focus-ring-offset, 2px);
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
::selection {
|
|
69
|
-
background-color: var(--sp-color-
|
|
63
|
+
background-color: var(--sp-color-brand-100, #ebe2ff);
|
|
70
64
|
color: inherit;
|
|
71
65
|
}
|
|
72
66
|
}
|
package/dist/components.css
CHANGED
|
@@ -54,21 +54,36 @@
|
|
|
54
54
|
--sp-component-card-ghost-border: var(--sp-component-card-ghost-bg);
|
|
55
55
|
|
|
56
56
|
/* input roles */
|
|
57
|
-
--sp-component-input-border: var(--sp-
|
|
58
|
-
|
|
59
|
-
--sp-component-input-
|
|
60
|
-
|
|
61
|
-
--sp-component-input-
|
|
62
|
-
|
|
63
|
-
--sp-component-input-
|
|
64
|
-
|
|
65
|
-
--sp-component-input-
|
|
66
|
-
|
|
67
|
-
--sp-component-input-
|
|
68
|
-
|
|
69
|
-
--sp-component-input-
|
|
70
|
-
|
|
71
|
-
--sp-component-input-
|
|
57
|
+
--sp-component-input-role-border: var(--sp-component-input-border,
|
|
58
|
+
var(--sp-surface-input, var(--sp-color-neutral-200, #e2e8f0)));
|
|
59
|
+
--sp-component-input-role-bg: var(--sp-component-input-bg,
|
|
60
|
+
var(--sp-surface-input, var(--sp-color-neutral-50, #f8fafc)));
|
|
61
|
+
--sp-component-input-role-text: var(--sp-component-input-text,
|
|
62
|
+
var(--sp-text-on-surface-default, var(--sp-color-neutral-900, #0f172a)));
|
|
63
|
+
--sp-component-input-role-placeholder: var(--sp-component-input-placeholder,
|
|
64
|
+
var(--sp-text-on-surface-muted, var(--sp-color-neutral-500, #64748b)));
|
|
65
|
+
--sp-component-input-role-border-focus: var(--sp-component-input-border-focus,
|
|
66
|
+
var(--sp-color-brand-500, #8652ff));
|
|
67
|
+
--sp-component-input-role-ring: var(--sp-component-input-ring,
|
|
68
|
+
var(--sp-color-brand-500, #8652ff));
|
|
69
|
+
--sp-component-input-role-border-error: var(--sp-component-input-border-error,
|
|
70
|
+
var(--sp-color-error-500, #ef4444));
|
|
71
|
+
--sp-component-input-role-bg-error: var(--sp-component-input-bg-error,
|
|
72
|
+
var(--sp-color-error-50, #fef2f2));
|
|
73
|
+
--sp-component-input-role-text-error: var(--sp-component-input-text-error,
|
|
74
|
+
var(--sp-color-error-700, #b91c1c));
|
|
75
|
+
--sp-component-input-role-border-success: var(--sp-component-input-border-success,
|
|
76
|
+
var(--sp-color-success-500, #22c55e));
|
|
77
|
+
--sp-component-input-role-bg-success: var(--sp-component-input-bg-success,
|
|
78
|
+
var(--sp-color-success-50, #f0fdf4));
|
|
79
|
+
--sp-component-input-role-text-success: var(--sp-component-input-text-success,
|
|
80
|
+
var(--sp-color-success-700, #15803d));
|
|
81
|
+
--sp-component-input-role-bg-disabled: var(--sp-component-input-bg-disabled,
|
|
82
|
+
var(--sp-surface-input, var(--sp-color-neutral-50, #f8fafc)));
|
|
83
|
+
--sp-component-input-role-text-disabled: var(--sp-component-input-text-disabled,
|
|
84
|
+
var(--sp-text-on-surface-muted, var(--sp-color-neutral-400, #94a3b8)));
|
|
85
|
+
--sp-component-input-role-border-disabled: var(--sp-component-input-border-disabled,
|
|
86
|
+
var(--sp-surface-input, var(--sp-color-neutral-200, #e2e8f0)));
|
|
72
87
|
}
|
|
73
88
|
|
|
74
89
|
/* BUTTONS -------------------------------------------------------------- */
|
|
@@ -79,10 +94,8 @@
|
|
|
79
94
|
gap: var(--sp-space-2xs, 0.25rem);
|
|
80
95
|
padding: var(--sp-space-2xs, 0.25rem) var(--sp-space-md, 1rem);
|
|
81
96
|
border-radius: var(--sp-radius-md, 4px);
|
|
82
|
-
border: 1px solid var(
|
|
83
|
-
|
|
84
|
-
var(--sp-component-button-ghost-bg, var(--sp-button-ghost-bg))
|
|
85
|
-
);
|
|
97
|
+
border: 1px solid var(--sp-component-button-border-base,
|
|
98
|
+
var(--sp-component-button-ghost-bg, var(--sp-button-ghost-bg)));
|
|
86
99
|
font-family: var(--sp-font-family-sans, system-ui);
|
|
87
100
|
font-size: var(--sp-font-md-size, 1rem);
|
|
88
101
|
line-height: 1;
|
|
@@ -143,10 +156,8 @@
|
|
|
143
156
|
.sp-btn--primary {
|
|
144
157
|
background-color: var(--sp-component-button-primary-bg);
|
|
145
158
|
color: var(--sp-component-button-primary-text);
|
|
146
|
-
box-shadow: var(
|
|
147
|
-
|
|
148
|
-
var(--sp-shadow-sm)
|
|
149
|
-
);
|
|
159
|
+
box-shadow: var(--sp-component-button-shadow,
|
|
160
|
+
var(--sp-shadow-sm));
|
|
150
161
|
}
|
|
151
162
|
|
|
152
163
|
.sp-btn--primary.sp-btn--hover,
|
|
@@ -265,7 +276,7 @@
|
|
|
265
276
|
}
|
|
266
277
|
|
|
267
278
|
.sp-label {
|
|
268
|
-
color: var(--sp-component-input-
|
|
279
|
+
color: var(--sp-component-input-role-text);
|
|
269
280
|
font-size: var(--sp-font-sm-size, 0.875rem);
|
|
270
281
|
font-weight: var(--sp-font-sm-weight, 500);
|
|
271
282
|
line-height: var(--sp-font-sm-line-height, 1.25rem);
|
|
@@ -278,7 +289,7 @@
|
|
|
278
289
|
}
|
|
279
290
|
|
|
280
291
|
.sp-error-message {
|
|
281
|
-
color: var(--sp-color-
|
|
292
|
+
color: var(--sp-color-error-600, #dc2626);
|
|
282
293
|
font-size: var(--sp-font-xs-size, 0.75rem);
|
|
283
294
|
line-height: var(--sp-font-xs-line-height, 1rem);
|
|
284
295
|
}
|
|
@@ -289,9 +300,9 @@
|
|
|
289
300
|
appearance: none;
|
|
290
301
|
padding: var(--sp-space-2xs, 0.25rem) var(--sp-space-md, 1rem);
|
|
291
302
|
border-radius: var(--sp-radius-md, 4px);
|
|
292
|
-
border: 1px solid var(--sp-component-input-
|
|
293
|
-
background-color: var(--sp-component-input-
|
|
294
|
-
color: var(--sp-component-input-
|
|
303
|
+
border: 1px solid var(--sp-component-input-role-border);
|
|
304
|
+
background-color: var(--sp-component-input-role-bg);
|
|
305
|
+
color: var(--sp-component-input-role-text);
|
|
295
306
|
font-family: var(--sp-font-family-sans, system-ui);
|
|
296
307
|
font-size: var(--sp-font-md-size, 1rem);
|
|
297
308
|
line-height: var(--sp-font-md-line-height, 1.5rem);
|
|
@@ -302,7 +313,7 @@
|
|
|
302
313
|
}
|
|
303
314
|
|
|
304
315
|
.sp-input::placeholder {
|
|
305
|
-
color: var(--sp-component-input-
|
|
316
|
+
color: var(--sp-component-input-role-placeholder);
|
|
306
317
|
}
|
|
307
318
|
|
|
308
319
|
.sp-input--sm {
|
|
@@ -329,33 +340,27 @@
|
|
|
329
340
|
|
|
330
341
|
.sp-input:focus,
|
|
331
342
|
.sp-input--focus {
|
|
332
|
-
border-color: var(
|
|
333
|
-
|
|
334
|
-
var(--sp-component-input-border, var(--sp-form-focus-border))
|
|
335
|
-
);
|
|
336
|
-
box-shadow: 0 0 0 var(--sp-focus-ring-width, 2px) var(
|
|
337
|
-
--sp-component-input-ring,
|
|
338
|
-
var(--sp-form-focus-ring, var(--sp-color-focus-primary))
|
|
339
|
-
);
|
|
343
|
+
border-color: var(--sp-component-input-role-border-focus);
|
|
344
|
+
box-shadow: 0 0 0 var(--sp-focus-ring-width, 2px) var(--sp-component-input-role-ring);
|
|
340
345
|
outline: none;
|
|
341
346
|
}
|
|
342
347
|
|
|
343
348
|
.sp-input--error {
|
|
344
|
-
border-color: var(--sp-component-input-border-
|
|
345
|
-
background-color: var(--sp-component-input-bg-
|
|
346
|
-
color: var(--sp-component-input-text-
|
|
349
|
+
border-color: var(--sp-component-input-role-border-error);
|
|
350
|
+
background-color: var(--sp-component-input-role-bg-error);
|
|
351
|
+
color: var(--sp-component-input-role-text-error);
|
|
347
352
|
}
|
|
348
353
|
|
|
349
354
|
.sp-input--success {
|
|
350
|
-
border-color: var(--sp-component-input-border-
|
|
351
|
-
background-color: var(--sp-component-input-bg-
|
|
352
|
-
color: var(--sp-component-input-text-
|
|
355
|
+
border-color: var(--sp-component-input-role-border-success);
|
|
356
|
+
background-color: var(--sp-component-input-role-bg-success);
|
|
357
|
+
color: var(--sp-component-input-role-text-success);
|
|
353
358
|
}
|
|
354
359
|
|
|
355
360
|
.sp-input--disabled {
|
|
356
|
-
background-color: var(--sp-component-input-bg-disabled
|
|
357
|
-
color: var(--sp-component-input-text-disabled
|
|
358
|
-
border-color: var(--sp-component-input-border-disabled
|
|
361
|
+
background-color: var(--sp-component-input-role-bg-disabled);
|
|
362
|
+
color: var(--sp-component-input-role-text-disabled);
|
|
363
|
+
border-color: var(--sp-component-input-role-border-disabled);
|
|
359
364
|
cursor: not-allowed;
|
|
360
365
|
}
|
|
361
366
|
|
|
@@ -372,10 +377,8 @@
|
|
|
372
377
|
border-radius: var(--sp-radius-lg, 8px);
|
|
373
378
|
padding: var(--sp-space-lg, 1.5rem);
|
|
374
379
|
box-shadow: var(--sp-component-card-shadow, var(--sp-shadow-sm));
|
|
375
|
-
border: 1px solid var(
|
|
376
|
-
|
|
377
|
-
var(--sp-component-card-ghost-border, var(--sp-component-card-bg))
|
|
378
|
-
);
|
|
380
|
+
border: 1px solid var(--sp-component-card-border-base,
|
|
381
|
+
var(--sp-component-card-ghost-border, var(--sp-component-card-bg)));
|
|
379
382
|
}
|
|
380
383
|
|
|
381
384
|
.sp-card p,
|
package/dist/index.cjs
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
var spectreTokens = require('@phcdevworks/spectre-tokens');
|
|
4
4
|
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var spectreTokens__default = /*#__PURE__*/_interopDefault(spectreTokens);
|
|
8
|
+
|
|
5
9
|
// src/css-constants.ts
|
|
6
|
-
var spectreBaseStylesPath = "@phcdevworks/spectre-ui/
|
|
7
|
-
var spectreComponentsStylesPath = "@phcdevworks/spectre-ui/
|
|
8
|
-
var spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/
|
|
10
|
+
var spectreBaseStylesPath = "@phcdevworks/spectre-ui/base.css";
|
|
11
|
+
var spectreComponentsStylesPath = "@phcdevworks/spectre-ui/components.css";
|
|
12
|
+
var spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/utilities.css";
|
|
13
|
+
var spectreIndexStylesPath = "@phcdevworks/spectre-ui/index.css";
|
|
9
14
|
var spectreStyles = {
|
|
15
|
+
index: spectreIndexStylesPath,
|
|
10
16
|
base: spectreBaseStylesPath,
|
|
11
17
|
components: spectreComponentsStylesPath,
|
|
12
18
|
utilities: spectreUtilitiesStylesPath
|
|
@@ -14,43 +20,34 @@ var spectreStyles = {
|
|
|
14
20
|
|
|
15
21
|
// src/tailwind/theme.ts
|
|
16
22
|
function createSpectreTailwindTheme(options) {
|
|
17
|
-
const { tokens, overrides } = options;
|
|
18
23
|
const mergedTokens = {
|
|
19
|
-
...tokens,
|
|
20
|
-
...overrides
|
|
21
|
-
};
|
|
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
|
|
24
|
+
...options.tokens ?? {},
|
|
25
|
+
...options.overrides ?? {}
|
|
33
26
|
};
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
27
|
+
const t = mergedTokens;
|
|
28
|
+
const colors = t.colors ?? t.color ?? t.palette ?? {};
|
|
29
|
+
const spacing = t.spacing ?? t.space ?? {};
|
|
30
|
+
const borderRadius = t.radii ?? t.radius ?? {};
|
|
31
|
+
const boxShadow = t.shadows ?? t.shadow ?? {};
|
|
32
|
+
const fontFamily = t.typography?.families ?? t.fonts ?? {};
|
|
33
|
+
const fontSize = t.typography?.scale ?? t.fontSize ?? {};
|
|
38
34
|
const theme2 = {
|
|
39
35
|
colors,
|
|
40
36
|
spacing,
|
|
41
37
|
borderRadius,
|
|
42
38
|
boxShadow,
|
|
43
|
-
fontFamily
|
|
39
|
+
fontFamily,
|
|
40
|
+
fontSize
|
|
44
41
|
};
|
|
45
42
|
return { theme: theme2 };
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
// src/tailwind/preset.ts
|
|
49
|
-
var { theme } = createSpectreTailwindTheme({ tokens:
|
|
46
|
+
var { theme } = createSpectreTailwindTheme({ tokens: spectreTokens__default.default });
|
|
50
47
|
var spectrePreset = {
|
|
51
48
|
content: [],
|
|
52
|
-
theme
|
|
53
|
-
//
|
|
49
|
+
theme
|
|
50
|
+
// theme is guaranteed non-undefined now
|
|
54
51
|
};
|
|
55
52
|
|
|
56
53
|
// src/recipes/button.ts
|
|
@@ -58,19 +55,18 @@ function getButtonClasses(opts = {}) {
|
|
|
58
55
|
const {
|
|
59
56
|
variant = "primary",
|
|
60
57
|
size = "md",
|
|
61
|
-
tone = "default",
|
|
62
58
|
fullWidth = false,
|
|
63
59
|
loading = false,
|
|
64
60
|
disabled = false,
|
|
65
61
|
iconOnly = false
|
|
66
62
|
} = opts;
|
|
67
|
-
const classes = [];
|
|
68
|
-
classes.push("sp-btn");
|
|
63
|
+
const classes = ["sp-btn"];
|
|
69
64
|
const variantMap = {
|
|
70
65
|
primary: "sp-btn--primary",
|
|
71
66
|
secondary: "sp-btn--secondary",
|
|
72
67
|
ghost: "sp-btn--ghost",
|
|
73
|
-
danger: "sp-btn--danger"
|
|
68
|
+
danger: "sp-btn--danger",
|
|
69
|
+
success: "sp-btn--success"
|
|
74
70
|
};
|
|
75
71
|
classes.push(variantMap[variant]);
|
|
76
72
|
const sizeMap = {
|
|
@@ -79,19 +75,11 @@ function getButtonClasses(opts = {}) {
|
|
|
79
75
|
lg: "sp-btn--lg"
|
|
80
76
|
};
|
|
81
77
|
classes.push(sizeMap[size]);
|
|
82
|
-
if (tone !== "default") {
|
|
83
|
-
const toneMap = {
|
|
84
|
-
success: "sp-btn--tone-success",
|
|
85
|
-
warning: "sp-btn--tone-warning",
|
|
86
|
-
danger: "sp-btn--tone-danger"
|
|
87
|
-
};
|
|
88
|
-
classes.push(toneMap[tone]);
|
|
89
|
-
}
|
|
90
78
|
if (fullWidth) classes.push("sp-btn--full");
|
|
91
79
|
if (loading) classes.push("sp-btn--loading");
|
|
92
80
|
if (disabled) classes.push("sp-btn--disabled");
|
|
93
81
|
if (iconOnly) classes.push("sp-btn--icon");
|
|
94
|
-
return classes.
|
|
82
|
+
return classes.join(" ").trim();
|
|
95
83
|
}
|
|
96
84
|
|
|
97
85
|
// src/recipes/card.ts
|
|
@@ -102,10 +90,10 @@ function getCardClasses(opts = {}) {
|
|
|
102
90
|
padded = false,
|
|
103
91
|
fullHeight = false
|
|
104
92
|
} = opts;
|
|
105
|
-
const classes = [];
|
|
106
|
-
classes.push("sp-card");
|
|
93
|
+
const classes = ["sp-card"];
|
|
107
94
|
const variantMap = {
|
|
108
95
|
elevated: "sp-card--elevated",
|
|
96
|
+
flat: "sp-card--flat",
|
|
109
97
|
outline: "sp-card--outline",
|
|
110
98
|
ghost: "sp-card--ghost"
|
|
111
99
|
};
|
|
@@ -113,38 +101,29 @@ function getCardClasses(opts = {}) {
|
|
|
113
101
|
if (interactive) classes.push("sp-card--interactive");
|
|
114
102
|
if (padded) classes.push("sp-card--padded");
|
|
115
103
|
if (fullHeight) classes.push("sp-card--full");
|
|
116
|
-
return classes.
|
|
104
|
+
return classes.join(" ").trim();
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
// src/recipes/input.ts
|
|
120
108
|
function getInputClasses(opts = {}) {
|
|
121
|
-
const {
|
|
122
|
-
|
|
123
|
-
size = "md",
|
|
124
|
-
fullWidth = false
|
|
125
|
-
} = opts;
|
|
126
|
-
const classes = [];
|
|
127
|
-
classes.push("sp-input");
|
|
128
|
-
if (state === "error") {
|
|
129
|
-
classes.push("sp-input--error");
|
|
130
|
-
} else if (state === "success") {
|
|
131
|
-
classes.push("sp-input--success");
|
|
132
|
-
}
|
|
109
|
+
const { state = "default", size = "md", fullWidth = false } = opts;
|
|
110
|
+
const classes = ["sp-input"];
|
|
133
111
|
const sizeMap = {
|
|
134
112
|
sm: "sp-input--sm",
|
|
135
113
|
md: "sp-input--md",
|
|
136
114
|
lg: "sp-input--lg"
|
|
137
115
|
};
|
|
138
116
|
classes.push(sizeMap[size]);
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
117
|
+
if (state === "error") classes.push("sp-input--error");
|
|
118
|
+
if (state === "success") classes.push("sp-input--success");
|
|
119
|
+
if (state === "disabled") classes.push("sp-input--disabled");
|
|
120
|
+
if (fullWidth) classes.push("sp-input--full");
|
|
121
|
+
return classes.join(" ").trim();
|
|
143
122
|
}
|
|
144
123
|
|
|
145
124
|
Object.defineProperty(exports, "spectreTokens", {
|
|
146
125
|
enumerable: true,
|
|
147
|
-
get: function () { return
|
|
126
|
+
get: function () { return spectreTokens__default.default; }
|
|
148
127
|
});
|
|
149
128
|
exports.createSpectreTailwindTheme = createSpectreTailwindTheme;
|
|
150
129
|
exports.getButtonClasses = getButtonClasses;
|
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"],"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"]}
|
|
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/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/utilities.css\";\nexport const spectreIndexStylesPath = \"@phcdevworks/spectre-ui/index.css\";\n\nexport const spectreStyles = {\n index: spectreIndexStylesPath,\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport type { SpectreTokens } from \"../tokens\";\n\ntype TailwindTheme = NonNullable<TailwindConfig[\"theme\"]>;\n\nexport interface SpectreTailwindTheme {\n theme: TailwindTheme;\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\n/**\n * Minimal, type-safe theme mapper.\n * Important: theme is NEVER undefined (fixes exactOptionalPropertyTypes + DTS).\n */\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions\n): SpectreTailwindTheme {\n const mergedTokens = {\n ...(options.tokens ?? ({} as SpectreTokens)),\n ...(options.overrides ?? {}),\n } as SpectreTokens;\n\n // We keep mapping shallow + permissive because token shapes will evolve.\n // Tailwind accepts nested objects of strings for colors.\n const t: any = mergedTokens;\n\n const colors = (t.colors ?? t.color ?? t.palette ?? {}) as Record<string, any>;\n const spacing = (t.spacing ?? t.space ?? {}) as Record<string, any>;\n const borderRadius = (t.radii ?? t.radius ?? {}) as Record<string, any>;\n const boxShadow = (t.shadows ?? t.shadow ?? {}) as Record<string, any>;\n const fontFamily = (t.typography?.families ?? t.fonts ?? {}) as Record<string, any>;\n const fontSize = (t.typography?.scale ?? t.fontSize ?? {}) as Record<string, any>;\n\n const theme: TailwindTheme = {\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 fontSize: fontSize 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 is guaranteed non-undefined now\n};\n\nexport const spectreTailwindPreset: TailwindConfig = spectrePreset;\n","export type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\" | \"success\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [\"sp-btn\"];\n\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 success: \"sp-btn--success\",\n };\n classes.push(variantMap[variant]);\n\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 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 return classes.join(\" \").trim();\n}\n","export type CardVariant = \"elevated\" | \"flat\" | \"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\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[] = [\"sp-card\"];\n\n const variantMap: Record<CardVariant, string> = {\n elevated: \"sp-card--elevated\",\n flat: \"sp-card--flat\",\n outline: \"sp-card--outline\",\n ghost: \"sp-card--ghost\",\n };\n classes.push(variantMap[variant]);\n\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.join(\" \").trim();\n}\n","export type InputState = \"default\" | \"error\" | \"success\" | \"disabled\";\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const { state = \"default\", size = \"md\", fullWidth = false } = opts;\n\n const classes: string[] = [\"sp-input\"];\n\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 // State\n if (state === \"error\") classes.push(\"sp-input--error\");\n if (state === \"success\") classes.push(\"sp-input--success\");\n if (state === \"disabled\") classes.push(\"sp-input--disabled\");\n\n if (fullWidth) classes.push(\"sp-input--full\");\n\n return classes.join(\" \").trim();\n}\n"]}
|
package/dist/index.css
ADDED
package/dist/index.d.cts
CHANGED
|
@@ -1,103 +1,61 @@
|
|
|
1
1
|
import { Config } from 'tailwindcss';
|
|
2
2
|
import { SpectreTokens } from '@phcdevworks/spectre-tokens';
|
|
3
|
-
export { SpectreTokens,
|
|
3
|
+
export { SpectreTokens, default as spectreTokens } from '@phcdevworks/spectre-tokens';
|
|
4
4
|
|
|
5
|
-
declare const spectreBaseStylesPath = "@phcdevworks/spectre-ui/
|
|
6
|
-
declare const spectreComponentsStylesPath = "@phcdevworks/spectre-ui/
|
|
7
|
-
declare const spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/
|
|
5
|
+
declare const spectreBaseStylesPath = "@phcdevworks/spectre-ui/base.css";
|
|
6
|
+
declare const spectreComponentsStylesPath = "@phcdevworks/spectre-ui/components.css";
|
|
7
|
+
declare const spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/utilities.css";
|
|
8
8
|
declare const spectreStyles: {
|
|
9
|
+
index: string;
|
|
9
10
|
base: string;
|
|
10
11
|
components: string;
|
|
11
12
|
utilities: string;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
type TailwindTheme = NonNullable<Config["theme"]>;
|
|
16
16
|
interface SpectreTailwindTheme {
|
|
17
|
-
theme:
|
|
17
|
+
theme: TailwindTheme;
|
|
18
18
|
}
|
|
19
19
|
interface CreateSpectreTailwindThemeOptions {
|
|
20
20
|
tokens: SpectreTokens;
|
|
21
21
|
overrides?: Partial<SpectreTokens>;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Minimal, type-safe theme mapper.
|
|
25
|
+
* Important: theme is NEVER undefined (fixes exactOptionalPropertyTypes + DTS).
|
|
26
|
+
*/
|
|
23
27
|
declare function createSpectreTailwindTheme(options: CreateSpectreTailwindThemeOptions): SpectreTailwindTheme;
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type
|
|
29
|
+
declare const spectrePreset: Config;
|
|
30
|
+
|
|
31
|
+
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success";
|
|
32
|
+
type ButtonSize = "sm" | "md" | "lg";
|
|
28
33
|
interface ButtonRecipeOptions {
|
|
29
34
|
variant?: ButtonVariant;
|
|
30
35
|
size?: ButtonSize;
|
|
31
|
-
tone?: ButtonTone;
|
|
32
36
|
fullWidth?: boolean;
|
|
33
37
|
loading?: boolean;
|
|
34
38
|
disabled?: boolean;
|
|
35
39
|
iconOnly?: boolean;
|
|
36
40
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Generate Spectre button classes.
|
|
39
|
-
*
|
|
40
|
-
* Rules:
|
|
41
|
-
* - Base: "sp-btn"
|
|
42
|
-
* - Variant: "sp-btn--primary" / "sp-btn--secondary" / "sp-btn--ghost" / "sp-btn--danger"
|
|
43
|
-
* - default variant is "primary"
|
|
44
|
-
* - Size: "sp-btn--sm" / "sp-btn--md" / "sp-btn--lg"
|
|
45
|
-
* - default size is "md"
|
|
46
|
-
* - Tone: "sp-btn--tone-success" / "sp-btn--tone-warning" / "sp-btn--tone-danger"
|
|
47
|
-
* - default tone is "default" (no tone class)
|
|
48
|
-
* - fullWidth: add "sp-btn--full"
|
|
49
|
-
* - loading: add "sp-btn--loading"
|
|
50
|
-
* - disabled: add "sp-btn--disabled"
|
|
51
|
-
* - iconOnly: add "sp-btn--icon"
|
|
52
|
-
*
|
|
53
|
-
* Must return a single space-joined, trimmed class string.
|
|
54
|
-
*/
|
|
55
41
|
declare function getButtonClasses(opts?: ButtonRecipeOptions): string;
|
|
56
42
|
|
|
57
|
-
type CardVariant =
|
|
43
|
+
type CardVariant = "elevated" | "flat" | "outline" | "ghost";
|
|
58
44
|
interface CardRecipeOptions {
|
|
59
45
|
variant?: CardVariant;
|
|
60
46
|
interactive?: boolean;
|
|
61
47
|
padded?: boolean;
|
|
62
48
|
fullHeight?: boolean;
|
|
63
49
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Generate Spectre card classes.
|
|
66
|
-
*
|
|
67
|
-
* Rules:
|
|
68
|
-
* - Base class: "sp-card"
|
|
69
|
-
* - Variant (default: elevated):
|
|
70
|
-
* - "sp-card--elevated"
|
|
71
|
-
* - "sp-card--outline"
|
|
72
|
-
* - "sp-card--ghost"
|
|
73
|
-
* - interactive: add "sp-card--interactive"
|
|
74
|
-
* - padded: add "sp-card--padded"
|
|
75
|
-
* - fullHeight: add "sp-card--full"
|
|
76
|
-
*/
|
|
77
50
|
declare function getCardClasses(opts?: CardRecipeOptions): string;
|
|
78
51
|
|
|
79
|
-
type InputState =
|
|
80
|
-
type InputSize =
|
|
52
|
+
type InputState = "default" | "error" | "success" | "disabled";
|
|
53
|
+
type InputSize = "sm" | "md" | "lg";
|
|
81
54
|
interface InputRecipeOptions {
|
|
82
55
|
state?: InputState;
|
|
83
56
|
size?: InputSize;
|
|
84
57
|
fullWidth?: boolean;
|
|
85
58
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Generate Spectre input classes.
|
|
88
|
-
*
|
|
89
|
-
* Rules:
|
|
90
|
-
* - Base class: "sp-input"
|
|
91
|
-
* - State:
|
|
92
|
-
* - "default" => no state modifier
|
|
93
|
-
* - "error" => "sp-input--error"
|
|
94
|
-
* - "success" => "sp-input--success"
|
|
95
|
-
* - Size (default: md):
|
|
96
|
-
* - "sp-input--sm"
|
|
97
|
-
* - "sp-input--md"
|
|
98
|
-
* - "sp-input--lg"
|
|
99
|
-
* - fullWidth: add "sp-input--full"
|
|
100
|
-
*/
|
|
101
59
|
declare function getInputClasses(opts?: InputRecipeOptions): string;
|
|
102
60
|
|
|
103
|
-
export { type ButtonRecipeOptions, type ButtonSize, type
|
|
61
|
+
export { type ButtonRecipeOptions, type ButtonSize, type ButtonVariant, type CardRecipeOptions, type CardVariant, type CreateSpectreTailwindThemeOptions, type InputRecipeOptions, type InputSize, type InputState, type SpectreTailwindTheme, createSpectreTailwindTheme, getButtonClasses, getCardClasses, getInputClasses, spectreBaseStylesPath, spectreComponentsStylesPath, spectrePreset, spectreStyles, spectreUtilitiesStylesPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,103 +1,61 @@
|
|
|
1
1
|
import { Config } from 'tailwindcss';
|
|
2
2
|
import { SpectreTokens } from '@phcdevworks/spectre-tokens';
|
|
3
|
-
export { SpectreTokens,
|
|
3
|
+
export { SpectreTokens, default as spectreTokens } from '@phcdevworks/spectre-tokens';
|
|
4
4
|
|
|
5
|
-
declare const spectreBaseStylesPath = "@phcdevworks/spectre-ui/
|
|
6
|
-
declare const spectreComponentsStylesPath = "@phcdevworks/spectre-ui/
|
|
7
|
-
declare const spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/
|
|
5
|
+
declare const spectreBaseStylesPath = "@phcdevworks/spectre-ui/base.css";
|
|
6
|
+
declare const spectreComponentsStylesPath = "@phcdevworks/spectre-ui/components.css";
|
|
7
|
+
declare const spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/utilities.css";
|
|
8
8
|
declare const spectreStyles: {
|
|
9
|
+
index: string;
|
|
9
10
|
base: string;
|
|
10
11
|
components: string;
|
|
11
12
|
utilities: string;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
type TailwindTheme = NonNullable<Config["theme"]>;
|
|
16
16
|
interface SpectreTailwindTheme {
|
|
17
|
-
theme:
|
|
17
|
+
theme: TailwindTheme;
|
|
18
18
|
}
|
|
19
19
|
interface CreateSpectreTailwindThemeOptions {
|
|
20
20
|
tokens: SpectreTokens;
|
|
21
21
|
overrides?: Partial<SpectreTokens>;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Minimal, type-safe theme mapper.
|
|
25
|
+
* Important: theme is NEVER undefined (fixes exactOptionalPropertyTypes + DTS).
|
|
26
|
+
*/
|
|
23
27
|
declare function createSpectreTailwindTheme(options: CreateSpectreTailwindThemeOptions): SpectreTailwindTheme;
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type
|
|
29
|
+
declare const spectrePreset: Config;
|
|
30
|
+
|
|
31
|
+
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success";
|
|
32
|
+
type ButtonSize = "sm" | "md" | "lg";
|
|
28
33
|
interface ButtonRecipeOptions {
|
|
29
34
|
variant?: ButtonVariant;
|
|
30
35
|
size?: ButtonSize;
|
|
31
|
-
tone?: ButtonTone;
|
|
32
36
|
fullWidth?: boolean;
|
|
33
37
|
loading?: boolean;
|
|
34
38
|
disabled?: boolean;
|
|
35
39
|
iconOnly?: boolean;
|
|
36
40
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Generate Spectre button classes.
|
|
39
|
-
*
|
|
40
|
-
* Rules:
|
|
41
|
-
* - Base: "sp-btn"
|
|
42
|
-
* - Variant: "sp-btn--primary" / "sp-btn--secondary" / "sp-btn--ghost" / "sp-btn--danger"
|
|
43
|
-
* - default variant is "primary"
|
|
44
|
-
* - Size: "sp-btn--sm" / "sp-btn--md" / "sp-btn--lg"
|
|
45
|
-
* - default size is "md"
|
|
46
|
-
* - Tone: "sp-btn--tone-success" / "sp-btn--tone-warning" / "sp-btn--tone-danger"
|
|
47
|
-
* - default tone is "default" (no tone class)
|
|
48
|
-
* - fullWidth: add "sp-btn--full"
|
|
49
|
-
* - loading: add "sp-btn--loading"
|
|
50
|
-
* - disabled: add "sp-btn--disabled"
|
|
51
|
-
* - iconOnly: add "sp-btn--icon"
|
|
52
|
-
*
|
|
53
|
-
* Must return a single space-joined, trimmed class string.
|
|
54
|
-
*/
|
|
55
41
|
declare function getButtonClasses(opts?: ButtonRecipeOptions): string;
|
|
56
42
|
|
|
57
|
-
type CardVariant =
|
|
43
|
+
type CardVariant = "elevated" | "flat" | "outline" | "ghost";
|
|
58
44
|
interface CardRecipeOptions {
|
|
59
45
|
variant?: CardVariant;
|
|
60
46
|
interactive?: boolean;
|
|
61
47
|
padded?: boolean;
|
|
62
48
|
fullHeight?: boolean;
|
|
63
49
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Generate Spectre card classes.
|
|
66
|
-
*
|
|
67
|
-
* Rules:
|
|
68
|
-
* - Base class: "sp-card"
|
|
69
|
-
* - Variant (default: elevated):
|
|
70
|
-
* - "sp-card--elevated"
|
|
71
|
-
* - "sp-card--outline"
|
|
72
|
-
* - "sp-card--ghost"
|
|
73
|
-
* - interactive: add "sp-card--interactive"
|
|
74
|
-
* - padded: add "sp-card--padded"
|
|
75
|
-
* - fullHeight: add "sp-card--full"
|
|
76
|
-
*/
|
|
77
50
|
declare function getCardClasses(opts?: CardRecipeOptions): string;
|
|
78
51
|
|
|
79
|
-
type InputState =
|
|
80
|
-
type InputSize =
|
|
52
|
+
type InputState = "default" | "error" | "success" | "disabled";
|
|
53
|
+
type InputSize = "sm" | "md" | "lg";
|
|
81
54
|
interface InputRecipeOptions {
|
|
82
55
|
state?: InputState;
|
|
83
56
|
size?: InputSize;
|
|
84
57
|
fullWidth?: boolean;
|
|
85
58
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Generate Spectre input classes.
|
|
88
|
-
*
|
|
89
|
-
* Rules:
|
|
90
|
-
* - Base class: "sp-input"
|
|
91
|
-
* - State:
|
|
92
|
-
* - "default" => no state modifier
|
|
93
|
-
* - "error" => "sp-input--error"
|
|
94
|
-
* - "success" => "sp-input--success"
|
|
95
|
-
* - Size (default: md):
|
|
96
|
-
* - "sp-input--sm"
|
|
97
|
-
* - "sp-input--md"
|
|
98
|
-
* - "sp-input--lg"
|
|
99
|
-
* - fullWidth: add "sp-input--full"
|
|
100
|
-
*/
|
|
101
59
|
declare function getInputClasses(opts?: InputRecipeOptions): string;
|
|
102
60
|
|
|
103
|
-
export { type ButtonRecipeOptions, type ButtonSize, type
|
|
61
|
+
export { type ButtonRecipeOptions, type ButtonSize, type ButtonVariant, type CardRecipeOptions, type CardVariant, type CreateSpectreTailwindThemeOptions, type InputRecipeOptions, type InputSize, type InputState, type SpectreTailwindTheme, createSpectreTailwindTheme, getButtonClasses, getCardClasses, getInputClasses, spectreBaseStylesPath, spectreComponentsStylesPath, spectrePreset, spectreStyles, spectreUtilitiesStylesPath };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
export {
|
|
1
|
+
import spectreTokens from '@phcdevworks/spectre-tokens';
|
|
2
|
+
export { default as spectreTokens } from '@phcdevworks/spectre-tokens';
|
|
3
3
|
|
|
4
4
|
// src/css-constants.ts
|
|
5
|
-
var spectreBaseStylesPath = "@phcdevworks/spectre-ui/
|
|
6
|
-
var spectreComponentsStylesPath = "@phcdevworks/spectre-ui/
|
|
7
|
-
var spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/
|
|
5
|
+
var spectreBaseStylesPath = "@phcdevworks/spectre-ui/base.css";
|
|
6
|
+
var spectreComponentsStylesPath = "@phcdevworks/spectre-ui/components.css";
|
|
7
|
+
var spectreUtilitiesStylesPath = "@phcdevworks/spectre-ui/utilities.css";
|
|
8
|
+
var spectreIndexStylesPath = "@phcdevworks/spectre-ui/index.css";
|
|
8
9
|
var spectreStyles = {
|
|
10
|
+
index: spectreIndexStylesPath,
|
|
9
11
|
base: spectreBaseStylesPath,
|
|
10
12
|
components: spectreComponentsStylesPath,
|
|
11
13
|
utilities: spectreUtilitiesStylesPath
|
|
@@ -13,43 +15,34 @@ var spectreStyles = {
|
|
|
13
15
|
|
|
14
16
|
// src/tailwind/theme.ts
|
|
15
17
|
function createSpectreTailwindTheme(options) {
|
|
16
|
-
const { tokens, overrides } = options;
|
|
17
18
|
const mergedTokens = {
|
|
18
|
-
...tokens,
|
|
19
|
-
...overrides
|
|
19
|
+
...options.tokens ?? {},
|
|
20
|
+
...options.overrides ?? {}
|
|
20
21
|
};
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
surface: mergedTokens.text?.onSurface?.default,
|
|
29
|
-
"surface-muted": mergedTokens.text?.onSurface?.muted
|
|
30
|
-
},
|
|
31
|
-
primary: mergedTokens.buttons?.primary?.bg ?? mergedTokens.colors?.primary
|
|
32
|
-
};
|
|
33
|
-
const spacing = mergedTokens.spacing ?? {};
|
|
34
|
-
const borderRadius = mergedTokens.radii ?? {};
|
|
35
|
-
const boxShadow = mergedTokens.shadows ?? {};
|
|
36
|
-
const fontFamily = mergedTokens.typography?.families ?? {};
|
|
22
|
+
const t = mergedTokens;
|
|
23
|
+
const colors = t.colors ?? t.color ?? t.palette ?? {};
|
|
24
|
+
const spacing = t.spacing ?? t.space ?? {};
|
|
25
|
+
const borderRadius = t.radii ?? t.radius ?? {};
|
|
26
|
+
const boxShadow = t.shadows ?? t.shadow ?? {};
|
|
27
|
+
const fontFamily = t.typography?.families ?? t.fonts ?? {};
|
|
28
|
+
const fontSize = t.typography?.scale ?? t.fontSize ?? {};
|
|
37
29
|
const theme2 = {
|
|
38
30
|
colors,
|
|
39
31
|
spacing,
|
|
40
32
|
borderRadius,
|
|
41
33
|
boxShadow,
|
|
42
|
-
fontFamily
|
|
34
|
+
fontFamily,
|
|
35
|
+
fontSize
|
|
43
36
|
};
|
|
44
37
|
return { theme: theme2 };
|
|
45
38
|
}
|
|
46
39
|
|
|
47
40
|
// src/tailwind/preset.ts
|
|
48
|
-
var { theme } = createSpectreTailwindTheme({ tokens:
|
|
41
|
+
var { theme } = createSpectreTailwindTheme({ tokens: spectreTokens });
|
|
49
42
|
var spectrePreset = {
|
|
50
43
|
content: [],
|
|
51
|
-
theme
|
|
52
|
-
//
|
|
44
|
+
theme
|
|
45
|
+
// theme is guaranteed non-undefined now
|
|
53
46
|
};
|
|
54
47
|
|
|
55
48
|
// src/recipes/button.ts
|
|
@@ -57,19 +50,18 @@ function getButtonClasses(opts = {}) {
|
|
|
57
50
|
const {
|
|
58
51
|
variant = "primary",
|
|
59
52
|
size = "md",
|
|
60
|
-
tone = "default",
|
|
61
53
|
fullWidth = false,
|
|
62
54
|
loading = false,
|
|
63
55
|
disabled = false,
|
|
64
56
|
iconOnly = false
|
|
65
57
|
} = opts;
|
|
66
|
-
const classes = [];
|
|
67
|
-
classes.push("sp-btn");
|
|
58
|
+
const classes = ["sp-btn"];
|
|
68
59
|
const variantMap = {
|
|
69
60
|
primary: "sp-btn--primary",
|
|
70
61
|
secondary: "sp-btn--secondary",
|
|
71
62
|
ghost: "sp-btn--ghost",
|
|
72
|
-
danger: "sp-btn--danger"
|
|
63
|
+
danger: "sp-btn--danger",
|
|
64
|
+
success: "sp-btn--success"
|
|
73
65
|
};
|
|
74
66
|
classes.push(variantMap[variant]);
|
|
75
67
|
const sizeMap = {
|
|
@@ -78,19 +70,11 @@ function getButtonClasses(opts = {}) {
|
|
|
78
70
|
lg: "sp-btn--lg"
|
|
79
71
|
};
|
|
80
72
|
classes.push(sizeMap[size]);
|
|
81
|
-
if (tone !== "default") {
|
|
82
|
-
const toneMap = {
|
|
83
|
-
success: "sp-btn--tone-success",
|
|
84
|
-
warning: "sp-btn--tone-warning",
|
|
85
|
-
danger: "sp-btn--tone-danger"
|
|
86
|
-
};
|
|
87
|
-
classes.push(toneMap[tone]);
|
|
88
|
-
}
|
|
89
73
|
if (fullWidth) classes.push("sp-btn--full");
|
|
90
74
|
if (loading) classes.push("sp-btn--loading");
|
|
91
75
|
if (disabled) classes.push("sp-btn--disabled");
|
|
92
76
|
if (iconOnly) classes.push("sp-btn--icon");
|
|
93
|
-
return classes.
|
|
77
|
+
return classes.join(" ").trim();
|
|
94
78
|
}
|
|
95
79
|
|
|
96
80
|
// src/recipes/card.ts
|
|
@@ -101,10 +85,10 @@ function getCardClasses(opts = {}) {
|
|
|
101
85
|
padded = false,
|
|
102
86
|
fullHeight = false
|
|
103
87
|
} = opts;
|
|
104
|
-
const classes = [];
|
|
105
|
-
classes.push("sp-card");
|
|
88
|
+
const classes = ["sp-card"];
|
|
106
89
|
const variantMap = {
|
|
107
90
|
elevated: "sp-card--elevated",
|
|
91
|
+
flat: "sp-card--flat",
|
|
108
92
|
outline: "sp-card--outline",
|
|
109
93
|
ghost: "sp-card--ghost"
|
|
110
94
|
};
|
|
@@ -112,33 +96,24 @@ function getCardClasses(opts = {}) {
|
|
|
112
96
|
if (interactive) classes.push("sp-card--interactive");
|
|
113
97
|
if (padded) classes.push("sp-card--padded");
|
|
114
98
|
if (fullHeight) classes.push("sp-card--full");
|
|
115
|
-
return classes.
|
|
99
|
+
return classes.join(" ").trim();
|
|
116
100
|
}
|
|
117
101
|
|
|
118
102
|
// src/recipes/input.ts
|
|
119
103
|
function getInputClasses(opts = {}) {
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
size = "md",
|
|
123
|
-
fullWidth = false
|
|
124
|
-
} = opts;
|
|
125
|
-
const classes = [];
|
|
126
|
-
classes.push("sp-input");
|
|
127
|
-
if (state === "error") {
|
|
128
|
-
classes.push("sp-input--error");
|
|
129
|
-
} else if (state === "success") {
|
|
130
|
-
classes.push("sp-input--success");
|
|
131
|
-
}
|
|
104
|
+
const { state = "default", size = "md", fullWidth = false } = opts;
|
|
105
|
+
const classes = ["sp-input"];
|
|
132
106
|
const sizeMap = {
|
|
133
107
|
sm: "sp-input--sm",
|
|
134
108
|
md: "sp-input--md",
|
|
135
109
|
lg: "sp-input--lg"
|
|
136
110
|
};
|
|
137
111
|
classes.push(sizeMap[size]);
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
112
|
+
if (state === "error") classes.push("sp-input--error");
|
|
113
|
+
if (state === "success") classes.push("sp-input--success");
|
|
114
|
+
if (state === "disabled") classes.push("sp-input--disabled");
|
|
115
|
+
if (fullWidth) classes.push("sp-input--full");
|
|
116
|
+
return classes.join(" ").trim();
|
|
142
117
|
}
|
|
143
118
|
|
|
144
119
|
export { createSpectreTailwindTheme, getButtonClasses, getCardClasses, getInputClasses, spectreBaseStylesPath, spectreComponentsStylesPath, spectrePreset, spectreStyles, spectreUtilitiesStylesPath };
|
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"],"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"]}
|
|
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"],"mappings":";;;;AAAO,IAAM,qBAAA,GAAwB;AAC9B,IAAM,2BAAA,GAA8B;AACpC,IAAM,0BAAA,GAA6B;AACnC,IAAM,sBAAA,GAAyB,mCAAA;AAE/B,IAAM,aAAA,GAAgB;AAAA,EAC3B,KAAA,EAAO,sBAAA;AAAA,EACP,IAAA,EAAM,qBAAA;AAAA,EACN,UAAA,EAAY,2BAAA;AAAA,EACZ,SAAA,EAAW;AACb;;;ACQO,SAAS,2BACd,OAAA,EACsB;AACtB,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,GAAI,OAAA,CAAQ,MAAA,IAAW,EAAC;AAAA,IACxB,GAAI,OAAA,CAAQ,SAAA,IAAa;AAAC,GAC5B;AAIA,EAAA,MAAM,CAAA,GAAS,YAAA;AAEf,EAAA,MAAM,SAAU,CAAA,CAAE,MAAA,IAAU,EAAE,KAAA,IAAS,CAAA,CAAE,WAAW,EAAC;AACrD,EAAA,MAAM,OAAA,GAAW,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,SAAS,EAAC;AAC1C,EAAA,MAAM,YAAA,GAAgB,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,UAAU,EAAC;AAC9C,EAAA,MAAM,SAAA,GAAa,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,UAAU,EAAC;AAC7C,EAAA,MAAM,aAAc,CAAA,CAAE,UAAA,EAAY,QAAA,IAAY,CAAA,CAAE,SAAS,EAAC;AAC1D,EAAA,MAAM,WAAY,CAAA,CAAE,UAAA,EAAY,KAAA,IAAS,CAAA,CAAE,YAAY,EAAC;AAExD,EAAA,MAAMA,MAAAA,GAAuB;AAAA,IAC3B,MAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,OAAAA,MAAAA,EAAM;AACjB;;;AC3CA,IAAM,EAAE,KAAA,EAAM,GAAI,2BAA2B,EAAE,MAAA,EAAQ,eAAe,CAAA;AAE/D,IAAM,aAAA,GAAgC;AAAA,EAC3C,SAAS,EAAC;AAAA,EACV;AAAA;AACF;;;ACGO,SAAS,gBAAA,CAAiB,IAAA,GAA4B,EAAC,EAAW;AACvE,EAAA,MAAM;AAAA,IACJ,OAAA,GAAU,SAAA;AAAA,IACV,IAAA,GAAO,IAAA;AAAA,IACP,SAAA,GAAY,KAAA;AAAA,IACZ,OAAA,GAAU,KAAA;AAAA,IACV,QAAA,GAAW,KAAA;AAAA,IACX,QAAA,GAAW;AAAA,GACb,GAAI,IAAA;AAEJ,EAAA,MAAM,OAAA,GAAoB,CAAC,QAAQ,CAAA;AAEnC,EAAA,MAAM,UAAA,GAA4C;AAAA,IAChD,OAAA,EAAS,iBAAA;AAAA,IACT,SAAA,EAAW,mBAAA;AAAA,IACX,KAAA,EAAO,eAAA;AAAA,IACP,MAAA,EAAQ,gBAAA;AAAA,IACR,OAAA,EAAS;AAAA,GACX;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,CAAC,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAsC;AAAA,IAC1C,EAAA,EAAI,YAAA;AAAA,IACJ,EAAA,EAAI,YAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAC,CAAA;AAE1B,EAAA,IAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,cAAc,CAAA;AAC1C,EAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA;AAC3C,EAAA,IAAI,QAAA,EAAU,OAAA,CAAQ,IAAA,CAAK,kBAAkB,CAAA;AAC7C,EAAA,IAAI,QAAA,EAAU,OAAA,CAAQ,IAAA,CAAK,cAAc,CAAA;AAEzC,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK;AAChC;;;ACrCO,SAAS,cAAA,CAAe,IAAA,GAA0B,EAAC,EAAW;AACnE,EAAA,MAAM;AAAA,IACJ,OAAA,GAAU,UAAA;AAAA,IACV,WAAA,GAAc,KAAA;AAAA,IACd,MAAA,GAAS,KAAA;AAAA,IACT,UAAA,GAAa;AAAA,GACf,GAAI,IAAA;AAEJ,EAAA,MAAM,OAAA,GAAoB,CAAC,SAAS,CAAA;AAEpC,EAAA,MAAM,UAAA,GAA0C;AAAA,IAC9C,QAAA,EAAU,mBAAA;AAAA,IACV,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS,kBAAA;AAAA,IACT,KAAA,EAAO;AAAA,GACT;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,CAAC,CAAA;AAEhC,EAAA,IAAI,WAAA,EAAa,OAAA,CAAQ,IAAA,CAAK,sBAAsB,CAAA;AACpD,EAAA,IAAI,MAAA,EAAQ,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA;AAC1C,EAAA,IAAI,UAAA,EAAY,OAAA,CAAQ,IAAA,CAAK,eAAe,CAAA;AAE5C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK;AAChC;;;ACvBO,SAAS,eAAA,CAAgB,IAAA,GAA2B,EAAC,EAAW;AACrE,EAAA,MAAM,EAAE,KAAA,GAAQ,SAAA,EAAW,OAAO,IAAA,EAAM,SAAA,GAAY,OAAM,GAAI,IAAA;AAE9D,EAAA,MAAM,OAAA,GAAoB,CAAC,UAAU,CAAA;AAErC,EAAA,MAAM,OAAA,GAAqC;AAAA,IACzC,EAAA,EAAI,cAAA;AAAA,IACJ,EAAA,EAAI,cAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAC,CAAA;AAG1B,EAAA,IAAI,KAAA,KAAU,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA;AACrD,EAAA,IAAI,KAAA,KAAU,SAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,mBAAmB,CAAA;AACzD,EAAA,IAAI,KAAA,KAAU,UAAA,EAAY,OAAA,CAAQ,IAAA,CAAK,oBAAoB,CAAA;AAE3D,EAAA,IAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,gBAAgB,CAAA;AAE5C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK;AAChC","file":"index.js","sourcesContent":["export const spectreBaseStylesPath = \"@phcdevworks/spectre-ui/base.css\";\nexport const spectreComponentsStylesPath = \"@phcdevworks/spectre-ui/components.css\";\nexport const spectreUtilitiesStylesPath = \"@phcdevworks/spectre-ui/utilities.css\";\nexport const spectreIndexStylesPath = \"@phcdevworks/spectre-ui/index.css\";\n\nexport const spectreStyles = {\n index: spectreIndexStylesPath,\n base: spectreBaseStylesPath,\n components: spectreComponentsStylesPath,\n utilities: spectreUtilitiesStylesPath,\n};\n","import type { Config as TailwindConfig } from \"tailwindcss\";\nimport type { SpectreTokens } from \"../tokens\";\n\ntype TailwindTheme = NonNullable<TailwindConfig[\"theme\"]>;\n\nexport interface SpectreTailwindTheme {\n theme: TailwindTheme;\n}\n\nexport interface CreateSpectreTailwindThemeOptions {\n tokens: SpectreTokens;\n overrides?: Partial<SpectreTokens>;\n}\n\n/**\n * Minimal, type-safe theme mapper.\n * Important: theme is NEVER undefined (fixes exactOptionalPropertyTypes + DTS).\n */\nexport function createSpectreTailwindTheme(\n options: CreateSpectreTailwindThemeOptions\n): SpectreTailwindTheme {\n const mergedTokens = {\n ...(options.tokens ?? ({} as SpectreTokens)),\n ...(options.overrides ?? {}),\n } as SpectreTokens;\n\n // We keep mapping shallow + permissive because token shapes will evolve.\n // Tailwind accepts nested objects of strings for colors.\n const t: any = mergedTokens;\n\n const colors = (t.colors ?? t.color ?? t.palette ?? {}) as Record<string, any>;\n const spacing = (t.spacing ?? t.space ?? {}) as Record<string, any>;\n const borderRadius = (t.radii ?? t.radius ?? {}) as Record<string, any>;\n const boxShadow = (t.shadows ?? t.shadow ?? {}) as Record<string, any>;\n const fontFamily = (t.typography?.families ?? t.fonts ?? {}) as Record<string, any>;\n const fontSize = (t.typography?.scale ?? t.fontSize ?? {}) as Record<string, any>;\n\n const theme: TailwindTheme = {\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 fontSize: fontSize 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 is guaranteed non-undefined now\n};\n\nexport const spectreTailwindPreset: TailwindConfig = spectrePreset;\n","export type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\" | \"success\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonRecipeOptions {\n variant?: ButtonVariant;\n size?: ButtonSize;\n fullWidth?: boolean;\n loading?: boolean;\n disabled?: boolean;\n iconOnly?: boolean;\n}\n\nexport function getButtonClasses(opts: ButtonRecipeOptions = {}): string {\n const {\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n loading = false,\n disabled = false,\n iconOnly = false,\n } = opts;\n\n const classes: string[] = [\"sp-btn\"];\n\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 success: \"sp-btn--success\",\n };\n classes.push(variantMap[variant]);\n\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 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 return classes.join(\" \").trim();\n}\n","export type CardVariant = \"elevated\" | \"flat\" | \"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\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[] = [\"sp-card\"];\n\n const variantMap: Record<CardVariant, string> = {\n elevated: \"sp-card--elevated\",\n flat: \"sp-card--flat\",\n outline: \"sp-card--outline\",\n ghost: \"sp-card--ghost\",\n };\n classes.push(variantMap[variant]);\n\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.join(\" \").trim();\n}\n","export type InputState = \"default\" | \"error\" | \"success\" | \"disabled\";\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputRecipeOptions {\n state?: InputState;\n size?: InputSize;\n fullWidth?: boolean;\n}\n\nexport function getInputClasses(opts: InputRecipeOptions = {}): string {\n const { state = \"default\", size = \"md\", fullWidth = false } = opts;\n\n const classes: string[] = [\"sp-input\"];\n\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 // State\n if (state === \"error\") classes.push(\"sp-input--error\");\n if (state === \"success\") classes.push(\"sp-input--success\");\n if (state === \"disabled\") classes.push(\"sp-input--disabled\");\n\n if (fullWidth) classes.push(\"sp-input--full\");\n\n return classes.join(\" \").trim();\n}\n"]}
|
package/dist/utilities.css
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
margin-right: auto;
|
|
19
19
|
padding-left: var(--sp-space-md, 1rem);
|
|
20
20
|
padding-right: var(--sp-space-md, 1rem);
|
|
21
|
-
max-width: var(--sp-container-max-width,
|
|
21
|
+
max-width: var(--sp-container-max-width,
|
|
22
|
+
var(--sp-breakpoint-2xl, 72rem));
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
.sp-section {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phcdevworks/spectre-ui",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
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"
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"tailwindcss": "^3.4.0 || ^4.0.0"
|
|
71
72
|
},
|
|
72
73
|
"dependencies": {
|
|
73
|
-
"@phcdevworks/spectre-tokens": "^0.0
|
|
74
|
+
"@phcdevworks/spectre-tokens": "^0.1.0"
|
|
74
75
|
},
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"autoprefixer": "^10.4.20",
|
|
@@ -78,6 +79,6 @@
|
|
|
78
79
|
"tailwindcss": "^3.4.15",
|
|
79
80
|
"tsup": "^8.5.1",
|
|
80
81
|
"typescript": "^5.9.3",
|
|
81
|
-
"vitest": "^
|
|
82
|
+
"vitest": "^4.0.15"
|
|
82
83
|
}
|
|
83
84
|
}
|