@phcdevworks/spectre-ui 1.0.0 β†’ 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,20 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 PHCDevworks
3
+ Copyright (c) 2026 PHCDevworks
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
11
 
12
12
  The above copyright notice and this permission notice shall be included in all
13
13
  copies or substantial portions of the Software.
14
14
 
15
15
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,121 +1,186 @@
1
1
  # @phcdevworks/spectre-ui
2
2
 
3
- ### **The Blueprint (Layer 2 of the Spectre 8-Layer Arsenal)**
3
+ [![GitHub issues](https://img.shields.io/github/issues/phcdevworks/spectre-ui)](https://github.com/phcdevworks/spectre-ui/issues)
4
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/phcdevworks/spectre-ui)](https://github.com/phcdevworks/spectre-ui/pulls)
5
+ [![License](https://img.shields.io/github/license/phcdevworks/spectre-ui)](LICENSE)
4
6
 
5
- `@phcdevworks/spectre-ui` is the structural engine of the Spectre design system. It consumes the raw "DNA" from `@phcdevworks/spectre-tokens` and translates it into standard CSS, a localized Tailwind preset, and type-safe class recipes.
7
+ `@phcdevworks/spectre-ui` is the implementation layer between
8
+ [`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens)
9
+ and downstream adapters or apps.
6
10
 
7
- 🀝 **[Contributing Guide](CONTRIBUTING.md)** | πŸ“ **[Changelog](CHANGELOG.md)** | πŸ›οΈ **[Spectre Arsenal](https://github.com/phcdevworks)**
11
+ Maintained by PHCDevworks, it turns Spectre tokens into reusable CSS bundles,
12
+ Tailwind tooling, and type-safe class recipes. It is framework-agnostic,
13
+ token-driven, and follows a strict zero-hex policy so visual values do not drift
14
+ locally.
8
15
 
9
- ---
16
+ [Contributing](CONTRIBUTING.md) | [Changelog](CHANGELOG.md) |
17
+ [Security Policy](SECURITY.md)
10
18
 
11
- ## πŸ—οΈ Core Architecture
19
+ ## Key capabilities
12
20
 
13
- This package operates as a pure structural layer. It follows a strict **Zero-Hex Enforcement** policyβ€”visual values are imported via `--sp-*` variables, ensuring that if tokens change, the entire UI layer updates automatically.
21
+ - Ships precompiled CSS: `index.css`, `base.css`, `components.css`, and
22
+ `utilities.css`
23
+ - Provides Tailwind theme and preset helpers built from Spectre tokens
24
+ - Exports type-safe class recipes for shared UI patterns
25
+ - Keeps CSS classes and recipe APIs aligned
26
+ - Gives adapters and apps a stable styling contract instead of re-implementing
27
+ classes
28
+ - Enforces a zero-hex approach so visual values stay tied to
29
+ `@phcdevworks/spectre-tokens`
14
30
 
15
- - πŸ’Ž **Token-Driven**: Fully compatible with `@phcdevworks/spectre-tokens` v2.0.0.
16
- - πŸ“¦ **Precompiled CSS**: Ships `base`, `components`, and `utilities` bundles.
17
- - πŸ§ͺ **Type-Safe Recipes**: Pure JS/TS functions for generating framework-agnostic class strings.
18
- - πŸŒͺ️ **Tailwind Preset**: Mirrors the design scale into the Tailwind utility engine.
31
+ ## Installation
19
32
 
20
- ---
33
+ ```bash
34
+ npm install @phcdevworks/spectre-ui
35
+ ```
21
36
 
22
- ## πŸš€ Quick Start
37
+ ## Quick start
23
38
 
24
- ### Installation
39
+ ### CSS import
25
40
 
26
- ```bash
27
- npm install @phcdevworks/spectre-ui
41
+ Import the full stylesheet:
42
+
43
+ ```ts
44
+ import '@phcdevworks/spectre-ui/index.css'
28
45
  ```
29
46
 
30
- ### 1. Import CSS
31
- For most applications, importing the unified `index.css` is recommended.
47
+ Or import the bundles separately:
32
48
 
33
49
  ```ts
34
- import "@phcdevworks/spectre-ui/index.css";
50
+ import '@phcdevworks/spectre-ui/base.css'
51
+ import '@phcdevworks/spectre-ui/components.css'
52
+ import '@phcdevworks/spectre-ui/utilities.css'
35
53
  ```
36
54
 
37
- ### 2. Tailwind Integration
38
- Synchronize your Tailwind theme with the Spectre token scale.
55
+ ### Tailwind preset usage
56
+
57
+ Use Spectre tokens as the source of truth for your Tailwind theme:
39
58
 
40
59
  ```ts
41
60
  // tailwind.config.ts
42
- import { createSpectreTailwindPreset } from "@phcdevworks/spectre-ui/tailwind";
43
- import { spectreTokens } from "@phcdevworks/spectre-tokens";
61
+ import type { Config } from 'tailwindcss'
62
+ import { createSpectreTailwindPreset } from '@phcdevworks/spectre-ui/tailwind'
63
+ import { spectreTokens } from '@phcdevworks/spectre-tokens'
44
64
 
45
- const spectrePreset = createSpectreTailwindPreset({ tokens: spectreTokens });
65
+ const config: Config = {
66
+ content: ['./src/**/*.{ts,tsx,js,jsx,html}'],
67
+ presets: [createSpectreTailwindPreset({ tokens: spectreTokens })]
68
+ }
46
69
 
47
- export default {
48
- content: ["./src/**/*.{js,ts,jsx,tsx}"],
49
- presets: [spectrePreset],
50
- };
70
+ export default config
51
71
  ```
52
72
 
53
- ---
73
+ ### Class recipe usage
54
74
 
55
- ## 🧩 Class Recipes
75
+ Class recipes are the stable styling API for adapters and apps. They return
76
+ predictable class strings and keep behavior consistent across frameworks.
56
77
 
57
- Recipes are the API contract for all Spectre framework adapters. They ensure `.sp-btn--primary` always behaves identical whether used in React, Astro, or WordPress.
78
+ ```ts
79
+ import {
80
+ getBadgeClasses,
81
+ getButtonClasses,
82
+ getPricingCardClasses
83
+ } from '@phcdevworks/spectre-ui'
84
+
85
+ const cta = getButtonClasses({ variant: 'primary', size: 'lg' })
86
+ const badge = getBadgeClasses({ variant: 'success', size: 'sm' })
87
+ const pricingCard = getPricingCardClasses({ featured: true })
88
+ ```
58
89
 
59
- ### Core Components
60
- | Recipe | Primary Variants | Sizes |
61
- | :--- | :--- | :--- |
62
- | `getButtonClasses` | `primary`, `secondary`, `ghost`, `danger`, `success` | `sm`, `md`, `lg` |
63
- | `getBadgeClasses` | `primary`, `success`, `warning`, `danger` | `sm`, `md`, `lg` |
64
- | `getCardClasses` | `elevated`, `outline`, `ghost` | `padded` |
65
- | `getInputClasses` | `default`, `error`, `success` | `sm`, `md`, `lg` |
66
- | `getIconBoxClasses` | `primary`, `success`, `warning`, `danger`, `info` | `sm`, `md`, `lg` |
90
+ ## What this package owns
67
91
 
68
- ### Specialized Components
69
- | Recipe | Description |
70
- | :--- | :--- |
71
- | `getPricingCardClasses` | Semantic structure for pricing tables and plans. |
72
- | `getTestimonialClasses` | Compound classes for quotes, authors, and roles. |
73
- | `getRatingClasses` | Layout recipes for star ratings and count labels. |
92
+ - Token-driven CSS implementation
93
+ - Precompiled CSS bundles and utility classes
94
+ - Tailwind helpers and preset generation
95
+ - Type-safe class recipes for shared UI contracts
96
+ - Stable styling behavior consumed by downstream adapters and apps
74
97
 
75
- ```ts
76
- import { getButtonClasses, getPricingCardClasses } from "@phcdevworks/spectre-ui";
98
+ Golden rule: consume tokens, do not redefine them.
77
99
 
78
- // Generate a primary CTA class string
79
- const cta = getButtonClasses({ variant: "primary", size: "lg" });
80
- // Result: "sp-btn sp-btn--primary sp-btn--lg"
100
+ ## What this package does not own
81
101
 
82
- // Generate pricing card layout
83
- const pricing = getPricingCardClasses({ featured: true });
84
- ```
102
+ - Design values or semantic meaning That belongs to
103
+ `@phcdevworks/spectre-tokens`.
104
+ - Framework-specific component delivery Adapters and apps consume
105
+ `@phcdevworks/spectre-ui`; they do not recreate its styling logic.
106
+ - Local visual values outside the token contract Hardcoded hex, spacing, or
107
+ shadow values are drift unless clearly intentional and documented.
85
108
 
86
- ---
109
+ ## Package exports / API surface
87
110
 
88
- ## πŸ›οΈ The Spectre Suite Hierarchy
111
+ ### Root package
89
112
 
90
- Spectre is built on a non-negotiable hierarchy to prevent style leakage and duplication:
113
+ Exports CSS path constants and class recipes, including:
91
114
 
92
- 1. **Layer 1: Tokens** ([@phcdevworks/spectre-tokens](https://github.com/phcdevworks/spectre-tokens)) – The source of truth for all design values.
93
- 2. **Layer 2: UI (This Package)** – Translates tokens into CSS structure and recipes.
94
- 3. **Layer 3: Adapters** (WordPress, Astro, etc.) – Thin bridges that map Layer 2 to specific frameworks.
115
+ - `spectreStyles`
116
+ - `getButtonClasses`
117
+ - `getBadgeClasses`
118
+ - `getCardClasses`
119
+ - `getInputClasses`
120
+ - `getIconBoxClasses`
121
+ - `getPricingCardClasses`
122
+ - `getTestimonialClasses`
123
+ - `getRatingClasses`
95
124
 
96
- > **The Golden Rule**: Tokens define *meaning*. UI defines *structure*. Adapters define *delivery*.
125
+ Recipes also export their related TypeScript option and variant types.
97
126
 
98
- ---
127
+ ### Tailwind entry point
99
128
 
100
- ## πŸ› οΈ Development
129
+ `@phcdevworks/spectre-ui/tailwind` exports:
101
130
 
102
- ### Build Pipeline
103
- Compiles TypeScript, processes PostCSS, and bundles artifacts into `dist/`.
131
+ - `createSpectreTailwindPreset`
132
+ - `createSpectreTailwindTheme`
104
133
 
105
- ```bash
106
- npm run build
107
- ```
134
+ ### CSS entry points
135
+
136
+ - `@phcdevworks/spectre-ui/index.css`
137
+ - `@phcdevworks/spectre-ui/base.css`
138
+ - `@phcdevworks/spectre-ui/components.css`
139
+ - `@phcdevworks/spectre-ui/utilities.css`
140
+
141
+ ## Relationship to the rest of Spectre
142
+
143
+ Spectre keeps responsibilities separate:
144
+
145
+ - [`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens)
146
+ defines design values and semantic meaning
147
+ - `@phcdevworks/spectre-ui` turns those tokens into reusable CSS, Tailwind
148
+ tooling, and type-safe class recipes
149
+ - Adapters and apps consume `@phcdevworks/spectre-ui` instead of re-implementing
150
+ its styling layer
151
+
152
+ That separation keeps recipe behavior consistent across frameworks and reduces
153
+ implementation drift.
154
+
155
+ ## Development
108
156
 
109
- ### Testing
110
- Run the Vitest suite to verify recipe outputs and token-first compliance.
157
+ Install dependencies, then run the package checks:
111
158
 
112
159
  ```bash
160
+ npm run build
113
161
  npm test
114
162
  ```
115
163
 
116
- ---
164
+ Key source areas:
165
+
166
+ - `src/styles/` for source CSS
167
+ - `src/recipes/` for class recipes
168
+ - `src/tailwind/` for Tailwind helpers
169
+ - `tests/` for contract and regression coverage
170
+
171
+ ## Contributing
172
+
173
+ PHCDevworks maintains this package as part of the Spectre suite.
174
+
175
+ When contributing:
176
+
177
+ - keep styling token-driven
178
+ - keep recipe APIs and CSS classes in sync
179
+ - avoid local visual values unless clearly intentional
180
+ - run `npm run build` and `npm test` before opening a pull request
181
+
182
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow.
117
183
 
118
- ## ❀️ Support & Community
184
+ ## License
119
185
 
120
- - **Sponsor**: [GitHub Sponsors](https://github.com/sponsors/phcdevworks) | [Buy Me a Coffee](https://buymeacoffee.com/phcdevworks)
121
- - **License**: MIT Β© [PHCDevworks](https://phcdevworks.com)
186
+ MIT Β© PHCDevworks. See [LICENSE](LICENSE).
package/dist/base.css CHANGED
@@ -54,7 +54,7 @@
54
54
  }
55
55
 
56
56
  :focus-visible {
57
- outline: var(--sp-focus-ring-width) solid var(--sp-color-focus-primary);
57
+ outline: var(--sp-focus-ring-width) var(--sp-focus-ring-style) var(--sp-color-focus-primary);
58
58
  outline-offset: var(--sp-focus-ring-offset);
59
59
  }
60
60
 
@@ -1,8 +1,8 @@
1
1
  @layer components {
2
2
 
3
3
  :root {
4
- /* structural border width β€” swap to token when spectre-tokens ships sp-border-width-base */
5
- --sp-component-border-width: 1px;
4
+ /* structural border width */
5
+ --sp-component-border-width: var(--sp-border-width-base);
6
6
 
7
7
  /* button roles */
8
8
  --sp-component-button-border-base: var(--sp-component-button-ghost-bg);
@@ -39,6 +39,8 @@
39
39
  --sp-component-button-success-bg-disabled: var(--sp-button-success-bgdisabled);
40
40
  --sp-component-button-success-text: var(--sp-button-success-text);
41
41
  --sp-component-button-success-text-disabled: var(--sp-button-success-textdisabled);
42
+ /* FLAG: buttons.cta tokens in spectre-tokens v2.x use warning.500 (Gold),
43
+ which violates the Aesthetic Audit guardrails. Remaining on accent palette. */
42
44
  --sp-component-button-cta-bg: var(--sp-color-accent-600);
43
45
  --sp-component-button-cta-bg-hover: var(--sp-color-accent-700);
44
46
  --sp-component-button-cta-bg-active: var(--sp-color-accent-800);
@@ -142,34 +144,57 @@
142
144
  /* testimonial roles */
143
145
  --sp-component-testimonial-bg: var(--sp-surface-card);
144
146
  --sp-component-testimonial-border: var(--sp-color-neutral-200);
145
- --sp-component-testimonial-text: var(--sp-text-on-surface-muted);
146
- --sp-component-testimonial-author-name: var(--sp-text-on-surface-default);
147
- --sp-component-testimonial-author-title: var(--sp-text-on-surface-subtle);
147
+ --sp-component-testimonial-text: var(--sp-color-neutral-700);
148
+ --sp-component-testimonial-author-name: var(--sp-color-neutral-900);
149
+ --sp-component-testimonial-author-title: var(--sp-color-neutral-500);
148
150
  --sp-component-testimonial-quote-mark: var(--sp-color-neutral-300);
149
151
 
150
152
  /* pricing card roles */
151
153
  --sp-component-pricing-card-bg: var(--sp-surface-card);
152
154
  --sp-component-pricing-card-border: var(--sp-color-neutral-200);
155
+ /* FLAG: component.pricingCard.featuredBg in tokens is info.600 (Blue), which clashing
156
+ with the warning.500 (Gold) badge. Remaining on neutral-900 to pass Aesthetic Audit. */
153
157
  --sp-component-pricing-card-featured-bg: var(--sp-color-neutral-900);
154
158
  --sp-component-pricing-card-featured-text: var(--sp-color-neutral-50);
155
159
  --sp-component-pricing-card-featured-badge-bg: var(--sp-color-warning-500);
156
160
  --sp-component-pricing-card-featured-badge-text: var(--sp-color-neutral-900);
157
- --sp-component-pricing-card-price: var(--sp-text-on-surface-default);
161
+ --sp-component-pricing-card-price: var(--sp-color-neutral-900);
158
162
  --sp-component-pricing-card-featured-price: var(--sp-color-neutral-50);
159
- --sp-component-pricing-card-price-description: var(--sp-text-on-surface-subtle);
163
+ --sp-component-pricing-card-price-description: var(--sp-color-neutral-500);
160
164
 
161
165
  /* rating roles */
162
166
  --sp-component-rating-star-filled: var(--sp-color-warning-500);
163
167
  --sp-component-rating-star-empty: var(--sp-color-neutral-200);
164
- --sp-component-rating-text: var(--sp-text-on-surface-subtle);
168
+ --sp-component-rating-text: var(--sp-color-neutral-500);
165
169
  }
166
170
 
167
171
  /* dark mode overrides for complex component tokens not yet exported by spectre-tokens v2.x */
168
172
  :root[data-spectre-theme="dark"] {
173
+ --sp-component-testimonial-bg: var(--sp-color-neutral-800);
169
174
  --sp-component-testimonial-border: var(--sp-color-neutral-700);
175
+ --sp-component-testimonial-text: var(--sp-color-neutral-300);
176
+ --sp-component-testimonial-author-name: var(--sp-color-neutral-100);
177
+ --sp-component-testimonial-author-title: var(--sp-color-neutral-400);
170
178
  --sp-component-testimonial-quote-mark: var(--sp-color-neutral-600);
179
+
180
+ --sp-component-pricing-card-bg: var(--sp-color-neutral-800);
171
181
  --sp-component-pricing-card-border: var(--sp-color-neutral-700);
182
+ --sp-component-pricing-card-price: var(--sp-color-neutral-100);
183
+ --sp-component-pricing-card-price-description: var(--sp-color-neutral-400);
184
+
172
185
  --sp-component-rating-star-empty: var(--sp-color-neutral-700);
186
+ --sp-component-rating-text: var(--sp-color-neutral-400);
187
+
188
+ --sp-component-badge-success-bg: var(--sp-color-success-800);
189
+ --sp-component-badge-success-text: var(--sp-color-success-100);
190
+ --sp-component-badge-warning-bg: var(--sp-color-warning-800);
191
+ --sp-component-badge-warning-text: var(--sp-color-warning-100);
192
+ --sp-component-badge-danger-bg: var(--sp-color-error-800);
193
+ --sp-component-badge-danger-text: var(--sp-color-error-100);
194
+ --sp-component-badge-neutral-bg: var(--sp-color-neutral-700);
195
+ --sp-component-badge-neutral-text: var(--sp-color-neutral-100);
196
+ --sp-component-badge-info-bg: var(--sp-color-info-800);
197
+ --sp-component-badge-info-text: var(--sp-color-info-100);
173
198
 
174
199
  --sp-component-badge-success-bg-hover: var(--sp-color-success-700);
175
200
  --sp-component-badge-warning-bg-hover: var(--sp-color-warning-700);
@@ -495,6 +520,10 @@
495
520
  width: 100%;
496
521
  }
497
522
 
523
+ .sp-input--pill {
524
+ border-radius: var(--sp-radius-pill);
525
+ }
526
+
498
527
  .sp-input:focus,
499
528
  .sp-input--focus {
500
529
  border-color: var(--sp-component-input-role-border-focus);
@@ -531,6 +560,11 @@
531
560
  box-shadow: none;
532
561
  }
533
562
 
563
+ .sp-input--loading {
564
+ pointer-events: none;
565
+ opacity: var(--sp-opacity-active);
566
+ }
567
+
534
568
  /* CARDS ---------------------------------------------------------------- */
535
569
 
536
570
  .sp-card {
@@ -580,6 +614,11 @@
580
614
  height: 100%;
581
615
  }
582
616
 
617
+ .sp-card--disabled {
618
+ opacity: var(--sp-opacity-disabled);
619
+ pointer-events: none;
620
+ }
621
+
583
622
  .sp-card--interactive {
584
623
  cursor: pointer;
585
624
  transition:
@@ -698,6 +737,16 @@
698
737
  transition: background-color var(--sp-duration-fast) var(--sp-easing-out);
699
738
  }
700
739
 
740
+ .sp-badge--disabled {
741
+ opacity: var(--sp-opacity-disabled);
742
+ pointer-events: none;
743
+ }
744
+
745
+ .sp-badge--loading {
746
+ opacity: var(--sp-opacity-active);
747
+ pointer-events: none;
748
+ }
749
+
701
750
  /* ICON BOXES ----------------------------------------------------------- */
702
751
 
703
752
  .sp-iconbox {
@@ -803,6 +852,16 @@
803
852
  color: var(--sp-component-iconbox-info-text);
804
853
  }
805
854
 
855
+ .sp-iconbox--disabled {
856
+ opacity: var(--sp-opacity-disabled);
857
+ pointer-events: none;
858
+ }
859
+
860
+ .sp-iconbox--loading {
861
+ opacity: var(--sp-opacity-active);
862
+ pointer-events: none;
863
+ }
864
+
806
865
  /* TESTIMONIALS --------------------------------------------------------- */
807
866
 
808
867
  .sp-testimonial {
@@ -815,6 +874,16 @@
815
874
  gap: var(--sp-space-24);
816
875
  }
817
876
 
877
+ .sp-testimonial--disabled {
878
+ opacity: var(--sp-opacity-disabled);
879
+ pointer-events: none;
880
+ }
881
+
882
+ .sp-testimonial--loading {
883
+ opacity: var(--sp-opacity-active);
884
+ pointer-events: none;
885
+ }
886
+
818
887
  .sp-testimonial-quote {
819
888
  color: var(--sp-component-testimonial-text);
820
889
  font-size: var(--sp-font-lg-size);
@@ -877,6 +946,11 @@
877
946
  border: none;
878
947
  }
879
948
 
949
+ .sp-pricing-card--disabled {
950
+ opacity: var(--sp-opacity-disabled);
951
+ pointer-events: none;
952
+ }
953
+
880
954
  .sp-pricing-card-badge {
881
955
  position: absolute;
882
956
  top: var(--sp-space-16);
@@ -923,6 +997,16 @@
923
997
  gap: var(--sp-space-8);
924
998
  }
925
999
 
1000
+ .sp-rating--disabled {
1001
+ opacity: var(--sp-opacity-disabled);
1002
+ pointer-events: none;
1003
+ }
1004
+
1005
+ .sp-rating--loading {
1006
+ opacity: var(--sp-opacity-active);
1007
+ pointer-events: none;
1008
+ }
1009
+
926
1010
  .sp-rating-stars {
927
1011
  display: flex;
928
1012
  gap: var(--sp-space-4);
@@ -934,7 +1018,7 @@
934
1018
  align-items: center;
935
1019
  justify-content: center;
936
1020
  }
937
-
1021
+
938
1022
  .sp-rating-star--filled {
939
1023
  color: var(--sp-component-rating-star-filled);
940
1024
  }
package/dist/index.cjs CHANGED
@@ -126,7 +126,8 @@ function getCardClasses(opts = {}) {
126
126
  variant: variantInput,
127
127
  interactive = false,
128
128
  padded = false,
129
- fullHeight = false
129
+ fullHeight = false,
130
+ disabled = false
130
131
  } = opts;
131
132
  const variant = resolveOption({
132
133
  name: "card variant",
@@ -146,7 +147,8 @@ function getCardClasses(opts = {}) {
146
147
  variantClass,
147
148
  interactive && "sp-card--interactive",
148
149
  padded && "sp-card--padded",
149
- fullHeight && "sp-card--full"
150
+ fullHeight && "sp-card--full",
151
+ disabled && "sp-card--disabled"
150
152
  );
151
153
  }
152
154
 
@@ -155,7 +157,8 @@ var INPUT_STATES = {
155
157
  default: true,
156
158
  error: true,
157
159
  success: true,
158
- disabled: true
160
+ disabled: true,
161
+ loading: true
159
162
  };
160
163
  var INPUT_SIZES = {
161
164
  sm: true,
@@ -163,7 +166,7 @@ var INPUT_SIZES = {
163
166
  lg: true
164
167
  };
165
168
  function getInputClasses(opts = {}) {
166
- const { state: stateInput, size: sizeInput, fullWidth = false } = opts;
169
+ const { state: stateInput, size: sizeInput, fullWidth = false, pill = false } = opts;
167
170
  const state = resolveOption({
168
171
  name: "input state",
169
172
  value: stateInput,
@@ -189,7 +192,9 @@ function getInputClasses(opts = {}) {
189
192
  state === "success" && "sp-input--success",
190
193
  // Visual state only; actual disabled attribute is handled by adapters.
191
194
  state === "disabled" && "sp-input--disabled",
192
- fullWidth && "sp-input--full"
195
+ state === "loading" && "sp-input--loading",
196
+ fullWidth && "sp-input--full",
197
+ pill && "sp-input--pill"
193
198
  );
194
199
  }
195
200
 
@@ -209,7 +214,7 @@ var BADGE_SIZES = {
209
214
  lg: true
210
215
  };
211
216
  function getBadgeClasses(opts = {}) {
212
- const { variant: variantInput, size: sizeInput, interactive } = opts;
217
+ const { variant: variantInput, size: sizeInput, interactive, disabled, loading } = opts;
213
218
  const variant = resolveOption({
214
219
  name: "badge variant",
215
220
  value: variantInput,
@@ -242,7 +247,9 @@ function getBadgeClasses(opts = {}) {
242
247
  "sp-badge",
243
248
  variantClass,
244
249
  sizeClass,
245
- interactive && "sp-badge--interactive"
250
+ interactive && "sp-badge--interactive",
251
+ disabled && "sp-badge--disabled",
252
+ loading && "sp-badge--loading"
246
253
  );
247
254
  }
248
255
 
@@ -260,7 +267,7 @@ var ICONBOX_SIZES = {
260
267
  lg: true
261
268
  };
262
269
  function getIconBoxClasses(opts = {}) {
263
- const { variant: variantInput, size: sizeInput } = opts;
270
+ const { variant: variantInput, size: sizeInput, disabled = false, loading = false } = opts;
264
271
  const variant = resolveOption({
265
272
  name: "icon box variant",
266
273
  value: variantInput,
@@ -287,12 +294,23 @@ function getIconBoxClasses(opts = {}) {
287
294
  lg: "sp-iconbox--lg"
288
295
  };
289
296
  const sizeClass = sizeMap[size];
290
- return cx("sp-iconbox", variantClass, sizeClass);
297
+ return cx(
298
+ "sp-iconbox",
299
+ variantClass,
300
+ sizeClass,
301
+ disabled && "sp-iconbox--disabled",
302
+ loading && "sp-iconbox--loading"
303
+ );
291
304
  }
292
305
 
293
306
  // src/recipes/testimonial.ts
294
- function getTestimonialClasses(_opts = {}) {
295
- return cx("sp-testimonial");
307
+ function getTestimonialClasses(opts = {}) {
308
+ const { disabled = false, loading = false } = opts;
309
+ return cx(
310
+ "sp-testimonial",
311
+ disabled && "sp-testimonial--disabled",
312
+ loading && "sp-testimonial--loading"
313
+ );
296
314
  }
297
315
  function getTestimonialQuoteClasses() {
298
316
  return cx("sp-testimonial-quote");
@@ -312,10 +330,11 @@ function getTestimonialAuthorTitleClasses() {
312
330
 
313
331
  // src/recipes/pricing-card.ts
314
332
  function getPricingCardClasses(opts = {}) {
315
- const { featured = false } = opts;
333
+ const { featured = false, disabled = false } = opts;
316
334
  return cx(
317
335
  "sp-pricing-card",
318
- featured && "sp-pricing-card--featured"
336
+ featured && "sp-pricing-card--featured",
337
+ disabled && "sp-pricing-card--disabled"
319
338
  );
320
339
  }
321
340
  function getPricingCardBadgeClasses() {
@@ -332,8 +351,13 @@ function getPricingCardDescriptionClasses() {
332
351
  }
333
352
 
334
353
  // src/recipes/rating.ts
335
- function getRatingClasses(_opts = {}) {
336
- return cx("sp-rating");
354
+ function getRatingClasses(opts = {}) {
355
+ const { disabled = false, loading = false } = opts;
356
+ return cx(
357
+ "sp-rating",
358
+ disabled && "sp-rating--disabled",
359
+ loading && "sp-rating--loading"
360
+ );
337
361
  }
338
362
  function getRatingStarsClasses() {
339
363
  return cx("sp-rating-stars");