@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
package/src/store.ts CHANGED
@@ -1,56 +1,78 @@
1
1
  import { createWithEqualityFn } from 'zustand/traditional';
2
2
  import { shallow } from 'zustand/shallow';
3
3
  import type { Device } from './types/Device';
4
- import type { Localication } from './types/PreviewConfig';
4
+ import {
5
+ defaultAppConfig,
6
+ type AppConfig,
7
+ type Localication,
8
+ } from './types/PreviewConfig';
5
9
  import { getDefaultDevice } from './utils/getDevices';
6
10
  import { ScreenStyle } from './RenderPage';
11
+ import { createJSONStorage } from 'zustand/middleware';
12
+ import { Node } from './types/Node';
13
+ import type { LogEntry, LogLevel } from './types/Project';
7
14
 
8
15
  type RenderStore = {
16
+ copiedNode: Node | null;
17
+ setCopiedNode: (node: Node | null) => void;
9
18
  device: Device;
10
- localication: Localication | null;
11
- defaultLanguage?: string;
12
- baseSize: {
13
- width: number;
14
- height: number;
15
- };
16
- theme: 'dark' | 'light';
17
- screenStyle: ScreenStyle;
18
- setBaseSize: (baseSize: { width: number; height: number }) => void;
19
19
  setDevice: (device: Device) => void;
20
- setLocalication: (localication: Localication | null) => void;
21
- setDefaultLanguage: (defaultLanguage?: string) => void;
22
- setTheme: (theme: 'dark' | 'light') => void;
23
- setScreenStyle: (screenStyle: ScreenStyle) => void;
20
+ appConfig: AppConfig;
21
+ setAppConfig: (appConfig: AppConfig) => void;
22
+ renderCount: number;
23
+ forceRender: () => void;
24
+ // Logging
25
+ logs: LogEntry[];
26
+ logLevel: LogLevel;
27
+ setLogLevel: (level: LogLevel) => void;
28
+ addLog: (
29
+ entry: Omit<LogEntry, 'id' | 'timestamp'> & {
30
+ id?: string;
31
+ timestamp?: number;
32
+ },
33
+ ) => void;
34
+ clearLogs: () => void;
24
35
  };
25
36
 
26
37
  export const useRenderStore = createWithEqualityFn<RenderStore>()(
27
38
  (set) => ({
39
+ copiedNode: null,
40
+ setCopiedNode: (node) => set({ copiedNode: node }),
41
+ renderCount: 0,
42
+ forceRender: () => set((state) => ({ renderCount: state.renderCount + 1 })),
28
43
  device: getDefaultDevice(),
29
- localication: null,
30
- defaultLanguage: undefined,
31
- baseSize: {
32
- width: 390,
33
- height: 844,
34
- },
35
- theme: 'light',
36
- screenStyle: {
37
- light: {
38
- backgroundColor: '#FDFDFD',
39
- color: '#161827',
40
- seperatorColor: '#E5E7EB',
41
- },
42
- dark: {
43
- backgroundColor: '#12131A',
44
- color: '#E9EBF9',
45
- seperatorColor: '#E5E7EB',
46
- },
47
- },
48
- setBaseSize: (baseSize) => set({ baseSize }),
49
44
  setDevice: (device) => set({ device }),
50
- setLocalication: (localication) => set({ localication }),
51
- setDefaultLanguage: (defaultLanguage) => set({ defaultLanguage }),
52
- setTheme: (theme) => set({ theme }),
53
- setScreenStyle: (screenStyle) => set({ screenStyle }),
45
+ appConfig: defaultAppConfig,
46
+ setAppConfig: (appConfig) => set({ appConfig }),
47
+ // Logging defaults
48
+ logs: [],
49
+ logLevel: 'INFO',
50
+ setLogLevel: (level) => set({ logLevel: level }),
51
+ addLog: (entry) =>
52
+ set((state) => {
53
+ const now = Date.now();
54
+ const id =
55
+ entry.id ?? `${now}-${Math.random().toString(36).slice(2, 8)}`;
56
+ const timestamp = entry.timestamp ?? now;
57
+ const newEntry: LogEntry = {
58
+ id,
59
+ timestamp,
60
+ level: entry.level,
61
+ source: entry.source,
62
+ message: entry.message,
63
+ payload: entry.payload,
64
+ };
65
+ return { logs: [...state.logs, newEntry] };
66
+ }),
67
+ clearLogs: () => set({ logs: [] }),
68
+ persist: {
69
+ name: 'render-store',
70
+ partialize: (state: RenderStore) => ({
71
+ copiedNode: state.copiedNode ?? null,
72
+ logLevel: state.logLevel,
73
+ }),
74
+ storage: createJSONStorage(() => localStorage),
75
+ },
54
76
  }),
55
77
  shallow,
56
78
  );
@@ -0,0 +1,21 @@
1
+ @use './variables' as *;
2
+ @mixin center-content {
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ }
7
+
8
+ @mixin card {
9
+ background: #fff;
10
+ border: 1px solid $color-border;
11
+ border-radius: $radius-xs;
12
+ }
13
+
14
+ @mixin thin-scrollbar {
15
+ scrollbar-width: thin;
16
+ scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
17
+ &::-webkit-scrollbar {
18
+ width: 8px;
19
+ height: 4px;
20
+ }
21
+ }
@@ -0,0 +1,27 @@
1
+ // Color palette
2
+ $color-background: #f3f4f6;
3
+ $color-border: #e5e7eb;
4
+ $color-text: #111827;
5
+ $color-muted: #9ca3af;
6
+ $color-error: #ef4444;
7
+ $color-button: cornflowerblue;
8
+
9
+ // Spacing
10
+ $space-1: 4px;
11
+ $space-2: 8px;
12
+ $space-3: 12px;
13
+ $space-4: 16px;
14
+ $space-5: 20px;
15
+ $space-6: 24px;
16
+
17
+ // Radius & shadow
18
+ $radius-xs: 4px;
19
+ $radius-sm: 8px;
20
+ $radius-md: 12px;
21
+ $radius-lg: 24px;
22
+ $shadow-card: 0 10px 30px rgba(0, 0, 0, 0.12);
23
+
24
+ // Fonts
25
+ $font-sans:
26
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
27
+ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif;
@@ -0,0 +1,60 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
3
+
4
+ .builder {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: $space-3;
8
+ }
9
+
10
+ .builder__breadcrumbs {
11
+ display: flex;
12
+ flex-direction: row;
13
+ gap: $space-2;
14
+ }
15
+
16
+ .builder__breadcrumb {
17
+ color: $color-muted;
18
+ font-size: 12px;
19
+ }
20
+
21
+ .builder__current {
22
+ font-weight: 600;
23
+ }
24
+
25
+ .builder__list {
26
+ display: flex;
27
+ flex-wrap: wrap;
28
+ gap: $space-2;
29
+ }
30
+
31
+ .builder__button {
32
+ @include card;
33
+ padding: $space-3 $space-3;
34
+ font-size: 14px;
35
+ background: $color-button;
36
+ color: #fff;
37
+ cursor: pointer;
38
+ }
39
+
40
+ .builder__node {
41
+ @include card;
42
+ padding: $space-3;
43
+ }
44
+
45
+ .builder__node-type {
46
+ margin: 0 0 $space-2 0;
47
+ font-weight: 600;
48
+ }
49
+
50
+ .builder__children {
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: $space-2;
54
+ }
55
+
56
+ .builder__text,
57
+ .builder__placeholder {
58
+ color: $color-muted;
59
+ font-size: 12px;
60
+ }
@@ -0,0 +1,88 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
3
+
4
+ .editor-controls {
5
+ display: grid;
6
+ grid-template-columns: auto 1fr;
7
+ gap: $space-3;
8
+ padding: $space-4;
9
+ }
10
+
11
+ .editor-section {
12
+ background: #fff;
13
+ border: 1px solid $color-border;
14
+ border-radius: $radius-md;
15
+ padding: $space-4;
16
+ }
17
+
18
+ .form-row {
19
+ display: grid;
20
+ grid-template-columns: 160px 1fr;
21
+ align-items: center;
22
+ gap: $space-3;
23
+ margin-bottom: $space-3;
24
+ }
25
+
26
+ .form-actions {
27
+ display: flex;
28
+ gap: $space-3;
29
+ margin-top: $space-4;
30
+ }
31
+
32
+ .btn {
33
+ padding: 8px 12px;
34
+ border-radius: 8px;
35
+ border: 1px solid $color-border;
36
+ background: #fff;
37
+ cursor: pointer;
38
+ transition:
39
+ background 0.2s ease,
40
+ box-shadow 0.2s ease;
41
+
42
+ &:hover {
43
+ background: #f9fafb;
44
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06);
45
+ }
46
+ }
47
+
48
+ /* Inputs */
49
+ .input {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ height: 32px;
53
+ padding: 0 8px;
54
+ border: 1px solid $color-border;
55
+ border-radius: $radius-md;
56
+ background: #fff;
57
+ color: $color-text;
58
+ font: inherit;
59
+ outline: none;
60
+ transition:
61
+ border-color 0.15s ease,
62
+ box-shadow 0.15s ease;
63
+
64
+ &:focus {
65
+ border-color: darken($color-border, 8%);
66
+ box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.04);
67
+ }
68
+ }
69
+
70
+ .input--color {
71
+ padding: 0;
72
+ width: 40px;
73
+ height: 28px;
74
+ border-radius: 6px;
75
+ cursor: pointer;
76
+
77
+ &::-webkit-color-swatch-wrapper {
78
+ padding: 0;
79
+ }
80
+ &::-webkit-color-swatch {
81
+ border: none;
82
+ border-radius: 4px;
83
+ }
84
+ &::-moz-color-swatch {
85
+ border: none;
86
+ border-radius: 4px;
87
+ }
88
+ }
@@ -0,0 +1,174 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
3
+
4
+ .editor-tabs {
5
+ display: flex;
6
+ gap: 8px;
7
+ border-bottom: 1px solid #e5e7eb;
8
+ }
9
+
10
+ .editor-tab {
11
+ padding: 8px 12px;
12
+ cursor: pointer;
13
+ border: 1px solid transparent;
14
+ border-top-left-radius: 4px;
15
+ border-top-right-radius: 4px;
16
+ color: #111827;
17
+ padding: 8px 12px;
18
+ }
19
+
20
+ .editor-tab--active {
21
+ background: #fff;
22
+ border-color: #e5e7eb #e5e7eb #fff #e5e7eb;
23
+ }
24
+
25
+ .editor-panels {
26
+ padding: 12px;
27
+ &.editor-panels-debug {
28
+ padding: 0;
29
+ }
30
+ }
31
+ .jer-editor-container {
32
+ padding-left: 0 !important;
33
+ padding-right: 0 !important;
34
+ }
35
+ .editor-panel {
36
+ display: none;
37
+ }
38
+
39
+ .editor-panel--active {
40
+ display: block;
41
+ }
42
+
43
+ /* Editor utility header */
44
+ .editor-header {
45
+ display: flex;
46
+ align-items: center;
47
+ gap: 12px;
48
+ padding: 0 $space-4;
49
+ height: 60px;
50
+ background: #f9fafb;
51
+ border-bottom: 1px solid #e5e7eb;
52
+ }
53
+
54
+ .editor-header__title {
55
+ color: #111827;
56
+ font-weight: 600;
57
+ }
58
+
59
+ .editor-header__devices {
60
+ @include thin-scrollbar;
61
+ display: flex;
62
+ flex-direction: row;
63
+ align-items: stretch;
64
+ gap: 8px;
65
+ overflow: auto;
66
+ height: 60px;
67
+ padding: $space-1;
68
+ }
69
+
70
+ .editor-device-button {
71
+ position: relative;
72
+ min-width: 160px;
73
+ height: 100%;
74
+ border: 1px solid #e5e7eb;
75
+ border-radius: 6px;
76
+ background: #ffffff;
77
+ color: #111827;
78
+ cursor: pointer;
79
+ font-size: 12px;
80
+ &.editor-device-button--selected {
81
+ border-color: #000;
82
+ }
83
+ }
84
+
85
+ .editor-device-button img {
86
+ position: absolute;
87
+ bottom: 4px;
88
+ right: 4px;
89
+ width: 16px;
90
+ height: 16px;
91
+ }
92
+
93
+ .editor-header__actions {
94
+ margin-left: auto; /* push actions to the far right */
95
+ display: flex;
96
+ align-items: center;
97
+ gap: 8px;
98
+ }
99
+
100
+ .editor-button {
101
+ display: inline-flex;
102
+ align-items: center;
103
+ justify-content: center;
104
+ height: 36px;
105
+ min-width: 120px; /* visible even without content */
106
+ padding: 0 12px;
107
+ border: 1px solid #e5e7eb;
108
+ border-radius: 6px;
109
+ background: #ffffff;
110
+ color: #111827;
111
+ cursor: pointer;
112
+ }
113
+
114
+ .editor-button:disabled {
115
+ opacity: 0.6;
116
+ cursor: default;
117
+ }
118
+
119
+ /* Specific hooks for save buttons (kept empty for now) */
120
+ .editor-save-button,
121
+ .editor-save-previewconfig-button {
122
+ color: #000;
123
+ font-weight: 600;
124
+ font-size: 12px;
125
+ }
126
+
127
+ /* Modal */
128
+ .editor-modal {
129
+ position: fixed;
130
+ inset: 0;
131
+ z-index: 1000;
132
+ }
133
+
134
+ .editor-modal__overlay {
135
+ position: absolute;
136
+ inset: 0;
137
+ background: rgba(0, 0, 0, 0.4);
138
+ }
139
+
140
+ .editor-modal__content {
141
+ position: absolute;
142
+ top: 50%;
143
+ left: 50%;
144
+ transform: translate(-50%, -50%);
145
+ background: #fff;
146
+ border-radius: 8px;
147
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
148
+ width: min(960px, calc(100vw - 40px));
149
+ max-height: calc(100vh - 120px);
150
+ display: flex;
151
+ flex-direction: column;
152
+ }
153
+
154
+ .editor-modal__header {
155
+ display: flex;
156
+ align-items: center;
157
+ justify-content: space-between;
158
+ padding: 12px 16px;
159
+ border-bottom: 1px solid #e5e7eb;
160
+ }
161
+
162
+ .editor-device-grid {
163
+ padding: 16px;
164
+ display: grid;
165
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
166
+ gap: 12px;
167
+ overflow: auto;
168
+ }
169
+
170
+ /* Reuse device button style inside modal grid */
171
+ .editor-device-grid .editor-device-button {
172
+ height: 80px;
173
+ min-width: unset;
174
+ }
@@ -0,0 +1,200 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
3
+ @use './reset';
4
+
5
+ /* Global utility classes */
6
+ html,
7
+ body,
8
+ #root {
9
+ font-family: $font-sans;
10
+ }
11
+
12
+ .editor-container {
13
+ height: 100vh;
14
+ width: 100vw;
15
+ display: flex;
16
+ overflow: hidden; /* Split panels manage their own scroll */
17
+ }
18
+ .editor-panel-builder {
19
+ padding: 4px 8px;
20
+ }
21
+ .app-shell {
22
+ min-height: 100vh;
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ .app-main {
28
+ flex: 1 1 auto;
29
+ background: $color-background;
30
+ }
31
+
32
+ .page-bg {
33
+ background: $color-background;
34
+ }
35
+
36
+ .grid-cards {
37
+ display: grid;
38
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
39
+ gap: $space-4;
40
+ }
41
+
42
+ .btn-add {
43
+ height: 120px;
44
+ border: 2px dashed $color-muted;
45
+ border-radius: $radius-md;
46
+ background: #fff;
47
+ cursor: pointer;
48
+ font-weight: 600;
49
+ color: $color-text;
50
+ transition:
51
+ border-color 0.2s ease,
52
+ transform 0.1s ease,
53
+ box-shadow 0.2s ease;
54
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
55
+
56
+ &:hover {
57
+ border-color: darken($color-muted, 10%);
58
+ transform: translateY(-1px);
59
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
60
+ }
61
+ }
62
+
63
+ .split-left {
64
+ @include thin-scrollbar;
65
+ flex: 1 1 30%;
66
+ min-width: 0;
67
+ border-right: 1px solid $color-border;
68
+ overflow: auto;
69
+ }
70
+
71
+ .split-right {
72
+ position: relative;
73
+ flex: 1 1 45%;
74
+ min-width: 0;
75
+ max-height: calc(100vh - 120px);
76
+ overflow: auto;
77
+ }
78
+
79
+ .split-third {
80
+ flex: 1 1 25%;
81
+ min-width: 0;
82
+ border-right: 1px solid $color-border;
83
+ overflow: auto;
84
+ max-height: calc(100vh - 120px);
85
+ }
86
+
87
+ .split-right-background {
88
+ position: absolute;
89
+ inset: 0;
90
+ background-size: cover;
91
+ background-position: center;
92
+ background-repeat: repeat;
93
+ background-size: 500px auto;
94
+ opacity: 0.2;
95
+ }
96
+
97
+ .stage-wrapper {
98
+ display: flex;
99
+ justify-content: center;
100
+ background: $color-background;
101
+ padding: $space-4;
102
+ }
103
+
104
+ .stage {
105
+ @include card;
106
+ border: 1px solid $color-border;
107
+
108
+ .scroll-container {
109
+ /* Mobile-like scrollbar styling */
110
+ &::-webkit-scrollbar {
111
+ width: 8px;
112
+ height: 8px;
113
+ }
114
+
115
+ &::-webkit-scrollbar-track {
116
+ background: transparent;
117
+ }
118
+
119
+ &::-webkit-scrollbar-thumb {
120
+ background: rgba(0, 0, 0, 0.25);
121
+ border-radius: 8px;
122
+ }
123
+
124
+ /* For Firefox */
125
+ scrollbar-width: thin;
126
+ scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
127
+ }
128
+ }
129
+
130
+ /* Header */
131
+ .app-header {
132
+ position: sticky;
133
+ top: 0;
134
+ z-index: 10;
135
+ background: #fff;
136
+ border-bottom: 1px solid $color-border;
137
+ height: 60px;
138
+ padding: 0 $space-4;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: space-between;
142
+
143
+ a {
144
+ color: $color-text;
145
+ text-decoration: none;
146
+ }
147
+ }
148
+
149
+ .app-header__brand {
150
+ font-weight: 700;
151
+ }
152
+
153
+ .app-header__nav {
154
+ display: flex;
155
+ gap: $space-4;
156
+ }
157
+ .warning {
158
+ color: $color-error;
159
+ font-size: 12px;
160
+ font-weight: 600;
161
+ margin-bottom: $space-4;
162
+ }
163
+
164
+ /* Breadcrumb */
165
+ .breadcrumb {
166
+ display: block;
167
+ font-size: 12px;
168
+ color: $color-muted;
169
+ }
170
+
171
+ .breadcrumb__list {
172
+ list-style: none;
173
+ padding: 0;
174
+ margin: 0;
175
+ display: flex;
176
+ align-items: center;
177
+ gap: $space-2;
178
+ }
179
+
180
+ .breadcrumb__item {
181
+ display: inline-flex;
182
+ align-items: center;
183
+ }
184
+
185
+ .breadcrumb__separator {
186
+ color: $color-border;
187
+ margin: 0 $space-1;
188
+ }
189
+
190
+ .breadcrumb__link {
191
+ color: $color-text;
192
+ text-decoration: none;
193
+ &:hover {
194
+ text-decoration: underline;
195
+ }
196
+ }
197
+
198
+ .breadcrumb__current {
199
+ color: $color-muted;
200
+ }
@@ -1,4 +1,11 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
1
3
  @use './reset';
4
+ @use './global.scss';
5
+ @use './pages.scss';
6
+ @use './components.scss';
7
+ @use './builder.scss';
8
+ @use './editor.scss';
2
9
 
3
10
  .embla {
4
11
  max-width: 48rem;
@@ -0,0 +1,2 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;