dynim-react 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,447 +1,19 @@
1
1
  # dynim-react
2
2
 
3
- React components, hooks, and providers for visual page building, AI chat, and multi-tenant customization. Built on top of `dynim-core`.
3
+ React components for visual page building and tenant customization.
4
4
 
5
- ## Installation
5
+ ## Documentation
6
6
 
7
- ```bash
8
- npm install dynim-react
9
- # dynim-core is included as a dependency
10
- ```
11
-
12
- **Peer Dependencies:**
13
- - `react` >= 17.0.0
14
- - `react-dom` >= 17.0.0
15
-
16
- ## Overview
17
-
18
- This package has two main modules:
19
-
20
- 1. **Builder** - Visual builder integration for editing pages/components with AI chat and code generation
21
- 2. **Inference** - Dynamic loading of tenant-specific customization bundles
22
-
23
- ## Folder Structure
24
-
25
- ```
26
- src/
27
- ├── index.ts # Main entry point
28
- ├── builder/
29
- │ ├── BuilderProvider.tsx # Visual builder React provider
30
- │ ├── EditableZone.tsx # Zone wrappers for customization control
31
- │ ├── ChatContext.tsx # Chat state context
32
- │ ├── useChatbot.ts # Headless chat hook
33
- │ ├── MessageList.tsx # Message display component
34
- │ └── ChatInput.tsx # Chat input component
35
- └── inference/
36
- ├── types.ts # TypeScript definitions
37
- ├── sharedContext.ts # Shared context registration
38
- └── InferenceProvider.tsx # Tenant bundle loader
39
- ```
40
-
41
- ## Builder Module
42
-
43
- ### BuilderProvider
44
-
45
- Main provider component that integrates the visual builder UI into your app.
46
-
47
- ```tsx
48
- import { BuilderProvider, useBuilder } from 'dynim-react';
49
-
50
- function App() {
51
- return (
52
- <BuilderProvider
53
- config={{
54
- apiBase: 'https://api.example.com',
55
- pageId: '/dashboard',
56
- sessionToken: jwtToken,
57
- onCodeEdit: (edit) => console.log('Code changed:', edit),
58
- }}
59
- onBuilderReady={(ctx) => console.log('Builder ready!')}
60
- >
61
- <YourApp />
62
- </BuilderProvider>
63
- );
64
- }
65
- ```
66
-
67
- **Config Options:**
68
-
69
- ```tsx
70
- interface BuilderConfig {
71
- apiBase?: string; // Default: 'http://localhost:8080'
72
- pageId?: string; // Default: window.location.pathname
73
- logo?: string; // Builder UI logo text
74
- contentRoot?: HTMLElement; // Default: document.body
75
- sessionToken?: string; // JWT authentication token
76
- refreshToken?: string; // For token renewal
77
- getSession?: () => Promise<{ token: string }>; // Dynamic token fetching
78
- onMessage?: (data: BuilderMessage) => void; // Chat message callback
79
- onError?: (error: Error) => void; // Error callback
80
- onCodeMessage?: (event: CodeEvent) => void; // Code generation events
81
- onCodeEdit?: (edit: CodeEdit) => void; // Code edit callback
82
- }
83
- ```
84
-
85
- ### useBuilder Hook
86
-
87
- Access builder controls from any child component:
88
-
89
- ```tsx
90
- function EditorToolbar() {
91
- const {
92
- // Builder controls
93
- enterBuilder, // () => void - Enter edit mode
94
- exitBuilder, // () => void - Exit without saving
95
- saveBuilder, // () => Promise<void> - Save and exit
96
- isBuilderActive, // boolean - Current edit state
97
-
98
- // Chat
99
- sendChat, // (message: string) => Promise<void>
100
- sendElementChat, // (message: string, element: HTMLElement) => Promise<void>
101
-
102
- // Code generation (Flexcode)
103
- sendCode, // (projectId: string, prompt: string) => Promise<void>
104
- saveCode, // (projectId: string) => Promise<void>
105
- abandonCode, // (projectId: string) => Promise<void>
106
- codeEdits, // CodeEdit[] - Pending code changes
107
-
108
- // Builder instance
109
- getBuilder, // () => Builder - Get underlying builder instance
110
- } = useBuilder();
7
+ See [SDK React Documentation](../../utils/docs/sdk/REACT.md)
111
8
 
112
- return (
113
- <div>
114
- <button onClick={enterBuilder} disabled={isBuilderActive}>
115
- Edit Page
116
- </button>
117
- <button onClick={saveBuilder} disabled={!isBuilderActive}>
118
- Save Changes
119
- </button>
120
- </div>
121
- );
122
- }
123
- ```
124
-
125
- ### Chat Components
126
-
127
- Pre-built chat UI components:
128
-
129
- ```tsx
130
- import { ChatProvider, MessageList, ChatInput } from 'dynim-react';
131
-
132
- function BuilderChat() {
133
- return (
134
- <ChatProvider endpoint="/api/chat" apiKey="...">
135
- <MessageList showAvatars showTimestamps={false} />
136
- <ChatInput placeholder="Ask the builder..." />
137
- </ChatProvider>
138
- );
139
- }
140
- ```
141
-
142
- ### useChatbot Hook
143
-
144
- Headless hook for building custom chat UIs:
145
-
146
- ```tsx
147
- import { useChatbot } from 'dynim-react';
148
-
149
- function CustomChat() {
150
- const {
151
- messages, // Message[] - Array of chat messages
152
- isLoading, // boolean - Response being fetched
153
- isTyping, // boolean - AI typing indicator
154
- sendMessage, // (text: string) => Promise<void>
155
- clearMessages, // () => void - Clear history
156
- } = useChatbot({
157
- endpoint: '/api/chat',
158
- apiKey: 'your-api-key',
159
- onError: (error) => console.error(error),
160
- });
161
-
162
- return (
163
- <div>
164
- {messages.map(msg => (
165
- <div key={msg.id} className={msg.role}>
166
- {msg.text}
167
- </div>
168
- ))}
169
- <form onSubmit={(e) => {
170
- e.preventDefault();
171
- sendMessage(e.target.message.value);
172
- e.target.reset();
173
- }}>
174
- <input name="message" disabled={isLoading} />
175
- <button type="submit">Send</button>
176
- </form>
177
- </div>
178
- );
179
- }
180
- ```
181
-
182
- **Message Type:**
183
-
184
- ```tsx
185
- interface Message {
186
- id: string;
187
- role: 'user' | 'assistant';
188
- text: string;
189
- timestamp: Date;
190
- }
191
- ```
192
-
193
- ### Zone Components
194
-
195
- Control which parts of your UI can be customized in the builder:
196
-
197
- ```tsx
198
- import { LockedZone, EditableZone } from 'dynim-react';
199
-
200
- function App() {
201
- return (
202
- <div>
203
- <LockedZone>
204
- <Navigation /> {/* Protected - cannot be modified */}
205
- </LockedZone>
206
-
207
- <main>
208
- {/* Editable by default */}
209
- <Hero />
210
- <Features />
211
- </main>
212
-
213
- <LockedZone>
214
- <Sidebar>
215
- <Logo /> {/* Locked */}
216
- <EditableZone>
217
- <CustomWidgets /> {/* Editable island inside locked zone */}
218
- </EditableZone>
219
- </Sidebar>
220
- </LockedZone>
221
- </div>
222
- );
223
- }
224
- ```
225
-
226
- **Zone Props:**
227
-
228
- ```tsx
229
- // Custom wrapper element
230
- <EditableZone as="section" className="content">
231
- <Content />
232
- </EditableZone>
233
-
234
- // Aliases
235
- <NonCustomizable> {/* Same as LockedZone */}
236
- <Customizable> {/* Same as EditableZone */}
237
- ```
9
+ Related:
10
+ - [SDK Overview](../../utils/docs/sdk/README.md)
11
+ - [SDK Core](../../utils/docs/sdk/CORE.md)
12
+ - [UI Builder](../../utils/docs/ui-builder/README.md)
13
+ - [Inference Server](../../utils/docs/inference-server/README.md)
238
14
 
239
- - `LockedZone` / `NonCustomizable` - Prevents builder customization (sets `vis="false"`)
240
- - `EditableZone` / `Customizable` - Creates editable areas (sets `vis="true"`)
15
+ ## Install
241
16
 
242
- ## Inference Module
243
-
244
- ### InferenceProvider
245
-
246
- Dynamically loads and renders tenant-specific customization bundles.
247
-
248
- ```tsx
249
- import { InferenceProvider } from 'dynim-react';
250
-
251
- function App() {
252
- const { tenantId } = useAuth();
253
-
254
- return (
255
- <InferenceProvider
256
- tenantId={tenantId}
257
- bundleUrl={(id) => `https://cdn.example.com/bundles/${id}.js`}
258
- checkCustomizations={async (id) => {
259
- const res = await fetch(`/api/customizations/${id}`);
260
- return res.ok;
261
- }}
262
- loadingComponent={<Spinner />}
263
- errorBanner={true}
264
- onLoad={(id) => console.log(`Loaded for ${id}`)}
265
- onError={(err, id) => console.error(`Failed for ${id}:`, err)}
266
- >
267
- <BaseApp />
268
- </InferenceProvider>
269
- );
270
- }
271
- ```
272
-
273
- **Props:**
274
-
275
- ```tsx
276
- interface InferenceProviderProps {
277
- tenantId: string | null; // Current tenant (null = no customization)
278
- bundleUrl: string | ((id: string) => string); // Bundle URL or URL builder
279
- bundleToken?: string; // Auth token for bundle fetch
280
- checkCustomizations?: (id: string) => Promise<bool>; // Pre-check if tenant has bundle
281
- loadingComponent?: ReactNode; // Custom loading UI
282
- errorBanner?: boolean | ReactNode; // Show errors (default: false)
283
- onError?: (error: Error, tenantId: string) => void;
284
- onLoad?: (tenantId: string) => void;
285
- children: ReactNode; // Fallback/default app
286
- }
287
- ```
288
-
289
- **Loading States:**
290
-
291
- `idle` → `checking` → `loading` → `loaded` / `error` / `no-customization`
292
-
293
- ### Shared Context
294
-
295
- Tenant bundles access the host app's React and custom hooks via a shared context on `window.__DYNIM__`:
296
-
297
- ```tsx
298
- import { createSharedContext, getSharedContext, isSharedContextReady } from 'dynim-react';
299
-
300
- // Register shared context (call once at app initialization)
301
- createSharedContext({
302
- React,
303
- ReactDOM,
304
- hooks: { useAuth, useTheme, useNotifications },
305
- contexts: { AuthContext, ThemeContext },
306
- globals: { utils: myUtils },
307
- });
308
-
309
- // Check if ready
310
- if (isSharedContextReady()) {
311
- const ctx = getSharedContext();
312
- // ...
313
- }
314
- ```
315
-
316
- **Writing a Tenant Bundle:**
317
-
318
- ```typescript
319
- // tenant-bundle.ts
320
- const { React, ReactDOM, hooks, contexts } = window.__DYNIM__;
321
- const { useAuth, useTheme } = hooks;
322
-
323
- function TenantCustomization() {
324
- const { user } = useAuth();
325
- const { theme } = useTheme();
326
-
327
- return (
328
- <div style={{ background: theme.bg }}>
329
- <h1>Welcome, {user.name}!</h1>
330
- <p>Custom content for {user.tenantId}</p>
331
- </div>
332
- );
333
- }
334
-
335
- // Render into the designated root
336
- const root = document.getElementById('dynim-root');
337
- ReactDOM.render(<TenantCustomization />, root);
338
- ```
339
-
340
- ## Architecture
341
-
342
- ```
343
- Application
344
-
345
- ├── BuilderProvider (visual editing)
346
- │ ├── Creates builder instance (dynim-core)
347
- │ ├── Manages SSE streaming for chat/code
348
- │ ├── Handles drag-and-drop, history, diffs
349
- │ └── Exposes useBuilder hook
350
-
351
- └── InferenceProvider (tenant customization)
352
- ├── Registers global SDK (window.__DYNIM__)
353
- ├── Loads tenant bundle script
354
- ├── Renders bundle into #dynim-root
355
- └── Falls back to children if no customizations
356
- ```
357
-
358
- ## Exports
359
-
360
- ```tsx
361
- // Builder
362
- export { BuilderProvider, useBuilder } from './builder';
363
- export { ChatProvider, useChatContext } from './builder';
364
- export { MessageList, ChatInput, useChatbot } from './builder';
365
- export { LockedZone, EditableZone, NonCustomizable, Customizable } from './builder';
366
-
367
- // Inference
368
- export { InferenceProvider } from './inference';
369
- export { createSharedContext, getSharedContext, isSharedContextReady } from './inference';
370
-
371
- // Re-exports everything from dynim-core
372
- export * from 'dynim-core';
373
- ```
374
-
375
- ## Re-exports from dynim-core
376
-
377
- For convenience, `dynim-react` re-exports all of `dynim-core`:
378
-
379
- ```tsx
380
- import {
381
- // State
382
- createState,
383
-
384
- // Clients
385
- createClient,
386
- createBuilderClient,
387
- createCodeClient,
388
-
389
- // Builder
390
- createBuilder,
391
- createEditorState,
392
- createHistoryState,
393
- createTreeState,
394
- createDiffState,
395
-
396
- // UI
397
- createWidget,
398
- createOverlays,
399
- createFreezeOverlay,
400
- createDragEngine,
401
- createAIPromptPopover,
402
-
403
- // DOM utilities
404
- scanDOM,
405
- getStableId,
406
- findByStableId,
407
- buildElementIdentifier,
408
-
409
- // Classifier
410
- createClassifier,
411
- } from 'dynim-react';
412
- ```
413
-
414
- ## TypeScript
415
-
416
- Full TypeScript support with exported types:
417
-
418
- ```tsx
419
- import type {
420
- // Config
421
- BuilderConfig,
422
- BuilderContextValue,
423
- ChatbotConfig,
424
- InferenceProviderProps,
425
- DynimSDKConfig,
426
-
427
- // Props
428
- ZoneProps,
429
- MessageListProps,
430
- ChatInputProps,
431
-
432
- // Data
433
- Message,
434
- ChatState,
435
- CodeEdit,
436
- CodeEvent,
437
- DiffEntry,
438
- BuilderMessage,
439
-
440
- // Global
441
- DynimGlobal,
442
- } from 'dynim-react';
17
+ ```bash
18
+ npm install dynim-react
443
19
  ```
444
-
445
- ## License
446
-
447
- MIT
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * BuilderProvider - React integration for the visual builder
3
3
  *
4
- * Integrates the visual builder UI (floating bar, drag engine, overlays)
5
- * from dynim-core. Loads tenant bundles via dynamic import() and renders
6
- * them as React components.
4
+ * Integrates the visual builder UI (floating bar, overlays) from dynim-core.
5
+ * Loads tenant bundles via dynamic import() and renders them as React components.
7
6
  */
8
7
  import { type ReactNode } from 'react';
9
8
  import type { BuilderInstance, CodeEdit, CodeEvent, CodeMessage } from 'dynim-core';
@@ -44,7 +43,6 @@ export interface BuilderConfig {
44
43
  export interface BuilderContextValue {
45
44
  enterBuilder: () => void;
46
45
  exitBuilder: () => void;
47
- saveBuilder: () => Promise<void>;
48
46
  isBuilderActive: boolean;
49
47
  getBuilder: () => BuilderInstance | null;
50
48
  sendCode: (query: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"BuilderProvider.d.ts","sourceRoot":"","sources":["../../src/builder/BuilderProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BuilderProvider.d.ts","sourceRoot":"","sources":["../../src/builder/BuilderProvider.tsx"],"names":[],"mappings":"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"}
@@ -2,9 +2,8 @@ import { jsxs as _jsxs, Fragment as _Fragment, jsx as _jsx } from "react/jsx-run
2
2
  /**
3
3
  * BuilderProvider - React integration for the visual builder
4
4
  *
5
- * Integrates the visual builder UI (floating bar, drag engine, overlays)
6
- * from dynim-core. Loads tenant bundles via dynamic import() and renders
7
- * them as React components.
5
+ * Integrates the visual builder UI (floating bar, overlays) from dynim-core.
6
+ * Loads tenant bundles via dynamic import() and renders them as React components.
8
7
  */
9
8
  import React, { createContext, useContext, useEffect, useRef, useCallback, useMemo, useState, } from 'react';
10
9
  import ReactDOM from 'react-dom';
@@ -107,15 +106,12 @@ export function BuilderProvider({ children, config = {}, onBuilderReady, }) {
107
106
  console.log('[BuilderProvider] Visual builder exited');
108
107
  setIsBuilderActive(false);
109
108
  },
110
- onSave: (diffs) => {
111
- console.log('[BuilderProvider] Changes saved:', diffs);
112
- },
113
109
  });
114
110
  return () => {
115
111
  builderRef.current?.destroy();
116
112
  };
117
113
  }, [config]);
118
- // Initialize builder client for visual builder operations (saveDiffs, preview, exit)
114
+ // Initialize builder client for visual builder operations (preview, exit)
119
115
  useEffect(() => {
120
116
  const { apiBase = 'http://localhost:8080', sessionToken, refreshToken, getSession, onError, } = config;
121
117
  builderClientRef.current = createBuilderClient({
@@ -141,12 +137,6 @@ export function BuilderProvider({ children, config = {}, onBuilderReady, }) {
141
137
  builderRef.current.exit();
142
138
  }
143
139
  }, []);
144
- // Save and exit builder mode
145
- const saveBuilder = useCallback(async () => {
146
- if (builderRef.current && builderRef.current.isActive()) {
147
- await builderRef.current.save();
148
- }
149
- }, []);
150
140
  /**
151
141
  * Get auth token for bundle requests
152
142
  */
@@ -313,7 +303,6 @@ export function BuilderProvider({ children, config = {}, onBuilderReady, }) {
313
303
  const contextValue = useMemo(() => ({
314
304
  enterBuilder,
315
305
  exitBuilder,
316
- saveBuilder,
317
306
  isBuilderActive,
318
307
  getBuilder: () => builderRef.current,
319
308
  // Code client methods
@@ -335,7 +324,6 @@ export function BuilderProvider({ children, config = {}, onBuilderReady, }) {
335
324
  }), [
336
325
  enterBuilder,
337
326
  exitBuilder,
338
- saveBuilder,
339
327
  isBuilderActive,
340
328
  sendCode,
341
329
  saveCode,
@@ -13,6 +13,4 @@ export { CodeChatPanel } from './CodeChatPanel';
13
13
  export type { CodeChatPanelProps } from './CodeChatPanel';
14
14
  export { useChatbot } from './useChatbot';
15
15
  export type { UseChatbotConfig, UseChatbotReturn } from './useChatbot';
16
- export { LockedZone, EditableZone, NonCustomizable, Customizable, } from './EditableZone';
17
- export type { ZoneProps } from './EditableZone';
18
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGlG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGvE,OAAO,EACL,UAAU,EACV,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGlG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -11,5 +11,3 @@ export { ChatInput } from './ChatInput';
11
11
  export { CodeChatPanel } from './CodeChatPanel';
12
12
  // Headless hook for custom UI
13
13
  export { useChatbot } from './useChatbot';
14
- // Zone wrappers for builder customization control
15
- export { LockedZone, EditableZone, NonCustomizable, Customizable, } from './EditableZone';
package/dist/index.d.ts CHANGED
@@ -7,8 +7,8 @@
7
7
  * - Inference SDK for tenant customization loading
8
8
  */
9
9
  export * from 'dynim-core';
10
- export { BuilderProvider, useBuilder, ChatProvider, useChatContext, MessageList, ChatInput, CodeChatPanel, useChatbot, LockedZone, EditableZone, NonCustomizable, Customizable, } from './builder';
11
- export type { BuilderConfig, BuilderContextValue, BuilderProviderProps, ChatProviderProps, MessageListProps, ChatInputProps, CodeChatPanelProps, UseChatbotConfig, UseChatbotReturn, ZoneProps, } from './builder';
10
+ export { BuilderProvider, useBuilder, ChatProvider, useChatContext, MessageList, ChatInput, CodeChatPanel, useChatbot, } from './builder';
11
+ export type { BuilderConfig, BuilderContextValue, BuilderProviderProps, ChatProviderProps, MessageListProps, ChatInputProps, CodeChatPanelProps, UseChatbotConfig, UseChatbotReturn, } from './builder';
12
12
  export { InferenceProvider, InferenceProviderDefault, createSharedContext, getSharedContext, isSharedContextReady, } from './inference';
13
13
  export type { DynimSDKConfig, InferenceProviderProps, InferenceState, DynimGlobal, } from './inference';
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAEL,eAAe,EACf,UAAU,EAEV,YAAY,EACZ,cAAc,EAEd,WAAW,EACX,SAAS,EACT,aAAa,EAEb,UAAU,EAEV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAEL,eAAe,EACf,UAAU,EAEV,YAAY,EACZ,cAAc,EAEd,WAAW,EACX,SAAS,EACT,aAAa,EAEb,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -17,8 +17,6 @@ ChatProvider, useChatContext,
17
17
  // Components
18
18
  MessageList, ChatInput, CodeChatPanel,
19
19
  // Headless hook
20
- useChatbot,
21
- // Zone wrappers for customization control
22
- LockedZone, EditableZone, NonCustomizable, Customizable, } from './builder';
20
+ useChatbot, } from './builder';
23
21
  // Inference exports
24
22
  export { InferenceProvider, InferenceProviderDefault, createSharedContext, getSharedContext, isSharedContextReady, } from './inference';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynim-react",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "dev": "tsc --watch"
14
14
  },
15
15
  "dependencies": {
16
- "dynim-core": "^1.0.4"
16
+ "dynim-core": "^1.0.6"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "react": ">=17.0.0",
@@ -1,73 +0,0 @@
1
- import { type ReactNode, type HTMLAttributes } from 'react';
2
- /**
3
- * Props for zone wrapper components
4
- */
5
- export interface ZoneProps extends HTMLAttributes<HTMLDivElement> {
6
- /** Content to wrap */
7
- children: ReactNode;
8
- /** HTML tag to render (default: 'div') */
9
- as?: keyof JSX.IntrinsicElements;
10
- }
11
- /**
12
- * LockedZone - Wraps content to prevent builder customization
13
- *
14
- * Elements inside a LockedZone cannot be:
15
- * - Dragged/moved by the builder
16
- * - Used as drop targets
17
- *
18
- * Use this to protect parts of your UI that should not be editable,
19
- * like navigation, footers, or critical UI elements.
20
- *
21
- * @example
22
- * ```tsx
23
- * <LockedZone>
24
- * <Navigation /> {/* Cannot be moved or modified *\/}
25
- * </LockedZone>
26
- *
27
- * <div>
28
- * {/* This content is editable *\/}
29
- * </div>
30
- * ```
31
- *
32
- * @example Nested zones
33
- * ```tsx
34
- * <LockedZone>
35
- * <Sidebar>
36
- * <Logo /> {/* Locked *\/}
37
- * <EditableZone>
38
- * <CustomWidgets /> {/* Editable "island" inside locked zone *\/}
39
- * </EditableZone>
40
- * </Sidebar>
41
- * </LockedZone>
42
- * ```
43
- */
44
- export declare const LockedZone: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
45
- /**
46
- * EditableZone - Explicitly marks content as editable in the builder
47
- *
48
- * Use this to:
49
- * - Create editable "islands" inside a LockedZone
50
- * - Explicitly mark content as editable (though content is editable by default)
51
- *
52
- * @example Create editable area inside locked zone
53
- * ```tsx
54
- * <LockedZone>
55
- * <Header>
56
- * <Logo /> {/* Locked *\/}
57
- * <EditableZone>
58
- * <UserMenu /> {/* Editable despite being inside LockedZone *\/}
59
- * </EditableZone>
60
- * </Header>
61
- * </LockedZone>
62
- * ```
63
- */
64
- export declare const EditableZone: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
65
- /**
66
- * Alias for LockedZone - more explicit naming
67
- */
68
- export declare const NonCustomizable: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
69
- /**
70
- * Alias for EditableZone - more explicit naming
71
- */
72
- export declare const Customizable: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
73
- //# sourceMappingURL=EditableZone.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EditableZone.d.ts","sourceRoot":"","sources":["../../src/builder/EditableZone.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAc,MAAM,OAAO,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC/D,sBAAsB;IACtB,QAAQ,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,iBAAiB,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,UAAU,sGAYtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,sGAYxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,sGAAa,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,YAAY,sGAAe,CAAC"}
@@ -1,83 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { forwardRef } from 'react';
3
- import { VISIBILITY_ATTR } from 'dynim-core';
4
- /**
5
- * LockedZone - Wraps content to prevent builder customization
6
- *
7
- * Elements inside a LockedZone cannot be:
8
- * - Dragged/moved by the builder
9
- * - Used as drop targets
10
- *
11
- * Use this to protect parts of your UI that should not be editable,
12
- * like navigation, footers, or critical UI elements.
13
- *
14
- * @example
15
- * ```tsx
16
- * <LockedZone>
17
- * <Navigation /> {/* Cannot be moved or modified *\/}
18
- * </LockedZone>
19
- *
20
- * <div>
21
- * {/* This content is editable *\/}
22
- * </div>
23
- * ```
24
- *
25
- * @example Nested zones
26
- * ```tsx
27
- * <LockedZone>
28
- * <Sidebar>
29
- * <Logo /> {/* Locked *\/}
30
- * <EditableZone>
31
- * <CustomWidgets /> {/* Editable "island" inside locked zone *\/}
32
- * </EditableZone>
33
- * </Sidebar>
34
- * </LockedZone>
35
- * ```
36
- */
37
- export const LockedZone = forwardRef(function LockedZone({ children, as: Component = 'div', ...props }, ref) {
38
- const zoneProps = {
39
- ...props,
40
- [VISIBILITY_ATTR]: 'false',
41
- ref,
42
- };
43
- // Use createElement to support dynamic tag
44
- const Element = Component;
45
- return _jsx(Element, { ...zoneProps, children: children });
46
- });
47
- /**
48
- * EditableZone - Explicitly marks content as editable in the builder
49
- *
50
- * Use this to:
51
- * - Create editable "islands" inside a LockedZone
52
- * - Explicitly mark content as editable (though content is editable by default)
53
- *
54
- * @example Create editable area inside locked zone
55
- * ```tsx
56
- * <LockedZone>
57
- * <Header>
58
- * <Logo /> {/* Locked *\/}
59
- * <EditableZone>
60
- * <UserMenu /> {/* Editable despite being inside LockedZone *\/}
61
- * </EditableZone>
62
- * </Header>
63
- * </LockedZone>
64
- * ```
65
- */
66
- export const EditableZone = forwardRef(function EditableZone({ children, as: Component = 'div', ...props }, ref) {
67
- const zoneProps = {
68
- ...props,
69
- [VISIBILITY_ATTR]: 'true',
70
- ref,
71
- };
72
- // Use createElement to support dynamic tag
73
- const Element = Component;
74
- return _jsx(Element, { ...zoneProps, children: children });
75
- });
76
- /**
77
- * Alias for LockedZone - more explicit naming
78
- */
79
- export const NonCustomizable = LockedZone;
80
- /**
81
- * Alias for EditableZone - more explicit naming
82
- */
83
- export const Customizable = EditableZone;
@@ -1,23 +0,0 @@
1
- import type { DynimProviderProps } from './types';
2
- /**
3
- * DynimProvider - A React component that dynamically loads tenant-specific bundles.
4
- *
5
- * This provider handles the lifecycle of loading, rendering, and cleaning up
6
- * tenant customization bundles. It supports optional pre-checks to determine
7
- * if a tenant has customizations before attempting to load them.
8
- *
9
- * @example
10
- * ```tsx
11
- * <DynimProvider
12
- * tenantId={user?.tenantId}
13
- * bundleUrl={(id) => `https://cdn.example.com/bundles/${id}.js`}
14
- * loadingComponent={<Spinner />}
15
- * errorBanner={true}
16
- * >
17
- * <YourBaseApp />
18
- * </DynimProvider>
19
- * ```
20
- */
21
- export declare function DynimProvider({ tenantId, bundleUrl, checkCustomizations, loadingComponent, errorBanner, onError, onLoad, children, }: DynimProviderProps): JSX.Element;
22
- export default DynimProvider;
23
- //# sourceMappingURL=DynimProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../../src/inference/DynimProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAc,MAAM,SAAS,CAAC;AA8E9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,WAAmB,EACnB,OAAO,EACP,MAAM,EACN,QAAQ,GACT,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAuLlC;AAED,eAAe,aAAa,CAAC"}
@@ -1,231 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState, useEffect, useCallback, useRef } from 'react';
3
- /**
4
- * Default loading component shown while bundle is loading
5
- */
6
- function DefaultLoadingComponent() {
7
- return (_jsx("div", { style: {
8
- display: 'flex',
9
- justifyContent: 'center',
10
- alignItems: 'center',
11
- padding: '20px',
12
- }, children: _jsx("span", { children: "Loading customizations..." }) }));
13
- }
14
- /**
15
- * Default error banner component
16
- */
17
- function DefaultErrorBanner({ error }) {
18
- return (_jsxs("div", { style: {
19
- background: '#fee2e2',
20
- border: '1px solid #ef4444',
21
- borderRadius: '4px',
22
- padding: '12px 16px',
23
- marginBottom: '16px',
24
- color: '#991b1b',
25
- }, children: [_jsx("strong", { children: "Customization Error:" }), " ", error.message] }));
26
- }
27
- /**
28
- * Container for rendering tenant bundle content
29
- */
30
- function BundleContainer() {
31
- return _jsx("div", { id: "dynim-root" });
32
- }
33
- /**
34
- * Loads a script from a URL and returns a promise that resolves when loaded
35
- */
36
- function loadScript(url) {
37
- return new Promise((resolve, reject) => {
38
- // Check if script already exists
39
- const existingScript = document.querySelector(`script[src="${url}"]`);
40
- if (existingScript) {
41
- resolve();
42
- return;
43
- }
44
- const script = document.createElement('script');
45
- script.src = url;
46
- script.async = true;
47
- script.onload = () => resolve();
48
- script.onerror = () => reject(new Error(`Failed to load bundle from ${url}`));
49
- document.head.appendChild(script);
50
- });
51
- }
52
- /**
53
- * Removes a previously loaded script
54
- */
55
- function removeScript(url) {
56
- const script = document.querySelector(`script[src="${url}"]`);
57
- if (script) {
58
- script.remove();
59
- }
60
- }
61
- /**
62
- * DynimProvider - A React component that dynamically loads tenant-specific bundles.
63
- *
64
- * This provider handles the lifecycle of loading, rendering, and cleaning up
65
- * tenant customization bundles. It supports optional pre-checks to determine
66
- * if a tenant has customizations before attempting to load them.
67
- *
68
- * @example
69
- * ```tsx
70
- * <DynimProvider
71
- * tenantId={user?.tenantId}
72
- * bundleUrl={(id) => `https://cdn.example.com/bundles/${id}.js`}
73
- * loadingComponent={<Spinner />}
74
- * errorBanner={true}
75
- * >
76
- * <YourBaseApp />
77
- * </DynimProvider>
78
- * ```
79
- */
80
- export function DynimProvider({ tenantId, bundleUrl, checkCustomizations, loadingComponent, errorBanner = false, onError, onLoad, children, }) {
81
- const [state, setState] = useState({
82
- status: 'idle',
83
- error: null,
84
- currentTenantId: null,
85
- });
86
- const loadedUrlRef = useRef(null);
87
- /**
88
- * Resolves the bundle URL for a given tenant ID
89
- */
90
- const resolveBundleUrl = useCallback((id) => {
91
- if (typeof bundleUrl === 'function') {
92
- return bundleUrl(id);
93
- }
94
- // If bundleUrl is a string template, replace {tenantId} placeholder
95
- return bundleUrl.replace('{tenantId}', id);
96
- }, [bundleUrl]);
97
- /**
98
- * Cleans up previously loaded bundle
99
- */
100
- const cleanup = useCallback(() => {
101
- if (loadedUrlRef.current) {
102
- removeScript(loadedUrlRef.current);
103
- loadedUrlRef.current = null;
104
- }
105
- // Clear the bundle render target
106
- const root = document.getElementById('dynim-root');
107
- if (root) {
108
- root.innerHTML = '';
109
- }
110
- }, []);
111
- /**
112
- * Main effect to handle tenant bundle loading
113
- */
114
- useEffect(() => {
115
- // No tenant - reset to idle and show children
116
- if (!tenantId) {
117
- cleanup();
118
- setState({
119
- status: 'idle',
120
- error: null,
121
- currentTenantId: null,
122
- });
123
- return;
124
- }
125
- // Same tenant already loaded - do nothing
126
- if (state.currentTenantId === tenantId && state.status === 'loaded') {
127
- return;
128
- }
129
- let cancelled = false;
130
- async function loadBundle() {
131
- try {
132
- // Step 1: Check if tenant has customizations (if check function provided)
133
- if (checkCustomizations) {
134
- setState((prev) => ({ ...prev, status: 'checking' }));
135
- const hasCustomizations = await checkCustomizations(tenantId);
136
- if (cancelled)
137
- return;
138
- if (!hasCustomizations) {
139
- cleanup();
140
- setState({
141
- status: 'no-customization',
142
- error: null,
143
- currentTenantId: tenantId,
144
- });
145
- return;
146
- }
147
- }
148
- // Step 2: Load the bundle
149
- setState((prev) => ({ ...prev, status: 'loading' }));
150
- // Clean up previous bundle
151
- cleanup();
152
- const url = resolveBundleUrl(tenantId);
153
- await loadScript(url);
154
- if (cancelled) {
155
- removeScript(url);
156
- return;
157
- }
158
- loadedUrlRef.current = url;
159
- setState({
160
- status: 'loaded',
161
- error: null,
162
- currentTenantId: tenantId,
163
- });
164
- onLoad?.(tenantId);
165
- }
166
- catch (err) {
167
- if (cancelled)
168
- return;
169
- const error = err instanceof Error ? err : new Error(String(err));
170
- setState({
171
- status: 'error',
172
- error,
173
- currentTenantId: tenantId,
174
- });
175
- onError?.(error, tenantId);
176
- }
177
- }
178
- loadBundle();
179
- return () => {
180
- cancelled = true;
181
- };
182
- }, [
183
- tenantId,
184
- checkCustomizations,
185
- resolveBundleUrl,
186
- cleanup,
187
- onError,
188
- onLoad,
189
- state.currentTenantId,
190
- state.status,
191
- ]);
192
- /**
193
- * Cleanup on unmount
194
- */
195
- useEffect(() => {
196
- return () => {
197
- cleanup();
198
- };
199
- }, [cleanup]);
200
- // Render error banner if enabled and there's an error
201
- const renderErrorBanner = () => {
202
- if (!errorBanner || state.status !== 'error' || !state.error) {
203
- return null;
204
- }
205
- if (errorBanner === true) {
206
- return _jsx(DefaultErrorBanner, { error: state.error });
207
- }
208
- return errorBanner;
209
- };
210
- // Determine what to render based on state
211
- const renderContent = () => {
212
- switch (state.status) {
213
- case 'checking':
214
- case 'loading':
215
- return loadingComponent ?? _jsx(DefaultLoadingComponent, {});
216
- case 'loaded':
217
- // Bundle is loaded and will render itself into #dynim-root
218
- return _jsx(BundleContainer, {});
219
- case 'error':
220
- // Show children as fallback with optional error banner
221
- return (_jsxs(_Fragment, { children: [renderErrorBanner(), children] }));
222
- case 'no-customization':
223
- case 'idle':
224
- default:
225
- // No customizations or no tenant - render base app
226
- return children;
227
- }
228
- };
229
- return _jsx(_Fragment, { children: renderContent() });
230
- }
231
- export default DynimProvider;
@@ -1,39 +0,0 @@
1
- import type { DynimSDKConfig, DynimGlobal } from './types';
2
- /**
3
- * Creates and registers the Dynim SDK on the window object.
4
- * This makes React, ReactDOM, hooks, and contexts available to tenant bundles.
5
- *
6
- * @param config - Configuration object containing React, ReactDOM, hooks, and contexts
7
- * @returns The created SDK object
8
- *
9
- * @example
10
- * ```tsx
11
- * import { createDynimSDK } from 'dynim-react';
12
- * import React from 'react';
13
- * import ReactDOM from 'react-dom';
14
- * import { useAuth, useNotifications } from './hooks';
15
- * import { AuthContext, NotificationContext } from './contexts';
16
- *
17
- * createDynimSDK({
18
- * React,
19
- * ReactDOM,
20
- * hooks: { useAuth, useNotifications },
21
- * contexts: { AuthContext, NotificationContext }
22
- * });
23
- * ```
24
- */
25
- export declare function createDynimSDK(config: DynimSDKConfig): DynimGlobal;
26
- /**
27
- * Gets the current Dynim SDK instance from the window object.
28
- * Useful for tenant bundles to access the SDK.
29
- *
30
- * @returns The SDK instance or undefined if not initialized
31
- */
32
- export declare function getDynimSDK(): DynimGlobal | undefined;
33
- /**
34
- * Checks if the Dynim SDK has been initialized.
35
- *
36
- * @returns true if the SDK is available
37
- */
38
- export declare function isDynimSDKReady(): boolean;
39
- //# sourceMappingURL=createDynimSDK.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createDynimSDK.d.ts","sourceRoot":"","sources":["../../src/inference/createDynimSDK.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAqBlE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,WAAW,GAAG,SAAS,CAKrD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC"}
@@ -1,61 +0,0 @@
1
- /**
2
- * Creates and registers the Dynim SDK on the window object.
3
- * This makes React, ReactDOM, hooks, and contexts available to tenant bundles.
4
- *
5
- * @param config - Configuration object containing React, ReactDOM, hooks, and contexts
6
- * @returns The created SDK object
7
- *
8
- * @example
9
- * ```tsx
10
- * import { createDynimSDK } from 'dynim-react';
11
- * import React from 'react';
12
- * import ReactDOM from 'react-dom';
13
- * import { useAuth, useNotifications } from './hooks';
14
- * import { AuthContext, NotificationContext } from './contexts';
15
- *
16
- * createDynimSDK({
17
- * React,
18
- * ReactDOM,
19
- * hooks: { useAuth, useNotifications },
20
- * contexts: { AuthContext, NotificationContext }
21
- * });
22
- * ```
23
- */
24
- export function createDynimSDK(config) {
25
- const { React, ReactDOM, hooks = {}, contexts = {}, globals = {} } = config;
26
- const sdk = {
27
- React,
28
- ReactDOM,
29
- hooks,
30
- contexts,
31
- ...globals,
32
- };
33
- // Register on window for tenant bundles to access
34
- if (typeof window !== 'undefined') {
35
- window.__DYNIM__ = sdk;
36
- // Also expose React and ReactDOM directly on window for bundles using standard imports
37
- window.React = React;
38
- window.ReactDOM = ReactDOM;
39
- }
40
- return sdk;
41
- }
42
- /**
43
- * Gets the current Dynim SDK instance from the window object.
44
- * Useful for tenant bundles to access the SDK.
45
- *
46
- * @returns The SDK instance or undefined if not initialized
47
- */
48
- export function getDynimSDK() {
49
- if (typeof window !== 'undefined') {
50
- return window.__DYNIM__;
51
- }
52
- return undefined;
53
- }
54
- /**
55
- * Checks if the Dynim SDK has been initialized.
56
- *
57
- * @returns true if the SDK is available
58
- */
59
- export function isDynimSDKReady() {
60
- return typeof window !== 'undefined' && window.__DYNIM__ !== undefined;
61
- }