@developer_tribe/react-builder 1.0.2 → 1.0.3
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/dist/AttributesEditor.d.ts +3 -1
- package/dist/RenderPage.d.ts +2 -1
- package/dist/attributes-editor/Field.d.ts +2 -1
- package/dist/attributes-editor/SpecialCategorySection.d.ts +2 -1
- package/dist/build-components/BackgroundImage/BackgroundImage.d.ts +5 -0
- package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +44 -0
- package/dist/build-components/Button/ButtonProps.generated.d.ts +7 -0
- package/dist/build-components/Carousel/CarouselProps.generated.d.ts +7 -0
- package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +7 -0
- package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +7 -0
- package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +7 -0
- package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +7 -0
- package/dist/build-components/Image/ImageProps.generated.d.ts +7 -0
- package/dist/build-components/Onboard/OnboardProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +7 -1
- package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +7 -0
- package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +7 -0
- package/dist/build-components/Text/TextProps.generated.d.ts +7 -0
- package/dist/build-components/View/ViewProps.generated.d.ts +7 -0
- package/dist/build-components/index.d.ts +2 -1
- package/dist/build-components/patterns.generated.d.ts +1444 -15
- package/dist/components/AttributesEditorPanel.d.ts +3 -4
- package/dist/components/Builder.d.ts +2 -1
- package/dist/components/BuilderButton.d.ts +9 -0
- package/dist/index.cjs.js +5 -5
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +5 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/modals/ColorModal.d.ts +3 -1
- package/dist/pages/ProjectPage.d.ts +3 -3
- package/dist/pages/tabs/BuilderPanel.d.ts +8 -0
- package/dist/pages/tabs/{DebugTab.d.ts → SideTool.d.ts} +2 -2
- package/dist/store.d.ts +7 -1
- package/dist/styles.css +1 -1
- package/dist/types/Project.d.ts +11 -0
- package/dist/utils/analyseNode.d.ts +1 -0
- package/dist/utils/extractTextStyle.d.ts +8 -1
- package/dist/utils/extractViewStyle.d.ts +8 -1
- package/dist/utils/parseColor.d.ts +7 -0
- package/package.json +1 -1
- package/src/AttributesEditor.tsx +76 -14
- package/src/RenderPage.tsx +82 -4
- package/src/attributes-editor/Field.tsx +12 -5
- package/src/attributes-editor/SpecialCategorySection.tsx +2 -1
- package/src/build-components/BackgroundImage/BackgroundImage.tsx +87 -0
- package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +60 -0
- package/src/build-components/BackgroundImage/pattern.json +45 -0
- package/src/build-components/Button/Button.tsx +31 -4
- package/src/build-components/Button/ButtonProps.generated.ts +7 -0
- package/src/build-components/Carousel/Carousel.tsx +27 -3
- package/src/build-components/Carousel/CarouselProps.generated.ts +7 -0
- package/src/build-components/CarouselButtons/CarouselButtons.tsx +19 -4
- package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +7 -0
- package/src/build-components/CarouselDots/CarouselDots.tsx +13 -4
- package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +7 -0
- package/src/build-components/CarouselItem/CarouselItem.tsx +20 -4
- package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +7 -0
- package/src/build-components/CarouselProvider/CarouselProvider.tsx +14 -3
- package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +7 -0
- package/src/build-components/Image/Image.tsx +29 -4
- package/src/build-components/Image/ImageProps.generated.ts +7 -0
- package/src/build-components/Onboard/Onboard.tsx +2 -2
- package/src/build-components/Onboard/OnboardProps.generated.ts +7 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +11 -4
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +7 -0
- package/src/build-components/OnboardButtons/OnboardButtons.tsx +17 -5
- package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +7 -0
- package/src/build-components/OnboardDot/OnboardDot.tsx +15 -6
- package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +7 -0
- package/src/build-components/OnboardDot/pattern.json +1 -1
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +15 -5
- package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +7 -0
- package/src/build-components/OnboardImage/OnboardImage.tsx +28 -6
- package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +7 -0
- package/src/build-components/OnboardItem/OnboardItem.tsx +14 -3
- package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +7 -0
- package/src/build-components/OnboardProvider/OnboardProvider.tsx +34 -12
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +7 -1
- package/src/build-components/OnboardProvider/pattern.json +0 -8
- package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +7 -0
- package/src/build-components/OnboardSubtitle/pattern.json +1 -1
- package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +7 -0
- package/src/build-components/OnboardTitle/pattern.json +1 -1
- package/src/build-components/RenderNode.generated.tsx +3 -0
- package/src/build-components/Text/Text.tsx +33 -9
- package/src/build-components/Text/TextProps.generated.ts +7 -0
- package/src/build-components/View/View.tsx +27 -3
- package/src/build-components/View/ViewProps.generated.ts +7 -0
- package/src/build-components/View/pattern.json +59 -1
- package/src/build-components/index.ts +5 -0
- package/src/build-components/patterns.generated.ts +1452 -15
- package/src/components/AttributesEditorPanel.tsx +13 -6
- package/src/components/Builder.tsx +140 -40
- package/src/components/BuilderButton.tsx +127 -0
- package/src/index.ts +2 -2
- package/src/mockOS/components/MockOSRouter.tsx +11 -3
- package/src/modals/ColorModal.tsx +212 -55
- package/src/pages/ProjectPage.tsx +293 -55
- package/src/pages/tabs/{BuilderTab.tsx → BuilderPanel.tsx} +13 -9
- package/src/pages/tabs/SideTool.tsx +259 -0
- package/src/size-matters/index.ts +6 -0
- package/src/store.ts +13 -1
- package/src/styles/base/_global.scss +158 -7
- package/src/styles/components/_attributes-editor.scss +12 -0
- package/src/styles/components/_editor-shell.scss +23 -0
- package/src/styles/foundation/_sizes.scss +1 -1
- package/src/styles/layout/_builder.scss +66 -10
- package/src/styles/modals/_color-modal.scss +29 -0
- package/src/types/Project.ts +14 -0
- package/src/utils/analyseNode.ts +98 -0
- package/src/utils/extractTextStyle.ts +24 -8
- package/src/utils/extractViewStyle.ts +27 -3
- package/src/utils/parseColor.ts +43 -0
- package/dist/pages/tabs/BuilderTab.d.ts +0 -9
- package/dist/pages/tabs/PreviewTab.d.ts +0 -3
- package/src/pages/tabs/DebugTab.tsx +0 -64
- package/src/pages/tabs/PreviewTab.tsx +0 -206
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import { AttributesEditor, Node, NodeData } from '..';
|
|
1
|
+
import { AttributesEditor, Node, NodeData, ProjectColors } from '..';
|
|
2
2
|
import { useLogRender } from '../utils/useLogRender';
|
|
3
|
+
import { useRenderStore } from '../store';
|
|
3
4
|
|
|
4
5
|
interface AttributesEditorPanelProps {
|
|
5
|
-
current: Node;
|
|
6
6
|
attributes: any;
|
|
7
7
|
onChange: (data: Node) => void;
|
|
8
|
-
|
|
8
|
+
projectColors?: ProjectColors;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function AttributesEditorPanel({
|
|
12
|
-
current,
|
|
13
12
|
attributes,
|
|
14
13
|
onChange,
|
|
15
|
-
|
|
14
|
+
projectColors,
|
|
16
15
|
}: AttributesEditorPanelProps) {
|
|
17
16
|
useLogRender('AttributesEditorPanel');
|
|
17
|
+
const { current, setCurrent } = useRenderStore((s) => ({
|
|
18
|
+
current: s.current,
|
|
19
|
+
setCurrent: s.setCurrent,
|
|
20
|
+
}));
|
|
18
21
|
if (!current) return null;
|
|
19
22
|
|
|
20
23
|
function replaceNode(root: Node, target: Node, next: Node): Node {
|
|
@@ -52,7 +55,11 @@ export function AttributesEditorPanel({
|
|
|
52
55
|
|
|
53
56
|
return (
|
|
54
57
|
<div style={{ padding: 12 }}>
|
|
55
|
-
<AttributesEditor
|
|
58
|
+
<AttributesEditor
|
|
59
|
+
node={current}
|
|
60
|
+
onChange={handleAttributesChange}
|
|
61
|
+
projectColors={projectColors}
|
|
62
|
+
/>
|
|
56
63
|
</div>
|
|
57
64
|
);
|
|
58
65
|
}
|
|
@@ -12,52 +12,34 @@ import { Breadcrumb } from './Breadcrumb';
|
|
|
12
12
|
import { useLogRender } from '../utils/useLogRender';
|
|
13
13
|
import { getDefaultsForType, getPatternByType } from '../utils/patterns';
|
|
14
14
|
import { AddComponentModal } from '../modals/AddComponentModal';
|
|
15
|
+
import { BuilderButton } from './BuilderButton';
|
|
15
16
|
|
|
16
17
|
type BuilderEditorProps = {
|
|
17
18
|
data: Node;
|
|
18
19
|
setData: (data: Node) => void;
|
|
19
20
|
current: Node;
|
|
20
21
|
setCurrent: (current: Node) => void;
|
|
22
|
+
onDeleteNode: (node: Node) => void;
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
interface BuilderEditorComponentProps {
|
|
24
26
|
node: Node;
|
|
25
27
|
onClick: (node: Node) => void;
|
|
26
28
|
onAdd?: () => void;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return <div className="builder__placeholder">Null or undefined</div>;
|
|
32
|
-
}
|
|
33
|
-
if (isNodeString(node)) {
|
|
34
|
-
return <div className="builder__text">{node as string}</div>;
|
|
35
|
-
}
|
|
36
|
-
const nodeData = node as NodeData<NodeDefaultAttribute>;
|
|
37
|
-
|
|
38
|
-
let extra = '';
|
|
39
|
-
if (nodeData.attributes?.condition) {
|
|
40
|
-
extra = ` (${nodeData.attributes.condition} ${nodeData.attributes.conditionVariable})`;
|
|
41
|
-
}
|
|
42
|
-
const patternLabel = getPatternByType(nodeData.type)?.meta?.label?.trim();
|
|
43
|
-
const baseLabel =
|
|
44
|
-
patternLabel && patternLabel.length > 0 ? patternLabel : nodeData.type;
|
|
45
|
-
const conditionLabel = extra.trim() ? extra : '';
|
|
46
|
-
const fullLabel = `${baseLabel}${conditionLabel}`.trim();
|
|
47
|
-
return (
|
|
48
|
-
<a onClick={onClick} className="builder__button">
|
|
49
|
-
<span className="builder__button-label">{baseLabel}</span> <br />
|
|
50
|
-
{conditionLabel && (
|
|
51
|
-
<span className="builder__button-condition">{conditionLabel}</span>
|
|
52
|
-
)}
|
|
53
|
-
</a>
|
|
54
|
-
);
|
|
29
|
+
onDelete?: (node: Node) => void;
|
|
30
|
+
onReorder?: (prev: Node[], next: Node[]) => void;
|
|
31
|
+
onMoveChildUp?: (parent: Node, childIndex: number) => void;
|
|
32
|
+
onMoveChildDown?: (parent: Node, childIndex: number) => void;
|
|
55
33
|
}
|
|
56
34
|
|
|
57
35
|
function BuilderComponent({
|
|
58
36
|
node,
|
|
59
37
|
onClick,
|
|
60
38
|
onAdd,
|
|
39
|
+
onDelete,
|
|
40
|
+
onReorder,
|
|
41
|
+
onMoveChildUp,
|
|
42
|
+
onMoveChildDown,
|
|
61
43
|
}: BuilderEditorComponentProps) {
|
|
62
44
|
if (isNodeNullOrUndefined(node)) {
|
|
63
45
|
return <div className="builder__placeholder">Null or undefined</div>;
|
|
@@ -84,16 +66,38 @@ function BuilderComponent({
|
|
|
84
66
|
);
|
|
85
67
|
|
|
86
68
|
if (isNodeArray(node)) {
|
|
69
|
+
const list = node as Node[];
|
|
70
|
+
|
|
71
|
+
const moveItem = (index: number, direction: -1 | 1) => {
|
|
72
|
+
if (!onReorder) return;
|
|
73
|
+
const targetIndex = index + direction;
|
|
74
|
+
if (targetIndex < 0 || targetIndex >= list.length) return;
|
|
75
|
+
const updated = [...list];
|
|
76
|
+
const [moved] = updated.splice(index, 1);
|
|
77
|
+
updated.splice(targetIndex, 0, moved);
|
|
78
|
+
onReorder(list, updated);
|
|
79
|
+
};
|
|
80
|
+
|
|
87
81
|
return (
|
|
88
82
|
<div className="builder__list">
|
|
89
|
-
{
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
onClick(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
83
|
+
{list.map((item, index) => (
|
|
84
|
+
<div key={index} className="builder__list-item">
|
|
85
|
+
<BuilderButton
|
|
86
|
+
onClick={() => {
|
|
87
|
+
onClick(item);
|
|
88
|
+
}}
|
|
89
|
+
node={item}
|
|
90
|
+
onDelete={onDelete}
|
|
91
|
+
onMoveUp={
|
|
92
|
+
onReorder && index > 0 ? () => moveItem(index, -1) : undefined
|
|
93
|
+
}
|
|
94
|
+
onMoveDown={
|
|
95
|
+
onReorder && index < list.length - 1
|
|
96
|
+
? () => moveItem(index, 1)
|
|
97
|
+
: undefined
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
97
101
|
))}
|
|
98
102
|
{addButton}
|
|
99
103
|
</div>
|
|
@@ -101,15 +105,24 @@ function BuilderComponent({
|
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
const nodeData = node as NodeData<NodeDefaultAttribute>;
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
const rawChildren = nodeData.children;
|
|
109
|
+
const hasArrayChildren = isNodeArray(rawChildren);
|
|
110
|
+
const children = rawChildren
|
|
111
|
+
? hasArrayChildren
|
|
112
|
+
? (rawChildren as Node[])
|
|
113
|
+
: [rawChildren]
|
|
108
114
|
: null;
|
|
109
115
|
|
|
110
116
|
return (
|
|
111
117
|
<div className="builder__node">
|
|
112
118
|
<div className="builder__children">
|
|
119
|
+
<BuilderButton
|
|
120
|
+
onClick={() => {
|
|
121
|
+
onClick(node);
|
|
122
|
+
}}
|
|
123
|
+
node={node}
|
|
124
|
+
onDelete={onDelete}
|
|
125
|
+
/>
|
|
113
126
|
{children &&
|
|
114
127
|
children.map((child, index) => (
|
|
115
128
|
<BuilderButton
|
|
@@ -118,6 +131,19 @@ function BuilderComponent({
|
|
|
118
131
|
}}
|
|
119
132
|
key={index}
|
|
120
133
|
node={child}
|
|
134
|
+
onDelete={onDelete}
|
|
135
|
+
onMoveUp={
|
|
136
|
+
onMoveChildUp && hasArrayChildren && index > 0
|
|
137
|
+
? () => onMoveChildUp(node, index)
|
|
138
|
+
: undefined
|
|
139
|
+
}
|
|
140
|
+
onMoveDown={
|
|
141
|
+
onMoveChildDown &&
|
|
142
|
+
hasArrayChildren &&
|
|
143
|
+
index < (children as Node[]).length - 1
|
|
144
|
+
? () => onMoveChildDown(node, index)
|
|
145
|
+
: undefined
|
|
146
|
+
}
|
|
121
147
|
/>
|
|
122
148
|
))}
|
|
123
149
|
</div>
|
|
@@ -131,6 +157,7 @@ export function Builder({
|
|
|
131
157
|
setData,
|
|
132
158
|
current,
|
|
133
159
|
setCurrent,
|
|
160
|
+
onDeleteNode,
|
|
134
161
|
}: BuilderEditorProps) {
|
|
135
162
|
useLogRender('Builder');
|
|
136
163
|
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
|
@@ -222,6 +249,75 @@ export function Builder({
|
|
|
222
249
|
[handleAddChild],
|
|
223
250
|
);
|
|
224
251
|
|
|
252
|
+
const handleReorder = useCallback(
|
|
253
|
+
(prev: Node[], next: Node[]) => {
|
|
254
|
+
const updatedRoot = replaceNode(data, prev, next);
|
|
255
|
+
setData(updatedRoot);
|
|
256
|
+
if (current === prev) {
|
|
257
|
+
setCurrent(next);
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
[current, data, setCurrent, setData],
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const handleMoveChildUp = useCallback(
|
|
264
|
+
(parentNode: Node, childIndex: number) => {
|
|
265
|
+
if (
|
|
266
|
+
isNodeNullOrUndefined(parentNode) ||
|
|
267
|
+
isNodeString(parentNode) ||
|
|
268
|
+
isNodeArray(parentNode)
|
|
269
|
+
) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const parentData = parentNode as NodeData<NodeDefaultAttribute>;
|
|
273
|
+
const children = parentData.children;
|
|
274
|
+
if (!Array.isArray(children)) return;
|
|
275
|
+
if (childIndex <= 0 || childIndex >= children.length) return;
|
|
276
|
+
const updatedChildren = [...children];
|
|
277
|
+
const [movedChild] = updatedChildren.splice(childIndex, 1);
|
|
278
|
+
updatedChildren.splice(childIndex - 1, 0, movedChild);
|
|
279
|
+
const updatedParent: NodeData<NodeDefaultAttribute> = {
|
|
280
|
+
...parentData,
|
|
281
|
+
children: updatedChildren,
|
|
282
|
+
};
|
|
283
|
+
const updatedRoot = replaceNode(data, parentNode, updatedParent);
|
|
284
|
+
setData(updatedRoot);
|
|
285
|
+
if (current === parentNode) {
|
|
286
|
+
setCurrent(updatedParent);
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
[current, data, setCurrent, setData],
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const handleMoveChildDown = useCallback(
|
|
293
|
+
(parentNode: Node, childIndex: number) => {
|
|
294
|
+
if (
|
|
295
|
+
isNodeNullOrUndefined(parentNode) ||
|
|
296
|
+
isNodeString(parentNode) ||
|
|
297
|
+
isNodeArray(parentNode)
|
|
298
|
+
) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const parentData = parentNode as NodeData<NodeDefaultAttribute>;
|
|
302
|
+
const children = parentData.children;
|
|
303
|
+
if (!Array.isArray(children)) return;
|
|
304
|
+
if (childIndex < 0 || childIndex >= children.length - 1) return;
|
|
305
|
+
const updatedChildren = [...children];
|
|
306
|
+
const [movedChild] = updatedChildren.splice(childIndex, 1);
|
|
307
|
+
updatedChildren.splice(childIndex + 1, 0, movedChild);
|
|
308
|
+
const updatedParent: NodeData<NodeDefaultAttribute> = {
|
|
309
|
+
...parentData,
|
|
310
|
+
children: updatedChildren,
|
|
311
|
+
};
|
|
312
|
+
const updatedRoot = replaceNode(data, parentNode, updatedParent);
|
|
313
|
+
setData(updatedRoot);
|
|
314
|
+
if (current === parentNode) {
|
|
315
|
+
setCurrent(updatedParent);
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
[current, data, setCurrent, setData],
|
|
319
|
+
);
|
|
320
|
+
|
|
225
321
|
function replaceNode(root: Node, target: Node, next: Node): Node {
|
|
226
322
|
if (root === target) return next;
|
|
227
323
|
if (root === null || root === undefined) return root;
|
|
@@ -312,6 +408,10 @@ export function Builder({
|
|
|
312
408
|
<BuilderComponent
|
|
313
409
|
onClick={handleNodeSelect}
|
|
314
410
|
onAdd={canAddChild ? handleOpenAddModal : undefined}
|
|
411
|
+
onDelete={onDeleteNode}
|
|
412
|
+
onReorder={handleReorder}
|
|
413
|
+
onMoveChildUp={handleMoveChildUp}
|
|
414
|
+
onMoveChildDown={handleMoveChildDown}
|
|
315
415
|
node={current}
|
|
316
416
|
/>
|
|
317
417
|
{isAddModalOpen && (
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
isNodeNullOrUndefined,
|
|
4
|
+
isNodeString,
|
|
5
|
+
Node,
|
|
6
|
+
NodeData,
|
|
7
|
+
NodeDefaultAttribute,
|
|
8
|
+
} from '..';
|
|
9
|
+
import { getPatternByType } from '../utils/patterns';
|
|
10
|
+
|
|
11
|
+
export type BuilderButtonProps = {
|
|
12
|
+
node: Node;
|
|
13
|
+
onClick: () => void;
|
|
14
|
+
onDelete?: (node: Node) => void;
|
|
15
|
+
onMoveUp?: () => void;
|
|
16
|
+
onMoveDown?: () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function BuilderButton({
|
|
20
|
+
node,
|
|
21
|
+
onClick,
|
|
22
|
+
onDelete,
|
|
23
|
+
onMoveUp,
|
|
24
|
+
onMoveDown,
|
|
25
|
+
}: BuilderButtonProps) {
|
|
26
|
+
if (isNodeNullOrUndefined(node)) {
|
|
27
|
+
return <div className="builder__placeholder">Null or undefined</div>;
|
|
28
|
+
}
|
|
29
|
+
if (isNodeString(node)) {
|
|
30
|
+
return <div className="builder__text">{node as string}</div>;
|
|
31
|
+
}
|
|
32
|
+
const nodeData = node as NodeData<NodeDefaultAttribute>;
|
|
33
|
+
|
|
34
|
+
const longPressTimeoutRef = useRef<number | null>(null);
|
|
35
|
+
const longPressTriggeredRef = useRef(false);
|
|
36
|
+
|
|
37
|
+
const handleDelete = () => {
|
|
38
|
+
if (onDelete) {
|
|
39
|
+
onDelete(node);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const clearLongPress = () => {
|
|
44
|
+
if (longPressTimeoutRef.current !== null) {
|
|
45
|
+
window.clearTimeout(longPressTimeoutRef.current);
|
|
46
|
+
longPressTimeoutRef.current = null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handlePressStart = () => {
|
|
51
|
+
longPressTriggeredRef.current = false;
|
|
52
|
+
longPressTimeoutRef.current = window.setTimeout(() => {
|
|
53
|
+
longPressTriggeredRef.current = true;
|
|
54
|
+
const shouldDelete = window.confirm('Do you want to delete');
|
|
55
|
+
if (shouldDelete) {
|
|
56
|
+
handleDelete();
|
|
57
|
+
}
|
|
58
|
+
}, 600);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handlePressEnd = () => {
|
|
62
|
+
if (!longPressTriggeredRef.current) {
|
|
63
|
+
onClick();
|
|
64
|
+
}
|
|
65
|
+
clearLongPress();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const handlePressCancel = () => {
|
|
69
|
+
clearLongPress();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
let extra = '';
|
|
73
|
+
if (nodeData.attributes?.condition) {
|
|
74
|
+
extra = ` (${nodeData.attributes.condition} ${nodeData.attributes.conditionVariable})`;
|
|
75
|
+
}
|
|
76
|
+
const patternLabel = getPatternByType(nodeData.type)?.meta?.label?.trim();
|
|
77
|
+
const baseLabel =
|
|
78
|
+
patternLabel && patternLabel.length > 0 ? patternLabel : nodeData.type;
|
|
79
|
+
const conditionLabel = extra.trim() ? extra : '';
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div className="builder__button">
|
|
83
|
+
{(onMoveUp || onMoveDown) && (
|
|
84
|
+
<div className="builder__sort-controls">
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
className="builder__sort-button"
|
|
88
|
+
onClick={(event) => {
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
onMoveUp?.();
|
|
91
|
+
}}
|
|
92
|
+
disabled={!onMoveUp}
|
|
93
|
+
aria-label="Move up"
|
|
94
|
+
>
|
|
95
|
+
↑
|
|
96
|
+
</button>
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
className="builder__sort-button"
|
|
100
|
+
onClick={(event) => {
|
|
101
|
+
event.stopPropagation();
|
|
102
|
+
onMoveDown?.();
|
|
103
|
+
}}
|
|
104
|
+
disabled={!onMoveDown}
|
|
105
|
+
aria-label="Move down"
|
|
106
|
+
>
|
|
107
|
+
↓
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
<a
|
|
112
|
+
className="builder__button-link"
|
|
113
|
+
onMouseDown={handlePressStart}
|
|
114
|
+
onMouseUp={handlePressEnd}
|
|
115
|
+
onMouseLeave={handlePressCancel}
|
|
116
|
+
onTouchStart={handlePressStart}
|
|
117
|
+
onTouchEnd={handlePressEnd}
|
|
118
|
+
onTouchCancel={handlePressCancel}
|
|
119
|
+
>
|
|
120
|
+
{baseLabel}
|
|
121
|
+
</a>
|
|
122
|
+
{conditionLabel && (
|
|
123
|
+
<span className="builder__button-condition">{conditionLabel}</span>
|
|
124
|
+
)}
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import AttributesEditor from './AttributesEditor';
|
|
|
3
3
|
|
|
4
4
|
export type { TargetedScreenSize } from './types/TargetedScreenSize';
|
|
5
5
|
export type { Node, NodeData, NodeDefaultAttribute } from './types/Node';
|
|
6
|
-
export type { Project } from './types/Project';
|
|
6
|
+
export type { Project, ProjectColors } from './types/Project';
|
|
7
7
|
export {
|
|
8
8
|
isNodeNullOrUndefined,
|
|
9
9
|
isNodeString,
|
|
@@ -28,7 +28,7 @@ export { extractViewStyle } from './utils/extractViewStyle';
|
|
|
28
28
|
export { extractImageStyle } from './utils/extractImageStyle';
|
|
29
29
|
export { extractTextStyle } from './utils/extractTextStyle';
|
|
30
30
|
export { ProjectPage } from './pages/ProjectPage';
|
|
31
|
-
export type { ProjectPageProps
|
|
31
|
+
export type { ProjectPageProps } from './pages/ProjectPage';
|
|
32
32
|
export { copyNode } from './utils/copyNode';
|
|
33
33
|
export { logger } from './utils/logger';
|
|
34
34
|
export type { LogLevel } from './types/Project';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
1
|
+
import React, { ReactNode, useCallback, useEffect } from 'react';
|
|
2
2
|
import { useMockOSContext } from '../context/MockOSContext';
|
|
3
3
|
import { MockLaunchScreenComponent } from './MockLaunchScreenComponent';
|
|
4
4
|
// Note: We might use react-router or similar library in the future for more complex routing
|
|
@@ -92,11 +92,19 @@ export function MockOSRouter({
|
|
|
92
92
|
|
|
93
93
|
const { currentRoute, navigation } = context;
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const handleLaunchApp = useCallback(() => {
|
|
96
96
|
// Navigate to the route specified in childrenBelongTo or default to 'onboard'
|
|
97
97
|
const targetRoute = childrenBelongTo || 'onboard';
|
|
98
98
|
navigation(targetRoute);
|
|
99
|
-
}
|
|
99
|
+
}, [childrenBelongTo, navigation]);
|
|
100
|
+
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const timer = setTimeout(() => {
|
|
103
|
+
handleLaunchApp();
|
|
104
|
+
}, 1000);
|
|
105
|
+
|
|
106
|
+
return () => clearTimeout(timer);
|
|
107
|
+
}, [handleLaunchApp]);
|
|
100
108
|
|
|
101
109
|
return (
|
|
102
110
|
<div className="mockos-router">
|