@janbox/storefront-builder 1.0.9 → 2.0.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 CHANGED
@@ -1,46 +1,38 @@
1
1
  # @janbox/storefront-builder
2
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.
3
+ Thư viện visual page builder độc lập, xây dựng trên [CraftJS](https://craft.js.org/). Hỗ trợ kéo-thả tạo storefront với giao diện editor đầy đủ, 33 node component sẵn và responsive design theo breakpoint.
4
4
 
5
- ## Installation
5
+ ## Cài đặt
6
6
 
7
7
  ```bash
8
- npm install @janbox/storefront-builder
9
- # or
10
8
  pnpm add @janbox/storefront-builder
11
9
  ```
12
10
 
13
11
  ### Peer dependencies
14
12
 
15
13
  ```bash
16
- npm install react@^19 react-dom@^19 @janbox/storefront-ui@>=2
14
+ pnpm add react@^19 react-dom@^19 @janbox/storefront-ui@>=2
17
15
  ```
18
16
 
19
17
  ## Package Exports
20
18
 
21
- | Import path | Contents |
19
+ | Import path | Nội dung |
22
20
  | --- | --- |
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 |
21
+ | `@janbox/storefront-builder` | Node components (33 nodes) |
22
+ | `@janbox/storefront-builder/editor` | Giao diện editor đầy đủ (`Editor` component + toolbars) |
23
+ | `@janbox/storefront-builder/templates` | Element groups section templates có sẵn |
24
+ | `@janbox/storefront-builder/style.css` | CSS bundle (bắt buộc import) |
27
25
 
28
26
  ---
29
27
 
30
28
  ## Quick Start — Full Editor
31
29
 
32
- The `Editor` component from `/editor` renders the complete visual builder UI (header toolbar, sidebar with component library, drag-and-drop canvas).
30
+ Component `Editor` render giao diện visual builder hoàn chỉnh: header toolbar, sidebar thư viện component, canvas kéo-thả.
33
31
 
34
32
  ```tsx
35
33
  import '@janbox/storefront-builder/style.css';
36
34
  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';
35
+ import { HERO_SECTION_GROUP, FAQS_SECTION_GROUP } from '@janbox/storefront-builder/templates';
44
36
  import type { Theme } from '@janbox/storefront-ui/theme';
45
37
 
46
38
  const myTheme: Theme = {
@@ -48,8 +40,9 @@ const myTheme: Theme = {
48
40
  primary: {
49
41
  500: '#fa8c16',
50
42
  600: '#d46b08',
43
+ // ...
51
44
  },
52
- // ... full theme
45
+ // ...
53
46
  },
54
47
  typography: {
55
48
  base: { fontSize: '1rem', lineHeight: '1.5rem' },
@@ -62,34 +55,36 @@ export default function BuilderPage() {
62
55
  <Editor
63
56
  theme={myTheme}
64
57
  handlers={{
65
- upload: async () => '',
66
- submit: (_data) => {},
67
- close: () => {},
58
+ upload: async (file) => URL.createObjectURL(file),
59
+ submit: async (data) => {
60
+ await savePage(data);
61
+ },
62
+ close: () => navigateBack(),
68
63
  }}
69
64
  insert={{
70
- elements: [LAYOUT_ELEMENT_GROUP, TEXT_ELEMENT_GROUP, MEDIA_ELEMENT_GROUP, INTERACTIVE_ELEMENT_GROUP],
71
- sections: [HERO_SECTION_GROUP],
65
+ groups: [HERO_SECTION_GROUP, FAQS_SECTION_GROUP],
72
66
  }}
73
67
  />
74
68
  );
75
69
  }
76
70
  ```
77
71
 
78
- `Editor` occupies the full viewport (`100vw × 100vh`). It should be the root of a dedicated page/route.
72
+ `Editor` chiếm toàn bộ viewport (`100vw × 100vh`), nên đặt một route/page riêng.
73
+
74
+ > Chi tiết đầy đủ về `Editor` xem tại [editor/lib/README.md](editor/lib/README.md).
79
75
 
80
76
  ---
81
77
 
82
- ## Quick Start — Render Only (No Editor UI)
78
+ ## Quick Start — Render Only (không editor UI)
83
79
 
84
- Use `Composer` + `Canvas` to render a saved page without the editor chrome. This is for the storefront-facing page.
80
+ Dùng `Composer` + `Canvas` để render một trang đã lưu, không cần giao diện editor. Đây cách dùng cho phía storefront hiển thị cho người mua.
85
81
 
86
82
  ```tsx
87
83
  import '@janbox/storefront-builder/style.css';
88
- import { Composer, Canvas } from '@janbox/storefront-builder';
89
- import { RootNode } from '@janbox/storefront-builder';
84
+ import { Composer, Canvas, RootNode } from '@janbox/storefront-builder';
90
85
  import type { SerializedNodes } from '@janbox/storefront-builder';
91
86
 
92
- const savedData: SerializedNodes = { /* JSON from editor */ };
87
+ const savedData: SerializedNodes = { /* JSON từ editor */ };
93
88
 
94
89
  export default function StorefrontPage() {
95
90
  return (
@@ -104,13 +99,13 @@ export default function StorefrontPage() {
104
99
 
105
100
  ---
106
101
 
107
- ## Core Concepts
102
+ ## Khái niệm cơ bản
108
103
 
109
104
  ### Nodes
110
105
 
111
- Every element on the canvas is a **node** — a React component registered with CraftJS. The library ships 33 built-in nodes:
106
+ Mỗi phần tử trên canvas một **node** — React component được đăng ký với CraftJS. Thư viện 33 node có sẵn:
112
107
 
113
- | Category | Nodes |
108
+ | Nhóm | Nodes |
114
109
  | --- | --- |
115
110
  | Layout | `RootNode`, `Box`, `Flexbox`, `FlexItem`, `Grid`, `Cell` |
116
111
  | Typography | `Text`, `Paragraph`, `Heading` |
@@ -122,29 +117,29 @@ Every element on the canvas is a **node** — a React component registered with
122
117
  | Carousel | `Swiper`, `SwiperSlide` |
123
118
  | Marquee | `Marquee`, `MarqueeItem` |
124
119
  | Utilities | `CountdownTimer` |
125
- | Internal | `UnknownNode` (fallback for unresolved nodes) |
120
+ | Internal | `UnknownNode` (fallback cho node không resolve được) |
126
121
 
127
- All nodes are exported from `@janbox/storefront-builder`.
122
+ Tất cả đều được export từ `@janbox/storefront-builder`.
128
123
 
129
124
  ### Responsive Props
130
125
 
131
- All style props accept either a plain value or a responsive object keyed by breakpoint:
126
+ Tất cả style prop đều nhận plain value hoặc responsive object theo breakpoint:
132
127
 
133
128
  ```ts
134
129
  // Breakpoints: xs (390px), sm (768px), md (1280px), lg (1680px)
135
130
 
136
- // Plain value (applies at all breakpoints)
131
+ // Plain value (áp dụng tại mọi breakpoint)
137
132
  { fontSize: '16px' }
138
133
 
139
- // Responsive object (xs is the base; other keys override upward)
134
+ // Responsive object (xs base; các key khác override theo hướng tăng dần)
140
135
  { fontSize: { xs: '14px', md: '18px' } }
141
136
  ```
142
137
 
143
- The current breakpoint is controlled via the `?screen=xs|sm|md|lg` query param.
138
+ Breakpoint hiện tại được điều khiển qua query param `?screen=xs|sm|md|lg`.
144
139
 
145
140
  ### Serialized State
146
141
 
147
- The canvas state is plain JSON (`SerializedNodes` from `@craftjs/core`). Use `useComposer()` to read and serialize it:
142
+ Trạng thái canvas plain JSON (`SerializedNodes`). Dùng `useComposer()` để đọc serialize:
148
143
 
149
144
  ```tsx
150
145
  import { useComposer } from '@janbox/storefront-builder';
@@ -153,11 +148,11 @@ function SaveButton() {
153
148
  const { query } = useComposer();
154
149
 
155
150
  const handleSave = () => {
156
- const json = query.serialize(); // SerializedNodes as JSON string
157
- // save to your backend
151
+ const json = query.serialize(); // JSON string dạng SerializedNodes
152
+ // lưu vào backend
158
153
  };
159
154
 
160
- return <button onClick={handleSave}>Save</button>;
155
+ return <button onClick={handleSave}>Lưu</button>;
161
156
  }
162
157
  ```
163
158
 
@@ -165,22 +160,11 @@ function SaveButton() {
165
160
 
166
161
  ## Templates
167
162
 
168
- Templates are pre-configured drag-and-drop groups shown in the editor sidebar.
163
+ Templates các nhóm kéo-thả sẵn trong sidebar editor.
169
164
 
170
- ### Element Groups (sidebar "Elements" tab)
165
+ Sidebar **Basics** được tích hợp sẵn trong editor và chứa toàn bộ element cơ bản. Consumer không cần import hay truyền các nhóm này.
171
166
 
172
- ```ts
173
- import {
174
- LAYOUT_ELEMENT_GROUP, // Box, Flexbox, Grid
175
- TEXT_ELEMENT_GROUP, // Text, Heading, Paragraph
176
- MEDIA_ELEMENT_GROUP, // Image, Video, Icon
177
- INTERACTIVE_ELEMENT_GROUP, // Button, Link, Accordion, Tabs
178
- CONTENT_LIST_ELEMENT_GROUP, // UnorderedList, Marquee, Swiper
179
- UTILITIES_ELEMENT_GROUP, // CountdownTimer
180
- } from '@janbox/storefront-builder/templates';
181
- ```
182
-
183
- ### Section Groups (sidebar "Sections" tab)
167
+ ### Section Groups
184
168
 
185
169
  ```ts
186
170
  import {
@@ -190,7 +174,7 @@ import {
190
174
  } from '@janbox/storefront-builder/templates';
191
175
  ```
192
176
 
193
- Pass them to `Editor` via the `insert` prop:
177
+ Truyền vào `Editor` qua prop `insert.groups`:
194
178
 
195
179
  ```tsx
196
180
  <Editor
@@ -201,8 +185,7 @@ Pass them to `Editor` via the `insert` prop:
201
185
  close: () => {},
202
186
  }}
203
187
  insert={{
204
- elements: [LAYOUT_ELEMENT_GROUP, TEXT_ELEMENT_GROUP],
205
- sections: [HERO_SECTION_GROUP],
188
+ groups: [HERO_SECTION_GROUP, FAQS_SECTION_GROUP],
206
189
  }}
207
190
  />
208
191
  ```
@@ -211,12 +194,11 @@ Pass them to `Editor` via the `insert` prop:
211
194
 
212
195
  ## Custom Nodes
213
196
 
214
- ### 1. Create a node component
197
+ ### 1. Tạo node component
215
198
 
216
199
  ```tsx
217
200
  // my-badge.node.tsx
218
- import { defineNode } from '@janbox/storefront-builder';
219
- import { useNode } from '@janbox/storefront-builder';
201
+ import { defineNode, useNode } from '@janbox/storefront-builder';
220
202
 
221
203
  type MyBadgeProps = { label: string; color?: string };
222
204
 
@@ -241,24 +223,20 @@ defineNode(MyBadge, {
241
223
  });
242
224
  ```
243
225
 
244
- ### 2. Pass a resolver to the editor
226
+ ### 2. Truyền resolver vào editor
245
227
 
246
228
  ```tsx
247
229
  import { MyBadge } from './my-badge.node';
248
230
 
249
231
  <Editor
250
232
  theme={myTheme}
251
- handlers={{
252
- upload: async () => '',
253
- submit: () => {},
254
- close: () => {},
255
- }}
233
+ handlers={{ upload: async () => '', submit: () => {}, close: () => {} }}
256
234
  resolver={{ MyBadge }}
257
- insert={{ elements: [/* ... */], sections: [] }}
235
+ insert={{ groups: [] }}
258
236
  />
259
237
  ```
260
238
 
261
- ### 3. Add a toolbar (optional)
239
+ ### 3. Thêm toolbar (tùy chọn)
262
240
 
263
241
  ```tsx
264
242
  // my-badge.toolbar.tsx
@@ -279,7 +257,7 @@ export function MyBadgeToolbar() {
279
257
  }
280
258
  ```
281
259
 
282
- Register the toolbar in `defineNode`:
260
+ Đăng toolbar trong `defineNode`:
283
261
 
284
262
  ```ts
285
263
  defineNode(MyBadge, {
@@ -293,42 +271,42 @@ defineNode(MyBadge, {
293
271
 
294
272
  ## Hooks
295
273
 
296
- All hooks must be called inside a `<Composer>` tree.
274
+ Tất cả hooks phải được gọi bên trong cây `<Composer>`.
297
275
 
298
276
  ### `useComposer(collector?)`
299
277
 
300
- Enhanced wrapper around CraftJS `useEditor`. Adds `actions.duplicate()` and `actions.move()`.
278
+ Wrapper nâng cao của CraftJS `useEditor`. Bổ sung thêm `actions.duplicate()` `actions.move()`.
301
279
 
302
280
  ```ts
303
281
  const { query, actions } = useComposer();
304
282
 
305
- // Serialize current canvas state
283
+ // Serialize trạng thái canvas hiện tại
306
284
  const json = query.serialize();
307
285
 
308
- // Duplicate a node
286
+ // Duplicate một node
309
287
  actions.duplicate(nodeId);
310
288
 
311
- // Move a node
289
+ // Di chuyển một node
312
290
  actions.move({ nodeId, sourceIndex: 0, destinationIndex: 2 });
313
291
  ```
314
292
 
315
293
  ### `useNodeProps<P>(options?)`
316
294
 
317
- Read and write props for the current node (or a specific node via `options.nodeId`). Supports responsive updates.
295
+ Đọc ghi props của node hiện tại (hoặc node chỉ định qua `options.nodeId`). Hỗ trợ cập nhật responsive.
318
296
 
319
297
  ```ts
320
298
  const { nodeProps, setNodeProps, setNodeResponsiveProps } = useNodeProps<MyProps>();
321
299
 
322
- // Set a flat prop
300
+ // Set prop thường
323
301
  setNodeProps({ color: '#ff0000' });
324
302
 
325
- // Set a responsive prop for a specific breakpoint
303
+ // Set responsive prop cho breakpoint cụ thể
326
304
  setNodeResponsiveProps({ fontSize: '18px' }, 'md');
327
305
  ```
328
306
 
329
307
  ### `useNode()`
330
308
 
331
- Direct access to the CraftJS node context (re-exported from `@craftjs/core`).
309
+ Truy cập trực tiếp CraftJS node context (re-export từ `@craftjs/core`).
332
310
 
333
311
  ```ts
334
312
  const { id, connectors, actions } = useNode();
@@ -336,9 +314,9 @@ const { id, connectors, actions } = useNode();
336
314
 
337
315
  ---
338
316
 
339
- ## TailwindCSS Integration
317
+ ## TailwindCSS
340
318
 
341
- The library uses TailwindCSS v4 internally with a `tw:` prefix. Import the stylesheet once at your app entry:
319
+ Thư viện dùng TailwindCSS v4 nội bộ với prefix `tw:`. Import stylesheet một lần entry của app:
342
320
 
343
321
  ```ts
344
322
  import '@janbox/storefront-builder/style.css';
@@ -348,7 +326,7 @@ import '@janbox/storefront-builder/style.css';
348
326
 
349
327
  ## Theme Shape
350
328
 
351
- The `theme` prop on `Editor` follows the `@janbox/storefront-ui` `Theme` type:
329
+ Prop `theme` của `Editor` tuân theo kiểu `Theme` của `@janbox/storefront-ui`:
352
330
 
353
331
  ```ts
354
332
  type Theme = {
@@ -356,14 +334,9 @@ type Theme = {
356
334
  primary: Record<100 | 200 | 300 | 400 | 500 | 600 | 700 | 800, string>;
357
335
  secondary: Record<...>;
358
336
  red, orange, yellow, green, blue, violet, neutral: Record<...>;
359
- black: string;
360
- white: string;
361
- background: { subtle, default, emphasis: string };
337
+ background: { subtle: string; default: string; emphasis: string };
362
338
  surface: { default: string };
363
339
  border: { default: string };
364
- inherit: string;
365
- current: string;
366
- transparent: string;
367
340
  };
368
341
  typography: Record<'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl', {
369
342
  fontSize: string;
@@ -376,15 +349,15 @@ type Theme = {
376
349
 
377
350
  ## TypeScript
378
351
 
379
- The package ships full `.d.ts` declarations. Key types:
352
+ Package đi kèm đầy đủ file `.d.ts`. Các type chính:
380
353
 
381
354
  ```ts
382
355
  import type {
383
- SerializedNodes, // canvas JSON state
384
- NodeId, // string node identifier
385
- NodeTree, // tree of nodes
386
- Resolver, // map of resolvedName → component
387
- NodeConfig, // config passed to defineNode()
356
+ SerializedNodes, // JSON state của canvas
357
+ NodeId, // string định danh node
358
+ NodeTree, // cây node
359
+ Resolver, // map resolvedName → component
360
+ NodeConfig, // config truyền vào defineNode()
388
361
  DisplayOnValue, // responsive visibility: Partial<Record<Screen, boolean>>
389
362
  } from '@janbox/storefront-builder';
390
363
  ```
@@ -397,7 +370,7 @@ Chi tiết props, usage và rules cho từng node:
397
370
 
398
371
  ### Layout
399
372
 
400
- - [RootNode](dist/lib/root/README.md) — top-level canvas container
373
+ - [RootNode](dist/lib/root/README.md) — container gốc của canvas
401
374
  - [BoxNode](dist/lib/box/README.md) — block container
402
375
  - [FlexboxNode](dist/lib/flexbox/README.md) — flex container
403
376
  - [FlexItemNode](dist/lib/flex-item/README.md) — flex item
@@ -412,7 +385,7 @@ Chi tiết props, usage và rules cho từng node:
412
385
 
413
386
  ### Media
414
387
 
415
- - [ImageNode](dist/lib/image/README.md) — image
388
+ - [ImageNode](dist/lib/image/README.md) — hình ảnh
416
389
  - [VideoNode](dist/lib/video/README.md) — video player
417
390
  - [IconNode](dist/lib/icon/README.md) — inline SVG icon
418
391
 
@@ -423,8 +396,8 @@ Chi tiết props, usage và rules cho từng node:
423
396
 
424
397
  ### Lists
425
398
 
426
- - [UnorderedListNode](dist/lib/unordered-list/README.md) — list container
427
- - [ListItemNode](dist/lib/list-item/README.md) — list item
399
+ - [UnorderedListNode](dist/lib/unordered-list/README.md) — danh sách không thứ tự
400
+ - [ListItemNode](dist/lib/list-item/README.md) — item trong danh sách
428
401
 
429
402
  ### Accordion
430
403
 
@@ -436,10 +409,10 @@ Chi tiết props, usage và rules cho từng node:
436
409
  ### Tabs
437
410
 
438
411
  - [TabsNode](dist/lib/tabs/README.md) — tabs container
439
- - [TabListNode](dist/lib/tab-list/README.md) — tab headers container
412
+ - [TabListNode](dist/lib/tab-list/README.md) — container chứa tab headers
440
413
  - [TabNode](dist/lib/tab/README.md) — tab header button
441
- - [TabContentNode](dist/lib/tab-content/README.md) — tab panels container
442
- - [TabPanelNode](dist/lib/tab-panel/README.md) — tab panel content
414
+ - [TabContentNode](dist/lib/tab-content/README.md) — container chứa tab panels
415
+ - [TabPanelNode](dist/lib/tab-panel/README.md) — nội dung tab panel
443
416
 
444
417
  ### Carousel
445
418
 
@@ -453,28 +426,28 @@ Chi tiết props, usage và rules cho từng node:
453
426
 
454
427
  ### Utilities
455
428
 
456
- - [CountdownTimerNode](dist/lib/countdown-timer/README.md) — countdown timer
429
+ - [CountdownTimerNode](dist/lib/countdown-timer/README.md) — đồng hồ đếm ngược
457
430
 
458
431
  ### Internal
459
432
 
460
- - [UnknownNode](dist/lib/unknown/README.md) — fallback for unresolved nodes
433
+ - [UnknownNode](dist/lib/unknown/README.md) — fallback cho node không resolve được
461
434
 
462
435
  ---
463
436
 
464
- ## Monorepo Development
437
+ ## Phát triển Monorepo
465
438
 
466
439
  ```bash
467
- # Install dependencies
440
+ # Cài đặt dependencies
468
441
  pnpm install
469
442
 
470
- # Start demo app (React Router 7)
443
+ # Chạy demo app (React Router 7)
471
444
  pnpm dev
472
445
 
473
- # Build the library
446
+ # Build thư viện
474
447
  pnpm build
475
448
 
476
449
  # Type check
477
450
  pnpm typecheck
478
451
  ```
479
452
 
480
- Requires Node.js >= 20 and pnpm.
453
+ Yêu cầu Node.js >= 20 pnpm.