@janbox/storefront-builder 1.0.4 → 1.0.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/README.md +477 -0
- package/dist/editor/ui/dialog/dialog/helpers.d.ts +1 -1
- package/dist/editor/ui/dialog/dialog-close/dialog-close.d.ts +1 -1
- package/dist/editor.js +2 -2
- package/dist/{index-CBDllFpx.js → index-DrJkOkbq.js} +13 -13
- package/dist/index.js +2 -2
- package/dist/lib/accordion/README.md +39 -0
- package/dist/lib/accordion-content/README.md +36 -0
- package/dist/lib/accordion-group/README.md +106 -0
- package/dist/lib/accordion-summary/README.md +37 -0
- package/dist/lib/box/README.md +107 -0
- package/dist/lib/button/README.md +94 -0
- package/dist/lib/cell/README.md +119 -0
- package/dist/lib/countdown-timer/README.md +157 -0
- package/dist/lib/flex-item/README.md +111 -0
- package/dist/lib/flexbox/README.md +120 -0
- package/dist/lib/grid/README.md +133 -0
- package/dist/lib/heading/README.md +53 -0
- package/dist/lib/icon/README.md +98 -0
- package/dist/lib/image/README.md +107 -0
- package/dist/lib/link/README.md +111 -0
- package/dist/lib/list-item/README.md +31 -0
- package/dist/lib/marquee/README.md +111 -0
- package/dist/lib/marquee-item/README.md +31 -0
- package/dist/lib/paragraph/README.md +82 -0
- package/dist/lib/root/README.md +33 -0
- package/dist/lib/swiper/README.md +108 -0
- package/dist/lib/swiper-slide/README.md +32 -0
- package/dist/lib/tab/README.md +35 -0
- package/dist/lib/tab-content/README.md +35 -0
- package/dist/lib/tab-list/README.md +35 -0
- package/dist/lib/tab-panel/README.md +35 -0
- package/dist/lib/tabs/README.md +90 -0
- package/dist/lib/text/README.md +90 -0
- package/dist/lib/unknown/README.md +48 -0
- package/dist/lib/unordered-list/README.md +82 -0
- package/dist/lib/video/README.md +91 -0
- package/lib/accordion/README.md +39 -0
- package/lib/accordion-content/README.md +36 -0
- package/lib/accordion-group/README.md +106 -0
- package/lib/accordion-summary/README.md +37 -0
- package/lib/box/README.md +107 -0
- package/lib/button/README.md +94 -0
- package/lib/cell/README.md +119 -0
- package/lib/countdown-timer/README.md +157 -0
- package/lib/flex-item/README.md +111 -0
- package/lib/flexbox/README.md +120 -0
- package/lib/grid/README.md +133 -0
- package/lib/heading/README.md +53 -0
- package/lib/icon/README.md +98 -0
- package/lib/image/README.md +107 -0
- package/lib/link/README.md +111 -0
- package/lib/list-item/README.md +31 -0
- package/lib/marquee/README.md +111 -0
- package/lib/marquee-item/README.md +31 -0
- package/lib/paragraph/README.md +82 -0
- package/lib/root/README.md +33 -0
- package/lib/swiper/README.md +108 -0
- package/lib/swiper-slide/README.md +32 -0
- package/lib/tab/README.md +35 -0
- package/lib/tab-content/README.md +35 -0
- package/lib/tab-list/README.md +35 -0
- package/lib/tab-panel/README.md +35 -0
- package/lib/tabs/README.md +90 -0
- package/lib/text/README.md +90 -0
- package/lib/unknown/README.md +48 -0
- package/lib/unordered-list/README.md +82 -0
- package/lib/video/README.md +91 -0
- package/package.json +5 -9
package/README.md
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# @janbox/storefront-builder
|
|
2
|
+
|
|
3
|
+
A standalone visual page builder library built on [CraftJS](https://craft.js.org/). Provides drag-and-drop storefront creation with a full editor UI, 33 pre-built node components, and responsive design support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @janbox/storefront-builder
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @janbox/storefront-builder
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer dependencies
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install react@^19 react-dom@^19 @janbox/storefront-ui@>=2
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Package Exports
|
|
20
|
+
|
|
21
|
+
| Import path | Contents |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `@janbox/storefront-builder` | Node components (all 33 nodes) |
|
|
24
|
+
| `@janbox/storefront-builder/editor` | Full editor UI (`Editor` component + toolbars) |
|
|
25
|
+
| `@janbox/storefront-builder/templates` | Pre-built element groups and section templates |
|
|
26
|
+
| `@janbox/storefront-builder/style.css` | Required CSS bundle |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start — Full Editor
|
|
31
|
+
|
|
32
|
+
The `Editor` component from `/editor` renders the complete visual builder UI (header toolbar, sidebar with component library, drag-and-drop canvas).
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import '@janbox/storefront-builder/style.css';
|
|
36
|
+
import { Editor } from '@janbox/storefront-builder/editor';
|
|
37
|
+
import {
|
|
38
|
+
LAYOUT_ELEMENT_GROUP,
|
|
39
|
+
TEXT_ELEMENT_GROUP,
|
|
40
|
+
MEDIA_ELEMENT_GROUP,
|
|
41
|
+
INTERACTIVE_ELEMENT_GROUP,
|
|
42
|
+
HERO_SECTION_GROUP,
|
|
43
|
+
} from '@janbox/storefront-builder/templates';
|
|
44
|
+
import type { Theme } from '@janbox/storefront-ui/theme';
|
|
45
|
+
|
|
46
|
+
const myTheme: Theme = {
|
|
47
|
+
palette: {
|
|
48
|
+
primary: {
|
|
49
|
+
500: '#fa8c16',
|
|
50
|
+
600: '#d46b08',
|
|
51
|
+
},
|
|
52
|
+
// ... full theme
|
|
53
|
+
},
|
|
54
|
+
typography: {
|
|
55
|
+
base: { fontSize: '1rem', lineHeight: '1.5rem' },
|
|
56
|
+
// ...
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default function BuilderPage() {
|
|
61
|
+
return (
|
|
62
|
+
<Editor
|
|
63
|
+
theme={myTheme}
|
|
64
|
+
insert={{
|
|
65
|
+
elements: [LAYOUT_ELEMENT_GROUP, TEXT_ELEMENT_GROUP, MEDIA_ELEMENT_GROUP, INTERACTIVE_ELEMENT_GROUP],
|
|
66
|
+
sections: [HERO_SECTION_GROUP],
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`Editor` occupies the full viewport (`100vw × 100vh`). It should be the root of a dedicated page/route.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Quick Start — Render Only (No Editor UI)
|
|
78
|
+
|
|
79
|
+
Use `Composer` + `Canvas` to render a saved page without the editor chrome. This is for the storefront-facing page.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import '@janbox/storefront-builder/style.css';
|
|
83
|
+
import { Composer, Canvas } from '@janbox/storefront-builder';
|
|
84
|
+
import { RootNode } from '@janbox/storefront-builder';
|
|
85
|
+
import type { SerializedNodes } from '@janbox/storefront-builder';
|
|
86
|
+
|
|
87
|
+
const savedData: SerializedNodes = { /* JSON from editor */ };
|
|
88
|
+
|
|
89
|
+
export default function StorefrontPage() {
|
|
90
|
+
return (
|
|
91
|
+
<Composer>
|
|
92
|
+
<Canvas data={savedData}>
|
|
93
|
+
<RootNode />
|
|
94
|
+
</Canvas>
|
|
95
|
+
</Composer>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Core Concepts
|
|
103
|
+
|
|
104
|
+
### Nodes
|
|
105
|
+
|
|
106
|
+
Every element on the canvas is a **node** — a React component registered with CraftJS. The library ships 33 built-in nodes:
|
|
107
|
+
|
|
108
|
+
| Category | Nodes |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| Layout | `RootNode`, `Box`, `Flexbox`, `FlexItem`, `Grid`, `Cell` |
|
|
111
|
+
| Typography | `Text`, `Paragraph`, `Heading` |
|
|
112
|
+
| Media | `Image`, `Video`, `Icon` |
|
|
113
|
+
| Navigation | `Link`, `Button` |
|
|
114
|
+
| Lists | `UnorderedList`, `ListItem` |
|
|
115
|
+
| Tabs | `Tabs`, `TabList`, `Tab`, `TabContent`, `TabPanel` |
|
|
116
|
+
| Accordion | `Accordion`, `AccordionGroup`, `AccordionSummary`, `AccordionContent` |
|
|
117
|
+
| Carousel | `Swiper`, `SwiperSlide` |
|
|
118
|
+
| Marquee | `Marquee`, `MarqueeItem` |
|
|
119
|
+
| Utilities | `CountdownTimer` |
|
|
120
|
+
| Internal | `UnknownNode` (fallback for unresolved nodes) |
|
|
121
|
+
|
|
122
|
+
All nodes are exported from `@janbox/storefront-builder`.
|
|
123
|
+
|
|
124
|
+
### Responsive Props
|
|
125
|
+
|
|
126
|
+
All style props accept either a plain value or a responsive object keyed by breakpoint:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
// Breakpoints: xs (390px), sm (768px), md (1280px), lg (1680px)
|
|
130
|
+
|
|
131
|
+
// Plain value (applies at all breakpoints)
|
|
132
|
+
{ fontSize: '16px' }
|
|
133
|
+
|
|
134
|
+
// Responsive object (xs is the base; other keys override upward)
|
|
135
|
+
{ fontSize: { xs: '14px', md: '18px' } }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The current breakpoint is controlled via the `?screen=xs|sm|md|lg` query param.
|
|
139
|
+
|
|
140
|
+
### Serialized State
|
|
141
|
+
|
|
142
|
+
The canvas state is plain JSON (`SerializedNodes` from `@craftjs/core`). Use `useComposer()` to read and serialize it:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import { useComposer } from '@janbox/storefront-builder';
|
|
146
|
+
|
|
147
|
+
function SaveButton() {
|
|
148
|
+
const { query } = useComposer();
|
|
149
|
+
|
|
150
|
+
const handleSave = () => {
|
|
151
|
+
const json = query.serialize(); // SerializedNodes as JSON string
|
|
152
|
+
// save to your backend
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return <button onClick={handleSave}>Save</button>;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Templates
|
|
162
|
+
|
|
163
|
+
Templates are pre-configured drag-and-drop groups shown in the editor sidebar.
|
|
164
|
+
|
|
165
|
+
### Element Groups (sidebar "Elements" tab)
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import {
|
|
169
|
+
LAYOUT_ELEMENT_GROUP, // Box, Flexbox, Grid
|
|
170
|
+
TEXT_ELEMENT_GROUP, // Text, Heading, Paragraph
|
|
171
|
+
MEDIA_ELEMENT_GROUP, // Image, Video, Icon
|
|
172
|
+
INTERACTIVE_ELEMENT_GROUP, // Button, Link, Accordion, Tabs
|
|
173
|
+
CONTENT_LIST_ELEMENT_GROUP, // UnorderedList, Marquee, Swiper
|
|
174
|
+
UTILITIES_ELEMENT_GROUP, // CountdownTimer
|
|
175
|
+
} from '@janbox/storefront-builder/templates';
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Section Groups (sidebar "Sections" tab)
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import {
|
|
182
|
+
HERO_SECTION_GROUP,
|
|
183
|
+
FAQS_SECTION_GROUP,
|
|
184
|
+
GUARANTEE_SECTION_GROUP,
|
|
185
|
+
} from '@janbox/storefront-builder/templates';
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Pass them to `Editor` via the `insert` prop:
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
<Editor
|
|
192
|
+
theme={myTheme}
|
|
193
|
+
insert={{
|
|
194
|
+
elements: [LAYOUT_ELEMENT_GROUP, TEXT_ELEMENT_GROUP],
|
|
195
|
+
sections: [HERO_SECTION_GROUP],
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Custom Nodes
|
|
203
|
+
|
|
204
|
+
### 1. Create a node component
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
// my-badge.node.tsx
|
|
208
|
+
import { defineNode } from '@janbox/storefront-builder';
|
|
209
|
+
import { useNode } from '@janbox/storefront-builder';
|
|
210
|
+
|
|
211
|
+
type MyBadgeProps = { label: string; color?: string };
|
|
212
|
+
|
|
213
|
+
export const MyBadge = ({ label, color = '#fa8c16' }: MyBadgeProps) => {
|
|
214
|
+
const { connectors } = useNode();
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<span
|
|
218
|
+
ref={(el) => el && connectors.connect(el)}
|
|
219
|
+
style={{ background: color, padding: '2px 8px', borderRadius: 4 }}
|
|
220
|
+
>
|
|
221
|
+
{label}
|
|
222
|
+
</span>
|
|
223
|
+
);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
defineNode(MyBadge, {
|
|
227
|
+
resolved: 'MyBadge',
|
|
228
|
+
isCanvas: false,
|
|
229
|
+
info: { displayName: 'Badge' },
|
|
230
|
+
defaultProps: { label: 'Badge', color: '#fa8c16' },
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 2. Pass a resolver to the editor
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
import { MyBadge } from './my-badge.node';
|
|
238
|
+
|
|
239
|
+
<Editor
|
|
240
|
+
theme={myTheme}
|
|
241
|
+
resolver={{ MyBadge }}
|
|
242
|
+
insert={{ elements: [/* ... */], sections: [] }}
|
|
243
|
+
/>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 3. Add a toolbar (optional)
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
// my-badge.toolbar.tsx
|
|
250
|
+
import { useNodeProps } from '@janbox/storefront-builder';
|
|
251
|
+
|
|
252
|
+
export function MyBadgeToolbar() {
|
|
253
|
+
const { nodeProps, setNodeProps } = useNodeProps<MyBadgeProps>();
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<div>
|
|
257
|
+
<label>Label</label>
|
|
258
|
+
<input
|
|
259
|
+
value={nodeProps.label}
|
|
260
|
+
onChange={(e) => setNodeProps({ label: e.target.value })}
|
|
261
|
+
/>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Register the toolbar in `defineNode`:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
defineNode(MyBadge, {
|
|
271
|
+
resolved: 'MyBadge',
|
|
272
|
+
info: { displayName: 'Badge' },
|
|
273
|
+
related: { inspector: MyBadgeToolbar },
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Hooks
|
|
280
|
+
|
|
281
|
+
All hooks must be called inside a `<Composer>` tree.
|
|
282
|
+
|
|
283
|
+
### `useComposer(collector?)`
|
|
284
|
+
|
|
285
|
+
Enhanced wrapper around CraftJS `useEditor`. Adds `actions.duplicate()` and `actions.move()`.
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
const { query, actions } = useComposer();
|
|
289
|
+
|
|
290
|
+
// Serialize current canvas state
|
|
291
|
+
const json = query.serialize();
|
|
292
|
+
|
|
293
|
+
// Duplicate a node
|
|
294
|
+
actions.duplicate(nodeId);
|
|
295
|
+
|
|
296
|
+
// Move a node
|
|
297
|
+
actions.move({ nodeId, sourceIndex: 0, destinationIndex: 2 });
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### `useNodeProps<P>(options?)`
|
|
301
|
+
|
|
302
|
+
Read and write props for the current node (or a specific node via `options.nodeId`). Supports responsive updates.
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
const { nodeProps, setNodeProps, setNodeResponsiveProps } = useNodeProps<MyProps>();
|
|
306
|
+
|
|
307
|
+
// Set a flat prop
|
|
308
|
+
setNodeProps({ color: '#ff0000' });
|
|
309
|
+
|
|
310
|
+
// Set a responsive prop for a specific breakpoint
|
|
311
|
+
setNodeResponsiveProps({ fontSize: '18px' }, 'md');
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### `useNode()`
|
|
315
|
+
|
|
316
|
+
Direct access to the CraftJS node context (re-exported from `@craftjs/core`).
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
const { id, connectors, actions } = useNode();
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## TailwindCSS Integration
|
|
325
|
+
|
|
326
|
+
The library uses TailwindCSS v4 internally with a `tw:` prefix. To extend it in your app:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
// tailwind.config.ts
|
|
330
|
+
import builderConfig from '@janbox/storefront-builder/tailwind.config';
|
|
331
|
+
|
|
332
|
+
export default {
|
|
333
|
+
presets: [builderConfig],
|
|
334
|
+
// your overrides
|
|
335
|
+
};
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Import the stylesheet once at your app entry:
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
import '@janbox/storefront-builder/style.css';
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Theme Shape
|
|
347
|
+
|
|
348
|
+
The `theme` prop on `Editor` follows the `@janbox/storefront-ui` `Theme` type:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
type Theme = {
|
|
352
|
+
palette: {
|
|
353
|
+
primary: Record<100 | 200 | 300 | 400 | 500 | 600 | 700 | 800, string>;
|
|
354
|
+
secondary: Record<...>;
|
|
355
|
+
red, orange, yellow, green, blue, violet, neutral: Record<...>;
|
|
356
|
+
black: string;
|
|
357
|
+
white: string;
|
|
358
|
+
background: { subtle, default, emphasis: string };
|
|
359
|
+
surface: { default: string };
|
|
360
|
+
border: { default: string };
|
|
361
|
+
inherit: string;
|
|
362
|
+
current: string;
|
|
363
|
+
transparent: string;
|
|
364
|
+
};
|
|
365
|
+
typography: Record<'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl', {
|
|
366
|
+
fontSize: string;
|
|
367
|
+
lineHeight: string;
|
|
368
|
+
}>;
|
|
369
|
+
};
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## TypeScript
|
|
375
|
+
|
|
376
|
+
The package ships full `.d.ts` declarations. Key types:
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
import type {
|
|
380
|
+
SerializedNodes, // canvas JSON state
|
|
381
|
+
NodeId, // string node identifier
|
|
382
|
+
NodeTree, // tree of nodes
|
|
383
|
+
Resolver, // map of resolvedName → component
|
|
384
|
+
NodeConfig, // config passed to defineNode()
|
|
385
|
+
DisplayOnValue, // responsive visibility: Partial<Record<Screen, boolean>>
|
|
386
|
+
} from '@janbox/storefront-builder';
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Node Reference
|
|
392
|
+
|
|
393
|
+
Chi tiết props, usage và rules cho từng node:
|
|
394
|
+
|
|
395
|
+
### Layout
|
|
396
|
+
|
|
397
|
+
- [RootNode](lib/root/README.md) — top-level canvas container
|
|
398
|
+
- [BoxNode](lib/box/README.md) — block container
|
|
399
|
+
- [FlexboxNode](lib/flexbox/README.md) — flex container
|
|
400
|
+
- [FlexItemNode](lib/flex-item/README.md) — flex item
|
|
401
|
+
- [GridNode](lib/grid/README.md) — CSS grid container
|
|
402
|
+
- [CellNode](lib/cell/README.md) — grid cell
|
|
403
|
+
|
|
404
|
+
### Typography
|
|
405
|
+
|
|
406
|
+
- [TextNode](lib/text/README.md) — inline/block text
|
|
407
|
+
- [HeadingNode](lib/heading/README.md) — h1–h6 heading
|
|
408
|
+
- [ParagraphNode](lib/paragraph/README.md) — paragraph
|
|
409
|
+
|
|
410
|
+
### Media
|
|
411
|
+
|
|
412
|
+
- [ImageNode](lib/image/README.md) — image
|
|
413
|
+
- [VideoNode](lib/video/README.md) — video player
|
|
414
|
+
- [IconNode](lib/icon/README.md) — inline SVG icon
|
|
415
|
+
|
|
416
|
+
### Navigation
|
|
417
|
+
|
|
418
|
+
- [LinkNode](lib/link/README.md) — anchor link
|
|
419
|
+
- [ButtonNode](lib/button/README.md) — CTA button
|
|
420
|
+
|
|
421
|
+
### Lists
|
|
422
|
+
|
|
423
|
+
- [UnorderedListNode](lib/unordered-list/README.md) — list container
|
|
424
|
+
- [ListItemNode](lib/list-item/README.md) — list item
|
|
425
|
+
|
|
426
|
+
### Accordion
|
|
427
|
+
|
|
428
|
+
- [AccordionGroupNode](lib/accordion-group/README.md) — accordion container
|
|
429
|
+
- [AccordionNode](lib/accordion/README.md) — accordion item
|
|
430
|
+
- [AccordionSummaryNode](lib/accordion-summary/README.md) — accordion header
|
|
431
|
+
- [AccordionContentNode](lib/accordion-content/README.md) — accordion content
|
|
432
|
+
|
|
433
|
+
### Tabs
|
|
434
|
+
|
|
435
|
+
- [TabsNode](lib/tabs/README.md) — tabs container
|
|
436
|
+
- [TabListNode](lib/tab-list/README.md) — tab headers container
|
|
437
|
+
- [TabNode](lib/tab/README.md) — tab header button
|
|
438
|
+
- [TabContentNode](lib/tab-content/README.md) — tab panels container
|
|
439
|
+
- [TabPanelNode](lib/tab-panel/README.md) — tab panel content
|
|
440
|
+
|
|
441
|
+
### Carousel
|
|
442
|
+
|
|
443
|
+
- [SwiperNode](lib/swiper/README.md) — carousel container
|
|
444
|
+
- [SwiperSlideNode](lib/swiper-slide/README.md) — carousel slide
|
|
445
|
+
|
|
446
|
+
### Marquee
|
|
447
|
+
|
|
448
|
+
- [MarqueeNode](lib/marquee/README.md) — auto-scrolling ticker
|
|
449
|
+
- [MarqueeItemNode](lib/marquee-item/README.md) — ticker item
|
|
450
|
+
|
|
451
|
+
### Utilities
|
|
452
|
+
|
|
453
|
+
- [CountdownTimerNode](lib/countdown-timer/README.md) — countdown timer
|
|
454
|
+
|
|
455
|
+
### Internal
|
|
456
|
+
|
|
457
|
+
- [UnknownNode](lib/unknown/README.md) — fallback for unresolved nodes
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## Monorepo Development
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
# Install dependencies
|
|
465
|
+
pnpm install
|
|
466
|
+
|
|
467
|
+
# Start demo app (React Router 7)
|
|
468
|
+
pnpm dev
|
|
469
|
+
|
|
470
|
+
# Build the library
|
|
471
|
+
pnpm build
|
|
472
|
+
|
|
473
|
+
# Type check
|
|
474
|
+
pnpm typecheck
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Requires Node.js >= 20 and pnpm.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useDialogContext: () => import('
|
|
1
|
+
export declare const useDialogContext: () => import('../..').WbFloatingContextValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const WbDialogClose: import('react').ForwardRefExoticComponent<Omit<import('
|
|
1
|
+
export declare const WbDialogClose: import('react').ForwardRefExoticComponent<Omit<import('../..').WbFloatingCloseProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
package/dist/editor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as n, Fragment as Ne, jsxs as g } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { u as _e, a as ae, b as te, D as ze, c as qe, W as j, d as E, e as Ge, f as Ue, g as Le, h as Ee, i as Ze, j as Qe, k as we, l as Ye, m as ue, n as oe, A as Se, o as Ke, C as Me, p as Re, q as Xe, r as Je, T as et, s as fe, R as tt } from "./index-
|
|
3
|
-
import { t as qr } from "./index-
|
|
2
|
+
import { u as _e, a as ae, b as te, D as ze, c as qe, W as j, d as E, e as Ge, f as Ue, g as Le, h as Ee, i as Ze, j as Qe, k as we, l as Ye, m as ue, n as oe, A as Se, o as Ke, C as Me, p as Re, q as Xe, r as Je, T as et, s as fe, R as tt } from "./index-DrJkOkbq.js";
|
|
3
|
+
import { t as qr } from "./index-DrJkOkbq.js";
|
|
4
4
|
import rt from "mitt";
|
|
5
5
|
import { c as I, N as pe, B as ge, g as nt, a as st, u as W, W as ot, b as $e, i as it, P as ct } from "./countdown-timer.node-CAsCNVin.js";
|
|
6
6
|
import { useRef as je, useState as _, useEffect as z, createElement as Ae, Fragment as J, Suspense as at } from "react";
|
|
@@ -7,8 +7,8 @@ import { u as St, x as oi, J as ue, D as C, c as L, W as ur, i as Bn, b as In, t
|
|
|
7
7
|
import { isFunction as Or, merge as ri, set as Ur, isNil as Wt, isString as Ne, isUndefined as Fe, get as ai } from "lodash-es";
|
|
8
8
|
import { OverlayScrollbarsComponent as _r } from "overlayscrollbars-react";
|
|
9
9
|
import { jsxs as Wr, jsx as li } from "react/jsx-runtime";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { useMergeRefs as de, useFloating as ci, autoUpdate as ui, offset as di, flip as hi, size as $r, useClick as Kr, useHover as Hr, safePolygon as zr, useDismiss as Gr, useRole as qr, useInteractions as Xr, useFloatingParentNodeId as Yr, FloatingTree as Zr, FloatingPortal as fi } from "@floating-ui/react";
|
|
11
|
+
import { useNode as tt, ROOT_NODE as Jr, Frame as Qr, Editor as ta, DefaultEventHandlers as ea } from "@craftjs/core";
|
|
12
12
|
import { useUpdateEffect as na } from "react-use";
|
|
13
13
|
import { useFrame as sa } from "react-frame-component";
|
|
14
14
|
import { Button as ia, UnorderedList as oa, ListItem as ra } from "@janbox/storefront-ui";
|
|
@@ -424,7 +424,7 @@ const bh = (t) => {
|
|
|
424
424
|
middleware: [
|
|
425
425
|
di(a),
|
|
426
426
|
hi(),
|
|
427
|
-
|
|
427
|
+
$r({
|
|
428
428
|
apply({ elements: S }) {
|
|
429
429
|
const b = {
|
|
430
430
|
zIndex: `${lr}`,
|
|
@@ -435,12 +435,12 @@ const bh = (t) => {
|
|
|
435
435
|
})
|
|
436
436
|
],
|
|
437
437
|
whileElementsMounted: ui
|
|
438
|
-
}), { context: h, refs: f } = d, m =
|
|
438
|
+
}), { context: h, refs: f } = d, m = Kr(h, {
|
|
439
439
|
enabled: o === "click"
|
|
440
|
-
}), y =
|
|
440
|
+
}), y = Hr(h, {
|
|
441
441
|
enabled: o === "hover",
|
|
442
|
-
handleClose:
|
|
443
|
-
}), g =
|
|
442
|
+
handleClose: zr()
|
|
443
|
+
}), g = Gr(
|
|
444
444
|
h,
|
|
445
445
|
ri(
|
|
446
446
|
{
|
|
@@ -448,7 +448,7 @@ const bh = (t) => {
|
|
|
448
448
|
},
|
|
449
449
|
s
|
|
450
450
|
)
|
|
451
|
-
), p =
|
|
451
|
+
), p = qr(h), v = Xr([m, g, p, y]), w = Y(
|
|
452
452
|
() => ({
|
|
453
453
|
...d,
|
|
454
454
|
...v
|
|
@@ -458,7 +458,7 @@ const bh = (t) => {
|
|
|
458
458
|
return na(() => {
|
|
459
459
|
Fe(r) || (f.setReference?.(r), h.onOpenChange(!Wt(r)));
|
|
460
460
|
}, [r]), /* @__PURE__ */ x(gi.Provider, { value: w, children: i });
|
|
461
|
-
}, va = (t) =>
|
|
461
|
+
}, va = (t) => Yr() ? /* @__PURE__ */ x(Un, { ...t }) : /* @__PURE__ */ x(Zr, { children: /* @__PURE__ */ x(Un, { ...t }) }), wa = ft(({ children: t, ...e }, n) => {
|
|
462
462
|
const { getReferenceProps: s, context: i } = yi(), r = de([i.refs.setReference, ai(t, "ref"), n]);
|
|
463
463
|
return _t(t) ? Je(
|
|
464
464
|
t,
|
|
@@ -5339,7 +5339,7 @@ const Yd = (t, e) => ln(t) ? new Xd(e) : new qd(e, {
|
|
|
5339
5339
|
} = tt((g) => {
|
|
5340
5340
|
let p = g.data.parent ? n.node(g.data.parent).get() : null;
|
|
5341
5341
|
for (; p && !Bn(p); )
|
|
5342
|
-
p = p.data.parent && p.data.parent !==
|
|
5342
|
+
p = p.data.parent && p.data.parent !== Jr ? n.node(p.data.parent).get() : null;
|
|
5343
5343
|
return {
|
|
5344
5344
|
dom: g.dom,
|
|
5345
5345
|
name: In(g),
|
|
@@ -5487,7 +5487,7 @@ const Bh = ({ children: t, data: e }) => {
|
|
|
5487
5487
|
});
|
|
5488
5488
|
}), i;
|
|
5489
5489
|
}, [e, n]);
|
|
5490
|
-
return /* @__PURE__ */ x(
|
|
5490
|
+
return /* @__PURE__ */ x(Qr, { data: s, children: t });
|
|
5491
5491
|
}, eh = {
|
|
5492
5492
|
// Root
|
|
5493
5493
|
[C.Root]: pi,
|
|
@@ -5532,7 +5532,7 @@ const Bh = ({ children: t, data: e }) => {
|
|
|
5532
5532
|
// Timer
|
|
5533
5533
|
[C.CountdownTimer]: dr
|
|
5534
5534
|
}, Ih = ({ resolver: t, children: e, ...n }) => /* @__PURE__ */ x(
|
|
5535
|
-
|
|
5535
|
+
ta,
|
|
5536
5536
|
{
|
|
5537
5537
|
enabled: !1,
|
|
5538
5538
|
onRender: nh,
|
|
@@ -5555,7 +5555,7 @@ const Bh = ({ children: t, data: e }) => {
|
|
|
5555
5555
|
);
|
|
5556
5556
|
}, [e, n]), t;
|
|
5557
5557
|
};
|
|
5558
|
-
class sh extends
|
|
5558
|
+
class sh extends ea {
|
|
5559
5559
|
handlers() {
|
|
5560
5560
|
const e = super.handlers();
|
|
5561
5561
|
return {
|
package/dist/index.js
CHANGED
|
@@ -7,8 +7,8 @@ import { Draggable as vt, DragDropContext as bt, Droppable as Nt } from "@hello-
|
|
|
7
7
|
import { getGridProps as so, getCellProps as ao, GRID_MINIMUM_COLS as Yt, GRID_MAXIMUM_COLS as io, getLinkProps as lo, getButtonProps as co, getFlexboxProps as uo, getFlexItemProps as ho, getTextProps as go, getImageProps as po, getMarqueeProps as wo, MarqueeDataAttributes as wt, getTabsProps as mo, getTabPanelProps as Co, getSwiperProps as xo, getUnorderedListProps as fo, getListItemProps as vo, getIconProps as bo, getAccordionProps as No, getAccordionGroupProps as ko, getAccordionDataAttributes as $e, AccordionDataAttributes as mt, getVideoProps as Ro, getBoxProps as Lo } from "@janbox/storefront-ui";
|
|
8
8
|
import { isNumber as nt, isNil as z, isFunction as To, assign as So, isUndefined as kt, get as ze, parseInt as yo, trimStart as Rt, isString as me, set as Bo } from "lodash-es";
|
|
9
9
|
import { useDebounceCallback as dn, useToggle as cn } from "usehooks-ts";
|
|
10
|
-
import { v as W, h as Y, W as T, d as f, n as Po, q as Io, A as ve, L as Mo, b as Lt, w as Se, x as ye, f as Ct, y as Be, z as Pe, a as Tt, B as Ao, e as U, r as ee, g as Q, o as Re, i as j, j as F, k as S, l as Z, m as y, E as St, T as yt, F as Wo, t as I, D as un, c as hn, G as Vo } from "./index-
|
|
11
|
-
import { p as pi, C as wi, R as mi, U as Ci, H as xi } from "./index-
|
|
10
|
+
import { v as W, h as Y, W as T, d as f, n as Po, q as Io, A as ve, L as Mo, b as Lt, w as Se, x as ye, f as Ct, y as Be, z as Pe, a as Tt, B as Ao, e as U, r as ee, g as Q, o as Re, i as j, j as F, k as S, l as Z, m as y, E as St, T as yt, F as Wo, t as I, D as un, c as hn, G as Vo } from "./index-DrJkOkbq.js";
|
|
11
|
+
import { p as pi, C as wi, R as mi, U as Ci, H as xi } from "./index-DrJkOkbq.js";
|
|
12
12
|
import { useNode as re } from "@craftjs/core";
|
|
13
13
|
import { useNode as vi } from "@craftjs/core";
|
|
14
14
|
import { W as Ho } from "./tooltip-CqfT80iK.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# AccordionNode
|
|
2
|
+
|
|
3
|
+
Một accordion item. Chứa `AccordionSummaryNode` (header) và `AccordionContentNode` (nội dung). Không selectable — chỉnh sửa qua parent `AccordionGroupNode`.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Accordion`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Không có props riêng. Tất cả styling được control qua `AccordionGroupNode`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { AccordionNode, AccordionSummaryNode, AccordionContentNode } from '@janbox/storefront-builder';
|
|
17
|
+
|
|
18
|
+
<AccordionNode>
|
|
19
|
+
<AccordionSummaryNode>
|
|
20
|
+
<TextNode>Question title</TextNode>
|
|
21
|
+
</AccordionSummaryNode>
|
|
22
|
+
<AccordionContentNode>
|
|
23
|
+
<TextNode>Answer content</TextNode>
|
|
24
|
+
</AccordionContentNode>
|
|
25
|
+
</AccordionNode>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Rules
|
|
29
|
+
|
|
30
|
+
- **Canvas**: no.
|
|
31
|
+
- **Selectable**: no — user không thể select trực tiếp node này trong editor.
|
|
32
|
+
- **Parent**: phải là `AccordionGroupNode`.
|
|
33
|
+
- **Children**: phải có `AccordionSummaryNode` và `AccordionContentNode`.
|
|
34
|
+
|
|
35
|
+
## Related nodes
|
|
36
|
+
|
|
37
|
+
- [`AccordionGroupNode`](../accordion-group/README.md) — parent container
|
|
38
|
+
- [`AccordionSummaryNode`](../accordion-summary/README.md) — header
|
|
39
|
+
- [`AccordionContentNode`](../accordion-content/README.md) — content area
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# AccordionContentNode
|
|
2
|
+
|
|
3
|
+
Content area của accordion item — phần expand/collapse khi click vào header. Là canvas node — chứa bất kỳ node con nào.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`AccordionContent`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Không có props riêng. Padding được config qua `AccordionGroupNode.accordionContentProps.sx`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { AccordionContentNode, ParagraphNode } from '@janbox/storefront-builder';
|
|
17
|
+
|
|
18
|
+
<AccordionContentNode>
|
|
19
|
+
<ParagraphNode>
|
|
20
|
+
Answer content goes here. Can contain any nodes.
|
|
21
|
+
</ParagraphNode>
|
|
22
|
+
</AccordionContentNode>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Rules
|
|
26
|
+
|
|
27
|
+
- **Canvas**: yes — chứa bất kỳ node con nào.
|
|
28
|
+
- **Selectable**: no.
|
|
29
|
+
- **canMoveOut**: no — không thể kéo ra khỏi `AccordionNode`.
|
|
30
|
+
- **Parent**: phải là `AccordionNode`.
|
|
31
|
+
|
|
32
|
+
## Related nodes
|
|
33
|
+
|
|
34
|
+
- [`AccordionNode`](../accordion/README.md) — parent item
|
|
35
|
+
- [`AccordionGroupNode`](../accordion-group/README.md) — root container
|
|
36
|
+
- [`AccordionSummaryNode`](../accordion-summary/README.md) — header
|