@phcdevworks/spectre-ui 0.1.0 → 0.2.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 CHANGED
@@ -91,6 +91,8 @@ import {
91
91
  getButtonClasses,
92
92
  getCardClasses,
93
93
  getInputClasses,
94
+ getBadgeClasses,
95
+ getIconBoxClasses,
94
96
  } from "@phcdevworks/spectre-ui";
95
97
 
96
98
  const buttonClasses = getButtonClasses({
@@ -109,6 +111,12 @@ const inputClasses = getInputClasses({
109
111
  fullWidth: true,
110
112
  });
111
113
  // "sp-input sp-input--error sp-input--sm sp-input--full"
114
+
115
+ const badgeClasses = getBadgeClasses({ variant: "success", size: "sm" });
116
+ // "sp-badge sp-badge--success sp-badge--sm"
117
+
118
+ const iconBoxClasses = getIconBoxClasses({ variant: "info", size: "lg" });
119
+ // "sp-iconbox sp-iconbox--info sp-iconbox--lg"
112
120
  ```
113
121
 
114
122
  ## Component Surfaces
@@ -162,6 +170,39 @@ getCardClasses({ variant: "outline" }); // Bordered
162
170
  getCardClasses({ variant: "ghost" }); // Transparent
163
171
  ```
164
172
 
173
+ ### Badge variants
174
+
175
+ ```ts
176
+ getBadgeClasses({ variant: "primary" }); // Primary/default
177
+ getBadgeClasses({ variant: "success" }); // Success state
178
+ getBadgeClasses({ variant: "warning" }); // Warning state
179
+ getBadgeClasses({ variant: "danger" }); // Danger/error state
180
+ ```
181
+
182
+ Available sizes: `sm`, `md`, `lg`
183
+
184
+ ```ts
185
+ getBadgeClasses({ variant: "success", size: "sm" });
186
+ // "sp-badge sp-badge--success sp-badge--sm"
187
+ ```
188
+
189
+ ### Icon Box variants
190
+
191
+ ```ts
192
+ getIconBoxClasses({ variant: "primary" }); // Primary/default
193
+ getIconBoxClasses({ variant: "success" }); // Success state
194
+ getIconBoxClasses({ variant: "warning" }); // Warning state
195
+ getIconBoxClasses({ variant: "danger" }); // Danger/error state
196
+ getIconBoxClasses({ variant: "info" }); // Info state
197
+ ```
198
+
199
+ Available sizes: `sm`, `md`, `lg`
200
+
201
+ ```ts
202
+ getIconBoxClasses({ variant: "info", size: "lg" });
203
+ // "sp-iconbox sp-iconbox--info sp-iconbox--lg"
204
+ ```
205
+
165
206
  ## Surface & Typography Roles
166
207
 
167
208
  Spectre exposes semantic layers that decouple structural styles from raw palette values. Override these roles at any scope (root, layout, or component wrapper) to restyle whole experiences without editing CSS.
@@ -281,9 +322,15 @@ import type {
281
322
  InputState,
282
323
  InputSize,
283
324
  CardVariant,
325
+ BadgeVariant,
326
+ BadgeSize,
327
+ IconBoxVariant,
328
+ IconBoxSize,
284
329
  ButtonRecipeOptions,
285
330
  CardRecipeOptions,
286
331
  InputRecipeOptions,
332
+ BadgeRecipeOptions,
333
+ IconBoxRecipeOptions,
287
334
  } from "@phcdevworks/spectre-ui";
288
335
  ```
289
336
 
@@ -84,6 +84,50 @@
84
84
  var(--sp-text-on-surface-muted, var(--sp-color-neutral-400, #94a3b8)));
85
85
  --sp-component-input-role-border-disabled: var(--sp-component-input-border-disabled,
86
86
  var(--sp-surface-input, var(--sp-color-neutral-200, #e2e8f0)));
87
+
88
+ /* badge roles */
89
+ --sp-component-badge-font: var(--sp-font-family-sans, system-ui);
90
+ --sp-component-badge-weight: var(--sp-font-sm-weight, 500);
91
+ --sp-component-badge-gap: var(--sp-space-4xs, 0.125rem);
92
+ --sp-component-badge-radius: var(--sp-radius-pill, 999px);
93
+ --sp-component-badge-primary-bg: var(--sp-badge-primary-bg,
94
+ var(--sp-color-brand-500, #8652ff));
95
+ --sp-component-badge-primary-text: var(--sp-badge-primary-text,
96
+ var(--sp-text-on-surface-default, var(--sp-color-neutral-900, #0f172a)));
97
+ --sp-component-badge-success-bg: var(--sp-badge-success-bg,
98
+ var(--sp-color-success-500, #22c55e));
99
+ --sp-component-badge-success-text: var(--sp-badge-success-text,
100
+ var(--sp-text-on-surface-default, var(--sp-color-neutral-900, #0f172a)));
101
+ --sp-component-badge-warning-bg: var(--sp-badge-warning-bg,
102
+ var(--sp-color-warning-500, #f59e0b));
103
+ --sp-component-badge-warning-text: var(--sp-badge-warning-text,
104
+ var(--sp-text-on-surface-default, var(--sp-color-neutral-900, #0f172a)));
105
+ --sp-component-badge-danger-bg: var(--sp-badge-danger-bg,
106
+ var(--sp-color-error-500, #ef4444));
107
+ --sp-component-badge-danger-text: var(--sp-badge-danger-text,
108
+ var(--sp-text-on-surface-default, var(--sp-color-neutral-900, #0f172a)));
109
+ --sp-component-badge-padding-x-sm: var(--sp-space-xs, 0.5rem);
110
+ --sp-component-badge-padding-x-md: var(--sp-space-sm, 0.75rem);
111
+ --sp-component-badge-padding-x-lg: var(--sp-space-md, 1rem);
112
+ --sp-component-badge-padding-y-sm: var(--sp-space-4xs, 0.125rem);
113
+ --sp-component-badge-padding-y-md: var(--sp-space-3xs, 0.1875rem);
114
+ --sp-component-badge-padding-y-lg: var(--sp-space-2xs, 0.25rem);
115
+
116
+ /* icon box roles */
117
+ --sp-component-iconbox-radius: var(--sp-radius-lg, 8px);
118
+ --sp-component-iconbox-size-sm: var(--sp-space-xl, 2rem);
119
+ --sp-component-iconbox-size-md: var(--sp-space-2xl, 3rem);
120
+ --sp-component-iconbox-size-lg: var(--sp-space-3xl, 4rem);
121
+ --sp-component-iconbox-primary-bg: var(--sp-color-brand-50, #f5f0ff);
122
+ --sp-component-iconbox-primary-text: var(--sp-color-brand-700, #5626b4);
123
+ --sp-component-iconbox-success-bg: var(--sp-color-success-50, #f0fdf4);
124
+ --sp-component-iconbox-success-text: var(--sp-color-success-700, #15803d);
125
+ --sp-component-iconbox-warning-bg: var(--sp-color-warning-50, #fffbeb);
126
+ --sp-component-iconbox-warning-text: var(--sp-color-warning-700, #b45309);
127
+ --sp-component-iconbox-danger-bg: var(--sp-color-error-50, #fef2f2);
128
+ --sp-component-iconbox-danger-text: var(--sp-color-error-700, #b91c1c);
129
+ --sp-component-iconbox-info-bg: var(--sp-color-info-50, #eff6ff);
130
+ --sp-component-iconbox-info-text: var(--sp-color-info-700, #1d4ed8);
87
131
  }
88
132
 
89
133
  /* BUTTONS -------------------------------------------------------------- */
@@ -433,4 +477,125 @@
433
477
  transform: translateY(-1px);
434
478
  box-shadow: var(--sp-component-card-shadow-elevated, var(--sp-shadow-lg));
435
479
  }
480
+
481
+ /* BADGES --------------------------------------------------------------- */
482
+
483
+ .sp-badge {
484
+ display: inline-flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ gap: var(--sp-component-badge-gap, var(--sp-space-4xs, 0.125rem));
488
+ border-radius: var(--sp-component-badge-radius, var(--sp-radius-pill, 999px));
489
+ font-family: var(--sp-component-badge-font, var(--sp-font-family-sans, system-ui));
490
+ font-weight: var(--sp-component-badge-weight, var(--sp-font-sm-weight, 500));
491
+ padding: var(--sp-component-badge-padding-y-md, var(--sp-space-3xs, 0.1875rem))
492
+ var(--sp-component-badge-padding-x-md, var(--sp-space-sm, 0.75rem));
493
+ font-size: var(--sp-font-sm-size, 0.875rem);
494
+ line-height: var(--sp-font-sm-line-height, 1.5rem);
495
+ border: 1px solid transparent;
496
+ white-space: nowrap;
497
+ }
498
+
499
+ .sp-badge--sm {
500
+ padding: var(--sp-component-badge-padding-y-sm, var(--sp-space-4xs, 0.125rem))
501
+ var(--sp-component-badge-padding-x-sm, var(--sp-space-xs, 0.5rem));
502
+ font-size: var(--sp-font-xs-size, 0.75rem);
503
+ line-height: var(--sp-font-xs-line-height, 1.25rem);
504
+ }
505
+
506
+ .sp-badge--md {
507
+ padding: var(--sp-component-badge-padding-y-md, var(--sp-space-3xs, 0.1875rem))
508
+ var(--sp-component-badge-padding-x-md, var(--sp-space-sm, 0.75rem));
509
+ font-size: var(--sp-font-sm-size, 0.875rem);
510
+ line-height: var(--sp-font-sm-line-height, 1.5rem);
511
+ }
512
+
513
+ .sp-badge--lg {
514
+ padding: var(--sp-component-badge-padding-y-lg, var(--sp-space-2xs, 0.25rem))
515
+ var(--sp-component-badge-padding-x-lg, var(--sp-space-md, 1rem));
516
+ font-size: var(--sp-font-md-size, 1rem);
517
+ line-height: var(--sp-font-md-line-height, 1.75rem);
518
+ }
519
+
520
+ .sp-badge--primary {
521
+ background-color: var(--sp-component-badge-primary-bg);
522
+ color: var(--sp-component-badge-primary-text);
523
+ }
524
+
525
+ .sp-badge--success {
526
+ background-color: var(--sp-component-badge-success-bg);
527
+ color: var(--sp-component-badge-success-text);
528
+ }
529
+
530
+ .sp-badge--warning {
531
+ background-color: var(--sp-component-badge-warning-bg);
532
+ color: var(--sp-component-badge-warning-text);
533
+ }
534
+
535
+ .sp-badge--danger {
536
+ background-color: var(--sp-component-badge-danger-bg);
537
+ color: var(--sp-component-badge-danger-text);
538
+ }
539
+
540
+ /* ICON BOXES ----------------------------------------------------------- */
541
+
542
+ .sp-iconbox {
543
+ display: inline-flex;
544
+ align-items: center;
545
+ justify-content: center;
546
+ border-radius: var(--sp-component-iconbox-radius, var(--sp-radius-lg, 8px));
547
+ color: var(--sp-component-iconbox-primary-text);
548
+ background-color: var(--sp-component-iconbox-primary-bg);
549
+ font-family: var(--sp-font-family-sans, system-ui);
550
+ font-weight: var(--sp-font-md-weight, 500);
551
+ }
552
+
553
+ .sp-iconbox--sm {
554
+ width: var(--sp-component-iconbox-size-sm, var(--sp-space-xl, 2rem));
555
+ height: var(--sp-component-iconbox-size-sm, var(--sp-space-xl, 2rem));
556
+ font-size: var(--sp-font-sm-size, 0.875rem);
557
+ }
558
+
559
+ .sp-iconbox--md {
560
+ width: var(--sp-component-iconbox-size-md, var(--sp-space-2xl, 3rem));
561
+ height: var(--sp-component-iconbox-size-md, var(--sp-space-2xl, 3rem));
562
+ font-size: var(--sp-font-md-size, 1rem);
563
+ }
564
+
565
+ .sp-iconbox--lg {
566
+ width: var(--sp-component-iconbox-size-lg, var(--sp-space-3xl, 4rem));
567
+ height: var(--sp-component-iconbox-size-lg, var(--sp-space-3xl, 4rem));
568
+ font-size: var(--sp-font-lg-size, 1.125rem);
569
+ }
570
+
571
+ .sp-iconbox > svg,
572
+ .sp-iconbox > i {
573
+ width: 1em;
574
+ height: 1em;
575
+ }
576
+
577
+ .sp-iconbox--primary {
578
+ background-color: var(--sp-component-iconbox-primary-bg);
579
+ color: var(--sp-component-iconbox-primary-text);
580
+ }
581
+
582
+ .sp-iconbox--success {
583
+ background-color: var(--sp-component-iconbox-success-bg);
584
+ color: var(--sp-component-iconbox-success-text);
585
+ }
586
+
587
+ .sp-iconbox--warning {
588
+ background-color: var(--sp-component-iconbox-warning-bg);
589
+ color: var(--sp-component-iconbox-warning-text);
590
+ }
591
+
592
+ .sp-iconbox--danger {
593
+ background-color: var(--sp-component-iconbox-danger-bg);
594
+ color: var(--sp-component-iconbox-danger-text);
595
+ }
596
+
597
+ .sp-iconbox--info {
598
+ background-color: var(--sp-component-iconbox-info-bg);
599
+ color: var(--sp-component-iconbox-info-text);
600
+ }
436
601
  }
package/dist/index.cjs CHANGED
@@ -31,7 +31,7 @@ function createSpectreTailwindTheme(options) {
31
31
  const boxShadow = t.shadows ?? t.shadow ?? {};
32
32
  const fontFamily = t.typography?.families ?? t.fonts ?? {};
33
33
  const fontSize = t.typography?.scale ?? t.fontSize ?? {};
34
- const theme2 = {
34
+ const theme = {
35
35
  colors,
36
36
  spacing,
37
37
  borderRadius,
@@ -39,28 +39,135 @@ function createSpectreTailwindTheme(options) {
39
39
  fontFamily,
40
40
  fontSize
41
41
  };
42
- return { theme: theme2 };
42
+ return { theme };
43
43
  }
44
44
 
45
45
  // src/tailwind/preset.ts
46
- var { theme } = createSpectreTailwindTheme({ tokens: spectreTokens__default.default });
47
- var spectrePreset = {
48
- content: [],
49
- theme
50
- // theme is guaranteed non-undefined now
46
+ var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
47
+ var deepMerge = (base, overrides) => {
48
+ if (!overrides) return base;
49
+ const result = { ...base };
50
+ for (const [key, overrideValue] of Object.entries(overrides)) {
51
+ const baseValue = result[key];
52
+ if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
53
+ result[key] = deepMerge(baseValue, overrideValue);
54
+ } else {
55
+ result[key] = overrideValue;
56
+ }
57
+ }
58
+ return result;
51
59
  };
60
+ var cachedTokens = null;
61
+ var getRequire = () => {
62
+ try {
63
+ return Function("return typeof require !== 'undefined' ? require : null")();
64
+ } catch {
65
+ return null;
66
+ }
67
+ };
68
+ var resolveTokens = (tokens) => {
69
+ if (tokens) return tokens;
70
+ if (cachedTokens) return cachedTokens;
71
+ const req = getRequire();
72
+ if (!req) {
73
+ throw new Error(
74
+ "[spectre-ui] Unable to load spectre tokens; pass tokens to createSpectreTailwindPreset."
75
+ );
76
+ }
77
+ const mod = req("../tokens");
78
+ cachedTokens = mod.spectreTokens;
79
+ return cachedTokens;
80
+ };
81
+ var createSpectreTailwindPreset = (options = {}) => {
82
+ const tokens = resolveTokens(options.tokens);
83
+ const { theme } = createSpectreTailwindTheme({ tokens });
84
+ const mergedTheme = deepMerge(
85
+ theme,
86
+ options.themeOverrides
87
+ );
88
+ const basePreset = {
89
+ content: [],
90
+ theme: mergedTheme
91
+ // theme is guaranteed non-undefined now
92
+ };
93
+ return deepMerge(
94
+ basePreset,
95
+ options.presetOverrides
96
+ );
97
+ };
98
+ var spectrePreset = createSpectreTailwindPreset();
99
+
100
+ // src/internal/cx.ts
101
+ function cx(...parts) {
102
+ const seen = /* @__PURE__ */ new Set();
103
+ const classes = [];
104
+ for (const part of parts) {
105
+ if (!part) continue;
106
+ const trimmed = part.trim();
107
+ if (!trimmed) continue;
108
+ if (!/\s/.test(trimmed)) {
109
+ if (!seen.has(trimmed)) {
110
+ seen.add(trimmed);
111
+ classes.push(trimmed);
112
+ }
113
+ continue;
114
+ }
115
+ for (const token of trimmed.split(/\s+/)) {
116
+ if (!token || seen.has(token)) continue;
117
+ seen.add(token);
118
+ classes.push(token);
119
+ }
120
+ }
121
+ return classes.join(" ");
122
+ }
123
+
124
+ // src/internal/resolve-option.ts
125
+ var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
126
+ var isAllowedValue = (value, allowed) => Array.isArray(allowed) ? allowed.includes(value) : hasOwn(allowed, value);
127
+ function resolveOption(config) {
128
+ const { name, value, allowed, fallback } = config;
129
+ if (value === void 0) return fallback;
130
+ if (isAllowedValue(value, allowed)) return value;
131
+ if (process.env.NODE_ENV !== "production") {
132
+ throw new Error(`[spectre-ui] Unknown ${name}: ${value}`);
133
+ }
134
+ return fallback;
135
+ }
52
136
 
53
137
  // src/recipes/button.ts
138
+ var BUTTON_VARIANTS = {
139
+ primary: true,
140
+ secondary: true,
141
+ ghost: true,
142
+ danger: true,
143
+ success: true
144
+ };
145
+ var BUTTON_SIZES = {
146
+ sm: true,
147
+ md: true,
148
+ lg: true
149
+ };
54
150
  function getButtonClasses(opts = {}) {
55
151
  const {
56
- variant = "primary",
57
- size = "md",
152
+ variant: variantInput,
153
+ size: sizeInput,
58
154
  fullWidth = false,
59
155
  loading = false,
60
156
  disabled = false,
61
157
  iconOnly = false
62
158
  } = opts;
63
- const classes = ["sp-btn"];
159
+ const variant = resolveOption({
160
+ name: "button variant",
161
+ value: variantInput,
162
+ allowed: BUTTON_VARIANTS,
163
+ fallback: "primary"
164
+ });
165
+ const size = resolveOption({
166
+ name: "button size",
167
+ value: sizeInput,
168
+ allowed: BUTTON_SIZES,
169
+ fallback: "md"
170
+ });
64
171
  const variantMap = {
65
172
  primary: "sp-btn--primary",
66
173
  secondary: "sp-btn--secondary",
@@ -68,57 +175,187 @@ function getButtonClasses(opts = {}) {
68
175
  danger: "sp-btn--danger",
69
176
  success: "sp-btn--success"
70
177
  };
71
- classes.push(variantMap[variant]);
178
+ const variantClass = variantMap[variant];
72
179
  const sizeMap = {
73
180
  sm: "sp-btn--sm",
74
181
  md: "sp-btn--md",
75
182
  lg: "sp-btn--lg"
76
183
  };
77
- classes.push(sizeMap[size]);
78
- if (fullWidth) classes.push("sp-btn--full");
79
- if (loading) classes.push("sp-btn--loading");
80
- if (disabled) classes.push("sp-btn--disabled");
81
- if (iconOnly) classes.push("sp-btn--icon");
82
- return classes.join(" ").trim();
184
+ const sizeClass = sizeMap[size];
185
+ return cx(
186
+ "sp-btn",
187
+ variantClass,
188
+ sizeClass,
189
+ fullWidth && "sp-btn--full",
190
+ loading && "sp-btn--loading",
191
+ disabled && "sp-btn--disabled",
192
+ iconOnly && "sp-btn--icon"
193
+ );
83
194
  }
84
195
 
85
196
  // src/recipes/card.ts
197
+ var CARD_VARIANTS = {
198
+ elevated: true,
199
+ flat: true,
200
+ outline: true,
201
+ ghost: true
202
+ };
86
203
  function getCardClasses(opts = {}) {
87
204
  const {
88
- variant = "elevated",
205
+ variant: variantInput,
89
206
  interactive = false,
90
207
  padded = false,
91
208
  fullHeight = false
92
209
  } = opts;
93
- const classes = ["sp-card"];
210
+ const variant = resolveOption({
211
+ name: "card variant",
212
+ value: variantInput,
213
+ allowed: CARD_VARIANTS,
214
+ fallback: "elevated"
215
+ });
94
216
  const variantMap = {
95
217
  elevated: "sp-card--elevated",
96
218
  flat: "sp-card--flat",
97
219
  outline: "sp-card--outline",
98
220
  ghost: "sp-card--ghost"
99
221
  };
100
- classes.push(variantMap[variant]);
101
- if (interactive) classes.push("sp-card--interactive");
102
- if (padded) classes.push("sp-card--padded");
103
- if (fullHeight) classes.push("sp-card--full");
104
- return classes.join(" ").trim();
222
+ const variantClass = variantMap[variant];
223
+ return cx(
224
+ "sp-card",
225
+ variantClass,
226
+ interactive && "sp-card--interactive",
227
+ padded && "sp-card--padded",
228
+ fullHeight && "sp-card--full"
229
+ );
105
230
  }
106
231
 
107
232
  // src/recipes/input.ts
233
+ var INPUT_STATES = {
234
+ default: true,
235
+ error: true,
236
+ success: true,
237
+ disabled: true
238
+ };
239
+ var INPUT_SIZES = {
240
+ sm: true,
241
+ md: true,
242
+ lg: true
243
+ };
108
244
  function getInputClasses(opts = {}) {
109
- const { state = "default", size = "md", fullWidth = false } = opts;
110
- const classes = ["sp-input"];
245
+ const { state: stateInput, size: sizeInput, fullWidth = false } = opts;
246
+ const state = resolveOption({
247
+ name: "input state",
248
+ value: stateInput,
249
+ allowed: INPUT_STATES,
250
+ fallback: "default"
251
+ });
252
+ const size = resolveOption({
253
+ name: "input size",
254
+ value: sizeInput,
255
+ allowed: INPUT_SIZES,
256
+ fallback: "md"
257
+ });
111
258
  const sizeMap = {
112
259
  sm: "sp-input--sm",
113
260
  md: "sp-input--md",
114
261
  lg: "sp-input--lg"
115
262
  };
116
- classes.push(sizeMap[size]);
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();
263
+ const sizeClass = sizeMap[size];
264
+ return cx(
265
+ "sp-input",
266
+ sizeClass,
267
+ state === "error" && "sp-input--error",
268
+ state === "success" && "sp-input--success",
269
+ // Visual state only; actual disabled attribute is handled by adapters.
270
+ state === "disabled" && "sp-input--disabled",
271
+ fullWidth && "sp-input--full"
272
+ );
273
+ }
274
+
275
+ // src/recipes/badge.ts
276
+ var BADGE_VARIANTS = {
277
+ primary: true,
278
+ success: true,
279
+ warning: true,
280
+ danger: true
281
+ };
282
+ var BADGE_SIZES = {
283
+ sm: true,
284
+ md: true,
285
+ lg: true
286
+ };
287
+ function getBadgeClasses(opts = {}) {
288
+ const { variant: variantInput, size: sizeInput } = opts;
289
+ const variant = resolveOption({
290
+ name: "badge variant",
291
+ value: variantInput,
292
+ allowed: BADGE_VARIANTS,
293
+ fallback: "primary"
294
+ });
295
+ const size = resolveOption({
296
+ name: "badge size",
297
+ value: sizeInput,
298
+ allowed: BADGE_SIZES,
299
+ fallback: "md"
300
+ });
301
+ const variantMap = {
302
+ primary: "sp-badge--primary",
303
+ success: "sp-badge--success",
304
+ warning: "sp-badge--warning",
305
+ danger: "sp-badge--danger"
306
+ };
307
+ const variantClass = variantMap[variant];
308
+ const sizeMap = {
309
+ sm: "sp-badge--sm",
310
+ md: "sp-badge--md",
311
+ lg: "sp-badge--lg"
312
+ };
313
+ const sizeClass = sizeMap[size];
314
+ return cx("sp-badge", variantClass, sizeClass);
315
+ }
316
+
317
+ // src/recipes/iconbox.ts
318
+ var ICONBOX_VARIANTS = {
319
+ primary: true,
320
+ success: true,
321
+ warning: true,
322
+ danger: true,
323
+ info: true
324
+ };
325
+ var ICONBOX_SIZES = {
326
+ sm: true,
327
+ md: true,
328
+ lg: true
329
+ };
330
+ function getIconBoxClasses(opts = {}) {
331
+ const { variant: variantInput, size: sizeInput } = opts;
332
+ const variant = resolveOption({
333
+ name: "icon box variant",
334
+ value: variantInput,
335
+ allowed: ICONBOX_VARIANTS,
336
+ fallback: "primary"
337
+ });
338
+ const size = resolveOption({
339
+ name: "icon box size",
340
+ value: sizeInput,
341
+ allowed: ICONBOX_SIZES,
342
+ fallback: "md"
343
+ });
344
+ const variantMap = {
345
+ primary: "sp-iconbox--primary",
346
+ success: "sp-iconbox--success",
347
+ warning: "sp-iconbox--warning",
348
+ danger: "sp-iconbox--danger",
349
+ info: "sp-iconbox--info"
350
+ };
351
+ const variantClass = variantMap[variant];
352
+ const sizeMap = {
353
+ sm: "sp-iconbox--sm",
354
+ md: "sp-iconbox--md",
355
+ lg: "sp-iconbox--lg"
356
+ };
357
+ const sizeClass = sizeMap[size];
358
+ return cx("sp-iconbox", variantClass, sizeClass);
122
359
  }
123
360
 
124
361
  Object.defineProperty(exports, "spectreTokens", {
@@ -126,8 +363,10 @@ Object.defineProperty(exports, "spectreTokens", {
126
363
  get: function () { return spectreTokens__default.default; }
127
364
  });
128
365
  exports.createSpectreTailwindTheme = createSpectreTailwindTheme;
366
+ exports.getBadgeClasses = getBadgeClasses;
129
367
  exports.getButtonClasses = getButtonClasses;
130
368
  exports.getCardClasses = getCardClasses;
369
+ exports.getIconBoxClasses = getIconBoxClasses;
131
370
  exports.getInputClasses = getInputClasses;
132
371
  exports.spectreBaseStylesPath = spectreBaseStylesPath;
133
372
  exports.spectreComponentsStylesPath = spectreComponentsStylesPath;