@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.
- package/README.md +477 -0
- package/dist/editor/lib/index.d.ts +3 -3
- package/dist/editor/lib/sidebar/index.d.ts +1 -1
- package/dist/editor/lib/sidebar/insert-action.d.ts +2 -2
- 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 +326 -313
- 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
|
@@ -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
|
+
```
|