@developer_tribe/react-builder 0.1.31 → 1.0.1

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 (120) hide show
  1. package/dist/DeviceMockFrame.d.ts +1 -17
  2. package/dist/RenderPage.d.ts +1 -9
  3. package/dist/build-components/Button/ButtonProps.generated.d.ts +2 -1
  4. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +2 -1
  5. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +2 -1
  6. package/dist/build-components/Image/ImageProps.generated.d.ts +2 -1
  7. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +8 -4
  8. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +6 -3
  9. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +2 -1
  10. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +10 -5
  11. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +4 -1
  12. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +4 -2
  13. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +10 -5
  14. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +10 -5
  15. package/dist/build-components/Text/TextProps.generated.d.ts +10 -5
  16. package/dist/build-components/View/ViewProps.generated.d.ts +6 -3
  17. package/dist/build-components/index.d.ts +1 -0
  18. package/dist/build-components/patterns.generated.d.ts +7 -2
  19. package/dist/components/AttributesEditorPanel.d.ts +9 -0
  20. package/dist/components/Breadcrumb.d.ts +13 -0
  21. package/dist/components/Builder.d.ts +9 -0
  22. package/dist/components/EditorHeader.d.ts +15 -0
  23. package/dist/index.cjs.js +7 -4
  24. package/dist/index.cjs.js.map +1 -0
  25. package/dist/index.d.ts +8 -4
  26. package/dist/index.esm.js +7 -4
  27. package/dist/index.esm.js.map +1 -0
  28. package/dist/pages/ProjectPage.d.ts +11 -0
  29. package/dist/pages/tabs/BuilderTab.d.ts +9 -0
  30. package/dist/pages/tabs/DebugTab.d.ts +7 -0
  31. package/dist/pages/tabs/PreviewTab.d.ts +3 -0
  32. package/dist/store.d.ts +17 -18
  33. package/dist/styles.css +1 -1
  34. package/dist/types/PreviewConfig.d.ts +6 -3
  35. package/dist/types/Project.d.ts +12 -2
  36. package/dist/utils/copyNode.d.ts +2 -0
  37. package/dist/utils/logger.d.ts +11 -0
  38. package/dist/utils/useLogRender.d.ts +1 -0
  39. package/package.json +17 -9
  40. package/scripts/prebuild/utils/createBuildComponentsIndex.js +15 -1
  41. package/scripts/prebuild/utils/createGeneratedProps.js +64 -5
  42. package/src/AttributesEditor.tsx +2 -0
  43. package/src/DeviceMockFrame.tsx +22 -31
  44. package/src/RenderPage.tsx +5 -42
  45. package/src/assets/images/android.svg +43 -0
  46. package/src/assets/images/apple.svg +16 -0
  47. package/src/assets/images/background.jpg +0 -0
  48. package/src/assets/samples/carousel-sample.json +2 -3
  49. package/src/assets/samples/getSamples.ts +51 -8
  50. package/src/assets/samples/simple-1.json +1 -2
  51. package/src/assets/samples/simple-2.json +1 -2
  52. package/src/assets/samples/vpn-onboard-1.json +1 -2
  53. package/src/assets/samples/vpn-onboard-2.json +1 -2
  54. package/src/assets/samples/vpn-onboard-3.json +1 -2
  55. package/src/assets/samples/vpn-onboard-4.json +1 -2
  56. package/src/assets/samples/vpn-onboard-5.json +1024 -0
  57. package/src/assets/samples/vpn-onboard-6.json +708 -0
  58. package/src/build-components/Button/Button.tsx +2 -0
  59. package/src/build-components/Button/ButtonProps.generated.ts +14 -12
  60. package/src/build-components/Carousel/Carousel.tsx +2 -0
  61. package/src/build-components/CarouselButtons/CarouselButtons.tsx +2 -0
  62. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +6 -1
  63. package/src/build-components/CarouselDots/CarouselDots.tsx +2 -0
  64. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +9 -7
  65. package/src/build-components/CarouselItem/CarouselItem.tsx +2 -0
  66. package/src/build-components/Image/Image.tsx +2 -0
  67. package/src/build-components/Image/ImageProps.generated.ts +3 -1
  68. package/src/build-components/Onboard/Onboard.tsx +2 -0
  69. package/src/build-components/OnboardButton/OnboardButton.tsx +7 -4
  70. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +14 -9
  71. package/src/build-components/OnboardButton/pattern.json +3 -2
  72. package/src/build-components/OnboardButtons/OnboardButtons.tsx +7 -7
  73. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +10 -3
  74. package/src/build-components/OnboardDot/OnboardDot.tsx +2 -0
  75. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +9 -7
  76. package/src/build-components/OnboardFooter/OnboardFooter.tsx +5 -3
  77. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +33 -22
  78. package/src/build-components/OnboardImage/OnboardImage.tsx +26 -1
  79. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +5 -1
  80. package/src/build-components/OnboardImage/pattern.json +3 -5
  81. package/src/build-components/OnboardItem/OnboardItem.tsx +2 -0
  82. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +5 -2
  83. package/src/build-components/OnboardProvider/OnboardProvider.tsx +2 -0
  84. package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +2 -0
  85. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +33 -22
  86. package/src/build-components/OnboardTitle/OnboardTitle.tsx +2 -0
  87. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +33 -22
  88. package/src/build-components/Text/Text.tsx +5 -3
  89. package/src/build-components/Text/TextProps.generated.ts +33 -22
  90. package/src/build-components/View/View.tsx +2 -0
  91. package/src/build-components/View/ViewProps.generated.ts +18 -9
  92. package/src/build-components/index.ts +22 -0
  93. package/src/build-components/patterns.generated.ts +7 -2
  94. package/src/components/AttributesEditorPanel.tsx +112 -0
  95. package/src/components/Breadcrumb.tsx +48 -0
  96. package/src/components/Builder.tsx +272 -0
  97. package/src/components/EditorHeader.tsx +186 -0
  98. package/src/index.ts +8 -4
  99. package/src/pages/ProjectPage.tsx +152 -0
  100. package/src/pages/tabs/BuilderTab.tsx +33 -0
  101. package/src/pages/tabs/DebugTab.tsx +23 -0
  102. package/src/pages/tabs/PreviewTab.tsx +194 -0
  103. package/src/size-matters/index.ts +5 -1
  104. package/src/store.ts +60 -38
  105. package/src/styles/_mixins.scss +21 -0
  106. package/src/styles/_variables.scss +27 -0
  107. package/src/styles/builder.scss +60 -0
  108. package/src/styles/components.scss +88 -0
  109. package/src/styles/editor.scss +174 -0
  110. package/src/styles/global.scss +200 -0
  111. package/src/styles/index.scss +7 -0
  112. package/src/styles/pages.scss +2 -0
  113. package/src/types/PreviewConfig.ts +14 -5
  114. package/src/types/Project.ts +15 -2
  115. package/src/utils/copyNode.ts +7 -0
  116. package/src/utils/extractTextStyle.ts +4 -2
  117. package/src/utils/getDevices.ts +1 -0
  118. package/src/utils/logger.ts +76 -0
  119. package/src/utils/novaToJson.ts +5 -0
  120. package/src/utils/useLogRender.ts +13 -0
@@ -0,0 +1,186 @@
1
+ import { useMemo, useState } from 'react';
2
+ import { Device, getDevices, Node, copyNode } from '..';
3
+ import { useRenderStore } from '../store';
4
+ import { Breadcrumb, BreadcrumbItem } from './Breadcrumb';
5
+ import { useLogRender } from '../utils/useLogRender';
6
+
7
+ const devices = getDevices();
8
+
9
+ interface EditorHeaderProps {
10
+ onSaveProject?: () => void;
11
+ current?: Node;
12
+ editorData?: Node;
13
+ setEditorData?: (data: Node) => void;
14
+ }
15
+
16
+ interface DeviceButtonProps {
17
+ device: Device;
18
+ selectedDevice: Device | null;
19
+ setSelectedDevice: (device: Device) => void;
20
+ }
21
+ export function DeviceButton({
22
+ device,
23
+ selectedDevice,
24
+ setSelectedDevice,
25
+ }: DeviceButtonProps) {
26
+ return (
27
+ <button
28
+ className={`editor-device-button ${selectedDevice === device ? 'editor-device-button--selected' : ''}`}
29
+ onClick={() => setSelectedDevice(device)}
30
+ >
31
+ {device.name} <br />
32
+ {device.width}x{device.height}
33
+ </button>
34
+ );
35
+ }
36
+
37
+ export function EditorHeader({
38
+ onSaveProject,
39
+ current,
40
+ editorData,
41
+ setEditorData,
42
+ }: EditorHeaderProps) {
43
+ useLogRender('EditorHeader');
44
+ const [isDevicesModalOpen, setIsDevicesModalOpen] = useState(false);
45
+ const copiedNode = useRenderStore((s) => s.copiedNode);
46
+ const { device, setDevice } = useRenderStore((s) => ({
47
+ device: s.device,
48
+ setDevice: s.setDevice,
49
+ }));
50
+
51
+ function replaceNode(root: Node, target: Node, next: Node): Node {
52
+ if (root === target) return next;
53
+ if (root === null || root === undefined) return root;
54
+ if (typeof root === 'string') return root;
55
+ if (Array.isArray(root)) {
56
+ let changed = false;
57
+ const arr = root.map((item) => {
58
+ const r = replaceNode(item, target, next);
59
+ if (r !== item) changed = true;
60
+ return r;
61
+ });
62
+ return changed ? arr : root;
63
+ }
64
+ const data = root as any;
65
+ if ('children' in data) {
66
+ const prev = data.children;
67
+ const replaced = Array.isArray(prev)
68
+ ? prev.map((c: Node) => replaceNode(c, target, next))
69
+ : replaceNode(prev as Node, target, next);
70
+ if (replaced !== prev) {
71
+ data.children = replaced;
72
+ return { ...data, children: replaced } as Node;
73
+ }
74
+ }
75
+ return root;
76
+ }
77
+ const handleCopy = () => {
78
+ if (current) copyNode(current);
79
+ };
80
+ const handlePaste = () => {
81
+ if (!current || !editorData || !setEditorData) return;
82
+ if (!copiedNode) return;
83
+ const cloned = JSON.parse(JSON.stringify(copiedNode)) as Node;
84
+ const updated = replaceNode(editorData, current, cloned);
85
+ useRenderStore.setState({
86
+ copiedNode: null,
87
+ });
88
+ useRenderStore.getState().forceRender();
89
+ setEditorData(updated);
90
+ };
91
+ return (
92
+ <div
93
+ className="editor-header"
94
+ role="region"
95
+ aria-label="Editor utility header"
96
+ >
97
+ <div className="editor-header__devices">
98
+ {devices.slice(0, 5).map((device: Device) => (
99
+ <DeviceButton
100
+ key={device.name}
101
+ selectedDevice={device}
102
+ setSelectedDevice={setDevice}
103
+ device={device}
104
+ />
105
+ ))}
106
+ <button
107
+ className="editor-device-button"
108
+ aria-label="More devices"
109
+ onClick={() => setIsDevicesModalOpen(true)}
110
+ >
111
+ More devices
112
+ </button>
113
+ </div>
114
+ <div className="editor-header__actions">
115
+ <button
116
+ className="editor-button editor-save-button"
117
+ aria-label="Save project data"
118
+ onClick={() => onSaveProject && onSaveProject()}
119
+ >
120
+ Save
121
+ </button>
122
+ <button
123
+ className="editor-button editor-save-previewconfig-button"
124
+ aria-label="Save previewConfig"
125
+ onClick={() => useRenderStore.getState().forceRender()}
126
+ >
127
+ Force Render
128
+ </button>
129
+ <button
130
+ className="editor-button"
131
+ aria-label="Copy node"
132
+ onClick={handleCopy}
133
+ >
134
+ Copy
135
+ </button>
136
+ {copiedNode && (
137
+ <button
138
+ className="editor-button"
139
+ aria-label="Paste node"
140
+ onClick={handlePaste}
141
+ >
142
+ Paste
143
+ </button>
144
+ )}
145
+ </div>
146
+ {isDevicesModalOpen && (
147
+ <div
148
+ className="editor-modal"
149
+ role="dialog"
150
+ aria-modal="true"
151
+ aria-labelledby="device-selector-title"
152
+ >
153
+ <div
154
+ className="editor-modal__overlay"
155
+ onClick={() => setIsDevicesModalOpen(false)}
156
+ />
157
+ <div className="editor-modal__content">
158
+ <div className="editor-modal__header">
159
+ <h3 id="device-selector-title">Select a device</h3>
160
+ <button
161
+ className="editor-button"
162
+ aria-label="Close device selector"
163
+ onClick={() => setIsDevicesModalOpen(false)}
164
+ >
165
+ Close
166
+ </button>
167
+ </div>
168
+ <div className="editor-device-grid" role="list">
169
+ {devices.map((device: Device) => (
170
+ <DeviceButton
171
+ key={device.name}
172
+ selectedDevice={device}
173
+ setSelectedDevice={(d: Device) => {
174
+ setDevice(d);
175
+ setIsDevicesModalOpen(false);
176
+ }}
177
+ device={device}
178
+ />
179
+ ))}
180
+ </div>
181
+ </div>
182
+ </div>
183
+ )}
184
+ </div>
185
+ );
186
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import './styles/index.scss';
2
2
  import AttributesEditor from './AttributesEditor';
3
3
 
4
- export { TargetedScreenSize } from './types/TargetedScreenSize';
5
- export { Node, NodeData, NodeDefaultAttribute } from './types/Node';
6
- export { Project } from './types/Project';
4
+ export type { TargetedScreenSize } from './types/TargetedScreenSize';
5
+ export type { Node, NodeData, NodeDefaultAttribute } from './types/Node';
6
+ export type { Project } from './types/Project';
7
7
  export {
8
8
  isNodeNullOrUndefined,
9
9
  isNodeString,
@@ -14,7 +14,6 @@ export {
14
14
  export { getSamples } from './assets/samples/getSamples';
15
15
  export { getBasicSamples } from './assets/samples/getSamples';
16
16
  export { getOnboardSamples } from './assets/samples/getSamples';
17
- export { PreviewConfig } from './types/PreviewConfig';
18
17
  export { RenderPage } from './RenderPage';
19
18
  export { DeviceMockFrame } from './DeviceMockFrame';
20
19
  export { novaToJson } from './utils/novaToJson';
@@ -28,3 +27,8 @@ export { querySelector } from './utils/querySelector';
28
27
  export { extractViewStyle } from './utils/extractViewStyle';
29
28
  export { extractImageStyle } from './utils/extractImageStyle';
30
29
  export { extractTextStyle } from './utils/extractTextStyle';
30
+ export { ProjectPage } from './pages/ProjectPage';
31
+ export type { ProjectPageProps, Tab } from './pages/ProjectPage';
32
+ export { copyNode } from './utils/copyNode';
33
+ export { logger } from './utils/logger';
34
+ export type { LogLevel } from './types/Project';
@@ -0,0 +1,152 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { Node, RenderPage, Project } from '..';
3
+ import { EditorHeader } from '../components/EditorHeader';
4
+ import { AttributesEditorPanel } from '../components/AttributesEditorPanel';
5
+ import { BuilderTab } from './tabs/BuilderTab';
6
+ import { PreviewTab } from './tabs/PreviewTab';
7
+ import { DebugTab } from './tabs/DebugTab';
8
+ import { AppConfig, defaultAppConfig } from '../types/PreviewConfig';
9
+ import { useRenderStore } from '../store';
10
+ import { logger } from '../utils/logger';
11
+ import { useLogRender } from '../utils/useLogRender';
12
+ import type { LogLevel } from '../types/Project';
13
+
14
+ export type Tab = 'builder' | 'preview' | 'debug';
15
+
16
+ export type ProjectPageProps = {
17
+ project: Project;
18
+ onSaveProject: (project: Project) => void;
19
+ appConfig?: AppConfig;
20
+ logLevel?: LogLevel;
21
+ };
22
+
23
+ export function ProjectPage({
24
+ project,
25
+ appConfig = defaultAppConfig,
26
+ onSaveProject,
27
+ logLevel,
28
+ }: ProjectPageProps) {
29
+ useLogRender('ProjectPage');
30
+ const [current, setCurrent] = useState<Node>(project.data);
31
+ const [editorData, setEditorData] = useState<Node>(project.data);
32
+ const [tab, setTab] = useState<Tab>('builder');
33
+
34
+ useEffect(() => {
35
+ logger.info('ProjectPage', 'mount', { projectName: project.name });
36
+ useRenderStore.getState().setAppConfig(appConfig);
37
+ logger.verbose('ProjectPage', 'appConfig applied', appConfig);
38
+ return () => {
39
+ logger.info('ProjectPage', 'unmount');
40
+ };
41
+ }, [appConfig, project.name]);
42
+
43
+ useEffect(() => {
44
+ if (!logLevel) return;
45
+ logger.setLevel(logLevel);
46
+ }, [logLevel]);
47
+
48
+ return (
49
+ <div className="container-full">
50
+ <EditorHeader
51
+ onSaveProject={() => {
52
+ logger.info('ProjectPage', 'save project', { name: project.name });
53
+ onSaveProject({
54
+ ...project,
55
+ data: editorData,
56
+ });
57
+ }}
58
+ current={current}
59
+ editorData={editorData}
60
+ setEditorData={setEditorData}
61
+ />
62
+ <div className="editor-container">
63
+ <div className="split-left">
64
+ <div>
65
+ <div
66
+ className="editor-tabs"
67
+ role="tablist"
68
+ aria-label="Editor tabs"
69
+ >
70
+ <button
71
+ className={`editor-tab ${tab === 'builder' ? 'editor-tab--active' : ''}`}
72
+ role="tab"
73
+ aria-selected={tab === 'builder'}
74
+ onClick={() => {
75
+ setTab('builder');
76
+ logger.info('ProjectPage', 'tab change', { to: 'builder' });
77
+ }}
78
+ >
79
+ Builder
80
+ </button>
81
+ <button
82
+ className={`editor-tab ${tab === 'preview' ? 'editor-tab--active' : ''}`}
83
+ role="tab"
84
+ aria-selected={tab === 'preview'}
85
+ onClick={() => {
86
+ setTab('preview');
87
+ logger.info('ProjectPage', 'tab change', { to: 'preview' });
88
+ }}
89
+ >
90
+ Preview Config
91
+ </button>
92
+ <button
93
+ className={`editor-tab ${tab === 'debug' ? 'editor-tab--active' : ''}`}
94
+ role="tab"
95
+ aria-selected={tab === 'debug'}
96
+ onClick={() => {
97
+ setTab('debug');
98
+ logger.info('ProjectPage', 'tab change', { to: 'debug' });
99
+ }}
100
+ >
101
+ Debug
102
+ </button>
103
+ </div>
104
+
105
+ {tab === 'builder' && (
106
+ <BuilderTab
107
+ data={editorData}
108
+ setData={setEditorData}
109
+ current={current}
110
+ setCurrent={setCurrent}
111
+ />
112
+ )}
113
+
114
+ {tab === 'preview' && <PreviewTab />}
115
+
116
+ {tab === 'debug' && (
117
+ <DebugTab data={editorData} setData={setEditorData} />
118
+ )}
119
+ </div>
120
+ </div>
121
+ <div className="split-right">
122
+ <div className="split-right-background" />
123
+ <RenderPage data={editorData} />
124
+ </div>
125
+ <div className="split-third">
126
+ <AttributesEditorPanel
127
+ current={current}
128
+ attributes={editorData}
129
+ onChange={(data) => {
130
+ setEditorData(data);
131
+ let nodeKey: string | undefined = undefined;
132
+ if (
133
+ data &&
134
+ typeof data === 'object' &&
135
+ !Array.isArray(data) &&
136
+ 'key' in (data as any)
137
+ ) {
138
+ nodeKey = (data as any).key as string | undefined;
139
+ }
140
+ logger.verbose(
141
+ 'ProjectPage',
142
+ 'attributes change',
143
+ nodeKey ? { nodeKey } : undefined,
144
+ );
145
+ }}
146
+ setCurrent={setCurrent}
147
+ />
148
+ </div>
149
+ </div>
150
+ </div>
151
+ );
152
+ }
@@ -0,0 +1,33 @@
1
+ import { Node } from '../..';
2
+ import { useLogRender } from '../../utils/useLogRender';
3
+ import { Builder } from '../../components/Builder';
4
+
5
+ type BuilderTabProps = {
6
+ data: Node;
7
+ setData: (data: Node) => void;
8
+ current: Node;
9
+ setCurrent: (current: Node) => void;
10
+ };
11
+
12
+ export function BuilderTab({
13
+ data,
14
+ setData,
15
+ current,
16
+ setCurrent,
17
+ }: BuilderTabProps) {
18
+ useLogRender('BuilderTab');
19
+ return (
20
+ <div
21
+ role="tabpanel"
22
+ className="editor-panel-builder editor-panel editor-panel--active"
23
+ aria-hidden={false}
24
+ >
25
+ <Builder
26
+ data={data}
27
+ setData={setData}
28
+ current={current}
29
+ setCurrent={setCurrent}
30
+ />
31
+ </div>
32
+ );
33
+ }
@@ -0,0 +1,23 @@
1
+ import { JsonEditor } from 'json-edit-react';
2
+ import { Node } from '../..';
3
+ import { useLogRender } from '../../utils/useLogRender';
4
+
5
+ type DebugTabProps = {
6
+ data: Node;
7
+ setData: (data: Node) => void;
8
+ };
9
+
10
+ export function DebugTab({ data, setData }: DebugTabProps) {
11
+ useLogRender('DebugTab');
12
+ return (
13
+ <div
14
+ role="tabpanel"
15
+ className="editor-panel editor-panel--active editor-panels-debug"
16
+ aria-hidden={false}
17
+ >
18
+ <div style={{ flex: '1 1 auto', minHeight: 0, overflow: 'auto' }}>
19
+ <JsonEditor data={data as any} setData={setData as any} />
20
+ </div>
21
+ </div>
22
+ );
23
+ }
@@ -0,0 +1,194 @@
1
+ import { JsonEditor } from 'json-edit-react';
2
+ import { Localication, TargetedScreenSize } from '../..';
3
+ import { useLogRender } from '../../utils/useLogRender';
4
+ import { useRenderStore } from '../../store';
5
+
6
+ type PreviewTabProps = {};
7
+
8
+ export function PreviewTab({}: PreviewTabProps) {
9
+ useLogRender('PreviewTab');
10
+ const { appConfig, setAppConfig } = useRenderStore((s) => ({
11
+ appConfig: s.appConfig,
12
+ setAppConfig: s.setAppConfig,
13
+ }));
14
+ return (
15
+ <div
16
+ role="tabpanel"
17
+ className="editor-panel editor-panel--active"
18
+ aria-hidden={false}
19
+ >
20
+ <div style={{ padding: 12 }}>
21
+ <div
22
+ style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}
23
+ >
24
+ <div>Default Language</div>
25
+ <select
26
+ value={appConfig.defaultLanguage ?? 'en'}
27
+ onChange={(e) => {
28
+ setAppConfig({
29
+ ...appConfig,
30
+ defaultLanguage: e.target.value,
31
+ });
32
+ }}
33
+ >
34
+ {Object.keys(appConfig.localication ?? {}).map((language) => (
35
+ <option key={language} value={language}>
36
+ {language}
37
+ </option>
38
+ ))}
39
+ </select>
40
+ </div>
41
+ <div
42
+ style={{
43
+ display: 'grid',
44
+ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
45
+ gap: 12,
46
+ marginTop: 8,
47
+ }}
48
+ >
49
+ <div>Light Background Color</div>
50
+ <input
51
+ type="color"
52
+ value={appConfig.screenStyle?.light.backgroundColor ?? '#FDFDFD'}
53
+ onChange={(e) => {
54
+ const next = {
55
+ ...appConfig.screenStyle,
56
+ light: {
57
+ ...(appConfig.screenStyle?.light ?? {
58
+ color: '#161827',
59
+ }),
60
+ backgroundColor: e.target.value,
61
+ },
62
+ };
63
+
64
+ setAppConfig({
65
+ ...appConfig,
66
+ screenStyle: next,
67
+ });
68
+ }}
69
+ className="input input--color"
70
+ />
71
+ <div>Light Color</div>
72
+ <input
73
+ type="color"
74
+ value={appConfig.screenStyle?.light.color ?? '#161827'}
75
+ onChange={(e) => {
76
+ const next = {
77
+ ...appConfig.screenStyle,
78
+ light: {
79
+ ...(appConfig.screenStyle?.light ?? {
80
+ backgroundColor: '#FDFDFD',
81
+ }),
82
+ color: e.target.value,
83
+ },
84
+ };
85
+
86
+ setAppConfig({
87
+ ...appConfig,
88
+ screenStyle: next,
89
+ });
90
+ }}
91
+ className="input input--color"
92
+ />
93
+ <div>Dark Background Color</div>
94
+ <input
95
+ type="color"
96
+ value={appConfig.screenStyle?.dark.backgroundColor ?? '#12131A'}
97
+ onChange={(e) => {
98
+ const next = {
99
+ ...appConfig.screenStyle,
100
+ dark: {
101
+ ...(appConfig.screenStyle?.dark ?? {
102
+ color: '#E9EBF9',
103
+ }),
104
+ backgroundColor: e.target.value,
105
+ },
106
+ };
107
+
108
+ setAppConfig({
109
+ ...appConfig,
110
+ screenStyle: next,
111
+ });
112
+ }}
113
+ className="input input--color"
114
+ />
115
+ <div>Dark Color</div>
116
+ <input
117
+ type="color"
118
+ value={appConfig.screenStyle?.dark.color ?? '#E9EBF9'}
119
+ onChange={(e) => {
120
+ const next = {
121
+ ...appConfig.screenStyle,
122
+ dark: {
123
+ ...(appConfig.screenStyle?.dark ?? {
124
+ backgroundColor: '#12131A',
125
+ }),
126
+ color: e.target.value,
127
+ },
128
+ };
129
+ setAppConfig({
130
+ ...appConfig,
131
+ screenStyle: next,
132
+ });
133
+ }}
134
+ className="input input--color"
135
+ />
136
+ </div>
137
+ <div
138
+ style={{
139
+ display: 'flex',
140
+ alignItems: 'center',
141
+ gap: 8,
142
+ marginTop: 8,
143
+ }}
144
+ >
145
+ <div>Dark Mode</div>
146
+ <input
147
+ type="checkbox"
148
+ checked={appConfig.theme === 'dark'}
149
+ onChange={(e) => {
150
+ const nextTheme = e.target.checked ? 'dark' : 'light';
151
+
152
+ setAppConfig({
153
+ ...appConfig,
154
+ theme: nextTheme,
155
+ });
156
+ }}
157
+ />
158
+ </div>
159
+ <div
160
+ style={{
161
+ display: 'flex',
162
+ alignItems: 'center',
163
+ gap: 8,
164
+ marginTop: 8,
165
+ }}
166
+ >
167
+ <div>Is RTL</div>
168
+ <input
169
+ type="checkbox"
170
+ checked={appConfig.isRtl ?? false}
171
+ onChange={(e) => {
172
+ setAppConfig({
173
+ ...appConfig,
174
+ isRtl: e.target.checked,
175
+ });
176
+ }}
177
+ />
178
+ </div>
179
+ <div style={{ marginTop: 8 }}>
180
+ <JsonEditor
181
+ rootName="localication"
182
+ data={appConfig.localication ?? {}}
183
+ setData={(data) => {
184
+ setAppConfig({
185
+ ...appConfig,
186
+ localication: data as Localication,
187
+ });
188
+ }}
189
+ />
190
+ </div>
191
+ </div>
192
+ </div>
193
+ );
194
+ }
@@ -8,7 +8,11 @@ function getBaseDimensions() {
8
8
  ? [device.width, device.height]
9
9
  : [device.height, device.width];
10
10
 
11
- return { baseSize: currentState.baseSize, shortDimension, longDimension };
11
+ return {
12
+ baseSize: currentState.appConfig.baseSize,
13
+ shortDimension,
14
+ longDimension,
15
+ };
12
16
  }
13
17
  export function scale(size: number) {
14
18
  const { baseSize, shortDimension } = getBaseDimensions();