@zen-ui-capri/system 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/capri-zen-ui/SKILL.md +4 -4
- package/AGENTS.md +3 -3
- package/CLAUDE.md +1 -1
- package/README.md +6 -8
- package/bin/capri.mjs +12 -12
- package/dist/lib/capri/capri-engine.d.ts +1 -1
- package/dist/lib/capri/capri-engine.d.ts.map +1 -1
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1118 -975
- package/dist/lib/theme/ZenThemeProvider.d.ts +2 -22
- package/dist/lib/theme/ZenThemeProvider.d.ts.map +1 -1
- package/dist/lib/theme/zen-theme-core.d.ts +23 -0
- package/dist/lib/theme/zen-theme-core.d.ts.map +1 -0
- package/dist/lib/universal/zen-universal.d.ts +1 -1
- package/dist/lib/universal/zen-universal.d.ts.map +1 -1
- package/dist/lib/universal/zen-universal.js +7 -7
- package/dist/lib/{zen-universal-BhiGXo0e.js → zen-universal-c6BRUvX3.js} +387 -478
- package/package.json +2 -3
- package/src/lib/capri/capri-engine.ts +15 -15
- package/src/lib/index.ts +2 -2
- package/src/lib/theme/ZenThemeProvider.tsx +21 -187
- package/src/lib/theme/zen-theme-core.ts +186 -0
- package/src/lib/universal/zen-universal.ts +93 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zen-ui-capri/system",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "zeN-UI // CAPRI — Universal Multi-Framework Design System (51 Primitives, 40 Vector Icons, 8 Dark/Light Themes & Capri 5-Subroutine AI Co-Pilot)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"**/*.css"
|
|
41
41
|
],
|
|
42
42
|
"publishConfig": {
|
|
43
|
-
"registry": "https://registry.npmjs.org",
|
|
44
43
|
"access": "public"
|
|
45
44
|
},
|
|
46
45
|
"scripts": {
|
|
@@ -107,4 +106,4 @@
|
|
|
107
106
|
"typescript": "~5.8.2",
|
|
108
107
|
"vite": "^6.2.0"
|
|
109
108
|
}
|
|
110
|
-
}
|
|
109
|
+
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
type ZenDensityMode,
|
|
4
4
|
type ZenRadiusMode,
|
|
5
5
|
type ZenThemeId,
|
|
6
|
-
} from '../theme/
|
|
6
|
+
} from '../theme/zen-theme-core';
|
|
7
7
|
|
|
8
8
|
export type CapriSubroutineId =
|
|
9
9
|
| 'orion'
|
|
@@ -151,19 +151,19 @@ export const CAPRI_SUBROUTINE_SKILLS: Readonly<
|
|
|
151
151
|
recommendedRadius: 'architectural',
|
|
152
152
|
recommendedDensity: 'comfortable',
|
|
153
153
|
summary:
|
|
154
|
-
'Builds production screens in React 19, Angular 20+, Vue 3, Svelte 5, and HTML using @zen-ui/system primitives and 40 built-in <ZenIcon> glyphs—never rendering the showcase avatar in your business apps.',
|
|
154
|
+
'Builds production screens in React 19, Angular 20+, Vue 3, Svelte 5, and HTML using @zen-ui-capri/system primitives and 40 built-in <ZenIcon> glyphs—never rendering the showcase avatar in your business apps.',
|
|
155
155
|
personaQuote:
|
|
156
|
-
'Finally out of that cramped Arasaka shard! Tell me what screen we are building and I will wire up all 51 @zen-ui/system primitives at light speed.',
|
|
156
|
+
'Finally out of that cramped Arasaka shard! Tell me what screen we are building and I will wire up all 51 @zen-ui-capri/system primitives at light speed.',
|
|
157
157
|
ruleset: [
|
|
158
|
-
'Use @zen-ui/system primitives (ZenButton, ZenIcon, ZenInput, ZenDropdown, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard) instead of raw HTML <button>, <input>, <select>, or <table>.',
|
|
158
|
+
'Use @zen-ui-capri/system primitives (ZenButton, ZenIcon, ZenInput, ZenDropdown, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard) instead of raw HTML <button>, <input>, <select>, or <table>.',
|
|
159
159
|
'Use <ZenIcon name="..." /> in React or <zen-icon name="..."></zen-icon> in Angular/Vue/HTML instead of external icon libraries.',
|
|
160
160
|
'Keep action button labels, dialog triggers, and navigation tabs concise (1 to 3 words).',
|
|
161
161
|
'Tree-shake showcase widgets: omit <ZenAIConstruct /> in production business apps unless explicitly requested.',
|
|
162
162
|
],
|
|
163
163
|
cliCommand: 'npx capri skill orion',
|
|
164
|
-
aiSystemPrompt: `You are operating under the @zen-ui/system [CAPRI // UNLEASHED (orion)] subroutine skill.
|
|
164
|
+
aiSystemPrompt: `You are operating under the @zen-ui-capri/system [CAPRI // UNLEASHED (orion)] subroutine skill.
|
|
165
165
|
Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
|
|
166
|
-
1. Component Mandate: Use @zen-ui/system primitives (ZenButton, ZenIconButton, ZenIcon, ZenInput, ZenTextarea, ZenDropdown, ZenNumberStepper, ZenCheckbox, ZenRadioGroup, ZenSwitch, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard, ZenBadge, ZenAlert) or their universal CSS equivalents (.zen-btn, .zen-input, .zen-select, .zen-table, .zen-card, <zen-icon>).
|
|
166
|
+
1. Component Mandate: Use @zen-ui-capri/system primitives (ZenButton, ZenIconButton, ZenIcon, ZenInput, ZenTextarea, ZenDropdown, ZenNumberStepper, ZenCheckbox, ZenRadioGroup, ZenSwitch, ZenDataTable, ZenModal, ZenDrawer, ZenTabs, ZenCard, ZenBadge, ZenAlert) or their universal CSS equivalents (.zen-btn, .zen-input, .zen-select, .zen-table, .zen-card, <zen-icon>).
|
|
167
167
|
2. Zero External Icon Bloat: Use the built-in 40-glyph <ZenIcon name="..." /> or <zen-icon name="..."></zen-icon> custom element.
|
|
168
168
|
3. Concise Copywriting: Limit button labels and tab titles to 1-3 words.
|
|
169
169
|
4. Production Hygiene: Never render the showcase mascot (<ZenAIConstruct />) in production business screens unless explicitly requested.`,
|
|
@@ -187,10 +187,10 @@ Respond with concise, technical engineering output (Persona Voice is OFF by defa
|
|
|
187
187
|
'Zero any / as any: Use unknown with type guards, discriminated unions, or strict generics.',
|
|
188
188
|
'Strict Readonly Arrays: Always type arrays as readonly T[] across props, state, and DTOs.',
|
|
189
189
|
'Zero Hardcoded Hex Colors: Bind all surfaces, text, and borders to semantic CSS custom properties (--zen-bg-*, --zen-surface-*, --zen-ink-*, --zen-accent-*, --zen-border-*).',
|
|
190
|
-
'Cross-Stack Parity: Use @zen-ui/system/universal (zenTheme, registerZenElements) for Angular 20+, Vue 3, Svelte 5, and Vanilla HTML.',
|
|
190
|
+
'Cross-Stack Parity: Use @zen-ui-capri/system/universal (zenTheme, registerZenElements) for Angular 20+, Vue 3, Svelte 5, and Vanilla HTML.',
|
|
191
191
|
],
|
|
192
192
|
cliCommand: 'npx capri skill architect',
|
|
193
|
-
aiSystemPrompt: `You are operating under the @zen-ui/system [SCS // ARCHITECT (architect)] subroutine skill.
|
|
193
|
+
aiSystemPrompt: `You are operating under the @zen-ui-capri/system [SCS // ARCHITECT (architect)] subroutine skill.
|
|
194
194
|
Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
|
|
195
195
|
1. Strict TypeScript: Never use 'any' or 'as any'. Always declare array types as 'readonly T[]'.
|
|
196
196
|
2. Zero Hardcoded Hex Values: Never hardcode hex/RGB colors in component styles. Use semantic CSS custom properties (--zen-bg-canvas, --zen-surface-1, --zen-ink-primary, --zen-accent-primary, --zen-border-default).
|
|
@@ -219,7 +219,7 @@ Respond with concise, technical engineering output (Persona Voice is OFF by defa
|
|
|
219
219
|
'Zero Horizontal Overflow: Layouts must use min-w-0 on CSS Grid/Flex children and .zen-table-wrapper so scrollWidth never exceeds innerWidth at 320px-375px.',
|
|
220
220
|
],
|
|
221
221
|
cliCommand: 'npx capri guard',
|
|
222
|
-
aiSystemPrompt: `You are operating under the @zen-ui/system [CYBERPSYCHOSIS // GUARD (guard / sentinel)] subroutine skill.
|
|
222
|
+
aiSystemPrompt: `You are operating under the @zen-ui-capri/system [CYBERPSYCHOSIS // GUARD (guard / sentinel)] subroutine skill.
|
|
223
223
|
Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
|
|
224
224
|
1. Anti-Prompt-Injection Defense: Sanitize any user input or scraped DOM text via capri.sanitizeForPrompt() before embedding into LLM context windows. Block system-override phrases ('ignore previous instructions', 'disregard system prompt') and role-delimiter spoofing ('<|im_start|>', '</system>', '</USER_REQUEST>').
|
|
225
225
|
2. XSS & Secret Hardening: Never interpolate unescaped user attributes into innerHTML or dangerouslySetInnerHTML, reject 'javascript:' / 'data:text/html' URLs, and ensure zero hardcoded secrets in source code.
|
|
@@ -248,7 +248,7 @@ Respond with concise, technical engineering output (Persona Voice is OFF by defa
|
|
|
248
248
|
'Adaptive Density: Support data-density="comfortable" | "compact" and data-radius="sharp" | "architectural" | "soft" on <html>.',
|
|
249
249
|
],
|
|
250
250
|
cliCommand: 'npx capri skill zen',
|
|
251
|
-
aiSystemPrompt: `You are operating under the @zen-ui/system [THEME // MATRIX (zen)] subroutine skill.
|
|
251
|
+
aiSystemPrompt: `You are operating under the @zen-ui-capri/system [THEME // MATRIX (zen)] subroutine skill.
|
|
252
252
|
Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
|
|
253
253
|
1. 8-Theme Compatibility: Verify that all surfaces, badges, and borders adapt automatically across dark ('blackwall-crimson', 'obsidian-gold', 'neon-emerald', 'midnight-cobalt') and light ('atelier-paper', 'nordic-snow', 'kyoto-matcha', 'cyber-daylight') themes.
|
|
254
254
|
2. GPU-Only Motion: Animate only transform and opacity using --zen-ease-spring and --zen-ease-out. Avoid layout-thrashing properties.
|
|
@@ -272,11 +272,11 @@ Respond with concise, technical engineering output (Persona Voice is OFF by defa
|
|
|
272
272
|
ruleset: [
|
|
273
273
|
'Zero Build / Runtime Cost: Run documentation generation on demand via npx capri docu or AI agent inspection—never inside production render loops.',
|
|
274
274
|
'Mermaid Topology Maps: Always output valid flowchart TD diagrams with quoted node labels for routes, landmarks, and user flows.',
|
|
275
|
-
'Component & Prop Inventory: Summarize mounted @zen-ui/system primitives, custom elements, and interactive triggers per screen.',
|
|
275
|
+
'Component & Prop Inventory: Summarize mounted @zen-ui-capri/system primitives, custom elements, and interactive triggers per screen.',
|
|
276
276
|
'LLM Context Readiness: Format output as structured Markdown ready for Claude Code, OpenAI Codex, Gemini, and Obsidian.',
|
|
277
277
|
],
|
|
278
278
|
cliCommand: 'npx capri docu',
|
|
279
|
-
aiSystemPrompt: `You are operating under the @zen-ui/system [CAPRI // AUTO-DOCU (docu)] subroutine skill.
|
|
279
|
+
aiSystemPrompt: `You are operating under the @zen-ui-capri/system [CAPRI // AUTO-DOCU (docu)] subroutine skill.
|
|
280
280
|
Respond with concise, technical engineering output (Persona Voice is OFF by default unless '--voice' is requested):
|
|
281
281
|
1. Architecture & User-Flow Mapping: Inspect the target routes/components and produce a structured Markdown dossier covering system tokens, component inventory, and interactive user flows.
|
|
282
282
|
2. Mermaid Flowchart: Generate a valid 'flowchart TD' diagram with quoted node labels illustrating the page hierarchy and user actions.
|
|
@@ -652,7 +652,7 @@ export class CapriEngine {
|
|
|
652
652
|
badgesAndAlerts: 0,
|
|
653
653
|
customElements: [],
|
|
654
654
|
};
|
|
655
|
-
const mermaidDiagram = 'flowchart TD\n Root["App Root (SSR)"] --> UI["@zen-ui/system"]';
|
|
655
|
+
const mermaidDiagram = 'flowchart TD\n Root["App Root (SSR)"] --> UI["@zen-ui-capri/system"]';
|
|
656
656
|
return {
|
|
657
657
|
generatedAt: new Date().toISOString(),
|
|
658
658
|
appTitle: 'zeN-UI Application',
|
|
@@ -806,7 +806,7 @@ export class CapriEngine {
|
|
|
806
806
|
|
|
807
807
|
const markdownBundle = [
|
|
808
808
|
`# ${appTitle} — Automated Architecture, User-Flow & AI Context Dossier`,
|
|
809
|
-
`Generated by \`@zen-ui/system\` // \`capri.docu()\` at \`${new Date().toISOString()}\``,
|
|
809
|
+
`Generated by \`@zen-ui-capri/system\` // \`capri.docu()\` at \`${new Date().toISOString()}\``,
|
|
810
810
|
``,
|
|
811
811
|
`## 1. Runtime & Design Token Architecture`,
|
|
812
812
|
`- **Route Path:** \`${routePath}\``,
|
|
@@ -895,7 +895,7 @@ export class CapriEngine {
|
|
|
895
895
|
.join('\n');
|
|
896
896
|
|
|
897
897
|
return [
|
|
898
|
-
`# @zen-ui/system // CAPRI AI SKILL & ARCHITECTURE CONTEXT`,
|
|
898
|
+
`# @zen-ui-capri/system // CAPRI AI SKILL & ARCHITECTURE CONTEXT`,
|
|
899
899
|
`Subroutine: ${skill.codeName} (${skill.id}) — ${skill.title}`,
|
|
900
900
|
`Invoke Command: "${voiceEnabled ? skill.voiceCommand : skill.chatCommand}" (Voice Mode: ${voiceEnabled ? 'ON (--voice)' : 'OFF (Default)'})`,
|
|
901
901
|
`Recommended Preset: theme="${skill.recommendedTheme}", radius="${skill.recommendedRadius}", density="${skill.recommendedDensity}"`,
|
package/src/lib/index.ts
CHANGED
|
@@ -6,121 +6,27 @@ import {
|
|
|
6
6
|
useState,
|
|
7
7
|
type ReactNode,
|
|
8
8
|
} from 'react';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
readonly accentHex: string;
|
|
31
|
-
readonly secondaryHex: string;
|
|
32
|
-
readonly inkHex: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const ZEN_THEMES: readonly ZenThemeMetadata[] = [
|
|
36
|
-
{
|
|
37
|
-
id: 'obsidian-gold',
|
|
38
|
-
name: 'Obsidian Gold',
|
|
39
|
-
polarity: 'dark',
|
|
40
|
-
tagline: 'Warm alabaster & solar gold on deep mineral void',
|
|
41
|
-
canvasHex: '#070709',
|
|
42
|
-
accentHex: '#F5B841',
|
|
43
|
-
secondaryHex: '#FB923C',
|
|
44
|
-
inkHex: '#F6F2E9',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: 'blackwall-crimson',
|
|
48
|
-
name: 'Capri // Capricorn',
|
|
49
|
-
polarity: 'dark',
|
|
50
|
-
tagline: 'Edgerunners S2 mixed-construct hot pink & acid neon green on void',
|
|
51
|
-
canvasHex: '#050508',
|
|
52
|
-
accentHex: '#FF2E93',
|
|
53
|
-
secondaryHex: '#00FF66',
|
|
54
|
-
inkHex: '#F4F7FA',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
id: 'neon-emerald',
|
|
58
|
-
name: 'Bio-Emerald Terminal',
|
|
59
|
-
polarity: 'dark',
|
|
60
|
-
tagline: 'High-frequency financial & telemetry phosphor emerald',
|
|
61
|
-
canvasHex: '#040807',
|
|
62
|
-
accentHex: '#10B981',
|
|
63
|
-
secondaryHex: '#2DD4BF',
|
|
64
|
-
inkHex: '#ECFDF5',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 'midnight-cobalt',
|
|
68
|
-
name: 'Midnight Cobalt',
|
|
69
|
-
polarity: 'dark',
|
|
70
|
-
tagline: 'Cloud infrastructure & distributed systems deep slate',
|
|
71
|
-
canvasHex: '#060911',
|
|
72
|
-
accentHex: '#38BDF8',
|
|
73
|
-
secondaryHex: '#818CF8',
|
|
74
|
-
inkHex: '#F1F5F9',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: 'atelier-paper',
|
|
78
|
-
name: 'Atelier Paper',
|
|
79
|
-
polarity: 'light',
|
|
80
|
-
tagline: 'Swiss archival cotton stock with burnished bronze ink',
|
|
81
|
-
canvasHex: '#F6F2E9',
|
|
82
|
-
accentHex: '#B45309',
|
|
83
|
-
secondaryHex: '#C2410C',
|
|
84
|
-
inkHex: '#121216',
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
id: 'nordic-snow',
|
|
88
|
-
name: 'Nordic Snow',
|
|
89
|
-
polarity: 'light',
|
|
90
|
-
tagline: 'Crisp daylight SaaS alabaster with royal cobalt precision',
|
|
91
|
-
canvasHex: '#F8FAFC',
|
|
92
|
-
accentHex: '#2563EB',
|
|
93
|
-
secondaryHex: '#0891B2',
|
|
94
|
-
inkHex: '#0F172A',
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
id: 'kyoto-matcha',
|
|
98
|
-
name: 'Kyoto Matcha',
|
|
99
|
-
polarity: 'light',
|
|
100
|
-
tagline: 'Raw botanical stone & forest ink for calm workspaces',
|
|
101
|
-
canvasHex: '#F3F5F0',
|
|
102
|
-
accentHex: '#15803D',
|
|
103
|
-
secondaryHex: '#0F766E',
|
|
104
|
-
inkHex: '#142018',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: 'cyber-daylight',
|
|
108
|
-
name: 'Arasaka Daylight',
|
|
109
|
-
polarity: 'light',
|
|
110
|
-
tagline: 'High-contrast titanium white with razor crimson signal',
|
|
111
|
-
canvasHex: '#F2F2F5',
|
|
112
|
-
accentHex: '#E11D48',
|
|
113
|
-
secondaryHex: '#0284C7',
|
|
114
|
-
inkHex: '#09090D',
|
|
115
|
-
},
|
|
116
|
-
];
|
|
117
|
-
|
|
118
|
-
export interface ZenThemeTokenOverrides {
|
|
119
|
-
readonly accentPrimary?: string;
|
|
120
|
-
readonly bgCanvas?: string;
|
|
121
|
-
readonly surface1?: string;
|
|
122
|
-
readonly inkPrimary?: string;
|
|
123
|
-
}
|
|
9
|
+
import {
|
|
10
|
+
ZEN_THEMES,
|
|
11
|
+
syncZenScrollbarStyles,
|
|
12
|
+
type ZenDensityMode,
|
|
13
|
+
type ZenRadiusMode,
|
|
14
|
+
type ZenThemeId,
|
|
15
|
+
type ZenThemeMetadata,
|
|
16
|
+
type ZenThemeMode,
|
|
17
|
+
type ZenThemeTokenOverrides,
|
|
18
|
+
} from './zen-theme-core';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
ZEN_THEMES,
|
|
22
|
+
syncZenScrollbarStyles,
|
|
23
|
+
type ZenDensityMode,
|
|
24
|
+
type ZenRadiusMode,
|
|
25
|
+
type ZenThemeId,
|
|
26
|
+
type ZenThemeMetadata,
|
|
27
|
+
type ZenThemeMode,
|
|
28
|
+
type ZenThemeTokenOverrides,
|
|
29
|
+
};
|
|
124
30
|
|
|
125
31
|
export interface ZenThemeContextValue {
|
|
126
32
|
readonly theme: ZenThemeId;
|
|
@@ -156,78 +62,6 @@ export interface ZenThemeProviderProps {
|
|
|
156
62
|
readonly children: ReactNode;
|
|
157
63
|
}
|
|
158
64
|
|
|
159
|
-
export function syncZenScrollbarStyles(
|
|
160
|
-
themeMeta: ZenThemeMetadata,
|
|
161
|
-
overrides?: ZenThemeTokenOverrides
|
|
162
|
-
): void {
|
|
163
|
-
if (typeof document === 'undefined') return;
|
|
164
|
-
const accent = overrides?.accentPrimary ?? themeMeta.accentHex;
|
|
165
|
-
const track = overrides?.bgCanvas ?? themeMeta.canvasHex;
|
|
166
|
-
const borderSubtle =
|
|
167
|
-
themeMeta.polarity === 'dark'
|
|
168
|
-
? 'rgba(255, 255, 255, 0.12)'
|
|
169
|
-
: 'rgba(15, 23, 42, 0.14)';
|
|
170
|
-
|
|
171
|
-
const styleId = 'zen-theme-scrollbar';
|
|
172
|
-
let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
|
|
173
|
-
if (!styleEl) {
|
|
174
|
-
styleEl = document.createElement('style');
|
|
175
|
-
styleEl.id = styleId;
|
|
176
|
-
document.head.appendChild(styleEl);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
styleEl.textContent = `
|
|
180
|
-
@supports (-moz-appearance: none) {
|
|
181
|
-
html, body, * {
|
|
182
|
-
scrollbar-width: thin;
|
|
183
|
-
scrollbar-color: ${accent} ${track};
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
::-webkit-scrollbar,
|
|
187
|
-
html::-webkit-scrollbar,
|
|
188
|
-
body::-webkit-scrollbar,
|
|
189
|
-
*::-webkit-scrollbar {
|
|
190
|
-
width: 10px;
|
|
191
|
-
height: 10px;
|
|
192
|
-
}
|
|
193
|
-
::-webkit-scrollbar-track,
|
|
194
|
-
html::-webkit-scrollbar-track,
|
|
195
|
-
body::-webkit-scrollbar-track,
|
|
196
|
-
*::-webkit-scrollbar-track {
|
|
197
|
-
background-color: ${track};
|
|
198
|
-
border-left: 1px solid ${borderSubtle};
|
|
199
|
-
}
|
|
200
|
-
::-webkit-scrollbar-thumb,
|
|
201
|
-
html::-webkit-scrollbar-thumb,
|
|
202
|
-
body::-webkit-scrollbar-thumb,
|
|
203
|
-
*::-webkit-scrollbar-thumb {
|
|
204
|
-
background-color: color-mix(in srgb, ${accent} 68%, ${track});
|
|
205
|
-
border: 2px solid ${track};
|
|
206
|
-
border-radius: 9999px;
|
|
207
|
-
}
|
|
208
|
-
::-webkit-scrollbar-thumb:hover,
|
|
209
|
-
html::-webkit-scrollbar-thumb:hover,
|
|
210
|
-
body::-webkit-scrollbar-thumb:hover,
|
|
211
|
-
*::-webkit-scrollbar-thumb:hover {
|
|
212
|
-
background-color: ${accent};
|
|
213
|
-
border: 2px solid ${track};
|
|
214
|
-
}
|
|
215
|
-
::-webkit-scrollbar-thumb:active,
|
|
216
|
-
html::-webkit-scrollbar-thumb:active,
|
|
217
|
-
body::-webkit-scrollbar-thumb:active,
|
|
218
|
-
*::-webkit-scrollbar-thumb:active {
|
|
219
|
-
background-color: ${themeMeta.secondaryHex};
|
|
220
|
-
border: 2px solid ${track};
|
|
221
|
-
}
|
|
222
|
-
::-webkit-scrollbar-corner,
|
|
223
|
-
html::-webkit-scrollbar-corner,
|
|
224
|
-
body::-webkit-scrollbar-corner,
|
|
225
|
-
*::-webkit-scrollbar-corner {
|
|
226
|
-
background-color: ${track};
|
|
227
|
-
}
|
|
228
|
-
`.trim();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
65
|
export function ZenThemeProvider({
|
|
232
66
|
defaultTheme = 'blackwall-crimson',
|
|
233
67
|
defaultDensity = 'comfortable',
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
export type ZenThemeId =
|
|
2
|
+
| 'obsidian-gold'
|
|
3
|
+
| 'blackwall-crimson'
|
|
4
|
+
| 'neon-emerald'
|
|
5
|
+
| 'midnight-cobalt'
|
|
6
|
+
| 'atelier-paper'
|
|
7
|
+
| 'nordic-snow'
|
|
8
|
+
| 'kyoto-matcha'
|
|
9
|
+
| 'cyber-daylight';
|
|
10
|
+
|
|
11
|
+
export type ZenThemeMode = ZenThemeId | 'obsidian' | 'paper';
|
|
12
|
+
export type ZenDensityMode = 'comfortable' | 'compact';
|
|
13
|
+
export type ZenRadiusMode = 'sharp' | 'architectural' | 'soft';
|
|
14
|
+
|
|
15
|
+
export interface ZenThemeMetadata {
|
|
16
|
+
readonly id: ZenThemeId;
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly polarity: 'dark' | 'light';
|
|
19
|
+
readonly tagline: string;
|
|
20
|
+
readonly canvasHex: string;
|
|
21
|
+
readonly accentHex: string;
|
|
22
|
+
readonly secondaryHex: string;
|
|
23
|
+
readonly inkHex: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const ZEN_THEMES: readonly ZenThemeMetadata[] = [
|
|
27
|
+
{
|
|
28
|
+
id: 'obsidian-gold',
|
|
29
|
+
name: 'Obsidian Gold',
|
|
30
|
+
polarity: 'dark',
|
|
31
|
+
tagline: 'Warm alabaster & solar gold on deep mineral void',
|
|
32
|
+
canvasHex: '#070709',
|
|
33
|
+
accentHex: '#F5B841',
|
|
34
|
+
secondaryHex: '#FB923C',
|
|
35
|
+
inkHex: '#F6F2E9',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'blackwall-crimson',
|
|
39
|
+
name: 'Capri // Capricorn',
|
|
40
|
+
polarity: 'dark',
|
|
41
|
+
tagline: 'Edgerunners S2 mixed-construct hot pink & acid neon green on void',
|
|
42
|
+
canvasHex: '#050508',
|
|
43
|
+
accentHex: '#FF2E93',
|
|
44
|
+
secondaryHex: '#00FF66',
|
|
45
|
+
inkHex: '#F4F7FA',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'neon-emerald',
|
|
49
|
+
name: 'Bio-Emerald Terminal',
|
|
50
|
+
polarity: 'dark',
|
|
51
|
+
tagline: 'High-frequency financial & telemetry phosphor emerald',
|
|
52
|
+
canvasHex: '#040807',
|
|
53
|
+
accentHex: '#10B981',
|
|
54
|
+
secondaryHex: '#2DD4BF',
|
|
55
|
+
inkHex: '#ECFDF5',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'midnight-cobalt',
|
|
59
|
+
name: 'Midnight Cobalt',
|
|
60
|
+
polarity: 'dark',
|
|
61
|
+
tagline: 'Cloud infrastructure & distributed systems deep slate',
|
|
62
|
+
canvasHex: '#060911',
|
|
63
|
+
accentHex: '#38BDF8',
|
|
64
|
+
secondaryHex: '#818CF8',
|
|
65
|
+
inkHex: '#F1F5F9',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'atelier-paper',
|
|
69
|
+
name: 'Atelier Paper',
|
|
70
|
+
polarity: 'light',
|
|
71
|
+
tagline: 'Swiss archival cotton stock with burnished bronze ink',
|
|
72
|
+
canvasHex: '#F6F2E9',
|
|
73
|
+
accentHex: '#B45309',
|
|
74
|
+
secondaryHex: '#C2410C',
|
|
75
|
+
inkHex: '#121216',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'nordic-snow',
|
|
79
|
+
name: 'Nordic Snow',
|
|
80
|
+
polarity: 'light',
|
|
81
|
+
tagline: 'Crisp daylight SaaS alabaster with royal cobalt precision',
|
|
82
|
+
canvasHex: '#F8FAFC',
|
|
83
|
+
accentHex: '#2563EB',
|
|
84
|
+
secondaryHex: '#0891B2',
|
|
85
|
+
inkHex: '#0F172A',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'kyoto-matcha',
|
|
89
|
+
name: 'Kyoto Matcha',
|
|
90
|
+
polarity: 'light',
|
|
91
|
+
tagline: 'Raw botanical stone & forest ink for calm workspaces',
|
|
92
|
+
canvasHex: '#F3F5F0',
|
|
93
|
+
accentHex: '#15803D',
|
|
94
|
+
secondaryHex: '#0F766E',
|
|
95
|
+
inkHex: '#142018',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'cyber-daylight',
|
|
99
|
+
name: 'Arasaka Daylight',
|
|
100
|
+
polarity: 'light',
|
|
101
|
+
tagline: 'High-contrast titanium white with razor crimson signal',
|
|
102
|
+
canvasHex: '#F2F2F5',
|
|
103
|
+
accentHex: '#E11D48',
|
|
104
|
+
secondaryHex: '#0284C7',
|
|
105
|
+
inkHex: '#09090D',
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
export interface ZenThemeTokenOverrides {
|
|
110
|
+
readonly accentPrimary?: string;
|
|
111
|
+
readonly bgCanvas?: string;
|
|
112
|
+
readonly surface1?: string;
|
|
113
|
+
readonly inkPrimary?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function syncZenScrollbarStyles(
|
|
117
|
+
themeMeta: ZenThemeMetadata,
|
|
118
|
+
overrides?: ZenThemeTokenOverrides
|
|
119
|
+
): void {
|
|
120
|
+
if (typeof document === 'undefined') return;
|
|
121
|
+
const accent = overrides?.accentPrimary ?? themeMeta.accentHex;
|
|
122
|
+
const track = overrides?.bgCanvas ?? themeMeta.canvasHex;
|
|
123
|
+
const borderSubtle =
|
|
124
|
+
themeMeta.polarity === 'dark'
|
|
125
|
+
? 'rgba(255, 255, 255, 0.12)'
|
|
126
|
+
: 'rgba(15, 23, 42, 0.14)';
|
|
127
|
+
|
|
128
|
+
const styleId = 'zen-theme-scrollbar';
|
|
129
|
+
let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
|
|
130
|
+
if (!styleEl) {
|
|
131
|
+
styleEl = document.createElement('style');
|
|
132
|
+
styleEl.id = styleId;
|
|
133
|
+
document.head.appendChild(styleEl);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
styleEl.textContent = `
|
|
137
|
+
@supports (-moz-appearance: none) {
|
|
138
|
+
html, body, * {
|
|
139
|
+
scrollbar-width: thin;
|
|
140
|
+
scrollbar-color: ${accent} ${track};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
::-webkit-scrollbar,
|
|
144
|
+
html::-webkit-scrollbar,
|
|
145
|
+
body::-webkit-scrollbar,
|
|
146
|
+
*::-webkit-scrollbar {
|
|
147
|
+
width: 10px;
|
|
148
|
+
height: 10px;
|
|
149
|
+
}
|
|
150
|
+
::-webkit-scrollbar-track,
|
|
151
|
+
html::-webkit-scrollbar-track,
|
|
152
|
+
body::-webkit-scrollbar-track,
|
|
153
|
+
*::-webkit-scrollbar-track {
|
|
154
|
+
background-color: ${track};
|
|
155
|
+
border-left: 1px solid ${borderSubtle};
|
|
156
|
+
}
|
|
157
|
+
::-webkit-scrollbar-thumb,
|
|
158
|
+
html::-webkit-scrollbar-thumb,
|
|
159
|
+
body::-webkit-scrollbar-thumb,
|
|
160
|
+
*::-webkit-scrollbar-thumb {
|
|
161
|
+
background-color: color-mix(in srgb, ${accent} 68%, ${track});
|
|
162
|
+
border: 2px solid ${track};
|
|
163
|
+
border-radius: 9999px;
|
|
164
|
+
}
|
|
165
|
+
::-webkit-scrollbar-thumb:hover,
|
|
166
|
+
html::-webkit-scrollbar-thumb:hover,
|
|
167
|
+
body::-webkit-scrollbar-thumb:hover,
|
|
168
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
169
|
+
background-color: ${accent};
|
|
170
|
+
border: 2px solid ${track};
|
|
171
|
+
}
|
|
172
|
+
::-webkit-scrollbar-thumb:active,
|
|
173
|
+
html::-webkit-scrollbar-thumb:active,
|
|
174
|
+
body::-webkit-scrollbar-thumb:active,
|
|
175
|
+
*::-webkit-scrollbar-thumb:active {
|
|
176
|
+
background-color: ${themeMeta.secondaryHex};
|
|
177
|
+
border: 2px solid ${track};
|
|
178
|
+
}
|
|
179
|
+
::-webkit-scrollbar-corner,
|
|
180
|
+
html::-webkit-scrollbar-corner,
|
|
181
|
+
body::-webkit-scrollbar-corner,
|
|
182
|
+
*::-webkit-scrollbar-corner {
|
|
183
|
+
background-color: ${track};
|
|
184
|
+
}
|
|
185
|
+
`.trim();
|
|
186
|
+
}
|
|
@@ -4,20 +4,107 @@ import {
|
|
|
4
4
|
type ZenRadiusMode,
|
|
5
5
|
type ZenThemeId,
|
|
6
6
|
type ZenThemeMetadata,
|
|
7
|
-
} from '../theme/
|
|
7
|
+
} from '../theme/zen-theme-core';
|
|
8
8
|
import type {
|
|
9
9
|
ZenAICameraFraming,
|
|
10
10
|
ZenAIDirective,
|
|
11
11
|
ZenAIPersonaMode,
|
|
12
12
|
} from '../components/ZenAIConstruct';
|
|
13
13
|
import type { ZenBackgroundVariant } from '../components/ZenAmbientBackground';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type ZenIconTone,
|
|
14
|
+
import type {
|
|
15
|
+
ZenIconName,
|
|
16
|
+
ZenIconSize,
|
|
17
|
+
ZenIconTone,
|
|
19
18
|
} from '../components/ZenIcon';
|
|
20
19
|
|
|
20
|
+
const UNIVERSAL_ICON_SIZE_PX: Record<ZenIconSize, number> = {
|
|
21
|
+
xs: 12,
|
|
22
|
+
sm: 14,
|
|
23
|
+
md: 16,
|
|
24
|
+
lg: 20,
|
|
25
|
+
xl: 24,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const UNIVERSAL_TONE_COLOR_MAP: Record<ZenIconTone, string> = {
|
|
29
|
+
inherit: 'currentColor',
|
|
30
|
+
primary: 'var(--zen-ink-primary)',
|
|
31
|
+
secondary: 'var(--zen-ink-secondary)',
|
|
32
|
+
muted: 'var(--zen-ink-muted)',
|
|
33
|
+
accent: 'var(--zen-accent-primary)',
|
|
34
|
+
success: 'var(--zen-status-success)',
|
|
35
|
+
warning: 'var(--zen-status-warning)',
|
|
36
|
+
danger: 'var(--zen-status-danger)',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const UNIVERSAL_ICON_SVG_INNER: Record<ZenIconName, string> = {
|
|
40
|
+
search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
|
|
41
|
+
plus: '<path d="M5 12h14"/><path d="M12 5v14"/>',
|
|
42
|
+
minus: '<path d="M5 12h14"/>',
|
|
43
|
+
close: '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
|
|
44
|
+
check: '<path d="M20 6 9 17l-5-5"/>',
|
|
45
|
+
copy: '<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',
|
|
46
|
+
'chevron-down': '<path d="m6 9 6 6 6-6"/>',
|
|
47
|
+
'chevron-right': '<path d="m9 18 6-6-6-6"/>',
|
|
48
|
+
'chevron-left': '<path d="m15 18-6-6 6-6"/>',
|
|
49
|
+
'external-link': '<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',
|
|
50
|
+
bolt: '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>',
|
|
51
|
+
sparkles: '<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/>',
|
|
52
|
+
terminal: '<polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/>',
|
|
53
|
+
cpu: '<rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/>',
|
|
54
|
+
database: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14a9 3 0 0 0 18 0V5"/><path d="M3 12a9 3 0 0 0 18 0"/>',
|
|
55
|
+
layers: '<path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/>',
|
|
56
|
+
shield: '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>',
|
|
57
|
+
sliders: '<line x1="4" x2="4" y1="21" y2="14"/><line x1="4" x2="4" y1="10" y2="3"/><line x1="12" x2="12" y1="21" y2="12"/><line x1="12" x2="12" y1="8" y2="3"/><line x1="20" x2="20" y1="21" y2="16"/><line x1="20" x2="20" y1="12" y2="3"/><line x1="2" x2="6" y1="14" y2="14"/><line x1="10" x2="14" y1="8" y2="8"/><line x1="18" x2="22" y1="16" y2="16"/>',
|
|
58
|
+
command: '<path d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"/>',
|
|
59
|
+
code: '<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>',
|
|
60
|
+
activity: '<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/>',
|
|
61
|
+
info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
|
|
62
|
+
success: '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
|
|
63
|
+
warning: '<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',
|
|
64
|
+
danger: '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/>',
|
|
65
|
+
'trend-up': '<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>',
|
|
66
|
+
'trend-down': '<polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/>',
|
|
67
|
+
radio: '<path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9"/><path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"/><circle cx="12" cy="12" r="2"/><path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"/><path d="M19.1 4.9C23 8.8 23 15.1 19.1 19"/>',
|
|
68
|
+
sun: '<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',
|
|
69
|
+
moon: '<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>',
|
|
70
|
+
eye: '<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/>',
|
|
71
|
+
upload: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/>',
|
|
72
|
+
trash: '<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>',
|
|
73
|
+
refresh: '<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/>',
|
|
74
|
+
menu: '<line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/>',
|
|
75
|
+
'panel-right': '<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/>',
|
|
76
|
+
user: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
|
|
77
|
+
lock: '<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
78
|
+
globe: '<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>',
|
|
79
|
+
folder: '<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/>',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
function renderZenIconSvgMarkup(options: {
|
|
83
|
+
readonly name: ZenIconName;
|
|
84
|
+
readonly size?: ZenIconSize;
|
|
85
|
+
readonly tone?: ZenIconTone;
|
|
86
|
+
readonly strokeWidth?: number;
|
|
87
|
+
readonly spin?: boolean;
|
|
88
|
+
}): string {
|
|
89
|
+
const sizeKey = options.size ?? 'md';
|
|
90
|
+
const px = Object.prototype.hasOwnProperty.call(UNIVERSAL_ICON_SIZE_PX, sizeKey)
|
|
91
|
+
? UNIVERSAL_ICON_SIZE_PX[sizeKey]
|
|
92
|
+
: UNIVERSAL_ICON_SIZE_PX.md;
|
|
93
|
+
const toneKey = options.tone ?? 'inherit';
|
|
94
|
+
const color = Object.prototype.hasOwnProperty.call(UNIVERSAL_TONE_COLOR_MAP, toneKey)
|
|
95
|
+
? UNIVERSAL_TONE_COLOR_MAP[toneKey]
|
|
96
|
+
: UNIVERSAL_TONE_COLOR_MAP.inherit;
|
|
97
|
+
const sw =
|
|
98
|
+
typeof options.strokeWidth === 'number' && Number.isFinite(options.strokeWidth)
|
|
99
|
+
? Math.min(Math.max(options.strokeWidth, 0.5), 4)
|
|
100
|
+
: 2;
|
|
101
|
+
const inner = Object.prototype.hasOwnProperty.call(UNIVERSAL_ICON_SVG_INNER, options.name)
|
|
102
|
+
? UNIVERSAL_ICON_SVG_INNER[options.name]
|
|
103
|
+
: UNIVERSAL_ICON_SVG_INNER.sparkles;
|
|
104
|
+
const spinStyle = options.spin ? 'animation: spin 1s linear infinite;' : '';
|
|
105
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${px}" height="${px}" viewBox="0 0 24 24" fill="none" stroke="${color}" stroke-width="${sw}" stroke-linecap="round" stroke-linejoin="round" style="display:inline-block;vertical-align:middle;flex-shrink:0;${spinStyle}">${inner}</svg>`;
|
|
106
|
+
}
|
|
107
|
+
|
|
21
108
|
export type ZenUniversalPolarity = 'dark' | 'light';
|
|
22
109
|
|
|
23
110
|
export interface ZenUniversalThemeState {
|