@stack-spot/portal-layout 0.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 (110) hide show
  1. package/dist/Layout.d.ts +22 -0
  2. package/dist/Layout.d.ts.map +1 -0
  3. package/dist/Layout.js +21 -0
  4. package/dist/Layout.js.map +1 -0
  5. package/dist/LayoutOverlayManager.d.ts +32 -0
  6. package/dist/LayoutOverlayManager.d.ts.map +1 -0
  7. package/dist/LayoutOverlayManager.js +154 -0
  8. package/dist/LayoutOverlayManager.js.map +1 -0
  9. package/dist/components/BottomNotification.d.ts +1 -0
  10. package/dist/components/BottomNotification.d.ts.map +1 -0
  11. package/dist/components/BottomNotification.js +2 -0
  12. package/dist/components/BottomNotification.js.map +1 -0
  13. package/dist/components/BottomPanel.d.ts +1 -0
  14. package/dist/components/BottomPanel.d.ts.map +1 -0
  15. package/dist/components/BottomPanel.js +2 -0
  16. package/dist/components/BottomPanel.js.map +1 -0
  17. package/dist/components/Dialog.d.ts +21 -0
  18. package/dist/components/Dialog.d.ts.map +1 -0
  19. package/dist/components/Dialog.js +19 -0
  20. package/dist/components/Dialog.js.map +1 -0
  21. package/dist/components/Header.d.ts +12 -0
  22. package/dist/components/Header.d.ts.map +1 -0
  23. package/dist/components/Header.js +6 -0
  24. package/dist/components/Header.js.map +1 -0
  25. package/dist/components/Logo.d.ts +2 -0
  26. package/dist/components/Logo.d.ts.map +1 -0
  27. package/dist/components/Logo.js +4 -0
  28. package/dist/components/Logo.js.map +1 -0
  29. package/dist/components/Menu/MenuContent.d.ts +3 -0
  30. package/dist/components/Menu/MenuContent.d.ts.map +1 -0
  31. package/dist/components/Menu/MenuContent.js +126 -0
  32. package/dist/components/Menu/MenuContent.js.map +1 -0
  33. package/dist/components/Menu/MenuSections.d.ts +3 -0
  34. package/dist/components/Menu/MenuSections.d.ts.map +1 -0
  35. package/dist/components/Menu/MenuSections.js +70 -0
  36. package/dist/components/Menu/MenuSections.js.map +1 -0
  37. package/dist/components/Menu/PageSelector.d.ts +3 -0
  38. package/dist/components/Menu/PageSelector.d.ts.map +1 -0
  39. package/dist/components/Menu/PageSelector.js +87 -0
  40. package/dist/components/Menu/PageSelector.js.map +1 -0
  41. package/dist/components/Menu/constants.d.ts +3 -0
  42. package/dist/components/Menu/constants.d.ts.map +1 -0
  43. package/dist/components/Menu/constants.js +3 -0
  44. package/dist/components/Menu/constants.js.map +1 -0
  45. package/dist/components/Menu/types.d.ts +45 -0
  46. package/dist/components/Menu/types.d.ts.map +1 -0
  47. package/dist/components/Menu/types.js +2 -0
  48. package/dist/components/Menu/types.js.map +1 -0
  49. package/dist/components/OverlayContent.d.ts +15 -0
  50. package/dist/components/OverlayContent.d.ts.map +1 -0
  51. package/dist/components/OverlayContent.js +26 -0
  52. package/dist/components/OverlayContent.js.map +1 -0
  53. package/dist/components/SelectionList.d.ts +34 -0
  54. package/dist/components/SelectionList.d.ts.map +1 -0
  55. package/dist/components/SelectionList.js +104 -0
  56. package/dist/components/SelectionList.js.map +1 -0
  57. package/dist/components/Toaster.d.ts +3 -0
  58. package/dist/components/Toaster.d.ts.map +1 -0
  59. package/dist/components/Toaster.js +8 -0
  60. package/dist/components/Toaster.js.map +1 -0
  61. package/dist/components/UserMenu.d.ts +9 -0
  62. package/dist/components/UserMenu.d.ts.map +1 -0
  63. package/dist/components/UserMenu.js +57 -0
  64. package/dist/components/UserMenu.js.map +1 -0
  65. package/dist/components/types.d.ts +6 -0
  66. package/dist/components/types.d.ts.map +1 -0
  67. package/dist/components/types.js +2 -0
  68. package/dist/components/types.js.map +1 -0
  69. package/dist/errors.d.ts +7 -0
  70. package/dist/errors.d.ts.map +1 -0
  71. package/dist/errors.js +11 -0
  72. package/dist/errors.js.map +1 -0
  73. package/dist/index.d.ts +11 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +11 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/layout.css +383 -0
  78. package/dist/toaster.d.ts +23 -0
  79. package/dist/toaster.d.ts.map +1 -0
  80. package/dist/toaster.js +41 -0
  81. package/dist/toaster.js.map +1 -0
  82. package/dist/utils.d.ts +2 -0
  83. package/dist/utils.d.ts.map +1 -0
  84. package/dist/utils.js +8 -0
  85. package/dist/utils.js.map +1 -0
  86. package/package.json +39 -0
  87. package/src/Layout.tsx +68 -0
  88. package/src/LayoutOverlayManager.tsx +180 -0
  89. package/src/citric.fix.d.ts +7 -0
  90. package/src/components/BottomNotification.tsx +0 -0
  91. package/src/components/BottomPanel.tsx +0 -0
  92. package/src/components/Dialog.tsx +55 -0
  93. package/src/components/Header.tsx +23 -0
  94. package/src/components/Logo.tsx +35 -0
  95. package/src/components/Menu/MenuContent.tsx +179 -0
  96. package/src/components/Menu/MenuSections.tsx +105 -0
  97. package/src/components/Menu/PageSelector.tsx +108 -0
  98. package/src/components/Menu/constants.ts +2 -0
  99. package/src/components/Menu/types.ts +53 -0
  100. package/src/components/OverlayContent.tsx +50 -0
  101. package/src/components/SelectionList.tsx +200 -0
  102. package/src/components/Toaster.tsx +12 -0
  103. package/src/components/UserMenu.tsx +91 -0
  104. package/src/components/types.ts +5 -0
  105. package/src/errors.ts +11 -0
  106. package/src/index.ts +10 -0
  107. package/src/layout.css +383 -0
  108. package/src/toaster.tsx +72 -0
  109. package/src/utils.ts +7 -0
  110. package/tsconfig.json +8 -0
package/src/layout.css ADDED
@@ -0,0 +1,383 @@
1
+ /* Scrollbars */
2
+
3
+ ::-webkit-scrollbar-track {
4
+ background-color: transparent;
5
+ }
6
+
7
+ ::-webkit-scrollbar {
8
+ width: 0.25rem;
9
+ background-color: transparent;
10
+ }
11
+
12
+ ::-webkit-scrollbar-thumb {
13
+ background-color: var(--light-600);
14
+ }
15
+
16
+ /* Layout */
17
+
18
+ html {
19
+ display: flex;
20
+ flex-direction: column;
21
+ height: 100%;
22
+ }
23
+
24
+ body {
25
+ margin: 0;
26
+ display: flex;
27
+ flex-direction: column;
28
+ flex: 1;
29
+ background: var(--light-400);
30
+ font: var(--font);
31
+ color: var(--light-contrastText);
32
+ }
33
+
34
+ #root, #layout {
35
+ display: flex;
36
+ flex-direction: column;
37
+ flex: 1;
38
+ }
39
+
40
+ #layout {
41
+ --header-height: 56px;
42
+ --menu-sections-width: 87px;
43
+ --menu-content-width: 233px;
44
+ --menu-item-height: 74px;
45
+ --modal-animation-duration: 0.3s;
46
+ --right-panel-animation-duration: 0.3s;
47
+ --menu-animation-duration: 0.3s;
48
+ --toastify-font-family: 'Roboto', sans-serif;
49
+ }
50
+
51
+ #layout.menu-compact {
52
+ --menu-sections-width: 56px;
53
+ --menu-item-height: 56px;
54
+ }
55
+
56
+ #header {
57
+ height: var(--header-height);
58
+ padding: 0 24px;
59
+ align-items: center;
60
+ flex-direction: row;
61
+ display: flex;
62
+ justify-content: space-between;
63
+ position: fixed;
64
+ left: 0;
65
+ right: 0;
66
+ top: 0;
67
+ background-color: var(--light-400);
68
+ }
69
+
70
+ #page {
71
+ flex: 1;
72
+ display: flex;
73
+ flex-direction: column;
74
+ background-color: var(--light-300);
75
+ border-top-left-radius: 0.5rem;
76
+ align-items: center;
77
+ padding: 24px;
78
+ margin-top: var(--header-height);
79
+ margin-left: var(--menu-sections-width);
80
+ transition: margin ease-in-out var(--menu-animation-duration);
81
+ }
82
+
83
+ #layout.menu-content-visible #page {
84
+ margin-left: calc(var(--menu-sections-width) + var(--menu-content-width));
85
+ }
86
+
87
+ #content {
88
+ width: 100%;
89
+ max-width: 1144px;
90
+ display: flex;
91
+ flex-direction: column;
92
+ }
93
+
94
+ /* Menu */
95
+
96
+ #menu {
97
+ position: fixed;
98
+ display: flex;
99
+ flex-direction: row;
100
+ top: var(--header-height);
101
+ bottom: 0;
102
+ }
103
+
104
+ #menu svg {
105
+ fill: var(--light-contrastText);
106
+ }
107
+
108
+ #menu .toggle .expand {
109
+ fill: var(--primary-500);
110
+ }
111
+
112
+ #menu .toggle .expand,
113
+ #menu .toggle .collapse {
114
+ position: absolute;
115
+ transition: opacity 0.3s;
116
+ }
117
+
118
+ #menu .toggle .expand,
119
+ #layout.menu-content-visible .toggle .collapse {
120
+ opacity: 1;
121
+ }
122
+
123
+ #menu .toggle .collapse,
124
+ #layout.menu-content-visible .toggle .expand {
125
+ opacity: 0;
126
+ }
127
+
128
+ #menuSections {
129
+ width: var(--menu-sections-width);
130
+ display: flex;
131
+ flex-direction: column;
132
+ padding: 10px 0;
133
+ justify-content: space-between;
134
+ background-color: var(--light-400);
135
+ z-index: 1;
136
+ }
137
+
138
+ #layout.menu-compact .section-label {
139
+ display: none;
140
+ }
141
+
142
+ #menuSections .toggle,
143
+ #menuSections > ul li a {
144
+ background: transparent;
145
+ border: none;
146
+ outline: none;
147
+ width: var(--menu-sections-width);
148
+ height: var(--menu-item-height);
149
+ display: flex;
150
+ flex-direction: column;
151
+ gap: 10px;
152
+ align-items: center;
153
+ justify-content: center;
154
+ transition: background-color 0.2s;
155
+ cursor: pointer;
156
+ position: relative;
157
+ }
158
+
159
+ #menuSections > ul li a:before {
160
+ content: '';
161
+ position: absolute;
162
+ width: 2px;
163
+ height: 24px;
164
+ transform: scaleY(0);
165
+ transition: transform ease-in 0.2s;
166
+ background-color: var(--primary-500);
167
+ border-radius: 50%;
168
+ left: 0;
169
+ }
170
+
171
+ #menuSections > ul li.active a {
172
+ background-color: var(--light-500);
173
+ }
174
+
175
+ #menuSections > ul li.active a:before {
176
+ transform: scaleY(1);
177
+ }
178
+
179
+ #menuSections .toggle:hover,
180
+ #menuSections > ul li a:hover {
181
+ background: var(--light-500);
182
+ }
183
+
184
+ #menuSections .toggle i {
185
+ position: relative;
186
+ }
187
+
188
+ #menuContentOverlay {
189
+ width: 232px;
190
+ position: fixed;
191
+ top: calc(var(--header-height) + 15px);
192
+ left: calc(var(--menu-sections-width) + 15px);
193
+ bottom: 15px;
194
+ background-color: var(--light-400);
195
+ box-shadow: 2px 2px 16px #000;
196
+ border-radius: 16px;
197
+ display: flex;
198
+ flex-direction: column;
199
+ overflow: hidden;
200
+ opacity: 0;
201
+ pointer-events: none;
202
+ z-index: 1;
203
+ transition: opacity 0.3s;
204
+ }
205
+
206
+ #menuContentOverlay.visible {
207
+ opacity: 1;
208
+ pointer-events: auto;
209
+ }
210
+
211
+ #menuContentOverlay > div {
212
+ flex: 1;
213
+ overflow: auto;
214
+ }
215
+
216
+ #menuContentOverlay > .arrow {
217
+ width: 0;
218
+ height: 0;
219
+ border-top: 12px solid transparent;
220
+ border-bottom: 12px solid transparent;
221
+ border-right: 12px solid var(--light-400);
222
+ position: fixed;
223
+ /* header + menu sections padding + item height / 2 - arrow height / 2 */
224
+ top: calc(var(--header-height) + 10px + var(--menu-item-height) / 2 - 12px);
225
+ left: calc(var(--menu-sections-width) + 3px);
226
+ transition: top ease-out 0.3s;
227
+ }
228
+
229
+ #menuContent {
230
+ width: var(--menu-content-width);
231
+ transition: left ease-out var(--menu-animation-duration);
232
+ background-color: var(--light-400);
233
+ overflow: auto;
234
+ position: absolute;
235
+ top: 0;
236
+ bottom: 0;
237
+ left: calc(var(--menu-sections-width) - var(--menu-content-width) - 2px); /* 2px from border */
238
+ border-left: 2px solid var(--light-500);
239
+ }
240
+
241
+ #layout.menu-content-visible #menuContent {
242
+ left: var(--menu-sections-width);
243
+ }
244
+
245
+ /* Overlays */
246
+
247
+ #backdrop {
248
+ position: fixed;
249
+ top: 0;
250
+ right: 0;
251
+ bottom: 0;
252
+ left: 0;
253
+ background-color: var(--backdrop-color);
254
+ opacity: 0;
255
+ pointer-events: none;
256
+ transition: opacity ease-in-out var(--modal-animation-duration);
257
+ display: flex;
258
+ flex-direction: column;
259
+ align-items: center;
260
+ justify-content: center;
261
+ }
262
+
263
+ #backdrop.visible {
264
+ opacity: 1;
265
+ pointer-events: auto;
266
+ }
267
+
268
+ #modal {
269
+ transform: scale(0);
270
+ display: flex;
271
+ flex-direction: column;
272
+ transition: transform ease-in-out var(--modal-animation-duration);
273
+ width: calc(100% - 60px);
274
+ }
275
+
276
+ #modal.fit-content {
277
+ width: auto;
278
+ }
279
+
280
+ #modal.large {
281
+ max-width: 1000px;
282
+ }
283
+
284
+ #modal.medium {
285
+ max-width: 800px;
286
+ }
287
+
288
+ #modal.small {
289
+ max-width: 600px;
290
+ }
291
+
292
+ #modal.visible {
293
+ transform: scale(1);
294
+ }
295
+
296
+ #rightPanel {
297
+ position: fixed;
298
+ display: flex;
299
+ flex-direction: column;
300
+ top: var(--header-height);
301
+ right: -307px;
302
+ bottom: 0;
303
+ width: 307px;
304
+ transition: right var(--right-panel-animation-duration);
305
+ background-color: var(--light-400);
306
+ }
307
+
308
+ #rightPanel.visible {
309
+ right: 0;
310
+ }
311
+
312
+ #bottomPanel {
313
+ position: fixed;
314
+ display: flex;
315
+ flex-direction: column;
316
+ bottom: -420px;
317
+ left: 20px;
318
+ height: 400px;
319
+ transition: transform bottom 0.3s;
320
+ }
321
+
322
+ #bottomPanel.visible {
323
+ bottom: 20px;
324
+ }
325
+
326
+ #bottomDialog {
327
+ position: fixed;
328
+ display: flex;
329
+ flex-direction: column;
330
+ bottom: -80px;
331
+ left: 0;
332
+ right: 0;
333
+ height: 80px;
334
+ transition: transform bottom 0.3s;
335
+ }
336
+
337
+ #bottomDialog.visible {
338
+ bottom: 0;
339
+ }
340
+
341
+ /* Overlay: toaster */
342
+
343
+ .main-toaster h1 {
344
+ font-size: 14px;
345
+ font-weight: 500;
346
+ margin: 0 0 8px 0;
347
+ }
348
+
349
+ .main-toaster p {
350
+ margin: 0;
351
+ font-size: 12px;
352
+ }
353
+
354
+ .main-toaster .toast-body {
355
+ align-items: start;
356
+ }
357
+
358
+ .main-toaster .Toastify__toast-icon {
359
+ margin-top: 2px;
360
+ width: auto;
361
+ }
362
+
363
+ /* Other */
364
+
365
+ svg path.stackspot-text {
366
+ fill: var(--light-contrastText)
367
+ }
368
+
369
+ a {
370
+ color: var(--light-contrastText);
371
+ text-decoration: none;
372
+ cursor: pointer;
373
+ }
374
+
375
+ ul {
376
+ list-style: none;
377
+ margin: 0;
378
+ padding: 0;
379
+ }
380
+
381
+ i {
382
+ fill: var(--light-contrastText);
383
+ }
@@ -0,0 +1,72 @@
1
+ import { IconBox } from '@citric/core'
2
+ import { OneOfColorSchemesWithVariants } from '@citric/core/utils/theme.types'
3
+ import { CheckCircleFill, ExclamationTriangleFill, InfoCircleFill, TimesCircleFill } from '@citric/icons'
4
+ import { toast } from 'react-toastify'
5
+ import 'react-toastify/dist/ReactToastify.css'
6
+
7
+ type ToastType = 'error' | 'success' | 'warning' | 'info'
8
+
9
+ interface BaseProps {
10
+ type?: ToastType,
11
+ /**
12
+ * Seconds until auto-close or false to not auto-close.
13
+ * @default 10
14
+ */
15
+ autoClose?: number | false,
16
+ }
17
+
18
+ interface BasicMessageProps extends BaseProps {
19
+ message: string,
20
+ title?: string,
21
+ onClick?: () => void,
22
+ }
23
+
24
+ interface RichMessageProps extends BaseProps {
25
+ content: React.ReactElement,
26
+ }
27
+
28
+ type Props = BasicMessageProps | RichMessageProps
29
+
30
+ const icons: Record<ToastType, { element: React.ReactElement, color: string }> = {
31
+ error: {
32
+ element: <TimesCircleFill />,
33
+ color: 'danger',
34
+ },
35
+ success: {
36
+ element: <CheckCircleFill />,
37
+ color: 'success',
38
+ },
39
+ warning: {
40
+ element: <ExclamationTriangleFill />,
41
+ color: 'warning',
42
+ },
43
+ info: {
44
+ element: <InfoCircleFill />,
45
+ color: 'inverse',
46
+ },
47
+ }
48
+
49
+ export function showToaster({ type = 'info', autoClose = 10, ...props }: Props) {
50
+ const icon = icons[type]
51
+ const bg = `var(--${icon.color}-500)`
52
+ const bgDark = `var(--${icon.color}-600)`
53
+ const fg = `var(--${icon.color}-contrastText)`
54
+ toast(
55
+ 'message' in props
56
+ ? <div onClick={props.onClick}><h1 style={{ textTransform: 'capitalize' }}>{props.title ?? type}</h1><p>{props.message}</p></div>
57
+ : props.content,
58
+ {
59
+ type,
60
+ autoClose: autoClose === false ? false : autoClose * 1000,
61
+ className:'main-toaster',
62
+ style: { backgroundColor: bg, color: fg },
63
+ progressStyle: { background: bgDark },
64
+ bodyClassName: 'toast-body',
65
+ icon: 'message' in props ? () => (
66
+ <IconBox colorScheme={fg as OneOfColorSchemesWithVariants}>
67
+ {icon.element}
68
+ </IconBox>
69
+ ) : undefined,
70
+ },
71
+ )
72
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { valueOf } from '@stack-spot/portal-theme'
2
+
3
+ export function valueOfLayoutVar(varname: string): string {
4
+ const layout = document.getElementById('layout')
5
+ if (!layout) return ''
6
+ return valueOf(varname, layout)
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src"]
8
+ }