@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,107 @@
1
+ # BoxNode
2
+
3
+ Block container đa năng (render ra `div`). Là canvas node — chứa bất kỳ node con nào. Dùng để nhóm các element, tạo section, hay làm wrapper có background/border.
4
+
5
+ ## Resolved name
6
+
7
+ `Box` (displayName: `Block`)
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `container` | `boolean` | Bật max-width container constraint |
16
+
17
+ ### `sx` props
18
+
19
+ ```ts
20
+ sx?: {
21
+ // size
22
+ width?: number | string
23
+ height?: number | string
24
+
25
+ // spacing
26
+ paddingTop?: number
27
+ paddingRight?: number
28
+ paddingBottom?: number
29
+ paddingLeft?: number
30
+ marginTop?: number
31
+ marginRight?: number
32
+ marginBottom?: number
33
+ marginLeft?: number
34
+
35
+ // border
36
+ borderStyle?: string
37
+ borderColor?: string
38
+ borderTopWidth?: number
39
+ borderRightWidth?: number
40
+ borderBottomWidth?: number
41
+ borderLeftWidth?: number
42
+ borderTopLeftRadius?: number | string
43
+ borderTopRightRadius?: number | string
44
+ borderBottomRightRadius?: number | string
45
+ borderBottomLeftRadius?: number | string
46
+
47
+ // background
48
+ backgroundColor?: string
49
+ backgroundImage?: string
50
+ backgroundPosition?: string
51
+ backgroundRepeat?: string
52
+ backgroundSize?: string
53
+ backgroundAttachment?: string
54
+ background?: string
55
+
56
+ // responsive overrides
57
+ sm?: { /* same keys above */ }
58
+ md?: { /* same keys above */ }
59
+ lg?: { /* same keys above */ }
60
+ }
61
+ ```
62
+
63
+ ## Usage
64
+
65
+ ```tsx
66
+ import { BoxNode } from '@janbox/storefront-builder';
67
+
68
+ // Wrapper đơn giản
69
+ <BoxNode sx={{ padding: 16 }}>
70
+ <TextNode>Hello</TextNode>
71
+ </BoxNode>
72
+
73
+ // Section có background
74
+ <BoxNode
75
+ sx={{
76
+ backgroundColor: '#f5f5f5',
77
+ paddingTop: 48,
78
+ paddingBottom: 48,
79
+ }}
80
+ >
81
+ ...
82
+ </BoxNode>
83
+
84
+ // Container với responsive padding
85
+ <BoxNode
86
+ container
87
+ sx={{
88
+ paddingTop: 24,
89
+ paddingBottom: 24,
90
+ md: {
91
+ paddingTop: 48,
92
+ paddingBottom: 48,
93
+ },
94
+ }}
95
+ >
96
+ ...
97
+ </BoxNode>
98
+
99
+ // Box ẩn trên mobile, hiện trên desktop — dùng DisplayOn (qua editor)
100
+ // Có thể kết hợp với sx.width/height để tạo spacer cố định
101
+ <BoxNode sx={{ width: '100%', height: 32, md: { height: 64 } }} />
102
+ ```
103
+
104
+ ## Rules
105
+
106
+ - **Canvas**: yes — chứa bất kỳ node con nào.
107
+ - **canMoveIn**: không giới hạn node type.
@@ -0,0 +1,94 @@
1
+ # ButtonNode
2
+
3
+ CTA button node dùng component `Button` từ `@janbox/storefront-ui`. Có thể render như button thường hoặc link button qua prop `anchor`.
4
+
5
+ ## Resolved name
6
+
7
+ `Button`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `dangerouslySetInnerHTML.__html` | `string` | Text hiển thị trong button |
16
+ | `color` | `ColorVariant` | Màu theme của button |
17
+ | `variant` | `ButtonVariant` | Kiểu hiển thị của button |
18
+ | `size` | `ButtonSizeVariant` | Kích thước button |
19
+ | `anchor.to` | `string \| { pathname: string }` | Link destination |
20
+ | `anchor.target` | `'_self' \| '_blank' \| '_parent' \| '_top'` | Cách mở link |
21
+
22
+ `size` hỗ trợ responsive: `size="sm"` xs, `md={{ size: 'lg' }}` desktop.
23
+
24
+ **`ColorVariant`:** `'primary' | 'secondary' | 'green' | 'red' | 'orange' | 'blue' | 'neutral'`
25
+
26
+ **`ButtonVariant`:** `'contained' | 'outlined' | 'text'`
27
+
28
+ **`ButtonSizeVariant`:** `'sm' | 'md' | 'lg'`
29
+
30
+ ### `sx` props
31
+
32
+ ```ts
33
+ sx?: {
34
+ // size
35
+ width?: number | string
36
+
37
+ // spacing (margin only)
38
+ marginTop?: number
39
+ marginRight?: number
40
+ marginBottom?: number
41
+ marginLeft?: number
42
+
43
+ // responsive overrides
44
+ sm?: { /* same keys above */ }
45
+ md?: { /* same keys above */ }
46
+ lg?: { /* same keys above */ }
47
+ }
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ```tsx
53
+ import { ButtonNode } from '@janbox/storefront-builder';
54
+
55
+ // Button cơ bản
56
+ <ButtonNode
57
+ color="primary"
58
+ variant="contained"
59
+ size="md"
60
+ dangerouslySetInnerHTML={{ __html: 'Buy now' }}
61
+ />
62
+
63
+ // Link button
64
+ <ButtonNode
65
+ color="primary"
66
+ variant="contained"
67
+ size="lg"
68
+ anchor={{ to: '/checkout', target: '_self' }}
69
+ dangerouslySetInnerHTML={{ __html: 'Checkout' }}
70
+ />
71
+
72
+ // Responsive size + width
73
+ <ButtonNode
74
+ color="orange"
75
+ variant="outlined"
76
+ size="sm"
77
+ md={{ size: 'lg' }}
78
+ sx={{
79
+ width: '100%',
80
+ marginTop: 16,
81
+ md: {
82
+ width: 'fit-content',
83
+ marginTop: 24,
84
+ },
85
+ }}
86
+ dangerouslySetInnerHTML={{ __html: 'View products' }}
87
+ />
88
+ ```
89
+
90
+ ## Rules
91
+
92
+ - **Canvas**: no — không chứa node con.
93
+ - Khi editor đang bật, `anchor` bị unset lúc render để tránh navigate trong canvas.
94
+ - Nội dung button được chỉnh qua `dangerouslySetInnerHTML.__html` trong inspector.
@@ -0,0 +1,119 @@
1
+ # CellNode
2
+
3
+ Một ô (column) trong `GridNode`. Hỗ trợ `colSpan` để chiếm nhiều cột. Là canvas node — chứa bất kỳ node con nào.
4
+
5
+ ## Resolved name
6
+
7
+ `Cell`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `colSpan` | `number` | Số cột mà cell chiếm (`grid-column: span colSpan`) |
16
+
17
+ `colSpan` hỗ trợ responsive: `colSpan={1}` cho mobile, `md={{ colSpan: 2 }}` cho desktop.
18
+
19
+ ### `sx` props
20
+
21
+ ```ts
22
+ sx?: {
23
+ // size
24
+ height?: number | string
25
+
26
+ // order (thứ tự hiển thị trong grid)
27
+ order?: number | string
28
+
29
+ // spacing
30
+ paddingTop?: number
31
+ paddingRight?: number
32
+ paddingBottom?: number
33
+ paddingLeft?: number
34
+ marginTop?: number
35
+ marginRight?: number
36
+ marginBottom?: number
37
+ marginLeft?: number
38
+
39
+ // border
40
+ borderStyle?: string
41
+ borderColor?: string
42
+ borderTopWidth?: number
43
+ borderRightWidth?: number
44
+ borderBottomWidth?: number
45
+ borderLeftWidth?: number
46
+ borderTopLeftRadius?: number | string
47
+ borderTopRightRadius?: number | string
48
+ borderBottomRightRadius?: number | string
49
+ borderBottomLeftRadius?: number | string
50
+
51
+ // background
52
+ backgroundColor?: string
53
+ backgroundImage?: string
54
+ backgroundPosition?: string
55
+ backgroundRepeat?: string
56
+ backgroundSize?: string
57
+ backgroundAttachment?: string
58
+ background?: string
59
+
60
+ // responsive overrides
61
+ sm?: { /* same keys above */ }
62
+ md?: { /* same keys above */ }
63
+ lg?: { /* same keys above */ }
64
+ }
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ```tsx
70
+ import { GridNode, CellNode } from '@janbox/storefront-builder';
71
+
72
+ // Cell mặc định (1 cột)
73
+ <GridNode cols={3}>
74
+ <CellNode>Content A</CellNode>
75
+ <CellNode>Content B</CellNode>
76
+ <CellNode>Content C</CellNode>
77
+ </GridNode>
78
+
79
+ // colSpan: cell chiếm 2/3 cột, cell còn lại chiếm 1/3
80
+ <GridNode cols={3}>
81
+ <CellNode colSpan={2}>Wide content</CellNode>
82
+ <CellNode colSpan={1}>Narrow content</CellNode>
83
+ </GridNode>
84
+
85
+ // colSpan responsive: full-width mobile, 2 cột trên desktop
86
+ <GridNode cols={1} md={{ cols: 3 }}>
87
+ <CellNode colSpan={1} md={{ colSpan: 2 }}>
88
+ Wide on desktop
89
+ </CellNode>
90
+ <CellNode colSpan={1}>
91
+ Normal
92
+ </CellNode>
93
+ </GridNode>
94
+
95
+ // sx responsive
96
+ <CellNode
97
+ colSpan={1}
98
+ sx={{
99
+ paddingTop: 12,
100
+ paddingBottom: 12,
101
+ backgroundColor: '#fff',
102
+ md: {
103
+ paddingTop: 24,
104
+ paddingBottom: 24,
105
+ },
106
+ }}
107
+ >
108
+ ...
109
+ </CellNode>
110
+ ```
111
+
112
+ ## Rules
113
+
114
+ - **Canvas**: yes — chứa bất kỳ node con nào.
115
+ - **Parent**: phải là `GridNode`.
116
+
117
+ ## Related nodes
118
+
119
+ - [`GridNode`](../grid/README.md) — parent bắt buộc của `CellNode`
@@ -0,0 +1,157 @@
1
+ # CountdownTimerNode
2
+
3
+ Đồng hồ đếm ngược đến một mốc thời gian. Hiển thị các time units (days, hours, minutes, seconds...) kèm caption.
4
+
5
+ ## Resolved name
6
+
7
+ `CountdownTimer`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `date` | `Date` | Thời điểm đích để đếm ngược đến |
16
+ | `units` | `{ value: TimeUnit; caption?: string }[]` | Danh sách time units hiển thị, theo thứ tự |
17
+ | `hideAfterExpired` | `boolean` | Ẩn toàn bộ component sau khi hết giờ |
18
+
19
+ **`TimeUnit`:** `'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds'`
20
+
21
+ ### `unitItemProps.sx` — Styling cho mỗi unit box
22
+
23
+ ```ts
24
+ unitItemProps?: {
25
+ sx?: {
26
+ width?: number | string
27
+ rowGap?: number // khoảng cách giữa số và caption
28
+ paddingTop?: number
29
+ paddingRight?: number
30
+ paddingBottom?: number
31
+ paddingLeft?: number
32
+ backgroundColor?: string
33
+ borderTopLeftRadius?: number | string
34
+ borderTopRightRadius?: number | string
35
+ borderBottomLeftRadius?: number | string
36
+ borderBottomRightRadius?: number | string
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### `timeProps` — Styling cho số đếm
42
+
43
+ ```ts
44
+ timeProps?: {
45
+ sizeVariant?: TypographySizeVariant // responsive
46
+ sx?: {
47
+ color?: string
48
+ fontWeight?: number | string
49
+ fontStyle?: 'normal' | 'italic'
50
+ textDecorationLine?: 'none' | 'underline' | 'line-through'
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### `captionProps` — Styling cho caption (label dưới số)
56
+
57
+ ```ts
58
+ captionProps?: {
59
+ sizeVariant?: TypographySizeVariant // responsive
60
+ sx?: {
61
+ color?: string
62
+ fontWeight?: number | string
63
+ fontStyle?: 'normal' | 'italic'
64
+ textDecorationLine?: 'none' | 'underline' | 'line-through'
65
+ textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize'
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### `sx` props (outer container)
71
+
72
+ ```ts
73
+ sx?: {
74
+ width?: number | string
75
+ flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse'
76
+
77
+ // spacing
78
+ paddingTop?: number
79
+ paddingRight?: number
80
+ paddingBottom?: number
81
+ paddingLeft?: number
82
+ marginTop?: number
83
+ marginRight?: number
84
+ marginBottom?: number
85
+ marginLeft?: number
86
+
87
+ // border
88
+ borderStyle?: string
89
+ borderColor?: string
90
+ borderTopWidth?: number
91
+ borderRightWidth?: number
92
+ borderBottomWidth?: number
93
+ borderLeftWidth?: number
94
+ borderTopLeftRadius?: number | string
95
+ borderTopRightRadius?: number | string
96
+ borderBottomRightRadius?: number | string
97
+ borderBottomLeftRadius?: number | string
98
+
99
+ // background
100
+ backgroundColor?: string
101
+ backgroundImage?: string
102
+ backgroundPosition?: string
103
+ backgroundRepeat?: string
104
+ backgroundSize?: string
105
+ backgroundAttachment?: string
106
+ background?: string
107
+
108
+ // responsive overrides
109
+ sm?: { /* same keys above */ }
110
+ md?: { /* same keys above */ }
111
+ lg?: { /* same keys above */ }
112
+ }
113
+ ```
114
+
115
+ ## Usage
116
+
117
+ ```tsx
118
+ import { CountdownTimerNode } from '@janbox/storefront-builder';
119
+
120
+ // Đếm ngược đến ngày sale
121
+ <CountdownTimerNode
122
+ date={new Date('2026-12-31T23:59:59')}
123
+ units={[
124
+ { value: 'days', caption: 'Days' },
125
+ { value: 'hours', caption: 'Hours' },
126
+ { value: 'minutes', caption: 'Mins' },
127
+ { value: 'seconds', caption: 'Secs' },
128
+ ]}
129
+ hideAfterExpired={false}
130
+ sx={{ columnGap: 8 }}
131
+ unitItemProps={{
132
+ sx: {
133
+ width: 64,
134
+ paddingTop: 8,
135
+ paddingBottom: 8,
136
+ backgroundColor: '#fa8c16',
137
+ borderTopLeftRadius: 8,
138
+ borderTopRightRadius: 8,
139
+ borderBottomLeftRadius: 8,
140
+ borderBottomRightRadius: 8,
141
+ },
142
+ }}
143
+ timeProps={{
144
+ sizeVariant: '2xl',
145
+ sx: { color: '#ffffff', fontWeight: 700 },
146
+ }}
147
+ captionProps={{
148
+ sizeVariant: 'xs',
149
+ sx: { color: '#ffffff', textTransform: 'uppercase' },
150
+ }}
151
+ />
152
+ ```
153
+
154
+ ## Rules
155
+
156
+ - **Canvas**: no — không chứa node con.
157
+ - Khi editor đang bật, component hiển thị placeholder nếu `units` rỗng hoặc đã hết giờ với `hideAfterExpired: true`.
@@ -0,0 +1,111 @@
1
+ # FlexItemNode
2
+
3
+ Một item trong `FlexboxNode`. Kiểm soát kích thước, grow/shrink, thứ tự của từng item trong flex container.
4
+
5
+ ## Resolved name
6
+
7
+ `FlexItem`
8
+
9
+ ## Configurable props
10
+
11
+ Tất cả props nằm trong `sx`. Không có top-level prop riêng.
12
+
13
+ ### `sx` props
14
+
15
+ ```ts
16
+ sx?: {
17
+ // flex item behavior
18
+ flexGrow?: number // auto grow: 1 = bật, undefined = tắt
19
+ flexShrink?: number // auto shrink: 0 = tắt, undefined = bật
20
+
21
+ // size
22
+ width?: number | string
23
+ height?: number | string
24
+
25
+ // order (thứ tự hiển thị)
26
+ order?: 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
+ // border
39
+ borderStyle?: string
40
+ borderColor?: string
41
+ borderTopWidth?: number
42
+ borderRightWidth?: number
43
+ borderBottomWidth?: number
44
+ borderLeftWidth?: number
45
+ borderTopLeftRadius?: number | string
46
+ borderTopRightRadius?: number | string
47
+ borderBottomRightRadius?: number | string
48
+ borderBottomLeftRadius?: number | string
49
+
50
+ // background
51
+ backgroundColor?: string
52
+ backgroundImage?: string
53
+ backgroundPosition?: string
54
+ backgroundRepeat?: string
55
+ backgroundSize?: string
56
+ backgroundAttachment?: string
57
+ background?: string
58
+
59
+ // responsive overrides
60
+ sm?: { /* same keys above */ }
61
+ md?: { /* same keys above */ }
62
+ lg?: { /* same keys above */ }
63
+ }
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ ```tsx
69
+ import { FlexboxNode, FlexItemNode } from '@janbox/storefront-builder';
70
+
71
+ // Item cố định width, item còn lại grow để fill
72
+ <FlexboxNode sx={{ flexDirection: 'row', columnGap: 16 }}>
73
+ <FlexItemNode sx={{ width: 200 }}>Sidebar</FlexItemNode>
74
+ <FlexItemNode sx={{ flexGrow: 1 }}>Main content</FlexItemNode>
75
+ </FlexboxNode>
76
+
77
+ // Item không shrink khi container hẹp
78
+ <FlexboxNode sx={{ flexDirection: 'row' }}>
79
+ <FlexItemNode sx={{ flexShrink: 0, width: 120 }}>Fixed</FlexItemNode>
80
+ <FlexItemNode sx={{ flexGrow: 1 }}>Flexible</FlexItemNode>
81
+ </FlexboxNode>
82
+
83
+ // Responsive: full width mobile, 50% desktop
84
+ <FlexboxNode sx={{ flexDirection: 'column', md: { flexDirection: 'row' } }}>
85
+ <FlexItemNode
86
+ sx={{
87
+ width: '100%',
88
+ md: { width: '50%' },
89
+ }}
90
+ >
91
+ Left
92
+ </FlexItemNode>
93
+ <FlexItemNode
94
+ sx={{
95
+ width: '100%',
96
+ md: { width: '50%' },
97
+ }}
98
+ >
99
+ Right
100
+ </FlexItemNode>
101
+ </FlexboxNode>
102
+ ```
103
+
104
+ ## Rules
105
+
106
+ - **Canvas**: yes — chứa bất kỳ node con nào.
107
+ - **Parent**: phải là `FlexboxNode`.
108
+
109
+ ## Related nodes
110
+
111
+ - [`FlexboxNode`](../flexbox/README.md) — parent bắt buộc của `FlexItemNode`
@@ -0,0 +1,120 @@
1
+ # FlexboxNode
2
+
3
+ Flex container node (`display: flex`). Chỉ chấp nhận `FlexItemNode` làm con trực tiếp.
4
+
5
+ ## Resolved name
6
+
7
+ `Flexbox`
8
+
9
+ ## Configurable props
10
+
11
+ ### Top-level props
12
+
13
+ | Prop | Type | Description |
14
+ | --- | --- | --- |
15
+ | `container` | `boolean` | Bật max-width container constraint |
16
+
17
+ ### `sx` props
18
+
19
+ ```ts
20
+ sx?: {
21
+ // flex layout
22
+ flexDirection?: 'row' | 'column'
23
+ flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse'
24
+ justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
25
+ alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
26
+ rowGap?: number
27
+ columnGap?: number
28
+
29
+ // size
30
+ width?: number | string
31
+ height?: number | string
32
+
33
+ // spacing
34
+ paddingTop?: number
35
+ paddingRight?: number
36
+ paddingBottom?: number
37
+ paddingLeft?: number
38
+ marginTop?: number
39
+ marginRight?: number
40
+ marginBottom?: number
41
+ marginLeft?: number
42
+
43
+ // border
44
+ borderStyle?: string
45
+ borderColor?: string
46
+ borderTopWidth?: number
47
+ borderRightWidth?: number
48
+ borderBottomWidth?: number
49
+ borderLeftWidth?: number
50
+ borderTopLeftRadius?: number | string
51
+ borderTopRightRadius?: number | string
52
+ borderBottomRightRadius?: number | string
53
+ borderBottomLeftRadius?: number | string
54
+
55
+ // background
56
+ backgroundColor?: string
57
+ backgroundImage?: string
58
+ backgroundPosition?: string
59
+ backgroundRepeat?: string
60
+ backgroundSize?: string
61
+ backgroundAttachment?: string
62
+ background?: string
63
+
64
+ // responsive overrides
65
+ sm?: { /* same keys above */ }
66
+ md?: { /* same keys above */ }
67
+ lg?: { /* same keys above */ }
68
+ }
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ ```tsx
74
+ import { FlexboxNode, FlexItemNode } from '@janbox/storefront-builder';
75
+
76
+ // Row ngang, căn giữa dọc
77
+ <FlexboxNode sx={{ flexDirection: 'row', alignItems: 'center', columnGap: 16 }}>
78
+ <FlexItemNode>Item A</FlexItemNode>
79
+ <FlexItemNode>Item B</FlexItemNode>
80
+ </FlexboxNode>
81
+
82
+ // Đổi direction theo breakpoint: column trên mobile, row trên desktop
83
+ <FlexboxNode
84
+ sx={{
85
+ flexDirection: 'column',
86
+ rowGap: 12,
87
+ md: {
88
+ flexDirection: 'row',
89
+ columnGap: 24,
90
+ alignItems: 'center',
91
+ },
92
+ }}
93
+ >
94
+ <FlexItemNode>Item A</FlexItemNode>
95
+ <FlexItemNode>Item B</FlexItemNode>
96
+ </FlexboxNode>
97
+
98
+ // Space-between, wrap
99
+ <FlexboxNode
100
+ sx={{
101
+ flexDirection: 'row',
102
+ flexWrap: 'wrap',
103
+ justifyContent: 'space-between',
104
+ rowGap: 16,
105
+ }}
106
+ >
107
+ <FlexItemNode>Item A</FlexItemNode>
108
+ <FlexItemNode>Item B</FlexItemNode>
109
+ <FlexItemNode>Item C</FlexItemNode>
110
+ </FlexboxNode>
111
+ ```
112
+
113
+ ## Rules
114
+
115
+ - **Canvas**: yes.
116
+ - **canMoveIn**: chỉ chấp nhận `FlexItemNode`.
117
+
118
+ ## Related nodes
119
+
120
+ - [`FlexItemNode`](../flex-item/README.md) — con trực tiếp duy nhất của `FlexboxNode`