@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,133 @@
|
|
|
1
|
+
# GridNode
|
|
2
|
+
|
|
3
|
+
A CSS Grid container node. Accepts only `CellNode` children — the editor enforces this via `canMoveIn`.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Grid`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Props mà user có thể chỉnh trong editor inspector. Tất cả đều hỗ trợ responsive trừ `container`.
|
|
12
|
+
|
|
13
|
+
### Top-level props
|
|
14
|
+
|
|
15
|
+
| Prop | Type | Description |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `cols` | `number` | Số cột — generates `grid-template-columns: repeat(cols, minmax(0, 1fr))` |
|
|
18
|
+
| `container` | `boolean` | Bật max-width container constraint |
|
|
19
|
+
|
|
20
|
+
### `sx` props
|
|
21
|
+
|
|
22
|
+
`sx` nhận `StyledCSS` với responsive keys `sm`, `md`, `lg` bên trong:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
sx?: {
|
|
26
|
+
// layout
|
|
27
|
+
columnGap?: number
|
|
28
|
+
rowGap?: number
|
|
29
|
+
alignItems?: 'start' | 'center' | 'end' | 'stretch'
|
|
30
|
+
justifyItems?: 'start' | 'center' | 'end' | 'stretch'
|
|
31
|
+
width?: number | string
|
|
32
|
+
height?: number | string
|
|
33
|
+
|
|
34
|
+
// spacing
|
|
35
|
+
paddingTop?: number
|
|
36
|
+
paddingRight?: number
|
|
37
|
+
paddingBottom?: number
|
|
38
|
+
paddingLeft?: number
|
|
39
|
+
marginTop?: number
|
|
40
|
+
marginRight?: number
|
|
41
|
+
marginBottom?: number
|
|
42
|
+
marginLeft?: number
|
|
43
|
+
|
|
44
|
+
// border
|
|
45
|
+
borderStyle?: string
|
|
46
|
+
borderColor?: string
|
|
47
|
+
borderTopWidth?: number
|
|
48
|
+
borderRightWidth?: number
|
|
49
|
+
borderBottomWidth?: number
|
|
50
|
+
borderLeftWidth?: number
|
|
51
|
+
borderTopLeftRadius?: number | string
|
|
52
|
+
borderTopRightRadius?: number | string
|
|
53
|
+
borderBottomRightRadius?: number | string
|
|
54
|
+
borderBottomLeftRadius?: number | string
|
|
55
|
+
|
|
56
|
+
// background
|
|
57
|
+
backgroundColor?: string
|
|
58
|
+
backgroundImage?: string
|
|
59
|
+
backgroundPosition?: string
|
|
60
|
+
backgroundRepeat?: string
|
|
61
|
+
backgroundSize?: string
|
|
62
|
+
backgroundAttachment?: string
|
|
63
|
+
background?: string
|
|
64
|
+
|
|
65
|
+
// responsive overrides
|
|
66
|
+
sm?: { /* same keys above */ }
|
|
67
|
+
md?: { /* same keys above */ }
|
|
68
|
+
lg?: { /* same keys above */ }
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { GridNode, CellNode } from '@janbox/storefront-builder';
|
|
76
|
+
|
|
77
|
+
// 2 cột cố định
|
|
78
|
+
<GridNode cols={2}>
|
|
79
|
+
<CellNode>...</CellNode>
|
|
80
|
+
<CellNode>...</CellNode>
|
|
81
|
+
</GridNode>
|
|
82
|
+
|
|
83
|
+
// Responsive: 1 cột mobile, 3 cột desktop
|
|
84
|
+
<GridNode cols={1} md={{ cols: 3 }}>
|
|
85
|
+
<CellNode>...</CellNode>
|
|
86
|
+
<CellNode>...</CellNode>
|
|
87
|
+
<CellNode>...</CellNode>
|
|
88
|
+
</GridNode>
|
|
89
|
+
|
|
90
|
+
// sx responsive: gap nhỏ trên mobile, lớn hơn trên desktop
|
|
91
|
+
<GridNode
|
|
92
|
+
cols={1}
|
|
93
|
+
md={{ cols: 2 }}
|
|
94
|
+
sx={{
|
|
95
|
+
columnGap: 8,
|
|
96
|
+
rowGap: 8,
|
|
97
|
+
paddingTop: 16,
|
|
98
|
+
paddingBottom: 16,
|
|
99
|
+
md: {
|
|
100
|
+
columnGap: 24,
|
|
101
|
+
rowGap: 24,
|
|
102
|
+
paddingTop: 32,
|
|
103
|
+
paddingBottom: 32,
|
|
104
|
+
},
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<CellNode>...</CellNode>
|
|
108
|
+
<CellNode>...</CellNode>
|
|
109
|
+
</GridNode>
|
|
110
|
+
|
|
111
|
+
// Container với background
|
|
112
|
+
<GridNode
|
|
113
|
+
container
|
|
114
|
+
cols={2}
|
|
115
|
+
sx={{
|
|
116
|
+
backgroundColor: '#f5f5f5',
|
|
117
|
+
paddingTop: 32,
|
|
118
|
+
paddingBottom: 32,
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
<CellNode>...</CellNode>
|
|
122
|
+
<CellNode>...</CellNode>
|
|
123
|
+
</GridNode>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Rules
|
|
127
|
+
|
|
128
|
+
- **Canvas**: yes — accepts dropped children.
|
|
129
|
+
- **canMoveIn**: only `CellNode` children are allowed.
|
|
130
|
+
|
|
131
|
+
## Related nodes
|
|
132
|
+
|
|
133
|
+
- [`CellNode`](../cell/README.md) — the only valid direct child of `GridNode`
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# HeadingNode
|
|
2
|
+
|
|
3
|
+
Text node dành cho tiêu đề. Dùng chung `TextInspector` với `TextNode` nhưng giới hạn tag trong `h1`–`h6` và `div`.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Heading`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Giống hệt `TextNode`. Xem chi tiết tại [TextNode](../text/README.md#configurable-props).
|
|
12
|
+
|
|
13
|
+
### Điểm khác biệt
|
|
14
|
+
|
|
15
|
+
| Prop | Giá trị cho phép | Default |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `as` | `'h1' \| 'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6' \| 'div'` | `'p'` (từ Text) |
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { HeadingNode } from '@janbox/storefront-builder';
|
|
23
|
+
|
|
24
|
+
// H1 mặc định
|
|
25
|
+
<HeadingNode as="h1" sizeVariant="4xl">
|
|
26
|
+
Page Title
|
|
27
|
+
</HeadingNode>
|
|
28
|
+
|
|
29
|
+
// Responsive size
|
|
30
|
+
<HeadingNode
|
|
31
|
+
as="h2"
|
|
32
|
+
sizeVariant="2xl"
|
|
33
|
+
md={{ sizeVariant: '4xl' }}
|
|
34
|
+
sx={{ color: '#111111', textAlign: 'center' }}
|
|
35
|
+
>
|
|
36
|
+
Section Title
|
|
37
|
+
</HeadingNode>
|
|
38
|
+
|
|
39
|
+
// Dùng div khi không cần semantic heading nhưng muốn style heading
|
|
40
|
+
<HeadingNode as="div" sizeVariant="xl" sx={{ fontWeight: 700 }}>
|
|
41
|
+
Display text
|
|
42
|
+
</HeadingNode>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
|
|
47
|
+
- **Canvas**: no — không chứa node con.
|
|
48
|
+
- **Inline editing**: có thể double-click để chỉnh nội dung trong canvas.
|
|
49
|
+
|
|
50
|
+
## Related nodes
|
|
51
|
+
|
|
52
|
+
- [`TextNode`](../text/README.md) — base component dùng chung inspector
|
|
53
|
+
- [`ParagraphNode`](../paragraph/README.md) — dành cho nội dung dạng đoạn văn
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# IconNode
|
|
2
|
+
|
|
3
|
+
SVG icon node. Render inline SVG từ raw string hoặc URL.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Icon`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
### Top-level props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `source` | `string` | Raw SVG string hoặc URL tới file SVG |
|
|
16
|
+
| `size` | `number` | Kích thước icon (px) — set cả `width` và `height` |
|
|
17
|
+
|
|
18
|
+
`size` hỗ trợ responsive: `size={24}` xs, `md={{ size: 32 }}` desktop.
|
|
19
|
+
|
|
20
|
+
### `sx` props
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
sx?: {
|
|
24
|
+
// color (áp dụng toàn breakpoint — không responsive)
|
|
25
|
+
color?: string
|
|
26
|
+
|
|
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
|
+
// responsive overrides
|
|
50
|
+
sm?: { /* same keys above */ }
|
|
51
|
+
md?: { /* same keys above */ }
|
|
52
|
+
lg?: { /* same keys above */ }
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { IconNode } from '@janbox/storefront-builder';
|
|
60
|
+
|
|
61
|
+
// Icon từ raw SVG
|
|
62
|
+
<IconNode
|
|
63
|
+
source='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="..."/></svg>'
|
|
64
|
+
size={24}
|
|
65
|
+
sx={{ color: '#333333' }}
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
// Responsive size
|
|
69
|
+
<IconNode
|
|
70
|
+
source="https://example.com/icon.svg"
|
|
71
|
+
size={20}
|
|
72
|
+
md={{ size: 28 }}
|
|
73
|
+
sx={{ color: '#fa8c16' }}
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
// Icon với background tròn
|
|
77
|
+
<IconNode
|
|
78
|
+
source='<svg>...</svg>'
|
|
79
|
+
size={16}
|
|
80
|
+
sx={{
|
|
81
|
+
color: '#ffffff',
|
|
82
|
+
paddingTop: 8,
|
|
83
|
+
paddingBottom: 8,
|
|
84
|
+
paddingLeft: 8,
|
|
85
|
+
paddingRight: 8,
|
|
86
|
+
backgroundColor: '#fa8c16',
|
|
87
|
+
borderTopLeftRadius: '50%',
|
|
88
|
+
borderTopRightRadius: '50%',
|
|
89
|
+
borderBottomLeftRadius: '50%',
|
|
90
|
+
borderBottomRightRadius: '50%',
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Rules
|
|
96
|
+
|
|
97
|
+
- **Canvas**: no — không chứa node con.
|
|
98
|
+
- `source` bắt buộc phải có — nếu không có, icon sẽ không hiển thị.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# ImageNode
|
|
2
|
+
|
|
3
|
+
Image node render ra `<img>`. Không chứa node con.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Image`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
### Top-level props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `src` | `string` | URL ảnh |
|
|
16
|
+
| `alt` | `string` | Alt text cho SEO và accessibility |
|
|
17
|
+
| `loading` | `'eager' \| 'lazy'` | Preload: `'eager'` = tải ngay, `'lazy'` = lazy load (default) |
|
|
18
|
+
|
|
19
|
+
### `sx` props
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
sx?: {
|
|
23
|
+
// size
|
|
24
|
+
width?: number | string
|
|
25
|
+
height?: number | string // chỉ hiển thị khi aspectRatio là 'auto'
|
|
26
|
+
|
|
27
|
+
// aspect ratio
|
|
28
|
+
aspectRatio?: 'auto' | '1 / 1' | '16 / 9' | '9 / 16' | string // ví dụ custom: '4 / 3'
|
|
29
|
+
|
|
30
|
+
// object fit (áp dụng toàn breakpoint — không responsive)
|
|
31
|
+
objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
|
|
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
|
+
// responsive overrides
|
|
56
|
+
sm?: { /* same keys above */ }
|
|
57
|
+
md?: { /* same keys above */ }
|
|
58
|
+
lg?: { /* same keys above */ }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> Khi `aspectRatio` được set (khác `auto`), prop `height` bị ẩn trong inspector vì chiều cao tự tính từ ratio.
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { ImageNode } from '@janbox/storefront-builder';
|
|
68
|
+
|
|
69
|
+
// Ảnh cơ bản
|
|
70
|
+
<ImageNode
|
|
71
|
+
src="https://example.com/photo.jpg"
|
|
72
|
+
alt="Product photo"
|
|
73
|
+
loading="lazy"
|
|
74
|
+
sx={{ width: '100%', objectFit: 'cover' }}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
// Tỉ lệ 16:9, full width
|
|
78
|
+
<ImageNode
|
|
79
|
+
src="https://example.com/banner.jpg"
|
|
80
|
+
alt="Banner"
|
|
81
|
+
sx={{
|
|
82
|
+
width: '100%',
|
|
83
|
+
aspectRatio: '16 / 9',
|
|
84
|
+
objectFit: 'cover',
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
// Thumbnail vuông, responsive width
|
|
89
|
+
<ImageNode
|
|
90
|
+
src="https://example.com/thumb.jpg"
|
|
91
|
+
alt="Thumbnail"
|
|
92
|
+
sx={{
|
|
93
|
+
width: 80,
|
|
94
|
+
aspectRatio: '1 / 1',
|
|
95
|
+
objectFit: 'cover',
|
|
96
|
+
borderTopLeftRadius: 8,
|
|
97
|
+
borderTopRightRadius: 8,
|
|
98
|
+
borderBottomLeftRadius: 8,
|
|
99
|
+
borderBottomRightRadius: 8,
|
|
100
|
+
md: { width: 120 },
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Rules
|
|
106
|
+
|
|
107
|
+
- **Canvas**: no — không chứa node con.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# LinkNode
|
|
2
|
+
|
|
3
|
+
Anchor node render ra `<a>` qua React Router `Link`. Là canvas node — có thể chứa text hoặc các node con khác làm nội dung link.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Link`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
### Top-level props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `to` | `string \| { pathname: string }` | Đường dẫn điều hướng |
|
|
16
|
+
| `target` | `'_self' \| '_blank' \| '_parent' \| '_top'` | Cách mở link |
|
|
17
|
+
| `rel` | `string` | SEO attribute, ví dụ `'nofollow noreferrer'` |
|
|
18
|
+
| `textVariant` | `TypographySizeVariant` | Preset typography size từ theme |
|
|
19
|
+
|
|
20
|
+
`textVariant` hỗ trợ responsive: `textVariant="sm"` xs, `md={{ textVariant: 'base' }}` desktop.
|
|
21
|
+
|
|
22
|
+
**`TypographySizeVariant`:** `'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl'`
|
|
23
|
+
|
|
24
|
+
### `sx` props
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
sx?: {
|
|
28
|
+
// typography (áp dụng toàn breakpoint — không responsive)
|
|
29
|
+
color?: string
|
|
30
|
+
fontStyle?: 'normal' | 'italic'
|
|
31
|
+
fontWeight?: number | string
|
|
32
|
+
textDecorationLine?: 'none' | 'underline' | 'line-through'
|
|
33
|
+
textAlign?: 'left' | 'center' | 'right' | 'justify'
|
|
34
|
+
textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize'
|
|
35
|
+
|
|
36
|
+
// spacing
|
|
37
|
+
paddingTop?: number
|
|
38
|
+
paddingRight?: number
|
|
39
|
+
paddingBottom?: number
|
|
40
|
+
paddingLeft?: number
|
|
41
|
+
marginTop?: number
|
|
42
|
+
marginRight?: number
|
|
43
|
+
marginBottom?: number
|
|
44
|
+
marginLeft?: number
|
|
45
|
+
|
|
46
|
+
// border
|
|
47
|
+
borderStyle?: string
|
|
48
|
+
borderColor?: string
|
|
49
|
+
borderTopWidth?: number
|
|
50
|
+
borderRightWidth?: number
|
|
51
|
+
borderBottomWidth?: number
|
|
52
|
+
borderLeftWidth?: number
|
|
53
|
+
borderTopLeftRadius?: number | string
|
|
54
|
+
borderTopRightRadius?: number | string
|
|
55
|
+
borderBottomRightRadius?: number | string
|
|
56
|
+
borderBottomLeftRadius?: number | 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 { LinkNode } from '@janbox/storefront-builder';
|
|
69
|
+
|
|
70
|
+
// Link đơn giản
|
|
71
|
+
<LinkNode to="/products">View all products</LinkNode>
|
|
72
|
+
|
|
73
|
+
// Mở tab mới, no-follow
|
|
74
|
+
<LinkNode to="https://example.com" target="_blank" rel="nofollow noreferrer">
|
|
75
|
+
External link
|
|
76
|
+
</LinkNode>
|
|
77
|
+
|
|
78
|
+
// Link dạng button (có border, padding)
|
|
79
|
+
<LinkNode
|
|
80
|
+
to="/checkout"
|
|
81
|
+
sx={{
|
|
82
|
+
paddingTop: 12,
|
|
83
|
+
paddingBottom: 12,
|
|
84
|
+
paddingLeft: 24,
|
|
85
|
+
paddingRight: 24,
|
|
86
|
+
borderTopLeftRadius: 6,
|
|
87
|
+
borderTopRightRadius: 6,
|
|
88
|
+
borderBottomLeftRadius: 6,
|
|
89
|
+
borderBottomRightRadius: 6,
|
|
90
|
+
backgroundColor: '#fa8c16',
|
|
91
|
+
color: '#ffffff',
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
Checkout
|
|
95
|
+
</LinkNode>
|
|
96
|
+
|
|
97
|
+
// textVariant responsive
|
|
98
|
+
<LinkNode to="/sale" textVariant="sm" md={{ textVariant: 'base' }}>
|
|
99
|
+
Sale items
|
|
100
|
+
</LinkNode>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Rules
|
|
104
|
+
|
|
105
|
+
- **Canvas**: yes — chứa node con.
|
|
106
|
+
- **canMoveIn**: bị block khi prop `dangerouslySetInnerHTML` đang được dùng.
|
|
107
|
+
- Editor preview: click bị `preventDefault` khi editor đang bật để tránh navigate.
|
|
108
|
+
|
|
109
|
+
## Related nodes
|
|
110
|
+
|
|
111
|
+
- [`ButtonNode`](../button/README.md) — dùng khi cần CTA có style button từ theme
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# ListItemNode
|
|
2
|
+
|
|
3
|
+
Một item trong `UnorderedListNode` (`li`). Là canvas node — chứa bất kỳ node con nào.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`ListItem`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Không có props riêng. Styling được control qua parent `UnorderedListNode`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { ListItemNode, TextNode } from '@janbox/storefront-builder';
|
|
17
|
+
|
|
18
|
+
<ListItemNode>
|
|
19
|
+
<TextNode>Item content</TextNode>
|
|
20
|
+
</ListItemNode>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Rules
|
|
24
|
+
|
|
25
|
+
- **Canvas**: yes — chứa bất kỳ node con nào.
|
|
26
|
+
- **Selectable**: no — chỉnh sửa qua parent `UnorderedListNode` inspector.
|
|
27
|
+
- **Parent**: phải là `UnorderedListNode`.
|
|
28
|
+
|
|
29
|
+
## Related nodes
|
|
30
|
+
|
|
31
|
+
- [`UnorderedListNode`](../unordered-list/README.md) — parent list container
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# MarqueeNode
|
|
2
|
+
|
|
3
|
+
Auto-scrolling ticker/marquee container dùng Embla Carousel Auto Scroll. Chỉ chấp nhận `MarqueeItemNode` children.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`Marquee`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
### Top-level props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `spaceBetween` | `number` | Khoảng cách giữa các items (px) |
|
|
16
|
+
| `autoScrollOptions` | `AutoScrollOptionsType` | Options từ embla-carousel-auto-scroll |
|
|
17
|
+
| `separatorIcon.source` | `string` | Raw SVG string cho icon phân cách giữa các items |
|
|
18
|
+
| `separatorIcon.size` | `number` | Kích thước separator icon (px) |
|
|
19
|
+
| `separatorIcon.sx.color` | `string` | Màu separator icon |
|
|
20
|
+
|
|
21
|
+
`spaceBetween` hỗ trợ responsive.
|
|
22
|
+
|
|
23
|
+
> Editor tự động set `autoScrollOptions.playOnInit = false` khi đang trong edit mode để tránh scroll khi đang drag/drop.
|
|
24
|
+
|
|
25
|
+
### `sx` props
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
sx?: {
|
|
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 { MarqueeNode, MarqueeItemNode, ImageNode } from '@janbox/storefront-builder';
|
|
71
|
+
|
|
72
|
+
// Marquee cơ bản, auto-scroll từ đầu
|
|
73
|
+
<MarqueeNode
|
|
74
|
+
spaceBetween={32}
|
|
75
|
+
autoScrollOptions={{ speed: 1 }}
|
|
76
|
+
>
|
|
77
|
+
<MarqueeItemNode><ImageNode src="..." alt="Logo 1" sx={{ width: 100 }} /></MarqueeItemNode>
|
|
78
|
+
<MarqueeItemNode><ImageNode src="..." alt="Logo 2" sx={{ width: 100 }} /></MarqueeItemNode>
|
|
79
|
+
<MarqueeItemNode><ImageNode src="..." alt="Logo 3" sx={{ width: 100 }} /></MarqueeItemNode>
|
|
80
|
+
</MarqueeNode>
|
|
81
|
+
|
|
82
|
+
// Với separator icon giữa các item
|
|
83
|
+
<MarqueeNode
|
|
84
|
+
spaceBetween={24}
|
|
85
|
+
separatorIcon={{
|
|
86
|
+
source: '<svg>...</svg>',
|
|
87
|
+
size: 16,
|
|
88
|
+
sx: { color: '#fa8c16' },
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<MarqueeItemNode>Item 1</MarqueeItemNode>
|
|
92
|
+
<MarqueeItemNode>Item 2</MarqueeItemNode>
|
|
93
|
+
</MarqueeNode>
|
|
94
|
+
|
|
95
|
+
// Responsive spacing
|
|
96
|
+
<MarqueeNode
|
|
97
|
+
spaceBetween={16}
|
|
98
|
+
md={{ spaceBetween: 32 }}
|
|
99
|
+
>
|
|
100
|
+
<MarqueeItemNode>...</MarqueeItemNode>
|
|
101
|
+
</MarqueeNode>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Rules
|
|
105
|
+
|
|
106
|
+
- **Canvas**: yes — chứa `MarqueeItemNode` children.
|
|
107
|
+
- **canMoveIn**: chỉ chấp nhận `MarqueeItemNode`.
|
|
108
|
+
|
|
109
|
+
## Related nodes
|
|
110
|
+
|
|
111
|
+
- [`MarqueeItemNode`](../marquee-item/README.md) — mỗi item trong marquee
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# MarqueeItemNode
|
|
2
|
+
|
|
3
|
+
Một item trong `MarqueeNode`. Là canvas node — chứa bất kỳ node con nào.
|
|
4
|
+
|
|
5
|
+
## Resolved name
|
|
6
|
+
|
|
7
|
+
`MarqueeItem`
|
|
8
|
+
|
|
9
|
+
## Configurable props
|
|
10
|
+
|
|
11
|
+
Không có props riêng. Styling được control qua parent `MarqueeNode`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { MarqueeItemNode, ImageNode, TextNode } from '@janbox/storefront-builder';
|
|
17
|
+
|
|
18
|
+
<MarqueeItemNode>
|
|
19
|
+
<ImageNode src="..." alt="Brand logo" sx={{ width: 80, height: 40, objectFit: 'contain' }} />
|
|
20
|
+
</MarqueeItemNode>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Rules
|
|
24
|
+
|
|
25
|
+
- **Canvas**: yes — chứa bất kỳ node con nào.
|
|
26
|
+
- **Selectable**: no — chỉnh sửa qua parent `MarqueeNode` inspector.
|
|
27
|
+
- **Parent**: phải là `MarqueeNode`.
|
|
28
|
+
|
|
29
|
+
## Related nodes
|
|
30
|
+
|
|
31
|
+
- [`MarqueeNode`](../marquee/README.md) — parent scrolling container
|