@janbox/storefront-builder 1.0.3 → 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.
Files changed (70) hide show
  1. package/README.md +477 -0
  2. package/dist/editor/lib/index.d.ts +3 -3
  3. package/dist/editor/lib/sidebar/index.d.ts +1 -1
  4. package/dist/editor/lib/sidebar/insert-action.d.ts +2 -2
  5. package/dist/editor/ui/dialog/dialog/helpers.d.ts +1 -1
  6. package/dist/editor/ui/dialog/dialog-close/dialog-close.d.ts +1 -1
  7. package/dist/editor.js +326 -313
  8. package/dist/lib/accordion/README.md +39 -0
  9. package/dist/lib/accordion-content/README.md +36 -0
  10. package/dist/lib/accordion-group/README.md +106 -0
  11. package/dist/lib/accordion-summary/README.md +37 -0
  12. package/dist/lib/box/README.md +107 -0
  13. package/dist/lib/button/README.md +94 -0
  14. package/dist/lib/cell/README.md +119 -0
  15. package/dist/lib/countdown-timer/README.md +157 -0
  16. package/dist/lib/flex-item/README.md +111 -0
  17. package/dist/lib/flexbox/README.md +120 -0
  18. package/dist/lib/grid/README.md +133 -0
  19. package/dist/lib/heading/README.md +53 -0
  20. package/dist/lib/icon/README.md +98 -0
  21. package/dist/lib/image/README.md +107 -0
  22. package/dist/lib/link/README.md +111 -0
  23. package/dist/lib/list-item/README.md +31 -0
  24. package/dist/lib/marquee/README.md +111 -0
  25. package/dist/lib/marquee-item/README.md +31 -0
  26. package/dist/lib/paragraph/README.md +82 -0
  27. package/dist/lib/root/README.md +33 -0
  28. package/dist/lib/swiper/README.md +108 -0
  29. package/dist/lib/swiper-slide/README.md +32 -0
  30. package/dist/lib/tab/README.md +35 -0
  31. package/dist/lib/tab-content/README.md +35 -0
  32. package/dist/lib/tab-list/README.md +35 -0
  33. package/dist/lib/tab-panel/README.md +35 -0
  34. package/dist/lib/tabs/README.md +90 -0
  35. package/dist/lib/text/README.md +90 -0
  36. package/dist/lib/unknown/README.md +48 -0
  37. package/dist/lib/unordered-list/README.md +82 -0
  38. package/dist/lib/video/README.md +91 -0
  39. package/lib/accordion/README.md +39 -0
  40. package/lib/accordion-content/README.md +36 -0
  41. package/lib/accordion-group/README.md +106 -0
  42. package/lib/accordion-summary/README.md +37 -0
  43. package/lib/box/README.md +107 -0
  44. package/lib/button/README.md +94 -0
  45. package/lib/cell/README.md +119 -0
  46. package/lib/countdown-timer/README.md +157 -0
  47. package/lib/flex-item/README.md +111 -0
  48. package/lib/flexbox/README.md +120 -0
  49. package/lib/grid/README.md +133 -0
  50. package/lib/heading/README.md +53 -0
  51. package/lib/icon/README.md +98 -0
  52. package/lib/image/README.md +107 -0
  53. package/lib/link/README.md +111 -0
  54. package/lib/list-item/README.md +31 -0
  55. package/lib/marquee/README.md +111 -0
  56. package/lib/marquee-item/README.md +31 -0
  57. package/lib/paragraph/README.md +82 -0
  58. package/lib/root/README.md +33 -0
  59. package/lib/swiper/README.md +108 -0
  60. package/lib/swiper-slide/README.md +32 -0
  61. package/lib/tab/README.md +35 -0
  62. package/lib/tab-content/README.md +35 -0
  63. package/lib/tab-list/README.md +35 -0
  64. package/lib/tab-panel/README.md +35 -0
  65. package/lib/tabs/README.md +90 -0
  66. package/lib/text/README.md +90 -0
  67. package/lib/unknown/README.md +48 -0
  68. package/lib/unordered-list/README.md +82 -0
  69. package/lib/video/README.md +91 -0
  70. package/package.json +5 -9
@@ -0,0 +1,82 @@
1
+ # ParagraphNode
2
+
3
+ Text node dành cho đoạn văn bản. Dùng chung `TextInspector` với `TextNode` nhưng không cho phép đổi tag — luôn render ra `p`.
4
+
5
+ ## Resolved name
6
+
7
+ `Paragraph`
8
+
9
+ ## Configurable props
10
+
11
+ Giống hệt `TextNode` ngoại trừ prop `as` bị loại bỏ. Xem chi tiết tại [TextNode](../text/README.md#configurable-props).
12
+
13
+ ### `sx` props
14
+
15
+ ```ts
16
+ sx?: {
17
+ // typography (áp dụng toàn breakpoint — không responsive)
18
+ color?: string
19
+ fontStyle?: 'normal' | 'italic'
20
+ fontWeight?: number | string
21
+ textDecorationLine?: 'none' | 'underline' | 'line-through'
22
+ textAlign?: 'left' | 'center' | 'right' | 'justify'
23
+ textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize'
24
+
25
+ // size
26
+ width?: number | string
27
+
28
+ // spacing
29
+ paddingTop?: number
30
+ paddingRight?: number
31
+ paddingBottom?: number
32
+ paddingLeft?: number
33
+ marginTop?: number
34
+ marginRight?: number
35
+ marginBottom?: number
36
+ marginLeft?: number
37
+
38
+ // responsive overrides
39
+ sm?: { /* same keys above */ }
40
+ md?: { /* same keys above */ }
41
+ lg?: { /* same keys above */ }
42
+ }
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ```tsx
48
+ import { ParagraphNode } from '@janbox/storefront-builder';
49
+
50
+ // Đoạn văn đơn giản
51
+ <ParagraphNode>
52
+ Lorem ipsum dolor sit amet.
53
+ </ParagraphNode>
54
+
55
+ // Với sizeVariant responsive
56
+ <ParagraphNode sizeVariant="sm" md={{ sizeVariant: 'base' }}>
57
+ Body copy text
58
+ </ParagraphNode>
59
+
60
+ // Styled
61
+ <ParagraphNode
62
+ sx={{
63
+ color: '#555555',
64
+ textAlign: 'center',
65
+ marginTop: 8,
66
+ marginBottom: 8,
67
+ }}
68
+ >
69
+ Centered paragraph
70
+ </ParagraphNode>
71
+ ```
72
+
73
+ ## Rules
74
+
75
+ - **Canvas**: no — không chứa node con.
76
+ - **Inline editing**: có thể double-click để chỉnh nội dung trong canvas.
77
+ - **Tag**: cố định là `p`, không thể đổi.
78
+
79
+ ## Related nodes
80
+
81
+ - [`TextNode`](../text/README.md) — base component dùng chung inspector
82
+ - [`HeadingNode`](../heading/README.md) — dành cho tiêu đề với tag `h1`–`h6`
@@ -0,0 +1,33 @@
1
+ # RootNode
2
+
3
+ Top-level canvas container của toàn bộ trang. Luôn là node gốc trong `Canvas` — không thể xóa hay di chuyển.
4
+
5
+ ## Resolved name
6
+
7
+ `Root`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props. Chỉ nhận `children`.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { Composer, Canvas } from '@janbox/storefront-builder';
17
+ import { RootNode } from '@janbox/storefront-builder';
18
+
19
+ // Render mode (storefront)
20
+ <Composer>
21
+ <Canvas data={savedNodes}>
22
+ <RootNode />
23
+ </Canvas>
24
+ </Composer>
25
+
26
+ // Editor mode — RootNode được Editor tự mount, không cần khai báo thủ công
27
+ ```
28
+
29
+ ## Notes
30
+
31
+ - Khi editor bật (`enabled: true`): render `div` với `minHeight: 100vh` và padding mặc định để tạo không gian kéo thả.
32
+ - Khi editor tắt (render mode): render `Fragment` — không thêm DOM wrapper.
33
+ - `RootNode` phải là node root duy nhất trong `Canvas`. Không được nest `RootNode` bên trong node khác.
@@ -0,0 +1,108 @@
1
+ # SwiperNode
2
+
3
+ Carousel/slider container dùng Embla Carousel. Chỉ chấp nhận `SwiperSlideNode` children.
4
+
5
+ ## Resolved name
6
+
7
+ `Swiper` (displayName: `Carousel`)
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `slidesPerView` | `number \| 'auto'` | Số slides hiển thị cùng lúc |
16
+ | `spaceBetween` | `number` | Khoảng cách giữa các slides (px) |
17
+ | `autoplayOptions.active` | `boolean` | Bật autoplay |
18
+ | `autoplayOptions.delay` | `number` | Delay giữa các lần chuyển slide (ms) |
19
+ | `autoplayOptions.stopOnLastSnap` | `boolean` | `false` = loop, `true` = dừng ở slide cuối |
20
+
21
+ `slidesPerView` và `spaceBetween` hỗ trợ responsive.
22
+
23
+ ### `sx` props
24
+
25
+ ```ts
26
+ sx?: {
27
+ // spacing
28
+ paddingTop?: number
29
+ paddingRight?: number
30
+ paddingBottom?: number
31
+ paddingLeft?: number
32
+ marginTop?: number
33
+ marginRight?: number
34
+ marginBottom?: number
35
+ marginLeft?: number
36
+
37
+ // border
38
+ borderStyle?: string
39
+ borderColor?: string
40
+ borderTopWidth?: number
41
+ borderRightWidth?: number
42
+ borderBottomWidth?: number
43
+ borderLeftWidth?: number
44
+ borderTopLeftRadius?: number | string
45
+ borderTopRightRadius?: number | string
46
+ borderBottomRightRadius?: number | string
47
+ borderBottomLeftRadius?: number | string
48
+
49
+ // background
50
+ backgroundColor?: string
51
+ backgroundImage?: string
52
+ backgroundPosition?: string
53
+ backgroundRepeat?: string
54
+ backgroundSize?: string
55
+ backgroundAttachment?: string
56
+ background?: string
57
+
58
+ // responsive overrides
59
+ sm?: { /* same keys above */ }
60
+ md?: { /* same keys above */ }
61
+ lg?: { /* same keys above */ }
62
+ }
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ ```tsx
68
+ import { SwiperNode, SwiperSlideNode } from '@janbox/storefront-builder';
69
+
70
+ // 3 slides hiển thị, autoplay với loop
71
+ <SwiperNode
72
+ slidesPerView={3}
73
+ spaceBetween={16}
74
+ autoplayOptions={{
75
+ active: true,
76
+ delay: 3000,
77
+ stopOnLastSnap: false, // loop
78
+ }}
79
+ >
80
+ <SwiperSlideNode>Slide 1</SwiperSlideNode>
81
+ <SwiperSlideNode>Slide 2</SwiperSlideNode>
82
+ <SwiperSlideNode>Slide 3</SwiperSlideNode>
83
+ </SwiperNode>
84
+
85
+ // Responsive: 1 slide mobile, 3 slides desktop
86
+ <SwiperNode
87
+ slidesPerView={1}
88
+ spaceBetween={8}
89
+ md={{ slidesPerView: 3, spaceBetween: 24 }}
90
+ sx={{
91
+ paddingTop: 16,
92
+ paddingBottom: 16,
93
+ }}
94
+ >
95
+ <SwiperSlideNode>...</SwiperSlideNode>
96
+ <SwiperSlideNode>...</SwiperSlideNode>
97
+ <SwiperSlideNode>...</SwiperSlideNode>
98
+ </SwiperNode>
99
+ ```
100
+
101
+ ## Rules
102
+
103
+ - **Canvas**: yes — chứa `SwiperSlideNode` children.
104
+ - **canMoveIn**: chỉ chấp nhận `SwiperSlideNode`.
105
+
106
+ ## Related nodes
107
+
108
+ - [`SwiperSlideNode`](../swiper-slide/README.md) — mỗi slide item
@@ -0,0 +1,32 @@
1
+ # SwiperSlideNode
2
+
3
+ Một slide trong `SwiperNode`. Là canvas node — chứa bất kỳ node con nào.
4
+
5
+ ## Resolved name
6
+
7
+ `SwiperSlide`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props riêng. Styling được control qua parent `SwiperNode`.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { SwiperSlideNode, ImageNode, TextNode } from '@janbox/storefront-builder';
17
+
18
+ <SwiperSlideNode>
19
+ <ImageNode src="..." alt="..." sx={{ width: '100%' }} />
20
+ <TextNode>Slide caption</TextNode>
21
+ </SwiperSlideNode>
22
+ ```
23
+
24
+ ## Rules
25
+
26
+ - **Canvas**: yes — chứa bất kỳ node con nào.
27
+ - **Selectable**: no — chỉnh sửa qua parent `SwiperNode` inspector.
28
+ - **Parent**: phải là `SwiperNode`.
29
+
30
+ ## Related nodes
31
+
32
+ - [`SwiperNode`](../swiper/README.md) — parent carousel container
@@ -0,0 +1,35 @@
1
+ # TabNode
2
+
3
+ Tab header button — click để switch giữa các panels.
4
+
5
+ ## Resolved name
6
+
7
+ `Tab`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `dangerouslySetInnerHTML.__html` | `string` | Text hiển thị trong tab button |
16
+
17
+ ## Usage
18
+
19
+ ```tsx
20
+ import { TabNode } from '@janbox/storefront-builder';
21
+
22
+ <TabNode dangerouslySetInnerHTML={{ __html: 'Overview' }} />
23
+ ```
24
+
25
+ ## Rules
26
+
27
+ - **Canvas**: no.
28
+ - **Selectable**: no — chỉnh sửa qua parent `TabsNode` inspector.
29
+ - **Parent**: phải là `TabListNode`.
30
+
31
+ ## Related nodes
32
+
33
+ - [`TabsNode`](../tabs/README.md) — root container
34
+ - [`TabListNode`](../tab-list/README.md) — parent container
35
+ - [`TabPanelNode`](../tab-panel/README.md) — panel tương ứng
@@ -0,0 +1,35 @@
1
+ # TabContentNode
2
+
3
+ Container cho danh sách tab panels. Chỉ chấp nhận `TabPanelNode` children.
4
+
5
+ ## Resolved name
6
+
7
+ `TabContent`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props riêng. Styling được control qua parent `TabsNode`.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { TabContentNode, TabPanelNode } from '@janbox/storefront-builder';
17
+
18
+ <TabContentNode>
19
+ <TabPanelNode>Panel 1 content</TabPanelNode>
20
+ <TabPanelNode>Panel 2 content</TabPanelNode>
21
+ <TabPanelNode>Panel 3 content</TabPanelNode>
22
+ </TabContentNode>
23
+ ```
24
+
25
+ ## Rules
26
+
27
+ - **Canvas**: yes — chứa `TabPanelNode` children.
28
+ - **Selectable**: no.
29
+ - **canMoveIn**: chỉ chấp nhận `TabPanelNode`.
30
+ - **Parent**: phải là `TabsNode`.
31
+
32
+ ## Related nodes
33
+
34
+ - [`TabsNode`](../tabs/README.md) — root container
35
+ - [`TabPanelNode`](../tab-panel/README.md) — mỗi panel content
@@ -0,0 +1,35 @@
1
+ # TabListNode
2
+
3
+ Container cho danh sách tab headers. Chỉ chấp nhận `TabNode` children.
4
+
5
+ ## Resolved name
6
+
7
+ `TabList`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props riêng. Styling được control qua parent `TabsNode`.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { TabListNode, TabNode } from '@janbox/storefront-builder';
17
+
18
+ <TabListNode>
19
+ <TabNode dangerouslySetInnerHTML={{ __html: 'Tab 1' }} />
20
+ <TabNode dangerouslySetInnerHTML={{ __html: 'Tab 2' }} />
21
+ <TabNode dangerouslySetInnerHTML={{ __html: 'Tab 3' }} />
22
+ </TabListNode>
23
+ ```
24
+
25
+ ## Rules
26
+
27
+ - **Canvas**: yes — chứa `TabNode` children.
28
+ - **Selectable**: no.
29
+ - **canMoveIn**: chỉ chấp nhận `TabNode`.
30
+ - **Parent**: phải là `TabsNode`.
31
+
32
+ ## Related nodes
33
+
34
+ - [`TabsNode`](../tabs/README.md) — root container
35
+ - [`TabNode`](../tab/README.md) — tab header button
@@ -0,0 +1,35 @@
1
+ # TabPanelNode
2
+
3
+ Nội dung của một tab — hiển thị khi tab tương ứng được active. Là canvas node — chứa bất kỳ node con nào.
4
+
5
+ ## Resolved name
6
+
7
+ `TabPanel`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props riêng.
12
+
13
+ ## Usage
14
+
15
+ ```tsx
16
+ import { TabPanelNode, ParagraphNode } from '@janbox/storefront-builder';
17
+
18
+ <TabPanelNode>
19
+ <ParagraphNode>
20
+ Tab panel content goes here. Can contain any nodes.
21
+ </ParagraphNode>
22
+ </TabPanelNode>
23
+ ```
24
+
25
+ ## Rules
26
+
27
+ - **Canvas**: yes — chứa bất kỳ node con nào.
28
+ - **Selectable**: no.
29
+ - **Parent**: phải là `TabContentNode`.
30
+
31
+ ## Related nodes
32
+
33
+ - [`TabsNode`](../tabs/README.md) — root container
34
+ - [`TabContentNode`](../tab-content/README.md) — parent container
35
+ - [`TabNode`](../tab/README.md) — tab header tương ứng
@@ -0,0 +1,90 @@
1
+ # TabsNode
2
+
3
+ Root container cho tabs component. Quản lý active state và chứa `TabListNode` (headers) + `TabContentNode` (panels).
4
+
5
+ ## Resolved name
6
+
7
+ `Tabs`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `defaultActiveIndex` | `number` | Index của tab active mặc định (0-based) |
16
+
17
+ ### `sx` props
18
+
19
+ ```ts
20
+ sx?: {
21
+ // size
22
+ width?: number | string
23
+
24
+ // spacing
25
+ paddingTop?: number
26
+ paddingRight?: number
27
+ paddingBottom?: number
28
+ paddingLeft?: number
29
+ marginTop?: number
30
+ marginRight?: number
31
+ marginBottom?: number
32
+ marginLeft?: number
33
+
34
+ // border
35
+ borderStyle?: string
36
+ borderColor?: string
37
+ borderTopWidth?: number
38
+ borderRightWidth?: number
39
+ borderBottomWidth?: number
40
+ borderLeftWidth?: number
41
+ borderTopLeftRadius?: number | string
42
+ borderTopRightRadius?: number | string
43
+ borderBottomRightRadius?: number | string
44
+ borderBottomLeftRadius?: number | string
45
+
46
+ // background
47
+ backgroundColor?: string
48
+ backgroundImage?: string
49
+ backgroundPosition?: string
50
+ backgroundRepeat?: string
51
+ backgroundSize?: string
52
+ backgroundAttachment?: string
53
+ background?: string
54
+
55
+ // responsive overrides
56
+ sm?: { /* same keys above */ }
57
+ md?: { /* same keys above */ }
58
+ lg?: { /* same keys above */ }
59
+ }
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ```tsx
65
+ import { TabsNode } from '@janbox/storefront-builder';
66
+
67
+ <TabsNode
68
+ defaultActiveIndex={0}
69
+ sx={{
70
+ width: '100%',
71
+ paddingTop: 16,
72
+ paddingBottom: 16,
73
+ }}
74
+ >
75
+ {/* TabListNode và TabContentNode tự động được thêm bởi editor */}
76
+ </TabsNode>
77
+ ```
78
+
79
+ ## Rules
80
+
81
+ - **Canvas**: no.
82
+ - **Children**: phải có `TabListNode` và `TabContentNode`.
83
+ - Inspector có "Items management" để add/remove/reorder tabs — sync giữa `TabNode` và `TabPanelNode`.
84
+
85
+ ## Related nodes
86
+
87
+ - [`TabListNode`](../tab-list/README.md) — container cho tab headers
88
+ - [`TabNode`](../tab/README.md) — mỗi tab header button
89
+ - [`TabContentNode`](../tab-content/README.md) — container cho tab panels
90
+ - [`TabPanelNode`](../tab-panel/README.md) — nội dung của mỗi tab
@@ -0,0 +1,90 @@
1
+ # TextNode
2
+
3
+ Inline/block text node có thể chỉnh typography. Render ra bất kỳ HTML tag nào qua prop `as`. Hỗ trợ inline editing trong canvas.
4
+
5
+ ## Resolved name
6
+
7
+ `Text`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `as` | `HTMLElementType` | HTML tag render ra (mặc định `p`) |
16
+ | `sizeVariant` | `TypographySizeVariant` | Preset typography size từ theme |
17
+
18
+ `sizeVariant` hỗ trợ responsive: `sizeVariant="base"` xs, `md={{ sizeVariant: 'lg' }}` desktop.
19
+
20
+ **`TypographySizeVariant`:** `'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl'`
21
+
22
+ ### `sx` props
23
+
24
+ ```ts
25
+ sx?: {
26
+ // typography (áp dụng toàn breakpoint — không responsive)
27
+ color?: string
28
+ fontStyle?: 'normal' | 'italic'
29
+ fontWeight?: number | string
30
+ textDecorationLine?: 'none' | 'underline' | 'line-through'
31
+ textAlign?: 'left' | 'center' | 'right' | 'justify'
32
+ textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize'
33
+
34
+ // size
35
+ width?: number | string
36
+
37
+ // spacing
38
+ paddingTop?: number
39
+ paddingRight?: number
40
+ paddingBottom?: number
41
+ paddingLeft?: number
42
+ marginTop?: number
43
+ marginRight?: number
44
+ marginBottom?: number
45
+ marginLeft?: number
46
+
47
+ // responsive overrides
48
+ sm?: { /* same keys above */ }
49
+ md?: { /* same keys above */ }
50
+ lg?: { /* same keys above */ }
51
+ }
52
+ ```
53
+
54
+ > `color`, `fontStyle`, `textDecorationLine`, `textAlign`, `textTransform` được editor set ở breakpoint `xs` (áp dụng toàn bộ). `fontWeight` và `sizeVariant` hỗ trợ responsive.
55
+
56
+ ## Usage
57
+
58
+ ```tsx
59
+ import { TextNode } from '@janbox/storefront-builder';
60
+
61
+ // Text đơn giản
62
+ <TextNode>Hello world</TextNode>
63
+
64
+ // Đổi tag, size variant
65
+ <TextNode as="span" sizeVariant="sm">
66
+ Small label
67
+ </TextNode>
68
+
69
+ // sizeVariant responsive
70
+ <TextNode sizeVariant="base" md={{ sizeVariant: 'lg' }}>
71
+ Body text
72
+ </TextNode>
73
+
74
+ // Màu, căn giữa, font weight responsive
75
+ <TextNode
76
+ sx={{
77
+ color: '#333333',
78
+ textAlign: 'center',
79
+ fontWeight: 400,
80
+ md: { fontWeight: 600 },
81
+ }}
82
+ >
83
+ Styled text
84
+ </TextNode>
85
+ ```
86
+
87
+ ## Rules
88
+
89
+ - **Canvas**: no — không chứa node con.
90
+ - **Inline editing**: có thể double-click để chỉnh nội dung trực tiếp trong canvas.
@@ -0,0 +1,48 @@
1
+ # UnknownNode
2
+
3
+ Fallback node hiển thị khi một node trong serialized data có `resolvedName` không tồn tại trong resolver.
4
+
5
+ ## Resolved name
6
+
7
+ `Unknown`
8
+
9
+ ## Configurable props
10
+
11
+ Không có props.
12
+
13
+ ## Behavior
14
+
15
+ - **Render mode** (`enabled: false`): render nothing — hoàn toàn invisible.
16
+ - **Editor mode** (`enabled: true`): hiển thị placeholder "Section is not available" kèm nút **Remove** để xóa node.
17
+
18
+ ## Khi nào xảy ra
19
+
20
+ `Canvas` tự động thay thế node bằng `UnknownNode` khi load `SerializedNodes` mà `resolvedName` không có trong resolver:
21
+
22
+ ```ts
23
+ // Trong Canvas component
24
+ const resolvedNode = resolver[resolvedName];
25
+ if (!resolvedNode) {
26
+ value.type = { resolvedName: CoreNodeResolvedEnum.Unknown };
27
+ }
28
+ ```
29
+
30
+ Thường xảy ra khi:
31
+ - Custom node bị xóa khỏi codebase nhưng data cũ vẫn còn lưu
32
+ - Resolver không được pass đầy đủ node types
33
+
34
+ ## Usage
35
+
36
+ Không cần dùng trực tiếp. Được xử lý tự động bởi `Canvas`.
37
+
38
+ Nếu muốn tránh `UnknownNode` xuất hiện, đảm bảo truyền đầy đủ resolver khi mount `Composer`:
39
+
40
+ ```tsx
41
+ import { MyCustomNode } from './my-custom-node';
42
+
43
+ <Composer resolver={{ MyCustomNode }}>
44
+ <Canvas data={savedNodes}>
45
+ <RootNode />
46
+ </Canvas>
47
+ </Composer>
48
+ ```