proteum 1.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 (156) hide show
  1. package/.dockerignore +10 -0
  2. package/Rte.zip +0 -0
  3. package/cli/app/config.ts +54 -0
  4. package/cli/app/index.ts +195 -0
  5. package/cli/bin.js +11 -0
  6. package/cli/commands/build.ts +34 -0
  7. package/cli/commands/deploy/app.ts +29 -0
  8. package/cli/commands/deploy/web.ts +60 -0
  9. package/cli/commands/dev.ts +109 -0
  10. package/cli/commands/init.ts +85 -0
  11. package/cli/compiler/client/identite.ts +72 -0
  12. package/cli/compiler/client/index.ts +334 -0
  13. package/cli/compiler/common/babel/index.ts +170 -0
  14. package/cli/compiler/common/babel/plugins/index.ts +0 -0
  15. package/cli/compiler/common/babel/plugins/services.ts +579 -0
  16. package/cli/compiler/common/babel/routes/imports.ts +127 -0
  17. package/cli/compiler/common/babel/routes/routes.ts +1130 -0
  18. package/cli/compiler/common/files/autres.ts +39 -0
  19. package/cli/compiler/common/files/images.ts +35 -0
  20. package/cli/compiler/common/files/style.ts +78 -0
  21. package/cli/compiler/common/index.ts +154 -0
  22. package/cli/compiler/index.ts +532 -0
  23. package/cli/compiler/server/index.ts +211 -0
  24. package/cli/index.ts +189 -0
  25. package/cli/paths.ts +165 -0
  26. package/cli/print.ts +12 -0
  27. package/cli/tsconfig.json +38 -0
  28. package/cli/utils/index.ts +22 -0
  29. package/cli/utils/keyboard.ts +78 -0
  30. package/client/app/component.tsx +54 -0
  31. package/client/app/index.ts +142 -0
  32. package/client/app/service.ts +34 -0
  33. package/client/app.tsconfig.json +28 -0
  34. package/client/components/Button.tsx +298 -0
  35. package/client/components/Dialog/Manager.tsx +309 -0
  36. package/client/components/Dialog/card.tsx +208 -0
  37. package/client/components/Dialog/index.less +151 -0
  38. package/client/components/Dialog/status.less +176 -0
  39. package/client/components/Dialog/status.tsx +48 -0
  40. package/client/components/index.ts +2 -0
  41. package/client/components/types.d.ts +3 -0
  42. package/client/data/input.ts +32 -0
  43. package/client/global.d.ts +5 -0
  44. package/client/hooks.ts +22 -0
  45. package/client/index.ts +6 -0
  46. package/client/pages/_layout/index.less +6 -0
  47. package/client/pages/_layout/index.tsx +43 -0
  48. package/client/pages/bug.tsx.old +60 -0
  49. package/client/pages/useHeader.tsx +50 -0
  50. package/client/services/captcha/index.ts +67 -0
  51. package/client/services/router/components/Link.tsx +46 -0
  52. package/client/services/router/components/Page.tsx +55 -0
  53. package/client/services/router/components/router.tsx +218 -0
  54. package/client/services/router/index.tsx +521 -0
  55. package/client/services/router/request/api.ts +267 -0
  56. package/client/services/router/request/history.ts +5 -0
  57. package/client/services/router/request/index.ts +53 -0
  58. package/client/services/router/request/multipart.ts +147 -0
  59. package/client/services/router/response/index.tsx +128 -0
  60. package/client/services/router/response/page.ts +86 -0
  61. package/client/services/socket/index.ts +147 -0
  62. package/client/utils/dom.ts +77 -0
  63. package/common/app/index.ts +9 -0
  64. package/common/data/chaines/index.ts +54 -0
  65. package/common/data/dates.ts +179 -0
  66. package/common/data/markdown.ts +73 -0
  67. package/common/data/rte/nodes.ts +83 -0
  68. package/common/data/stats.ts +90 -0
  69. package/common/errors/index.tsx +326 -0
  70. package/common/router/index.ts +213 -0
  71. package/common/router/layouts.ts +93 -0
  72. package/common/router/register.ts +55 -0
  73. package/common/router/request/api.ts +77 -0
  74. package/common/router/request/index.ts +35 -0
  75. package/common/router/response/index.ts +45 -0
  76. package/common/router/response/page.ts +128 -0
  77. package/common/utils/rte.ts +183 -0
  78. package/common/utils.ts +7 -0
  79. package/doc/TODO.md +71 -0
  80. package/doc/front/router.md +27 -0
  81. package/doc/workspace/workspace.png +0 -0
  82. package/doc/workspace/workspace2.png +0 -0
  83. package/doc/workspace/workspace_26.01.22.png +0 -0
  84. package/package.json +171 -0
  85. package/server/app/commands.ts +141 -0
  86. package/server/app/container/config.ts +203 -0
  87. package/server/app/container/console/index.ts +550 -0
  88. package/server/app/container/index.ts +137 -0
  89. package/server/app/index.ts +273 -0
  90. package/server/app/service/container.ts +88 -0
  91. package/server/app/service/index.ts +235 -0
  92. package/server/app.tsconfig.json +28 -0
  93. package/server/context.ts +4 -0
  94. package/server/index.ts +4 -0
  95. package/server/services/auth/index.ts +250 -0
  96. package/server/services/auth/old.ts +277 -0
  97. package/server/services/auth/router/index.ts +95 -0
  98. package/server/services/auth/router/request.ts +54 -0
  99. package/server/services/auth/router/service.json +6 -0
  100. package/server/services/auth/service.json +6 -0
  101. package/server/services/cache/commands.ts +41 -0
  102. package/server/services/cache/index.ts +297 -0
  103. package/server/services/cache/service.json +6 -0
  104. package/server/services/cron/CronTask.ts +86 -0
  105. package/server/services/cron/index.ts +112 -0
  106. package/server/services/cron/service.json +6 -0
  107. package/server/services/disks/driver.ts +103 -0
  108. package/server/services/disks/drivers/local/index.ts +188 -0
  109. package/server/services/disks/drivers/local/service.json +6 -0
  110. package/server/services/disks/drivers/s3/index.ts +301 -0
  111. package/server/services/disks/drivers/s3/service.json +6 -0
  112. package/server/services/disks/index.ts +90 -0
  113. package/server/services/disks/service.json +6 -0
  114. package/server/services/email/index.ts +188 -0
  115. package/server/services/email/utils.ts +53 -0
  116. package/server/services/fetch/index.ts +201 -0
  117. package/server/services/fetch/service.json +7 -0
  118. package/server/services/models.7z +0 -0
  119. package/server/services/prisma/Facet.ts +142 -0
  120. package/server/services/prisma/index.ts +201 -0
  121. package/server/services/prisma/service.json +6 -0
  122. package/server/services/router/http/index.ts +217 -0
  123. package/server/services/router/http/multipart.ts +102 -0
  124. package/server/services/router/http/session.ts.old +40 -0
  125. package/server/services/router/index.ts +801 -0
  126. package/server/services/router/request/api.ts +87 -0
  127. package/server/services/router/request/index.ts +184 -0
  128. package/server/services/router/request/service.ts +21 -0
  129. package/server/services/router/request/validation/zod.ts +180 -0
  130. package/server/services/router/response/index.ts +338 -0
  131. package/server/services/router/response/mask/Filter.ts +323 -0
  132. package/server/services/router/response/mask/index.ts +60 -0
  133. package/server/services/router/response/mask/selecteurs.ts +92 -0
  134. package/server/services/router/response/page/document.tsx +160 -0
  135. package/server/services/router/response/page/index.tsx +196 -0
  136. package/server/services/router/service.json +6 -0
  137. package/server/services/router/service.ts +36 -0
  138. package/server/services/schema/index.ts +44 -0
  139. package/server/services/schema/request.ts +49 -0
  140. package/server/services/schema/router/index.ts +28 -0
  141. package/server/services/schema/router/service.json +6 -0
  142. package/server/services/schema/service.json +6 -0
  143. package/server/services/security/encrypt/aes/index.ts +85 -0
  144. package/server/services/security/encrypt/aes/service.json +6 -0
  145. package/server/services/socket/index.ts +162 -0
  146. package/server/services/socket/scope.ts +226 -0
  147. package/server/services/socket/service.json +6 -0
  148. package/server/services_old/SocketClient.ts +92 -0
  149. package/server/services_old/Token.old.ts +97 -0
  150. package/server/utils/slug.ts +79 -0
  151. package/tsconfig.common.json +45 -0
  152. package/tsconfig.json +3 -0
  153. package/types/aliases.d.ts +54 -0
  154. package/types/global/modules.d.ts +49 -0
  155. package/types/global/utils.d.ts +103 -0
  156. package/types/icons.d.ts +1 -0
@@ -0,0 +1,309 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import React from 'react';
7
+ import { ComponentChild } from 'preact';
8
+
9
+ // Core
10
+ import useContext from '@/client/context';
11
+ import { blurable, deepContains, focusContent } from '@client/utils/dom';
12
+
13
+ // Specific
14
+ import type Application from '../../app';
15
+ import Card, { Props as CardInfos } from './card';
16
+ import Button from '../Button';
17
+
18
+ /*----------------------------------
19
+ - TYPES: IMPORTATIONS
20
+ ----------------------------------*/
21
+
22
+ /*----------------------------------
23
+ - TYPES: DECLARATIONS
24
+ ----------------------------------*/
25
+
26
+ type TParams = { [cle: string]: unknown }
27
+
28
+ type ComposantToast = React.FunctionComponent<{ close?: any }> & { data?: object };
29
+
30
+ type TOptsToast = (CardInfos & {
31
+ content?: ComponentChild,
32
+ data?: {},
33
+ className?: string,
34
+ })
35
+
36
+ type TOnCloseCallback<TReturnType extends any> = (returnedValue: TReturnType) => void
37
+
38
+ type TToastShortcutArgs = [
39
+ title: TOptsToast["title"],
40
+ content?: TOptsToast["content"],
41
+ boutons?: TOptsToast["boutons"],
42
+ options?: TOptsToast,
43
+ ]
44
+
45
+ export type TDialogControls = {
46
+ close: TOnCloseCallback<any>,
47
+ then: (cb: TOnCloseCallback<any>) => any
48
+ }
49
+
50
+ type TDialogContentArg = ComposantToast | Promise<{ default: ComposantToast }> | TOptsToast;
51
+
52
+ type TDialogShowArgs = [
53
+ // On utilise une fonction pour pouvoir accéder aux fonctions (close, ...) lors de la déclaration des infos de la toast
54
+ Content: TDialogContentArg,
55
+ paramsInit?: TParams
56
+ ] | [
57
+ title: string,
58
+ // On utilise une fonction pour pouvoir accéder aux fonctions (close, ...) lors de la déclaration des infos de la toast
59
+ Content: TDialogContentArg,
60
+ paramsInit?: TParams
61
+ ]
62
+
63
+ type DialogActions = {
64
+
65
+ setToasts: ( setter: (old: ComponentChild[]) => ComponentChild[]) => void,
66
+ setModals: ( setter: (old: ComponentChild[]) => ComponentChild[]) => void,
67
+
68
+ show: (...args: TDialogShowArgs ) => TDialogControls,
69
+
70
+ confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No') => TDialogControls,
71
+
72
+ loading: (title: string) => TDialogControls,
73
+
74
+ info: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
75
+
76
+ success: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
77
+
78
+ warning: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
79
+
80
+ error: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
81
+ }
82
+
83
+ /*----------------------------------
84
+ - SERVICE CONTEXTE
85
+ ----------------------------------*/
86
+ let idA: number = 0;
87
+ export const createDialog = (app: Application, isToast: boolean): DialogActions => {
88
+
89
+ const show = <TReturnType extends any = true>( ...args: TDialogShowArgs ): TDialogControls => {
90
+
91
+ let onClose: TOnCloseCallback<TReturnType>;
92
+ const id = idA++;
93
+
94
+ // Parse args
95
+ let title: string | undefined;
96
+ let Content: TDialogContentArg;
97
+ let paramsInit: TParams = {};
98
+ if (typeof args[0] === 'string') {
99
+ [title, Content, paramsInit] = args;
100
+ } else {
101
+ [Content, paramsInit] = args;
102
+ }
103
+
104
+ // Set instance management function
105
+ const setDialog = isToast
106
+ ? instance.setToasts
107
+ : instance.setModals;
108
+
109
+ // Close function
110
+ const close = (retour: TReturnType) => {
111
+
112
+ setDialog(q => q.filter(m => m.id !== id))
113
+
114
+ if (onClose !== undefined)
115
+ onClose(retour);
116
+ };
117
+
118
+ const promise = new Promise(async (resolve: TOnCloseCallback<TReturnType>) => {
119
+ onClose = resolve
120
+
121
+ let render: ComponentChild;
122
+ let propsRendu: CardInfos = {
123
+ ...paramsInit,
124
+ close: close
125
+ };
126
+
127
+ // modal.show( import('./modalSupprimer') )
128
+ // -> Fetch component
129
+ if (Content.constructor === Promise)
130
+ Content = (await Content).default;
131
+
132
+ // modal.show('Supprimer', import('./modalSupprimer'))
133
+ // -> Shortcut for modal.show({ title: 'Suoorimer', content: <Component> })
134
+ if (title !== undefined) {
135
+ Content = {
136
+ title: title,
137
+ content: Content
138
+ }
139
+ }
140
+
141
+ // modal.show({ title: 'supprimer', content: <>...</> })
142
+ if (Content.constructor === Object) {
143
+
144
+ const { content: CardContent, data = {}, ...propsToast } = Content as TOptsToast;
145
+
146
+ let cardContent: ComponentChild;
147
+ if (typeof CardContent === 'function') {
148
+ cardContent = <CardContent {...propsRendu} {...data} />
149
+ propsToast.boutons = null; // Component content = advanced content = should include buttons
150
+ } else {
151
+ cardContent = CardContent;
152
+ }
153
+
154
+ render = (
155
+ <Card {...propsRendu} {...propsToast} isToast={isToast}>
156
+ {cardContent}
157
+ </Card>
158
+ )
159
+
160
+ // modal.show( ToastSupprimer )
161
+ // -> Content is a component rendering a Card
162
+ } else {
163
+
164
+ render = (
165
+ <Content {...propsRendu} isToast={isToast} />
166
+ )
167
+ }
168
+
169
+ // Chargeur de données
170
+ /*if (('data' in ComposantCharge) && typeof ComposantCharge.data === 'function') {
171
+
172
+ propsRendu.data = await ComposantCharge.data(app, paramsInit);
173
+
174
+ const { fetchersStateA } = initStateAsync(propsRendu.data, {}, false);
175
+
176
+ await execFetchersState(fetchersStateA);
177
+
178
+ }*/
179
+
180
+ if (!isToast)
181
+ render = (
182
+ <div class="modal">
183
+ {render}
184
+ </div>
185
+ )
186
+
187
+ render["id"] = id;
188
+
189
+ setDialog(q => [...q, render]);
190
+ });
191
+
192
+ return {
193
+ close,
194
+ then: (cb) => promise.then(cb)
195
+ }
196
+ };
197
+
198
+ const instance: DialogActions = {
199
+
200
+ show: show,
201
+
202
+ setToasts: undefined as unknown as DialogActions["setToasts"],
203
+ setModals: undefined as unknown as DialogActions["setModals"],
204
+
205
+ confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No' = 'No') => show<boolean>(({ close }) => (
206
+ <div class="card col">
207
+ <header>
208
+ <h2>{title}</h2>
209
+ </header>
210
+ {typeof content === 'string' ? <p>{content}</p> : content}
211
+ <footer class="row fill">
212
+ <Button type={defaultBtn === 'Yes' ? 'primary' : undefined}
213
+ onClick={() => close(true)}>
214
+ Yes
215
+ </Button>
216
+ <Button type={defaultBtn === 'No' ? 'primary' : undefined}
217
+ onClick={() => close(false)}>
218
+ No
219
+ </Button>
220
+ </footer>
221
+ </div>
222
+ )),
223
+
224
+ loading: (title: string) => show({
225
+ title: title,
226
+ type: 'loading'
227
+ }),
228
+
229
+ info: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
230
+ title: title,
231
+ type: 'info',
232
+ content: content && <p>{content}</p>,
233
+ boutons,
234
+ ...options
235
+ }),
236
+
237
+ success: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
238
+ title: title,
239
+ type: 'success',
240
+ content: content && <p>{content}</p>,
241
+ boutons,
242
+ ...options
243
+ }),
244
+
245
+ warning: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
246
+ title: title,
247
+ type: 'warn',
248
+ content: content && <p>{content}</p>,
249
+ boutons,
250
+ ...options
251
+ }),
252
+
253
+ error: (...[title, content, boutons, options]: TToastShortcutArgs) => show({
254
+ title: title,
255
+ type: 'error',
256
+ content: content && <p>{content}</p>,
257
+ boutons,
258
+ ...options
259
+ }),
260
+ }
261
+
262
+ return instance;
263
+ }
264
+
265
+ /*----------------------------------
266
+ - COMPOSANT
267
+ ----------------------------------*/
268
+ import './index.less';
269
+ export default () => {
270
+
271
+ const app = useContext();
272
+
273
+ const [modals, setModals] = React.useState<ComponentChild[]>([]);
274
+ const [toasts, setToasts] = React.useState<ComponentChild[]>([]);
275
+
276
+ if (app.side === 'client') {
277
+ app.modal.setModals = setModals;
278
+ app.toast.setToasts = setToasts;
279
+ }
280
+
281
+ React.useEffect(() => {
282
+
283
+ console.log('Updated toast list');
284
+
285
+ const modals = document.querySelectorAll("#modals > .modal");
286
+ if (modals.length === 0)
287
+ return;
288
+
289
+ // Focus
290
+ const lastToast = modals[ modals.length - 1 ];
291
+ focusContent( lastToast );
292
+
293
+ });
294
+
295
+ return <>
296
+ {modals.length !== 0 ? (
297
+ <div id="modals">
298
+ {modals}
299
+ </div>
300
+ ) : null}
301
+
302
+ {toasts.length !== 0 ? (
303
+ <div id="toasts">
304
+ {toasts}
305
+ </div>
306
+ ) : null}
307
+ </>
308
+
309
+ }
@@ -0,0 +1,208 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import React from 'react';
7
+
8
+ // Composants globaux
9
+ import Button from '@client/components/Button';
10
+
11
+ /*----------------------------------
12
+ - TYPES
13
+ ----------------------------------*/
14
+ import { ComponentChild } from 'preact';
15
+
16
+ type funcBtns = () => void
17
+
18
+ type Boutons = { [label: string]: funcBtns }
19
+
20
+ /*----------------------------------
21
+ - CONTENU
22
+ ----------------------------------*/
23
+ export type Props = {
24
+
25
+ // Informations modale
26
+ type?: 'primary' | 'success' | 'warning' | 'error' | 'loading' | 'info',
27
+ cover?: string,
28
+ icon?: ComponentChild,
29
+ title?: string | ComponentChild,
30
+ className?: string,
31
+
32
+ children?: ComponentChild,
33
+ isToast?: boolean,
34
+ width?: number,
35
+
36
+ footer?: ComponentChild,
37
+ boutons?: Boutons | null, // nul = pas de footer
38
+ defaultBtn?: string,
39
+
40
+ prison?: boolean,
41
+ /* Hide after x seconds */autohide?: number | false,
42
+ close?: funcBtns,
43
+ onClose?: () => Promise<any>,
44
+ }
45
+
46
+ export default ({
47
+
48
+ // Content
49
+ type,
50
+ cover,
51
+ icon,
52
+ title,
53
+ className = '',
54
+
55
+ children,
56
+ isToast,
57
+ width,
58
+
59
+ footer,
60
+ boutons,
61
+ defaultBtn,
62
+
63
+ onClose,
64
+ close,
65
+ autohide,
66
+ prison,
67
+
68
+ }: Props) => {
69
+
70
+ // Boutons
71
+ if (footer === undefined && boutons !== null) {
72
+
73
+ // Default buttons
74
+ if (boutons === undefined || !Object.keys(boutons).length) {
75
+
76
+ // Toast: by default, if no buttons, we autohide after 3 seconds
77
+ if (autohide === undefined)
78
+ autohide = 3;
79
+
80
+ // If isToast, we show a default OK button
81
+ if (close && !isToast)
82
+ boutons = { 'Ok': () => close(true) };
83
+ else
84
+ boutons = null;
85
+
86
+ }
87
+
88
+ if (boutons !== null) {
89
+
90
+ const nbBtns = Object.keys(boutons).length;
91
+
92
+ footer = Object.entries(boutons).map(([texte, action]: [string, Function], index: number) => {
93
+ const dernier = nbBtns > 1 && index === nbBtns - 1;
94
+ return (
95
+ <Button
96
+ async
97
+ onClick={() => action()}
98
+ type={(defaultBtn === undefined ? dernier : (defaultBtn === texte)) ? 'primary' : undefined}
99
+ >
100
+ {texte}
101
+ </Button>
102
+ )
103
+ });
104
+ }
105
+ }
106
+
107
+ if (typeof icon === 'string')
108
+ icon = <i class={"svg-" + icon} />
109
+ else if (icon === undefined)
110
+ switch (type) {
111
+ case 'info':
112
+ icon = <i src="info-circle" />
113
+ break;
114
+ case 'success':
115
+ icon = <i src="check-circle" />
116
+ break;
117
+ case 'warning':
118
+ icon = <i src="exclamation-circle" />
119
+ break;
120
+ case 'error':
121
+ icon = <i src="times-circle" />
122
+ break;
123
+ case 'loading':
124
+ icon = <i src="spin" />
125
+ break;
126
+ }
127
+
128
+ // Autohide
129
+ if (isToast)
130
+ React.useEffect(() => {
131
+ if (autohide) {
132
+ const timeout = setTimeout(() => close(true), autohide * 1000);
133
+ return () => clearTimeout(timeout);
134
+ }
135
+ }, []);
136
+
137
+ let render = isToast ? (
138
+ <div class="card row bg dark" onClick={() => isToast && !prison && close(true)}>
139
+
140
+ {icon}
141
+
142
+ <div>
143
+
144
+ {typeof title === "string" ? (
145
+ <strong>{title}</strong>
146
+ ) : title}
147
+
148
+ {children}
149
+
150
+ </div>
151
+
152
+ </div>
153
+ ) : (
154
+ <div class={"card pd-2 col al-top " + className} style={width === undefined
155
+ ? {}
156
+ : { minWidth: width + "px", maxWidth: width + "px" }
157
+ }>
158
+
159
+ {(title || icon) && (
160
+ <header {...{
161
+ class: ('col ' + type),
162
+ style: cover ? {
163
+ backgroundImage: 'url(' + cover + ')'
164
+ } : undefined
165
+ }}>
166
+
167
+ {icon}
168
+
169
+ {typeof title === "string" ? (
170
+ <strong>{title}</strong>
171
+ ) : title}
172
+
173
+ {(!prison && close) && (
174
+ <Button class="close" icon="times" size="s" shape="pill" onClick={async () => {
175
+ if (typeof close === "function") {
176
+
177
+ if (onClose !== undefined)
178
+ onClose(false);
179
+ else
180
+ close(false);
181
+ }
182
+ }} />
183
+ )}
184
+
185
+ </header>
186
+ )}
187
+
188
+ {children && (
189
+ <div class="col content">
190
+
191
+ {children}
192
+
193
+ </div>
194
+ )}
195
+
196
+ {footer && (
197
+ <footer class="row fill actions">
198
+
199
+ {footer}
200
+
201
+ </footer>
202
+ )}
203
+
204
+ </div>
205
+ )
206
+
207
+ return render;
208
+ }
@@ -0,0 +1,151 @@
1
+
2
+ @c1: #6c5dd3; // Should be darker than c1
3
+ @spacing: 1.2em;
4
+ @toast-zindex: 200;
5
+ @radius: 1rem;
6
+
7
+ #modals,
8
+ #toasts {
9
+
10
+ z-index: @toast-zindex;
11
+
12
+ display: flex;
13
+ flex-direction: column;
14
+ align-items: center;
15
+ justify-content: flex-end;
16
+ gap: @spacing;
17
+ padding: @spacing;
18
+
19
+ &,
20
+ > .modal {
21
+ position: fixed;
22
+ left: 0px;
23
+ right: 0px;
24
+ bottom: 0px;
25
+ max-height: 100vh;
26
+ }
27
+
28
+ // Toast
29
+ > .card,
30
+ // Modal (pas forcément une card quand bcp de contenu. Ex: inventory)
31
+ > .modal > div {
32
+
33
+ .btn.close {
34
+ position: absolute;
35
+ top: @spacing;
36
+ right: @spacing;
37
+
38
+ // Vire le margin-top créé par .col > *
39
+ margin-top: 0;
40
+ }
41
+ }
42
+ }
43
+
44
+ #modals {
45
+
46
+ &,
47
+ > .modal {
48
+ top: 0px;
49
+ }
50
+
51
+ > .modal {
52
+
53
+ @modal-zindex: 9;
54
+
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ justify-content: center;
59
+ gap: @spacing;
60
+ z-index: @modal-zindex;
61
+
62
+ background: fade(#000, 20%);
63
+ border-radius: @radius;
64
+
65
+ // Pour les animations (ex: conffetis
66
+ > canvas {
67
+ position: absolute;
68
+ top: 0; left: 0;
69
+ width: 100%;
70
+ height: 100%;
71
+ z-index: 0;
72
+ }
73
+
74
+ > .card {
75
+
76
+ position: relative;
77
+ min-width: 300px;
78
+ max-height: 99vh;
79
+ max-width: 99vw;
80
+ width: 400px; // Default width
81
+ box-shadow: none;
82
+ overflow-y: auto;
83
+
84
+ // Pas d'anim quand pas card,
85
+ // Car peut contenir bcp d'elemnts => performance
86
+ animation: aff-modale 0.1s ease;
87
+ @keyframes aff-modale {
88
+ 0% {
89
+ opacity: 0;
90
+ transform: scale(0.8);
91
+ }
92
+ 100% {
93
+ opacity: 1;
94
+ transform: scale(1);
95
+ }
96
+ }
97
+
98
+ > header {
99
+ > i {
100
+ color: @c1;
101
+ font-size: 3em;
102
+ }
103
+ }
104
+
105
+ z-index: 1; // Au dessus de l'animation canvas
106
+ }
107
+ }
108
+ }
109
+
110
+ #toasts {
111
+ // Toast
112
+ > .card {
113
+
114
+ text-align: left;
115
+ max-width: 450px;
116
+ z-index: 999;
117
+ cursor: pointer;
118
+ padding-right: @spacing * 1.5;
119
+
120
+ animation: aff-toast 0.1s ease;
121
+ @keyframes aff-toast {
122
+ 0% {
123
+ opacity: 0.5;
124
+ transform: scale(0.5);
125
+ }
126
+ 100% {
127
+ opacity: 1;
128
+ transform: scale(1);
129
+ }
130
+ }
131
+
132
+ > i {
133
+ color: @c1;
134
+ flex: 0 0 1em;
135
+ }
136
+
137
+ h2 {
138
+ font-size: 1em;
139
+ }
140
+
141
+ p {
142
+ text-align: left;
143
+ }
144
+ }
145
+ }
146
+
147
+ // Selecteur moins profond pour que les clases utilitaires (w-a-x) soient prioritaires
148
+ .modal > .card {
149
+ // Modal content should always be whiteys adapt from content width
150
+ //max-width: 500px;
151
+ }