@zantopia/zephyr-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,267 @@
1
+ # 🦊 @zephyr/ui
2
+
3
+ Embeddable AI assistant widget for any web project. Import `<Zephyr />` into React, Vue, or vanilla JS — configure everything via a single config file.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @zephyr/ui
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### React
14
+
15
+ ```tsx
16
+ import { Zephyr } from '@zephyr/ui/react';
17
+
18
+ function App() {
19
+ return (
20
+ <div>
21
+ <h1>Mon App</h1>
22
+ <Zephyr
23
+ server="http://localhost:8000"
24
+ theme="dark"
25
+ persona="friendly"
26
+ logo="zephyr-default"
27
+ accentColor="#ff6b35"
28
+ />
29
+ </div>
30
+ );
31
+ }
32
+ ```
33
+
34
+ ### Vue 3
35
+
36
+ ```vue
37
+ <script setup>
38
+ import { Zephyr } from '@zephyr/ui/vue';
39
+ </script>
40
+
41
+ <template>
42
+ <div>
43
+ <h1>Mon App</h1>
44
+ <Zephyr
45
+ server="http://localhost:8000"
46
+ theme="dark"
47
+ persona="friendly"
48
+ logo="zephyr-default"
49
+ accent-color="#ff6b35"
50
+ />
51
+ </div>
52
+ </template>
53
+ ```
54
+
55
+ ### Vanilla JS
56
+
57
+ ```js
58
+ import { init } from '@zephyr/ui';
59
+
60
+ init({
61
+ server: 'http://localhost:8000',
62
+ theme: 'dark',
63
+ persona: 'friendly',
64
+ logo: 'zephyr-default',
65
+ accentColor: '#ff6b35',
66
+ });
67
+ ```
68
+
69
+ ## Configuration File
70
+
71
+ Create a `zephyr.config.ts` in your project:
72
+
73
+ ```ts
74
+ import { defineZephyrConfig } from '@zephyr/ui/config';
75
+
76
+ export default defineZephyrConfig({
77
+ // Connection
78
+ server: 'http://localhost:8000',
79
+ apiKey: 'your-api-key',
80
+
81
+ // Appearance
82
+ logo: 'zephyr-default', // Built-in or custom URL
83
+ persona: 'friendly', // Built-in or custom object
84
+ theme: 'dark', // 'dark' | 'light' | 'auto' | custom
85
+ accentColor: '#ff6b35',
86
+
87
+ // Animations
88
+ openAnimation: 'slide-up', // Panel open animation
89
+ triggerAnimation: 'float', // Trigger button animation
90
+
91
+ // Panel
92
+ panel: {
93
+ position: 'bottom-right',
94
+ size: 'md',
95
+ borderRadius: 16,
96
+ backdrop: false,
97
+ draggable: false,
98
+ },
99
+
100
+ // Content
101
+ language: 'fr',
102
+ greeting: 'Bonjour ! Comment puis-je vous aider ? 🦊',
103
+ placeholder: 'Posez une question...',
104
+ features: ['chat', 'guide', 'search'],
105
+ });
106
+ ```
107
+
108
+ Then use it:
109
+
110
+ ```tsx
111
+ import config from './zephyr.config';
112
+ import { Zephyr } from '@zephyr/ui/react';
113
+
114
+ <Zephyr config={config} />
115
+ ```
116
+
117
+ ## Configuration Reference
118
+
119
+ ### Logo
120
+
121
+ | Value | Description |
122
+ |---|---|
123
+ | `'zephyr-default'` | Official Zephyr fox logo |
124
+ | `'https://...'` | Custom image URL |
125
+ | `{ trigger: '...', header: '...' }` | Separate trigger & header images |
126
+
127
+ ### Persona
128
+
129
+ | Value | Description |
130
+ |---|---|
131
+ | `'friendly'` | Warm, approachable (default) |
132
+ | `'professional'` | Clean, business-like |
133
+ | `'playful'` | Fun, animated |
134
+ | `'futuristic'` | Sci-fi, cyber |
135
+ | `{ name, avatar, avatarType }` | Custom persona (gif/svg/lottie/image) |
136
+
137
+ ### Theme
138
+
139
+ | Value | Description |
140
+ |---|---|
141
+ | `'dark'` | Dark mode (default) |
142
+ | `'light'` | Light mode |
143
+ | `'auto'` | Follows system preference |
144
+ | `{ background, surface, text, ... }` | Full custom theme object |
145
+
146
+ ### Open Animation
147
+
148
+ `slide-up` · `slide-down` · `slide-left` · `slide-right` · `fade` · `scale` · `bounce` · `none`
149
+
150
+ ### Trigger Animation
151
+
152
+ `float` · `pulse` · `bounce` · `glow` · `none`
153
+
154
+ ### Panel Position
155
+
156
+ `bottom-right` · `bottom-left` · `top-right` · `top-left`
157
+
158
+ ### Panel Size
159
+
160
+ | Size | Width | Height |
161
+ |---|---|---|
162
+ | `sm` | 320px | 440px |
163
+ | `md` | 380px | 520px |
164
+ | `lg` | 440px | 600px |
165
+
166
+ ## Runtime API
167
+
168
+ ### React Hook
169
+
170
+ ```tsx
171
+ import { useZephyr } from '@zephyr/ui/react';
172
+
173
+ function MyButton() {
174
+ const { send, toggle, setTheme, setPersona, isOpen } = useZephyr();
175
+
176
+ return (
177
+ <button onClick={() => toggle()}>
178
+ {isOpen() ? 'Close' : 'Open'} Zephyr
179
+ </button>
180
+ );
181
+ }
182
+ ```
183
+
184
+ ### Vanilla JS
185
+
186
+ ```js
187
+ import { init, getInstance, destroy } from '@zephyr/ui';
188
+
189
+ const widget = init({ server: '...' });
190
+
191
+ widget.toggle();
192
+ widget.send('Hello!');
193
+ widget.setTheme('light');
194
+ widget.setAccentColor('#00bcd4');
195
+
196
+ // Later:
197
+ destroy();
198
+ ```
199
+
200
+ ## Backend Configuration
201
+
202
+ Create `zephyr.server.yaml` in your project to configure the LLM backend:
203
+
204
+ ```yaml
205
+ # Which LLM subscription to use
206
+ provider: openai # github-copilot | claude | openai | ollama
207
+
208
+ # Provider settings
209
+ openai:
210
+ api_key: ${OPENAI_API_KEY}
211
+ model: gpt-4o
212
+
213
+ github-copilot:
214
+ token: ${GITHUB_TOKEN}
215
+ model: gpt-4o
216
+
217
+ claude:
218
+ api_key: ${ANTHROPIC_API_KEY}
219
+ model: claude-sonnet-4-20250514
220
+
221
+ ollama:
222
+ base_url: http://localhost:11434
223
+ model: llama3
224
+ ```
225
+
226
+ ## Dev Mode (MCP)
227
+
228
+ For developers who want to debug UI with Copilot or Claude Code:
229
+
230
+ 1. Configure `.vscode/mcp.json`:
231
+
232
+ ```json
233
+ {
234
+ "servers": {
235
+ "zephyr": {
236
+ "command": "python",
237
+ "args": ["-m", "mcp_server.server"],
238
+ "cwd": "${workspaceFolder}/ui-intelligence"
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ 2. Install the MCP server: `pip install mcp[cli]`
245
+
246
+ 3. Reload VS Code and use MCP tools in Copilot Chat:
247
+ - `capture_screenshot` — Visual page inspection
248
+ - `extract_dom` — DOM structure analysis
249
+ - `console_errors` — JavaScript error capture
250
+ - `performance_audit` — Perf metrics
251
+ - `accessibility_check` — A11y audit
252
+ - `visual_diff` — Regression detection
253
+ - `full_analysis` — Complete UI analysis
254
+
255
+ ## Exports Map
256
+
257
+ | Import | Contents |
258
+ |---|---|
259
+ | `@zephyr/ui` | Everything: widget, types, config, themes |
260
+ | `@zephyr/ui/react` | `<Zephyr />`, `ZephyrProvider`, `useZephyr()` |
261
+ | `@zephyr/ui/vue` | `<Zephyr />` Vue component |
262
+ | `@zephyr/ui/config` | `defineZephyrConfig()`, types |
263
+ | `@zephyr/ui/themes` | Theme objects and helpers |
264
+
265
+ ## License
266
+
267
+ MIT
@@ -0,0 +1,118 @@
1
+ import { jsx as g } from "react/jsx-runtime";
2
+ import { createContext as l, useContext as d, useRef as a, useEffect as r } from "react";
3
+ import { Z as u } from "./widget-BjgCJR9K.js";
4
+ const c = l({
5
+ config: null,
6
+ widget: null
7
+ });
8
+ function h({ config: t, children: e }) {
9
+ const n = a(null);
10
+ return /* @__PURE__ */ g(c.Provider, { value: { config: t, widget: n.current }, children: e });
11
+ }
12
+ function A() {
13
+ const t = a(null);
14
+ return {
15
+ send: (e) => {
16
+ var n;
17
+ return (n = t.current) == null ? void 0 : n.send(e);
18
+ },
19
+ open: () => {
20
+ var e;
21
+ return (e = t.current) == null ? void 0 : e.open();
22
+ },
23
+ close: () => {
24
+ var e;
25
+ return (e = t.current) == null ? void 0 : e.close();
26
+ },
27
+ toggle: () => {
28
+ var e;
29
+ return (e = t.current) == null ? void 0 : e.toggle();
30
+ },
31
+ setTheme: (e) => {
32
+ var n;
33
+ return (n = t.current) == null ? void 0 : n.setTheme(e);
34
+ },
35
+ setLogo: (e) => {
36
+ var n;
37
+ return (n = t.current) == null ? void 0 : n.setLogo(e);
38
+ },
39
+ setPersona: (e) => {
40
+ var n;
41
+ return (n = t.current) == null ? void 0 : n.setPersona(e);
42
+ },
43
+ setAccentColor: (e) => {
44
+ var n;
45
+ return (n = t.current) == null ? void 0 : n.setAccentColor(e);
46
+ },
47
+ getMessages: () => {
48
+ var e;
49
+ return ((e = t.current) == null ? void 0 : e.getMessages()) || [];
50
+ },
51
+ isOpen: () => {
52
+ var e;
53
+ return ((e = t.current) == null ? void 0 : e.getIsOpen()) || !1;
54
+ }
55
+ };
56
+ }
57
+ function w(t) {
58
+ const e = d(c), n = a(null);
59
+ a(null);
60
+ const i = f(e.config, t);
61
+ return r(() => {
62
+ if (!i.server) {
63
+ console.warn("[Zephyr] No server URL. Provide server prop or config.");
64
+ return;
65
+ }
66
+ const o = new u(i, {
67
+ onReady: t.onReady,
68
+ onMessage: t.onMessage,
69
+ onError: t.onError,
70
+ onToggle: t.onToggle
71
+ });
72
+ return o.mount(t.container || null), n.current = o, () => {
73
+ o.destroy(), n.current = null;
74
+ };
75
+ }, [i.server]), r(() => {
76
+ var o;
77
+ (o = n.current) == null || o.setTheme(i.theme);
78
+ }, [i.theme]), r(() => {
79
+ var o;
80
+ (o = n.current) == null || o.setAccentColor(i.accentColor || "#ff6b35");
81
+ }, [i.accentColor]), r(() => {
82
+ var o;
83
+ i.persona && ((o = n.current) == null || o.setPersona(i.persona));
84
+ }, [i.persona]), r(() => {
85
+ var o;
86
+ i.logo && ((o = n.current) == null || o.setLogo(i.logo));
87
+ }, [i.logo]), r(() => {
88
+ var o;
89
+ i.openAnimation && ((o = n.current) == null || o.setOpenAnimation(i.openAnimation));
90
+ }, [i.openAnimation]), r(() => {
91
+ var o;
92
+ i.triggerAnimation && ((o = n.current) == null || o.setTriggerAnimation(i.triggerAnimation));
93
+ }, [i.triggerAnimation]), null;
94
+ }
95
+ function f(t, e) {
96
+ var i;
97
+ const n = {
98
+ ...t || {},
99
+ ...e.config || {},
100
+ server: e.server || ((i = e.config) == null ? void 0 : i.server) || (t == null ? void 0 : t.server) || ""
101
+ };
102
+ return e.apiKey !== void 0 && (n.apiKey = e.apiKey), e.logo !== void 0 && (n.logo = e.logo), e.persona !== void 0 && (n.persona = e.persona), e.theme !== void 0 && (n.theme = e.theme), e.accentColor !== void 0 && (n.accentColor = e.accentColor), e.openAnimation !== void 0 && (n.openAnimation = e.openAnimation), e.triggerAnimation !== void 0 && (n.triggerAnimation = e.triggerAnimation), e.language !== void 0 && (n.language = e.language), e.greeting !== void 0 && (n.greeting = e.greeting), e.placeholder !== void 0 && (n.placeholder = e.placeholder), e.features !== void 0 && (n.features = e.features), e.startOpen !== void 0 && (n.startOpen = e.startOpen), e.showBadge !== void 0 && (n.showBadge = e.showBadge), e.customCSS !== void 0 && (n.customCSS = e.customCSS), e.container !== void 0 && (n.container = e.container), (e.position || e.size || e.panelWidth || e.panelHeight || e.panelBorderRadius || e.backdrop !== void 0 || e.zIndex) && (n.panel = {
103
+ ...n.panel,
104
+ ...e.position && { position: e.position },
105
+ ...e.size && { size: e.size },
106
+ ...e.panelWidth && { width: e.panelWidth },
107
+ ...e.panelHeight && { height: e.panelHeight },
108
+ ...e.panelBorderRadius != null && { borderRadius: e.panelBorderRadius },
109
+ ...e.backdrop !== void 0 && { backdrop: e.backdrop },
110
+ ...e.zIndex && { zIndex: e.zIndex }
111
+ }), n;
112
+ }
113
+ export {
114
+ w as Z,
115
+ h as a,
116
+ A as u
117
+ };
118
+ //# sourceMappingURL=Zephyr-BupwOffR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Zephyr-BupwOffR.js","sources":["../src/react/Zephyr.tsx"],"sourcesContent":["/**\n * 🦊 <Zephyr /> — React Component\n *\n * Usage:\n * import { Zephyr } from '@zephyr/ui/react';\n * // or: import { Zephyr } from '@zephyr/ui';\n *\n * // Option A: Props-based (all config via props)\n * <Zephyr server=\"http://localhost:8000\" persona=\"friendly\" theme=\"dark\" />\n *\n * // Option B: Config-file based (uses zephyr.config.ts)\n * import config from './zephyr.config';\n * <Zephyr config={config} />\n *\n * // Option C: Provider pattern (config shared across app)\n * import { ZephyrProvider } from '@zephyr/ui/react';\n * <ZephyrProvider config={config}><App /></ZephyrProvider>\n * // Then anywhere: <Zephyr />\n */\n\nimport React, {\n useEffect,\n useRef,\n useCallback,\n createContext,\n useContext,\n type ReactNode,\n} from \"react\";\n\nimport type {\n ZephyrConfig,\n ZephyrTheme,\n ZephyrLogo,\n ZephyrPersona,\n ZephyrOpenAnimation,\n ZephyrTriggerAnimation,\n ZephyrPosition,\n ZephyrSize,\n ZephyrFeature,\n} from \"../core/config\";\nimport { ZephyrWidget, type ZephyrMessage } from \"../core/widget\";\n\n// ─── Props ───────────────────────────────────────────────────\n\nexport interface ZephyrProps {\n // ── Config object (takes precedence over individual props) ──\n /** Full config object (from defineZephyrConfig) */\n config?: ZephyrConfig;\n\n // ── Individual props (override config) ─────────────────────\n /** Zephyr server URL */\n server?: string;\n /** API key */\n apiKey?: string;\n /** Logo preset or custom */\n logo?: ZephyrLogo;\n /** Persona preset or custom */\n persona?: ZephyrPersona;\n /** Theme */\n theme?: ZephyrTheme;\n /** Accent color */\n accentColor?: string;\n /** Opening animation */\n openAnimation?: ZephyrOpenAnimation;\n /** Trigger button animation */\n triggerAnimation?: ZephyrTriggerAnimation;\n /** Position */\n position?: ZephyrPosition;\n /** Size */\n size?: ZephyrSize;\n /** Language */\n language?: string;\n /** Greeting message */\n greeting?: string;\n /** Input placeholder */\n placeholder?: string;\n /** Enabled features */\n features?: ZephyrFeature[];\n /** Start open */\n startOpen?: boolean;\n /** Show badge */\n showBadge?: boolean;\n /** Custom CSS */\n customCSS?: string;\n /** Mount container selector */\n container?: string | null;\n /** Panel width */\n panelWidth?: number;\n /** Panel height */\n panelHeight?: number;\n /** Panel border radius */\n panelBorderRadius?: number;\n /** Show backdrop */\n backdrop?: boolean;\n /** z-index */\n zIndex?: number;\n\n // ── Events ─────────────────────────────────────────────────\n onReady?: () => void;\n onMessage?: (msg: ZephyrMessage) => void;\n onError?: (err: { message: string }) => void;\n onToggle?: (open: boolean) => void;\n}\n\n// ─── Context ─────────────────────────────────────────────────\n\ninterface ZephyrContextValue {\n config: ZephyrConfig | null;\n widget: ZephyrWidget | null;\n}\n\nconst ZephyrContext = createContext<ZephyrContextValue>({\n config: null,\n widget: null,\n});\n\n// ─── Provider ────────────────────────────────────────────────\n\nexport interface ZephyrProviderProps {\n config: ZephyrConfig;\n children: ReactNode;\n}\n\nexport function ZephyrProvider({ config, children }: ZephyrProviderProps) {\n const widgetRef = useRef<ZephyrWidget | null>(null);\n\n return (\n <ZephyrContext.Provider value={{ config, widget: widgetRef.current }}>\n {children}\n </ZephyrContext.Provider>\n );\n}\n\n// ─── Hook ────────────────────────────────────────────────────\n\nexport interface UseZephyrReturn {\n /** Send a message */\n send: (text: string) => void;\n /** Open the panel */\n open: () => void;\n /** Close the panel */\n close: () => void;\n /** Toggle the panel */\n toggle: () => void;\n /** Change theme */\n setTheme: (theme: ZephyrTheme) => void;\n /** Change logo */\n setLogo: (logo: ZephyrLogo) => void;\n /** Change persona */\n setPersona: (persona: ZephyrPersona) => void;\n /** Change accent color */\n setAccentColor: (color: string) => void;\n /** Get all messages */\n getMessages: () => ZephyrMessage[];\n /** Is the panel open? */\n isOpen: () => boolean;\n}\n\n/**\n * Imperative access to the Zephyr widget instance.\n * Must be used in a component that renders <Zephyr />.\n */\nexport function useZephyr(): UseZephyrReturn {\n const widgetRef = useRef<ZephyrWidget | null>(null);\n\n return {\n send: (text) => widgetRef.current?.send(text),\n open: () => widgetRef.current?.open(),\n close: () => widgetRef.current?.close(),\n toggle: () => widgetRef.current?.toggle(),\n setTheme: (t) => widgetRef.current?.setTheme(t),\n setLogo: (l) => widgetRef.current?.setLogo(l),\n setPersona: (p) => widgetRef.current?.setPersona(p),\n setAccentColor: (c) => widgetRef.current?.setAccentColor(c),\n getMessages: () => widgetRef.current?.getMessages() || [],\n isOpen: () => widgetRef.current?.getIsOpen() || false,\n };\n}\n\n// ─── Component ───────────────────────────────────────────────\n\n/**\n * <Zephyr /> — Renders the Zephyr chat widget.\n *\n * @example\n * ```tsx\n * import { Zephyr } from '@zephyr/ui/react';\n *\n * function App() {\n * return (\n * <div>\n * <h1>My App</h1>\n * <Zephyr\n * server=\"http://localhost:8000\"\n * persona=\"friendly\"\n * theme=\"dark\"\n * accentColor=\"#ff6b35\"\n * openAnimation=\"bounce\"\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function Zephyr(props: ZephyrProps) {\n const context = useContext(ZephyrContext);\n const widgetRef = useRef<ZephyrWidget | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Merge: context config < config prop < individual props\n const resolvedConfig = buildConfig(context.config, props);\n\n // Mount effect\n useEffect(() => {\n if (!resolvedConfig.server) {\n console.warn(\"[Zephyr] No server URL. Provide server prop or config.\");\n return;\n }\n\n const widget = new ZephyrWidget(resolvedConfig, {\n onReady: props.onReady,\n onMessage: props.onMessage,\n onError: props.onError,\n onToggle: props.onToggle,\n });\n\n widget.mount(props.container || null);\n widgetRef.current = widget;\n\n return () => {\n widget.destroy();\n widgetRef.current = null;\n };\n // Intentionally only depend on server — other changes are handled by watchers below\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [resolvedConfig.server]);\n\n // Watch runtime changes\n useEffect(() => {\n widgetRef.current?.setTheme(resolvedConfig.theme);\n }, [resolvedConfig.theme]);\n\n useEffect(() => {\n widgetRef.current?.setAccentColor(resolvedConfig.accentColor || \"#ff6b35\");\n }, [resolvedConfig.accentColor]);\n\n useEffect(() => {\n if (resolvedConfig.persona) {\n widgetRef.current?.setPersona(resolvedConfig.persona);\n }\n }, [resolvedConfig.persona]);\n\n useEffect(() => {\n if (resolvedConfig.logo) {\n widgetRef.current?.setLogo(resolvedConfig.logo);\n }\n }, [resolvedConfig.logo]);\n\n useEffect(() => {\n if (resolvedConfig.openAnimation) {\n widgetRef.current?.setOpenAnimation(resolvedConfig.openAnimation);\n }\n }, [resolvedConfig.openAnimation]);\n\n useEffect(() => {\n if (resolvedConfig.triggerAnimation) {\n widgetRef.current?.setTriggerAnimation(resolvedConfig.triggerAnimation);\n }\n }, [resolvedConfig.triggerAnimation]);\n\n // The widget renders itself to the DOM — this component is just a lifecycle manager\n return null;\n}\n\n// ─── Utility ─────────────────────────────────────────────────\n\nfunction buildConfig(\n contextConfig: ZephyrConfig | null,\n props: ZephyrProps\n): ZephyrConfig {\n const base: ZephyrConfig = {\n ...(contextConfig || {}),\n ...(props.config || {}),\n server: props.server || props.config?.server || contextConfig?.server || \"\",\n };\n\n // Override with individual props\n if (props.apiKey !== undefined) base.apiKey = props.apiKey;\n if (props.logo !== undefined) base.logo = props.logo;\n if (props.persona !== undefined) base.persona = props.persona;\n if (props.theme !== undefined) base.theme = props.theme;\n if (props.accentColor !== undefined) base.accentColor = props.accentColor;\n if (props.openAnimation !== undefined) base.openAnimation = props.openAnimation;\n if (props.triggerAnimation !== undefined) base.triggerAnimation = props.triggerAnimation;\n if (props.language !== undefined) base.language = props.language;\n if (props.greeting !== undefined) base.greeting = props.greeting;\n if (props.placeholder !== undefined) base.placeholder = props.placeholder;\n if (props.features !== undefined) base.features = props.features;\n if (props.startOpen !== undefined) base.startOpen = props.startOpen;\n if (props.showBadge !== undefined) base.showBadge = props.showBadge;\n if (props.customCSS !== undefined) base.customCSS = props.customCSS;\n if (props.container !== undefined) base.container = props.container;\n\n // Panel overrides\n if (props.position || props.size || props.panelWidth || props.panelHeight ||\n props.panelBorderRadius || props.backdrop !== undefined || props.zIndex) {\n base.panel = {\n ...base.panel,\n ...(props.position && { position: props.position }),\n ...(props.size && { size: props.size }),\n ...(props.panelWidth && { width: props.panelWidth }),\n ...(props.panelHeight && { height: props.panelHeight }),\n ...(props.panelBorderRadius != null && { borderRadius: props.panelBorderRadius }),\n ...(props.backdrop !== undefined && { backdrop: props.backdrop }),\n ...(props.zIndex && { zIndex: props.zIndex }),\n };\n }\n\n return base;\n}\n"],"names":["ZephyrContext","createContext","ZephyrProvider","config","children","widgetRef","useRef","jsx","useZephyr","text","_a","t","l","p","c","Zephyr","props","context","useContext","resolvedConfig","buildConfig","useEffect","widget","ZephyrWidget","contextConfig","base"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { ZephyrOpenAnimation, ZephyrTriggerAnimation } from './config';
2
+
3
+ export interface AnimationKeyframes {
4
+ open: string;
5
+ close: string;
6
+ }
7
+ export declare const OPEN_ANIMATIONS: Record<ZephyrOpenAnimation, AnimationKeyframes>;
8
+ export declare const TRIGGER_ANIMATIONS: Record<ZephyrTriggerAnimation, string>;
9
+ /** Get CSS keyframes for a given open animation preset */
10
+ export declare function getOpenAnimationCSS(preset: ZephyrOpenAnimation): string;
11
+ /** Get animation name for panel open */
12
+ export declare function getOpenAnimationName(preset: ZephyrOpenAnimation): string;
13
+ /** Get animation name for panel close */
14
+ export declare function getCloseAnimationName(preset: ZephyrOpenAnimation): string;
15
+ /** Get CSS keyframes for a given trigger animation preset */
16
+ export declare function getTriggerAnimationCSS(preset: ZephyrTriggerAnimation): string;
17
+ /** Get animation name for trigger */
18
+ export declare function getTriggerAnimationName(preset: ZephyrTriggerAnimation): string;
@@ -0,0 +1,154 @@
1
+ /**
2
+ * 🦊 Zephyr Configuration System
3
+ *
4
+ * Usage in your project:
5
+ *
6
+ * // zephyr.config.ts
7
+ * import { defineZephyrConfig } from '@zephyr/ui/config';
8
+ *
9
+ * export default defineZephyrConfig({
10
+ * server: 'https://your-zephyr-server.com',
11
+ * logo: 'zephyr-default',
12
+ * persona: 'friendly',
13
+ * theme: 'dark',
14
+ * openAnimation: 'slide-up',
15
+ * });
16
+ */
17
+ /** Built-in logo preset. Pass a URL string or object for custom logos. */
18
+ export type ZephyrLogoPreset = "zephyr-default";
19
+ export interface ZephyrCustomLogo {
20
+ /** URL or imported asset for the trigger button icon */
21
+ trigger: string;
22
+ /** URL or imported asset for the chat header avatar (optional, defaults to trigger) */
23
+ header?: string;
24
+ /** Alt text */
25
+ alt?: string;
26
+ }
27
+ export type ZephyrLogo = ZephyrLogoPreset | ZephyrCustomLogo | string;
28
+ /** Built-in persona presets for the chat avatar animations */
29
+ export type ZephyrPersonaPreset = "friendly" | "professional" | "playful" | "futuristic";
30
+ export interface ZephyrCustomPersona {
31
+ /** Display name */
32
+ name: string;
33
+ /** Avatar (Lottie URL, GIF URL, SVG string, or image URL) */
34
+ avatar: string;
35
+ /** Avatar format */
36
+ avatarType?: "lottie" | "gif" | "svg" | "image";
37
+ /** Idle animation (Lottie/GIF for when the bot is waiting) */
38
+ idle?: string;
39
+ /** Thinking animation */
40
+ thinking?: string;
41
+ /** Speaking animation */
42
+ speaking?: string;
43
+ }
44
+ export type ZephyrPersona = ZephyrPersonaPreset | ZephyrCustomPersona;
45
+ export type ZephyrOpenAnimation = "slide-up" | "slide-down" | "slide-left" | "slide-right" | "fade" | "scale" | "bounce" | "none";
46
+ export type ZephyrTriggerAnimation = "float" | "pulse" | "bounce" | "glow" | "none";
47
+ export type ZephyrThemePreset = "dark" | "light" | "auto";
48
+ export interface ZephyrCustomTheme {
49
+ /** Background color of the panel */
50
+ background: string;
51
+ /** Surface color (header, input area) */
52
+ surface: string;
53
+ /** Primary text color */
54
+ text: string;
55
+ /** Muted/secondary text */
56
+ muted: string;
57
+ /** Border color */
58
+ border: string;
59
+ /** User message bubble color (defaults to accentColor) */
60
+ userBubble?: string;
61
+ /** User message text color */
62
+ userText?: string;
63
+ /** Bot message bubble color */
64
+ botBubble?: string;
65
+ /** Bot message text color */
66
+ botText?: string;
67
+ }
68
+ export type ZephyrTheme = ZephyrThemePreset | ZephyrCustomTheme;
69
+ export type ZephyrPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
70
+ export type ZephyrSize = "sm" | "md" | "lg";
71
+ export interface ZephyrPanelConfig {
72
+ /** Position of the widget trigger + panel */
73
+ position?: ZephyrPosition;
74
+ /** Panel size preset */
75
+ size?: ZephyrSize;
76
+ /** Custom width in px (overrides size) */
77
+ width?: number;
78
+ /** Custom height in px (overrides size) */
79
+ height?: number;
80
+ /** Border radius in px */
81
+ borderRadius?: number;
82
+ /** Show backdrop overlay when open */
83
+ backdrop?: boolean;
84
+ /** Custom z-index */
85
+ zIndex?: number;
86
+ /** Draggable trigger */
87
+ draggable?: boolean;
88
+ }
89
+ export type ZephyrFeature = "chat" | "guide" | "search" | "onboarding";
90
+ export interface ZephyrConfig {
91
+ /** Zephyr backend server URL */
92
+ server: string;
93
+ /** API key for authentication */
94
+ apiKey?: string;
95
+ /** Logo for the trigger button + header */
96
+ logo?: ZephyrLogo;
97
+ /** Animated persona in the chat */
98
+ persona?: ZephyrPersona;
99
+ /** Theme (dark/light/auto or custom) */
100
+ theme?: ZephyrTheme;
101
+ /** Accent color (hex) */
102
+ accentColor?: string;
103
+ /** Animation when the chat panel opens */
104
+ openAnimation?: ZephyrOpenAnimation;
105
+ /** Animation of the trigger button when idle */
106
+ triggerAnimation?: ZephyrTriggerAnimation;
107
+ /** Panel layout & positioning */
108
+ panel?: ZephyrPanelConfig;
109
+ /** Language ('fr', 'en', etc.) */
110
+ language?: string;
111
+ /** Custom greeting message */
112
+ greeting?: string;
113
+ /** Input placeholder text */
114
+ placeholder?: string;
115
+ /** Enabled features */
116
+ features?: ZephyrFeature[];
117
+ /** Start with panel open */
118
+ startOpen?: boolean;
119
+ /** Show unread badge on trigger */
120
+ showBadge?: boolean;
121
+ /** Custom CSS to inject */
122
+ customCSS?: string;
123
+ /** Mount inside a specific container selector (null = body) */
124
+ container?: string | null;
125
+ }
126
+ export declare const ZEPHYR_DEFAULTS: Required<Pick<ZephyrConfig, "logo" | "persona" | "theme" | "accentColor" | "openAnimation" | "triggerAnimation" | "language" | "features" | "startOpen" | "showBadge">> & {
127
+ panel: Required<ZephyrPanelConfig>;
128
+ };
129
+ /**
130
+ * Define your Zephyr config with full type-safety & autocompletion.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * // zephyr.config.ts
135
+ * import { defineZephyrConfig } from '@zephyr/ui/config';
136
+ *
137
+ * export default defineZephyrConfig({
138
+ * server: 'http://localhost:8000',
139
+ * logo: 'zephyr-minimal',
140
+ * persona: 'professional',
141
+ * theme: 'dark',
142
+ * accentColor: '#6c63ff',
143
+ * openAnimation: 'scale',
144
+ * panel: {
145
+ * position: 'bottom-right',
146
+ * size: 'lg',
147
+ * backdrop: true,
148
+ * },
149
+ * });
150
+ * ```
151
+ */
152
+ export declare function defineZephyrConfig(config: ZephyrConfig): ZephyrConfig;
153
+ /** Merge user config with defaults */
154
+ export declare function resolveConfig(userConfig: ZephyrConfig): ZephyrConfig & typeof ZEPHYR_DEFAULTS;
@@ -0,0 +1,41 @@
1
+ const a = {
2
+ logo: "zephyr-default",
3
+ persona: "friendly",
4
+ theme: "dark",
5
+ accentColor: "#ff6b35",
6
+ openAnimation: "slide-up",
7
+ triggerAnimation: "float",
8
+ language: "fr",
9
+ features: ["chat", "guide", "search"],
10
+ startOpen: !1,
11
+ showBadge: !0,
12
+ panel: {
13
+ position: "bottom-right",
14
+ size: "md",
15
+ width: 380,
16
+ height: 520,
17
+ borderRadius: 16,
18
+ backdrop: !1,
19
+ zIndex: 99999,
20
+ draggable: !1
21
+ }
22
+ };
23
+ function n(e) {
24
+ return e;
25
+ }
26
+ function t(e) {
27
+ return {
28
+ ...a,
29
+ ...e,
30
+ panel: {
31
+ ...a.panel,
32
+ ...e.panel
33
+ }
34
+ };
35
+ }
36
+ export {
37
+ a as ZEPHYR_DEFAULTS,
38
+ n as defineZephyrConfig,
39
+ t as resolveConfig
40
+ };
41
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sources":["../../src/core/config.ts"],"sourcesContent":["/**\n * 🦊 Zephyr Configuration System\n *\n * Usage in your project:\n *\n * // zephyr.config.ts\n * import { defineZephyrConfig } from '@zephyr/ui/config';\n *\n * export default defineZephyrConfig({\n * server: 'https://your-zephyr-server.com',\n * logo: 'zephyr-default',\n * persona: 'friendly',\n * theme: 'dark',\n * openAnimation: 'slide-up',\n * });\n */\n\n// ─── Logo ────────────────────────────────────────────────────\n\n/** Built-in logo preset. Pass a URL string or object for custom logos. */\nexport type ZephyrLogoPreset = \"zephyr-default\";\n\nexport interface ZephyrCustomLogo {\n /** URL or imported asset for the trigger button icon */\n trigger: string;\n /** URL or imported asset for the chat header avatar (optional, defaults to trigger) */\n header?: string;\n /** Alt text */\n alt?: string;\n}\n\nexport type ZephyrLogo = ZephyrLogoPreset | ZephyrCustomLogo | string;\n\n// ─── Persona ─────────────────────────────────────────────────\n\n/** Built-in persona presets for the chat avatar animations */\nexport type ZephyrPersonaPreset =\n | \"friendly\"\n | \"professional\"\n | \"playful\"\n | \"futuristic\";\n\nexport interface ZephyrCustomPersona {\n /** Display name */\n name: string;\n /** Avatar (Lottie URL, GIF URL, SVG string, or image URL) */\n avatar: string;\n /** Avatar format */\n avatarType?: \"lottie\" | \"gif\" | \"svg\" | \"image\";\n /** Idle animation (Lottie/GIF for when the bot is waiting) */\n idle?: string;\n /** Thinking animation */\n thinking?: string;\n /** Speaking animation */\n speaking?: string;\n}\n\nexport type ZephyrPersona = ZephyrPersonaPreset | ZephyrCustomPersona;\n\n// ─── Animations ──────────────────────────────────────────────\n\nexport type ZephyrOpenAnimation =\n | \"slide-up\"\n | \"slide-down\"\n | \"slide-left\"\n | \"slide-right\"\n | \"fade\"\n | \"scale\"\n | \"bounce\"\n | \"none\";\n\nexport type ZephyrTriggerAnimation =\n | \"float\"\n | \"pulse\"\n | \"bounce\"\n | \"glow\"\n | \"none\";\n\n// ─── Theme ───────────────────────────────────────────────────\n\nexport type ZephyrThemePreset = \"dark\" | \"light\" | \"auto\";\n\nexport interface ZephyrCustomTheme {\n /** Background color of the panel */\n background: string;\n /** Surface color (header, input area) */\n surface: string;\n /** Primary text color */\n text: string;\n /** Muted/secondary text */\n muted: string;\n /** Border color */\n border: string;\n /** User message bubble color (defaults to accentColor) */\n userBubble?: string;\n /** User message text color */\n userText?: string;\n /** Bot message bubble color */\n botBubble?: string;\n /** Bot message text color */\n botText?: string;\n}\n\nexport type ZephyrTheme = ZephyrThemePreset | ZephyrCustomTheme;\n\n// ─── Panel ───────────────────────────────────────────────────\n\nexport type ZephyrPosition =\n | \"bottom-right\"\n | \"bottom-left\"\n | \"top-right\"\n | \"top-left\";\n\nexport type ZephyrSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ZephyrPanelConfig {\n /** Position of the widget trigger + panel */\n position?: ZephyrPosition;\n /** Panel size preset */\n size?: ZephyrSize;\n /** Custom width in px (overrides size) */\n width?: number;\n /** Custom height in px (overrides size) */\n height?: number;\n /** Border radius in px */\n borderRadius?: number;\n /** Show backdrop overlay when open */\n backdrop?: boolean;\n /** Custom z-index */\n zIndex?: number;\n /** Draggable trigger */\n draggable?: boolean;\n}\n\n// ─── Features ────────────────────────────────────────────────\n\nexport type ZephyrFeature = \"chat\" | \"guide\" | \"search\" | \"onboarding\";\n\n// ─── Full Config ─────────────────────────────────────────────\n\nexport interface ZephyrConfig {\n // ── Connection ──────────────────────────────────────────\n /** Zephyr backend server URL */\n server: string;\n /** API key for authentication */\n apiKey?: string;\n\n // ── Appearance ──────────────────────────────────────────\n /** Logo for the trigger button + header */\n logo?: ZephyrLogo;\n /** Animated persona in the chat */\n persona?: ZephyrPersona;\n /** Theme (dark/light/auto or custom) */\n theme?: ZephyrTheme;\n /** Accent color (hex) */\n accentColor?: string;\n\n // ── Animations ──────────────────────────────────────────\n /** Animation when the chat panel opens */\n openAnimation?: ZephyrOpenAnimation;\n /** Animation of the trigger button when idle */\n triggerAnimation?: ZephyrTriggerAnimation;\n\n // ── Panel ───────────────────────────────────────────────\n /** Panel layout & positioning */\n panel?: ZephyrPanelConfig;\n\n // ── Content ─────────────────────────────────────────────\n /** Language ('fr', 'en', etc.) */\n language?: string;\n /** Custom greeting message */\n greeting?: string;\n /** Input placeholder text */\n placeholder?: string;\n\n // ── Features ────────────────────────────────────────────\n /** Enabled features */\n features?: ZephyrFeature[];\n /** Start with panel open */\n startOpen?: boolean;\n /** Show unread badge on trigger */\n showBadge?: boolean;\n\n // ── Advanced ────────────────────────────────────────────\n /** Custom CSS to inject */\n customCSS?: string;\n /** Mount inside a specific container selector (null = body) */\n container?: string | null;\n}\n\n// ─── Defaults ────────────────────────────────────────────────\n\nexport const ZEPHYR_DEFAULTS: Required<\n Pick<\n ZephyrConfig,\n | \"logo\"\n | \"persona\"\n | \"theme\"\n | \"accentColor\"\n | \"openAnimation\"\n | \"triggerAnimation\"\n | \"language\"\n | \"features\"\n | \"startOpen\"\n | \"showBadge\"\n >\n> & { panel: Required<ZephyrPanelConfig> } = {\n logo: \"zephyr-default\",\n persona: \"friendly\",\n theme: \"dark\",\n accentColor: \"#ff6b35\",\n openAnimation: \"slide-up\",\n triggerAnimation: \"float\",\n language: \"fr\",\n features: [\"chat\", \"guide\", \"search\"],\n startOpen: false,\n showBadge: true,\n panel: {\n position: \"bottom-right\",\n size: \"md\",\n width: 380,\n height: 520,\n borderRadius: 16,\n backdrop: false,\n zIndex: 99999,\n draggable: false,\n },\n};\n\n// ─── Helper ──────────────────────────────────────────────────\n\n/**\n * Define your Zephyr config with full type-safety & autocompletion.\n *\n * @example\n * ```ts\n * // zephyr.config.ts\n * import { defineZephyrConfig } from '@zephyr/ui/config';\n *\n * export default defineZephyrConfig({\n * server: 'http://localhost:8000',\n * logo: 'zephyr-minimal',\n * persona: 'professional',\n * theme: 'dark',\n * accentColor: '#6c63ff',\n * openAnimation: 'scale',\n * panel: {\n * position: 'bottom-right',\n * size: 'lg',\n * backdrop: true,\n * },\n * });\n * ```\n */\nexport function defineZephyrConfig(config: ZephyrConfig): ZephyrConfig {\n return config;\n}\n\n/** Merge user config with defaults */\nexport function resolveConfig(\n userConfig: ZephyrConfig\n): ZephyrConfig & typeof ZEPHYR_DEFAULTS {\n return {\n ...ZEPHYR_DEFAULTS,\n ...userConfig,\n panel: {\n ...ZEPHYR_DEFAULTS.panel,\n ...userConfig.panel,\n },\n };\n}\n"],"names":["ZEPHYR_DEFAULTS","defineZephyrConfig","config","resolveConfig","userConfig"],"mappings":"AAgMO,MAAMA,IAcgC;AAAA,EAC3C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,UAAU,CAAC,QAAQ,SAAS,QAAQ;AAAA,EACpC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,OAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA;AAEf;AA2BO,SAASC,EAAmBC,GAAoC;AACrE,SAAOA;AACT;AAGO,SAASC,EACdC,GACuC;AACvC,SAAO;AAAA,IACL,GAAGJ;AAAA,IACH,GAAGI;AAAA,IACH,OAAO;AAAA,MACL,GAAGJ,EAAgB;AAAA,MACnB,GAAGI,EAAW;AAAA,IAAA;AAAA,EAChB;AAEJ;"}