@themal/editor 0.17.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 +338 -0
- package/dist/index.d.ts +299 -0
- package/dist/index.js +10764 -0
- package/dist/style.css +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# @themal/editor
|
|
2
|
+
|
|
3
|
+
Interactive design system editor for React apps. Pick colors, generate harmony palettes, enforce WCAG AA contrast, customize typography and interaction states, and export CSS custom properties — all in real time. Fully responsive — works on desktop, tablet, and mobile.
|
|
4
|
+
|
|
5
|
+
> Free tier available with core features. Pro features ($9/mo or $50/yr) require a subscription.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @themal/editor
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer Dependencies
|
|
14
|
+
|
|
15
|
+
| Package | Version | Required |
|
|
16
|
+
|---------|---------|----------|
|
|
17
|
+
| `react` | `^18.0.0 \|\| ^19.0.0` | Yes |
|
|
18
|
+
| `react-dom` | `^18.0.0 \|\| ^19.0.0` | Yes |
|
|
19
|
+
| `axe-core` | `>=4.0.0` | Optional — enables accessibility auditing |
|
|
20
|
+
| `lucide-react` | `>=0.294.0` | Optional — enables icon previews |
|
|
21
|
+
|
|
22
|
+
Install optional peers for full functionality:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install axe-core lucide-react
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { DesignSystemEditor } from '@themal/editor';
|
|
32
|
+
import '@themal/editor/style.css';
|
|
33
|
+
|
|
34
|
+
function App() {
|
|
35
|
+
return <DesignSystemEditor />;
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The editor writes CSS custom properties (HSL values) to `:root`, so it works with any framework that consumes CSS variables.
|
|
40
|
+
|
|
41
|
+
## Props
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| `licenseKey` | `string` | — | License key to unlock premium features. |
|
|
46
|
+
| `upgradeUrl` | `string` | `"/pricing"` | URL shown in premium gate upgrade prompts. |
|
|
47
|
+
| `signInUrl` | `string` | — | URL shown in premium gate sign-in prompts. |
|
|
48
|
+
| `prEndpointUrl` | `string` | — | URL for PR creation endpoint. PR button hidden if omitted. |
|
|
49
|
+
| `accessibilityAudit` | `boolean` | `true` | Enable axe-core color contrast auditing. |
|
|
50
|
+
| `onChange` | `(colors: Record<string, string>) => void` | — | Callback on every color change with the full color map. |
|
|
51
|
+
| `onExport` | `(css: string) => void` | — | Override built-in CSS modal. Receives the generated CSS string. |
|
|
52
|
+
| `className` | `string` | — | Additional CSS class for the wrapper element. |
|
|
53
|
+
| `showHeader` | `boolean` | `true` | Show the editor header with logo and navigation. |
|
|
54
|
+
| `showNavLinks` | `boolean` | `true` | Show page navigation links in the header and mobile menu. |
|
|
55
|
+
| `headerRight` | `React.ReactNode` | — | Custom content rendered on the right side of the header (e.g. auth buttons). |
|
|
56
|
+
| `aboutUrl` | `string` | — | URL for the About page link in the header navigation. |
|
|
57
|
+
|
|
58
|
+
## Premium Features
|
|
59
|
+
|
|
60
|
+
The following features require a valid license key:
|
|
61
|
+
|
|
62
|
+
| Feature | Description |
|
|
63
|
+
|---------|-------------|
|
|
64
|
+
| Harmony schemes | Generate palettes using complementary, analogous, triadic, or split-complementary color relationships. |
|
|
65
|
+
| Color locks | Lock up to 4 colors to preserve them during palette regeneration. |
|
|
66
|
+
| PR integration | Create design system pull requests directly from the editor. |
|
|
67
|
+
| Undo/redo | History management for color changes. |
|
|
68
|
+
| Image palette extraction | Extract color palettes from uploaded images with preview confirmation. |
|
|
69
|
+
| Palette export | Download palette as SVG/PNG, or copy as HEX/RGB/RGBA text. |
|
|
70
|
+
| Interaction states | Style hover, focus, and active states for buttons and components. |
|
|
71
|
+
| Typography interactions | Customize hover, active, and underline behavior for links and headings. |
|
|
72
|
+
| Custom fonts | Add any Google Font by name — validated, loaded, and persisted across sessions. |
|
|
73
|
+
|
|
74
|
+
### License Key Format
|
|
75
|
+
|
|
76
|
+
Keys follow the format `THEMAL-XXXX-XXXX-XXXX` with a checksum-validated third segment. Use `generateLicenseKey()` to create valid keys.
|
|
77
|
+
|
|
78
|
+
### PremiumGate Component
|
|
79
|
+
|
|
80
|
+
Wrap any feature in `PremiumGate` to gate it behind a license key. Clicking a gated feature opens a modal with upgrade and sign-in options:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { PremiumGate } from '@themal/editor';
|
|
84
|
+
|
|
85
|
+
<PremiumGate feature="harmony-schemes" upgradeUrl="/pricing" signInUrl="/sign-in">
|
|
86
|
+
<HarmonyControls />
|
|
87
|
+
</PremiumGate>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Prop | Type | Default | Description |
|
|
91
|
+
|------|------|---------|-------------|
|
|
92
|
+
| `feature` | `string` | — | Name of the premium feature being gated. |
|
|
93
|
+
| `variant` | `"section" \| "inline"` | `"section"` | `"section"` dims content with a lock overlay; `"inline"` shows a lock icon inline. Both open a modal on click. |
|
|
94
|
+
| `upgradeUrl` | `string` | `"/pricing"` | URL for the upgrade prompt. |
|
|
95
|
+
| `signInUrl` | `string` | — | URL for the sign-in prompt. |
|
|
96
|
+
|
|
97
|
+
### LicenseProvider
|
|
98
|
+
|
|
99
|
+
If using `PremiumGate` or `useLicense` outside of `DesignSystemEditor`, wrap your tree in `LicenseProvider`:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { LicenseProvider } from '@themal/editor';
|
|
103
|
+
|
|
104
|
+
<LicenseProvider licenseKey="THEMAL-XXXX-XXXX-XXXX">
|
|
105
|
+
<App />
|
|
106
|
+
</LicenseProvider>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Usage Examples
|
|
110
|
+
|
|
111
|
+
### Basic — color picker only
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<DesignSystemEditor accessibilityAudit={false} />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### With PR creation
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<DesignSystemEditor prEndpointUrl="/api/create-design-pr" />
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### With premium features
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
<DesignSystemEditor
|
|
127
|
+
licenseKey="THEMAL-XXXX-XXXX-XXXX"
|
|
128
|
+
upgradeUrl="/pricing"
|
|
129
|
+
signInUrl="/sign-in"
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### With custom header content
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<DesignSystemEditor
|
|
137
|
+
headerRight={<button onClick={handleSignIn}>Sign In</button>}
|
|
138
|
+
aboutUrl="/about"
|
|
139
|
+
/>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Listen for changes
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
<DesignSystemEditor
|
|
146
|
+
onChange={(colors) => {
|
|
147
|
+
console.log('Brand color:', colors['--brand']);
|
|
148
|
+
}}
|
|
149
|
+
/>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Custom export handler
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
<DesignSystemEditor
|
|
156
|
+
onExport={(css) => {
|
|
157
|
+
navigator.clipboard.writeText(css);
|
|
158
|
+
}}
|
|
159
|
+
/>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Embedded / headless
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
<DesignSystemEditor
|
|
166
|
+
showHeader={false}
|
|
167
|
+
showNavLinks={false}
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Exported Utilities
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import {
|
|
175
|
+
// Color utilities
|
|
176
|
+
hslStringToHex, // "210 50% 40%" -> "#336699"
|
|
177
|
+
hexToHslString, // "#336699" -> "210.0 50.0% 40.0%"
|
|
178
|
+
contrastRatio, // WCAG contrast ratio between two HSL strings
|
|
179
|
+
fgForBg, // Best foreground (black/white) for a background HSL
|
|
180
|
+
EDITABLE_VARS, // Array of { key, label } token definitions
|
|
181
|
+
HARMONY_SCHEMES, // ['Complementary', 'Analogous', 'Triadic', 'Split-Complementary']
|
|
182
|
+
applyStoredThemeColors, // Restore persisted theme from localStorage
|
|
183
|
+
|
|
184
|
+
// localStorage key constants
|
|
185
|
+
CARD_STYLE_KEY, // Key for card style storage
|
|
186
|
+
TYPOGRAPHY_KEY, // Key for typography storage
|
|
187
|
+
ALERT_STYLE_KEY, // Key for dialog alert style storage
|
|
188
|
+
TOAST_STYLE_KEY, // Key for toast style storage
|
|
189
|
+
INTERACTION_STYLE_KEY, // Key for interaction style storage
|
|
190
|
+
|
|
191
|
+
// Card, typography & interaction style utilities
|
|
192
|
+
applyStoredCardStyle, // Restore card style from localStorage
|
|
193
|
+
applyStoredTypography, // Restore typography from localStorage
|
|
194
|
+
applyStoredAlertStyle, // Restore dialog alert style from localStorage
|
|
195
|
+
applyStoredToastStyle, // Restore toast style from localStorage
|
|
196
|
+
applyStoredInteractionStyle, // Restore button interaction style from localStorage
|
|
197
|
+
|
|
198
|
+
// Shareable URL utilities
|
|
199
|
+
serializeThemeState, // Encode full theme state as base64 string
|
|
200
|
+
deserializeThemeState, // Decode base64 string back to theme state
|
|
201
|
+
|
|
202
|
+
// Export utilities
|
|
203
|
+
generateDesignTokens, // Generate W3C Design Token JSON from theme state
|
|
204
|
+
exportPaletteAsText, // Export palette as HEX, RGB, or RGBA text
|
|
205
|
+
exportPaletteAsSvg, // Export palette as SVG string
|
|
206
|
+
exportPaletteAsPng, // Export palette as PNG Blob
|
|
207
|
+
|
|
208
|
+
// Custom font utilities
|
|
209
|
+
getCustomFonts, // Load custom fonts from localStorage
|
|
210
|
+
addCustomFont, // Validate & add a Google Font by name
|
|
211
|
+
removeCustomFont, // Remove a custom font by label
|
|
212
|
+
initCustomFonts, // Re-register all custom fonts on startup
|
|
213
|
+
|
|
214
|
+
// License utilities
|
|
215
|
+
validateLicenseKey, // Validate a THEMAL-XXXX-XXXX-XXXX key
|
|
216
|
+
generateLicenseKey, // Generate a valid license key
|
|
217
|
+
|
|
218
|
+
// Premium components & hooks
|
|
219
|
+
LicenseProvider, // Context provider for license state
|
|
220
|
+
useLicense, // Hook: { isValid, isPremium }
|
|
221
|
+
PremiumGate, // Gate component for premium features
|
|
222
|
+
} from '@themal/editor';
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Exported Types
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import type {
|
|
229
|
+
DesignSystemEditorProps,
|
|
230
|
+
TokenDefinition,
|
|
231
|
+
HarmonyScheme,
|
|
232
|
+
CardStyleState,
|
|
233
|
+
TypographyState,
|
|
234
|
+
AlertStyleState,
|
|
235
|
+
ToastStyleState,
|
|
236
|
+
InteractionStyleState,
|
|
237
|
+
TypoInteractionStyleState,
|
|
238
|
+
CustomFontEntry,
|
|
239
|
+
PremiumFeature,
|
|
240
|
+
LicenseValidation,
|
|
241
|
+
LicenseProviderProps,
|
|
242
|
+
PremiumGateProps,
|
|
243
|
+
} from '@themal/editor';
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## How It Works
|
|
247
|
+
|
|
248
|
+
1. **Color picking** — Click any swatch to open the native color picker. Changing a key color (brand, secondary, accent, background) automatically derives related tokens.
|
|
249
|
+
2. **Harmony schemes** *(Pro)* — Generate palettes using complementary, analogous, triadic, or split-complementary color relationships.
|
|
250
|
+
3. **Contrast enforcement** — Every foreground/background pair is checked against WCAG AA (4.5:1). Failing pairs are auto-corrected by adjusting lightness.
|
|
251
|
+
4. **Typography** — Choose heading and body fonts (including custom Google Fonts), adjust sizes, weights, line height, and letter spacing with live preview. Five built-in presets (System, Modern, Classic, Compact, Editorial).
|
|
252
|
+
5. **Button interactions** *(Pro)* — Fine-tune hover opacity, hover/active scale, transition duration, and focus ring width with presets (Subtle, Elevated, Bold).
|
|
253
|
+
6. **Typography interactions** *(Pro)* — Customize link hover/active behavior (opacity, scale, underline) and heading hover effects with live preview.
|
|
254
|
+
7. **Persistence** — All settings (colors, typography, card styles, dialog styles, toast styles, interactions) are saved to `localStorage` and restored on reload.
|
|
255
|
+
8. **Per-section export** — Every section header includes a CSS | Tokens split button to export CSS custom properties with Tailwind config, or W3C Design Token JSON, for that section.
|
|
256
|
+
9. **Shareable URLs** — Encode your full theme state in the URL hash and share it with anyone via a single link.
|
|
257
|
+
10. **Palette export** *(Pro)* — Download your palette as SVG or PNG, or copy as a HEX/RGB/RGBA text list.
|
|
258
|
+
11. **Custom fonts** *(Pro)* — Add any Google Font by name. The editor validates the font exists, loads all weights, adds it to heading/body dropdowns, and persists it across sessions.
|
|
259
|
+
12. **Mobile friendly** — Fully responsive UI with mobile-optimized dropdowns, compact swatch labels, and stacked layouts for smaller screens.
|
|
260
|
+
|
|
261
|
+
## Package Architecture
|
|
262
|
+
|
|
263
|
+
The editor is built with Vite in library mode and published as an ES module:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
@themal/editor
|
|
267
|
+
├── dist/index.js # ESM bundle (all components + utilities)
|
|
268
|
+
├── dist/index.d.ts # TypeScript declarations
|
|
269
|
+
└── dist/style.css # Pre-compiled, scoped Tailwind styles
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Exports Map
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
|
|
277
|
+
"./style.css": "./dist/style.css"
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Import the main entry point for components and utilities, and `style.css` separately for styles. This keeps CSS opt-in and avoids side effects during tree-shaking.
|
|
282
|
+
|
|
283
|
+
## Tailwind Scoping
|
|
284
|
+
|
|
285
|
+
The editor ships pre-compiled CSS via `@themal/editor/style.css`. Styles are scoped using Tailwind's `important: '.ds-editor'` so they don't conflict with your app's styles. The root element is automatically wrapped in `<div className="ds-editor">`.
|
|
286
|
+
|
|
287
|
+
## Development
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# From the repo root
|
|
291
|
+
npm install
|
|
292
|
+
|
|
293
|
+
# Build the package
|
|
294
|
+
cd packages/editor
|
|
295
|
+
npm run build
|
|
296
|
+
|
|
297
|
+
# Watch mode
|
|
298
|
+
npm run dev
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Testing
|
|
302
|
+
|
|
303
|
+
The project includes automated accessibility testing:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# Run all tests (includes axe-core a11y checks)
|
|
307
|
+
npm run test:run
|
|
308
|
+
|
|
309
|
+
# Lint for accessibility issues
|
|
310
|
+
npm run lint
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The test suite uses **vitest-axe** to run axe-core against rendered components, catching WCAG violations automatically. ESLint with **eslint-plugin-jsx-a11y** provides static analysis for common accessibility anti-patterns.
|
|
314
|
+
|
|
315
|
+
## Publishing to npm
|
|
316
|
+
|
|
317
|
+
The package is published as `@themal/editor` on npm. To publish a new version:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# 1. Build
|
|
321
|
+
cd packages/editor
|
|
322
|
+
npm run build
|
|
323
|
+
|
|
324
|
+
# 2. Verify the tarball contents (should only include dist/)
|
|
325
|
+
npm pack --dry-run
|
|
326
|
+
|
|
327
|
+
# 3. Bump the version
|
|
328
|
+
npm version patch # or minor / major
|
|
329
|
+
|
|
330
|
+
# 4. Publish (scoped packages require --access public on first publish)
|
|
331
|
+
npm publish --access public
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
You must be logged in to npm (`npm login`) with publish access to the `@themal` scope.
|
|
335
|
+
|
|
336
|
+
## License
|
|
337
|
+
|
|
338
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { default as default_2 } from 'react';
|
|
2
|
+
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
export declare function addCustomFont(name: string): Promise<CustomFontEntry>;
|
|
5
|
+
|
|
6
|
+
export declare const ALERT_STYLE_KEY = "ds-alert-style";
|
|
7
|
+
|
|
8
|
+
export declare interface AlertStyleState {
|
|
9
|
+
preset: "filled" | "soft" | "outline" | "minimal" | "custom";
|
|
10
|
+
borderRadius: number;
|
|
11
|
+
borderWidth: number;
|
|
12
|
+
iconStyle: "circle" | "plain";
|
|
13
|
+
padding: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export declare function applyStoredAlertStyle(): AlertStyleState | null;
|
|
17
|
+
|
|
18
|
+
export declare function applyStoredCardStyle(themeColors: Record<string, string>): CardStyleState | null;
|
|
19
|
+
|
|
20
|
+
export declare function applyStoredInteractionStyle(): InteractionStyleState | null;
|
|
21
|
+
|
|
22
|
+
export declare function applyStoredThemeColors(): void;
|
|
23
|
+
|
|
24
|
+
export declare function applyStoredToastStyle(): ToastStyleState | null;
|
|
25
|
+
|
|
26
|
+
export declare function applyStoredTypography(): TypographyState | null;
|
|
27
|
+
|
|
28
|
+
declare interface ButtonStyleState {
|
|
29
|
+
paddingX: number;
|
|
30
|
+
paddingY: number;
|
|
31
|
+
fontSize: number;
|
|
32
|
+
fontWeight: number;
|
|
33
|
+
borderRadius: number;
|
|
34
|
+
shadowOffsetX: number;
|
|
35
|
+
shadowOffsetY: number;
|
|
36
|
+
shadowBlur: number;
|
|
37
|
+
shadowSpread: number;
|
|
38
|
+
shadowColor: string;
|
|
39
|
+
borderWidth: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export declare const CARD_STYLE_KEY = "ds-card-style";
|
|
43
|
+
|
|
44
|
+
export declare interface CardStyleState {
|
|
45
|
+
preset: "liquid-glass" | "solid" | "gradient" | "border-only" | "custom";
|
|
46
|
+
shadowOffsetX: number;
|
|
47
|
+
shadowOffsetY: number;
|
|
48
|
+
shadowBlur: number;
|
|
49
|
+
shadowSpread: number;
|
|
50
|
+
shadowColor: string;
|
|
51
|
+
borderRadius: number;
|
|
52
|
+
bgType: "solid" | "gradient" | "transparent";
|
|
53
|
+
bgGradientAngle: number;
|
|
54
|
+
borderWidth: number;
|
|
55
|
+
backdropBlur: number;
|
|
56
|
+
bgOpacity: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export declare function contrastRatio(hsl1: string, hsl2: string): number;
|
|
60
|
+
|
|
61
|
+
export declare interface CustomFontEntry {
|
|
62
|
+
label: string;
|
|
63
|
+
value: string;
|
|
64
|
+
spec: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export declare function deserializeThemeState(hash: string): {
|
|
68
|
+
colors: Record<string, string>;
|
|
69
|
+
cardStyle: CardStyleState;
|
|
70
|
+
typographyState: TypographyState;
|
|
71
|
+
alertStyle: AlertStyleState;
|
|
72
|
+
interactionStyle: InteractionStyleState;
|
|
73
|
+
typoInteractionStyle: TypoInteractionStyleState;
|
|
74
|
+
buttonStyle: ButtonStyleState;
|
|
75
|
+
} | null;
|
|
76
|
+
|
|
77
|
+
export declare function DesignSystemEditor({ licenseKey, ...props }: DesignSystemEditorProps): JSX_2.Element;
|
|
78
|
+
|
|
79
|
+
export declare interface DesignSystemEditorProps {
|
|
80
|
+
/** URL for the PR creation endpoint. Hides PR button if omitted. */
|
|
81
|
+
prEndpointUrl?: string;
|
|
82
|
+
/** Enable accessibility audit via axe-core. Default: true */
|
|
83
|
+
accessibilityAudit?: boolean;
|
|
84
|
+
/** Callback fired on every color change with the full color map */
|
|
85
|
+
onChange?: (colors: Record<string, string>) => void;
|
|
86
|
+
/** Override built-in CSS export modal - receives the generated CSS string */
|
|
87
|
+
onExport?: (css: string) => void;
|
|
88
|
+
/** Additional CSS class for the wrapper element */
|
|
89
|
+
className?: string;
|
|
90
|
+
/** Show "How It Works", "README", and "Pricing" nav links. Default: true */
|
|
91
|
+
showNavLinks?: boolean;
|
|
92
|
+
/** Show the sticky header bar (logo, nav, PR button). Default: true. Set false for embedded/plugin usage. */
|
|
93
|
+
showHeader?: boolean;
|
|
94
|
+
/** License key to unlock premium features */
|
|
95
|
+
licenseKey?: string;
|
|
96
|
+
/** Custom URL for the "Upgrade" link shown on gated features */
|
|
97
|
+
upgradeUrl?: string;
|
|
98
|
+
/** Custom URL for the "Sign in" link shown on gated features */
|
|
99
|
+
signInUrl?: string;
|
|
100
|
+
/** Content rendered at the far right of the header row (e.g. auth buttons) */
|
|
101
|
+
headerRight?: default_2.ReactNode;
|
|
102
|
+
/** URL for the "Learn more about features" link */
|
|
103
|
+
featuresUrl?: string;
|
|
104
|
+
/** URL for the About page link in the header */
|
|
105
|
+
aboutUrl?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export declare const EDITABLE_VARS: readonly [{
|
|
109
|
+
readonly key: "--brand";
|
|
110
|
+
readonly label: "Brand Blue";
|
|
111
|
+
}, {
|
|
112
|
+
readonly key: "--secondary";
|
|
113
|
+
readonly label: "Secondary";
|
|
114
|
+
}, {
|
|
115
|
+
readonly key: "--background";
|
|
116
|
+
readonly label: "Background";
|
|
117
|
+
}, {
|
|
118
|
+
readonly key: "--foreground";
|
|
119
|
+
readonly label: "Foreground";
|
|
120
|
+
}, {
|
|
121
|
+
readonly key: "--card";
|
|
122
|
+
readonly label: "Card";
|
|
123
|
+
}, {
|
|
124
|
+
readonly key: "--card-foreground";
|
|
125
|
+
readonly label: "Card FG";
|
|
126
|
+
}, {
|
|
127
|
+
readonly key: "--popover";
|
|
128
|
+
readonly label: "Popover";
|
|
129
|
+
}, {
|
|
130
|
+
readonly key: "--popover-foreground";
|
|
131
|
+
readonly label: "Popover FG";
|
|
132
|
+
}, {
|
|
133
|
+
readonly key: "--primary";
|
|
134
|
+
readonly label: "Primary";
|
|
135
|
+
}, {
|
|
136
|
+
readonly key: "--primary-foreground";
|
|
137
|
+
readonly label: "Primary FG";
|
|
138
|
+
}, {
|
|
139
|
+
readonly key: "--secondary-foreground";
|
|
140
|
+
readonly label: "Secondary FG";
|
|
141
|
+
}, {
|
|
142
|
+
readonly key: "--muted";
|
|
143
|
+
readonly label: "Muted";
|
|
144
|
+
}, {
|
|
145
|
+
readonly key: "--muted-foreground";
|
|
146
|
+
readonly label: "Muted FG";
|
|
147
|
+
}, {
|
|
148
|
+
readonly key: "--accent";
|
|
149
|
+
readonly label: "Accent";
|
|
150
|
+
}, {
|
|
151
|
+
readonly key: "--accent-foreground";
|
|
152
|
+
readonly label: "Accent FG";
|
|
153
|
+
}, {
|
|
154
|
+
readonly key: "--destructive";
|
|
155
|
+
readonly label: "Destructive";
|
|
156
|
+
}, {
|
|
157
|
+
readonly key: "--destructive-foreground";
|
|
158
|
+
readonly label: "Destructive FG";
|
|
159
|
+
}, {
|
|
160
|
+
readonly key: "--success";
|
|
161
|
+
readonly label: "Success";
|
|
162
|
+
}, {
|
|
163
|
+
readonly key: "--success-foreground";
|
|
164
|
+
readonly label: "Success FG";
|
|
165
|
+
}, {
|
|
166
|
+
readonly key: "--warning";
|
|
167
|
+
readonly label: "Warning";
|
|
168
|
+
}, {
|
|
169
|
+
readonly key: "--warning-foreground";
|
|
170
|
+
readonly label: "Warning FG";
|
|
171
|
+
}, {
|
|
172
|
+
readonly key: "--border";
|
|
173
|
+
readonly label: "Border";
|
|
174
|
+
}, {
|
|
175
|
+
readonly key: "--ring";
|
|
176
|
+
readonly label: "Ring";
|
|
177
|
+
}];
|
|
178
|
+
|
|
179
|
+
export declare function exportPaletteAsPng(colors: Record<string, string>): Promise<Blob>;
|
|
180
|
+
|
|
181
|
+
export declare function exportPaletteAsSvg(colors: Record<string, string>): string;
|
|
182
|
+
|
|
183
|
+
export declare function exportPaletteAsText(colors: Record<string, string>, format: "hex" | "rgb" | "rgba"): string;
|
|
184
|
+
|
|
185
|
+
export declare function fgForBg(hslBg: string): string;
|
|
186
|
+
|
|
187
|
+
export declare function generateDesignTokens(colors: Record<string, string>, cardStyle: CardStyleState, typographyState: TypographyState, alertStyle: AlertStyleState, interactionStyle: InteractionStyleState): Record<string, unknown>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Generate a valid license key (for admin / sales tooling).
|
|
191
|
+
*/
|
|
192
|
+
export declare function generateLicenseKey(): string;
|
|
193
|
+
|
|
194
|
+
export declare function getCustomFonts(): CustomFontEntry[];
|
|
195
|
+
|
|
196
|
+
export declare const HARMONY_SCHEMES: readonly ["Complementary", "Analogous", "Triadic", "Split-Complementary"];
|
|
197
|
+
|
|
198
|
+
export declare type HarmonyScheme = typeof HARMONY_SCHEMES[number];
|
|
199
|
+
|
|
200
|
+
export declare function hexToHslString(hex: string): string;
|
|
201
|
+
|
|
202
|
+
export declare function hslStringToHex(hsl: string): string;
|
|
203
|
+
|
|
204
|
+
export declare function initCustomFonts(): void;
|
|
205
|
+
|
|
206
|
+
export declare const INTERACTION_STYLE_KEY = "ds-interaction-style";
|
|
207
|
+
|
|
208
|
+
export declare interface InteractionStyleState {
|
|
209
|
+
preset: "subtle" | "elevated" | "bold" | "custom";
|
|
210
|
+
hoverOpacity: number;
|
|
211
|
+
hoverScale: number;
|
|
212
|
+
activeScale: number;
|
|
213
|
+
transitionDuration: number;
|
|
214
|
+
focusRingWidth: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export declare function LicenseProvider({ children }: LicenseProviderProps): JSX_2.Element;
|
|
218
|
+
|
|
219
|
+
export declare interface LicenseProviderProps {
|
|
220
|
+
licenseKey?: string;
|
|
221
|
+
children: default_2.ReactNode;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export declare interface LicenseValidation {
|
|
225
|
+
isValid: boolean;
|
|
226
|
+
isPremium: boolean;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* License key validation and generation for @themal/editor premium features.
|
|
231
|
+
*
|
|
232
|
+
* Key format: THEMAL-XXXX-XXXX-XXXX
|
|
233
|
+
* - Segments use alphanumeric chars excluding ambiguous ones (0/O, 1/I/L).
|
|
234
|
+
* - The third segment is a checksum derived from the first two.
|
|
235
|
+
*/
|
|
236
|
+
export declare type PremiumFeature = "harmony-schemes" | "color-locks" | "pr-integration" | "undo" | "palette-export" | "image-palette" | "typography-spacing" | "custom-fonts" | "interaction-states" | "typography-interactions" | "toast-messages";
|
|
237
|
+
|
|
238
|
+
export declare function PremiumGate({ feature, variant, hideLock, upgradeUrl, signInUrl, children, }: PremiumGateProps): JSX_2.Element;
|
|
239
|
+
|
|
240
|
+
export declare interface PremiumGateProps {
|
|
241
|
+
feature: string;
|
|
242
|
+
/** "section" blocks content; "inline" shows lock inline. Default: "section" */
|
|
243
|
+
variant?: "section" | "inline";
|
|
244
|
+
/** Hide the external lock icon (e.g. when the button already has one inside) */
|
|
245
|
+
hideLock?: boolean;
|
|
246
|
+
upgradeUrl?: string;
|
|
247
|
+
signInUrl?: string;
|
|
248
|
+
children: default_2.ReactNode;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export declare function removeCustomFont(label: string): void;
|
|
252
|
+
|
|
253
|
+
export declare function serializeThemeState(colors: Record<string, string>, cardStyle: CardStyleState, typographyState: TypographyState, alertStyle: AlertStyleState, interactionStyle: InteractionStyleState, typoInteractionStyle: TypoInteractionStyleState, buttonStyle?: ButtonStyleState): string;
|
|
254
|
+
|
|
255
|
+
export declare const TOAST_STYLE_KEY = "ds-toast-style";
|
|
256
|
+
|
|
257
|
+
export declare type ToastStyleState = AlertStyleState;
|
|
258
|
+
|
|
259
|
+
export declare interface TokenDefinition {
|
|
260
|
+
key: string;
|
|
261
|
+
label: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export declare const TYPOGRAPHY_KEY = "ds-typography-v2";
|
|
265
|
+
|
|
266
|
+
export declare interface TypographyState {
|
|
267
|
+
preset: "system" | "modern" | "classic" | "compact" | "editorial" | "custom";
|
|
268
|
+
headingFamily: string;
|
|
269
|
+
bodyFamily: string;
|
|
270
|
+
baseFontSize: number;
|
|
271
|
+
headingWeight: number;
|
|
272
|
+
bodyWeight: number;
|
|
273
|
+
lineHeight: number;
|
|
274
|
+
letterSpacing: number;
|
|
275
|
+
headingLetterSpacing: number;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export declare interface TypoInteractionStyleState {
|
|
279
|
+
preset: "subtle" | "elevated" | "bold" | "custom";
|
|
280
|
+
linkHoverOpacity: number;
|
|
281
|
+
linkHoverScale: number;
|
|
282
|
+
linkActiveScale: number;
|
|
283
|
+
linkTransitionDuration: number;
|
|
284
|
+
linkUnderline: "always" | "hover" | "none";
|
|
285
|
+
headingHoverOpacity: number;
|
|
286
|
+
headingHoverScale: number;
|
|
287
|
+
headingTransitionDuration: number;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export declare function useLicense(): LicenseValidation;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Validate a license key string.
|
|
294
|
+
* Returns `{ isValid: true, isPremium: true }` for a correct key,
|
|
295
|
+
* or `{ isValid: false, isPremium: false }` otherwise.
|
|
296
|
+
*/
|
|
297
|
+
export declare function validateLicenseKey(key: string | undefined | null): LicenseValidation;
|
|
298
|
+
|
|
299
|
+
export { }
|