5htp-core 0.6.0 → 0.6.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 (48) hide show
  1. package/client/app/component.tsx +1 -0
  2. package/client/assets/css/colors.less +46 -25
  3. package/client/assets/css/components/button.less +14 -5
  4. package/client/assets/css/components/card.less +5 -10
  5. package/client/assets/css/components/mantine.less +6 -5
  6. package/client/assets/css/components/table.less +1 -1
  7. package/client/assets/css/text/icons.less +1 -1
  8. package/client/assets/css/text/text.less +4 -0
  9. package/client/assets/css/utils/borders.less +1 -1
  10. package/client/assets/css/utils/layouts.less +8 -5
  11. package/client/components/Button.tsx +20 -17
  12. package/client/components/Checkbox.tsx +6 -1
  13. package/client/components/ConnectedInput.tsx +34 -0
  14. package/client/components/DropDown.tsx +21 -4
  15. package/client/components/Input.tsx +2 -2
  16. package/client/components/Rte/Editor.tsx +23 -9
  17. package/client/components/Rte/ToolbarPlugin/ElementFormat.tsx +1 -1
  18. package/client/components/Rte/ToolbarPlugin/index.tsx +272 -183
  19. package/client/components/Rte/currentEditor.ts +31 -2
  20. package/client/components/Rte/index.tsx +3 -0
  21. package/client/components/Rte/plugins/FloatingTextFormatToolbarPlugin/index.tsx +4 -1
  22. package/client/components/Select.tsx +29 -16
  23. package/client/components/Table/index.tsx +27 -11
  24. package/client/components/containers/Popover/index.tsx +21 -4
  25. package/client/components/index.ts +4 -2
  26. package/client/services/router/index.tsx +7 -5
  27. package/common/errors/index.tsx +27 -3
  28. package/common/router/index.ts +4 -1
  29. package/common/utils/rte.ts +183 -0
  30. package/package.json +3 -2
  31. package/server/app/container/console/index.ts +62 -42
  32. package/server/app/container/index.ts +4 -0
  33. package/server/app/service/index.ts +4 -2
  34. package/server/services/auth/index.ts +28 -14
  35. package/server/services/auth/router/index.ts +1 -1
  36. package/server/services/auth/router/request.ts +4 -4
  37. package/server/services/email/index.ts +8 -51
  38. package/server/services/prisma/Facet.ts +118 -0
  39. package/server/services/prisma/index.ts +24 -0
  40. package/server/services/router/http/index.ts +0 -2
  41. package/server/services/router/index.ts +220 -86
  42. package/server/services/router/response/index.ts +0 -15
  43. package/server/utils/rte.ts +21 -132
  44. package/types/global/utils.d.ts +4 -22
  45. package/types/icons.d.ts +1 -1
  46. package/server/services/email/service.json +0 -6
  47. package/server/services/email/templates.ts +0 -49
  48. package/server/services/email/transporter.ts +0 -31
@@ -70,6 +70,7 @@ export default function App({ context }: {
70
70
  Menu: { defaultProps: { size: 'md' } },
71
71
  MenuItem: { defaultProps: { size: 'md' } },
72
72
  Autocomplete: { defaultProps: { size: 'md' } },
73
+ TagsInput: { defaultProps: { size: 'md' } },
73
74
  // Add any others you use...
74
75
  },
75
76
  }} withGlobalStyles withNormalizeCSS>
@@ -14,7 +14,7 @@
14
14
 
15
15
  @greyTheme: {
16
16
  alpha: false;
17
- background: #F3F3F3;
17
+ background: #F9F9F9;
18
18
  foreground: #4D4D4D;
19
19
  accent1: @c1;
20
20
  accent2: @c2;
@@ -75,6 +75,14 @@
75
75
 
76
76
 
77
77
  @accentTheme: {
78
+ alpha: false;
79
+ background: @c1;
80
+ foreground: #fff;
81
+ accent1: #fff;
82
+ accent2: #fff;;
83
+ }
84
+
85
+ @accentLightTheme: {
78
86
  alpha: false;
79
87
  background: #EAE8F9;
80
88
  foreground: @c1 - #444;
@@ -87,11 +95,15 @@
87
95
  .apply-theme(@primaryTheme);
88
96
  }
89
97
 
90
- .bg.accent,
91
- .btn.bg.col.active {
98
+ .bg.accent {
92
99
  .apply-theme(@accentTheme);
93
100
  }
94
101
 
102
+ .bg.accent.light,
103
+ .btn.bg.col.active {
104
+ .apply-theme(@accentLightTheme);
105
+ }
106
+
95
107
  .bg.grey {
96
108
  .apply-theme(@greyTheme, @whiteTheme);
97
109
  }
@@ -134,21 +146,30 @@
134
146
  border: 1px solid var(--cLine);
135
147
  }
136
148
 
137
- .bg.color1 { .color-theme(#0066ff ); }
138
- .bg.color2 { .color-theme(#00e6da ); }
139
- .bg.color3 { .color-theme(#00e417 ); }
140
- .bg.color4 { .color-theme(#ffb700 ); }
141
- .bg.color5 { .color-theme(#eb4a00 ); }
142
- .bg.color6 { .color-theme(#e500ac ); }
143
- .bg.color7 { .color-theme(#6200ff ); }
149
+ /* --- vivid swatches --- */
150
+ .bg.color1 { .color-theme(#1fb4ff ); } // bright cyan
151
+ .bg.color2 { .color-theme(#ff6a1a ); } // vivid orange
152
+ .bg.color3 { .color-theme(#f52ff9 ); } // hot magenta
153
+ .bg.color4 { .color-theme(#962eff ); } // electric violet
154
+ .bg.color5 { .color-theme(#23ff6e ); } // neon green
155
+ .bg.color6 { .color-theme(#ffde1f ); } // vibrant yellow
156
+ .bg.color7 { .color-theme(#ff145d ); } // punch‑red
157
+ .bg.color8 { .color-theme(#12fff9 ); } // aqua glow
158
+ .bg.color9 { .color-theme(#ffba1f ); } // golden amber
159
+ .bg.color10 { .color-theme(#1eff5e ); } // lime burst
160
+
161
+ /* --- matching light versions (≈20 % tint of base) --- */
162
+ .bg.light1 { .color-theme(#d2f0ff ); }
163
+ .bg.light2 { .color-theme(#ffe1d1 ); }
164
+ .bg.light3 { .color-theme(#fdd5fe ); }
165
+ .bg.light4 { .color-theme(#ead5ff ); }
166
+ .bg.light5 { .color-theme(#d3ffe2 ); }
167
+ .bg.light6 { .color-theme(#fff8d2 ); }
168
+ .bg.light7 { .color-theme(#ffd0df ); }
169
+ .bg.light8 { .color-theme(#d0fffe ); }
170
+ .bg.light9 { .color-theme(#fff1d2 ); }
171
+ .bg.light10 { .color-theme(#d2ffdf ); }
144
172
 
145
- .bg.light1 { .color-theme(#cce0fe ); }
146
- .bg.light2 { .color-theme(#c7f0ee ); }
147
- .bg.light3 { .color-theme(#cef5d2 ); }
148
- .bg.light4 { .color-theme(#feeab6 ); }
149
- .bg.light5 { .color-theme(#ffdccc ); }
150
- .bg.light6 { .color-theme(#fcccf0 ); }
151
- .bg.light7 { .color-theme(#e2d5f7 ); }
152
173
 
153
174
  .bg.success {
154
175
  box-shadow: none;
@@ -156,10 +177,10 @@
156
177
 
157
178
  .apply-theme({
158
179
  alpha: false;
159
- background: #D7FEEE;
160
- foreground: darken( #D7FEEE, 80% );
161
- accent1: #111;
162
- accent2: #111;
180
+ background: #179e50;
181
+ foreground: #fff;
182
+ accent1: #fff;
183
+ accent2: #fff;
163
184
  });
164
185
 
165
186
  &.light {
@@ -215,10 +236,10 @@
215
236
 
216
237
  .apply-theme({
217
238
  alpha: false;
218
- background: lighten( @cInfo, 50% );
219
- foreground: darken( @cInfo, 50% );
220
- accent1: #111;
221
- accent2: #111;
239
+ background: #6C5DD3;
240
+ foreground: #fff;
241
+ accent1: #fff;
242
+ accent2: #fff;
222
243
  });
223
244
 
224
245
  &.light {
@@ -21,7 +21,7 @@
21
21
  min-height: @sizeComponent;
22
22
 
23
23
  // Shape
24
- border-radius: @radius;
24
+ border-radius: @sizeComponent / 2; // Default = pill
25
25
  border: none;
26
26
 
27
27
  // Text
@@ -117,7 +117,7 @@
117
117
  }
118
118
 
119
119
  > i {
120
- font-size: 1.2em;
120
+ font-size: 1.1em;
121
121
  color: inherit;
122
122
  }
123
123
 
@@ -208,8 +208,11 @@
208
208
  }
209
209
  }
210
210
 
211
- &.pill {
212
- border-radius: @sizeComponent / 2;
211
+ &.rect,
212
+ &.col,
213
+ .col.menu > &,
214
+ .col.menu > li > & {
215
+ border-radius: @radius;
213
216
  }
214
217
 
215
218
  &.link {
@@ -242,7 +245,6 @@
242
245
 
243
246
  // Give less imortance to buttons which are in lists
244
247
  color: var(--cTxtBase);
245
- padding: 0 1em; // Row display = more condensed
246
248
 
247
249
  &.active,
248
250
  &:hover {
@@ -290,6 +292,13 @@
290
292
  }
291
293
  }
292
294
 
295
+ .row {
296
+ &.menu > .btn:not(.col),
297
+ &.menu > li > .btn:not(.col) {
298
+ padding: 0 1em; // Row display = more condensed
299
+ }
300
+ }
301
+
293
302
  .submenu.card {
294
303
  animation: aff-submenu 0.1s ease;
295
304
  @keyframes aff-submenu {
@@ -25,10 +25,14 @@
25
25
  z-index: 10;
26
26
  }
27
27
 
28
- &.minimal {
28
+ &.minimal, &.flat {
29
29
  box-shadow: none;
30
30
  }
31
31
 
32
+ &.flat {
33
+ border: none;
34
+ }
35
+
32
36
  &.row {
33
37
  padding: @cardPadding @cardPaddingLong;
34
38
 
@@ -97,15 +101,6 @@
97
101
  }
98
102
  }
99
103
 
100
- &.active {
101
-
102
- box-shadow: 0 0 0 3px @c1;
103
-
104
- > * {
105
- --cTxtImportant: @c1;
106
- }
107
- }
108
-
109
104
  /*----------------------------------
110
105
  - VARIANTS
111
106
  ----------------------------------*/
@@ -63,13 +63,14 @@
63
63
 
64
64
  .mantine-TextInput-input,
65
65
  .mantine-Input-input {
66
-
67
66
  border: solid 1px var(--cLine) !important;
67
+ }
68
68
 
69
- &:focus {
70
- border-color: @c1 !important;
71
- box-shadow: 0 0 0 4px fade(@c1, 20%) !important;
72
- }
69
+ .card.active,
70
+ .mantine-TextInput-input:focus,
71
+ .mantine-Input-input:focus {
72
+ border: solid 1px @c1 !important;
73
+ box-shadow: 0 0 0 4px fade(@c1, 20%) !important;
73
74
  }
74
75
 
75
76
  .mantine-MultiSelect-pill {
@@ -61,7 +61,7 @@ table {
61
61
  position: sticky;
62
62
  background: var(--cBg);
63
63
  white-space: break-spaces;
64
- z-index: 1;
64
+ z-index: 2;
65
65
 
66
66
  &:first-child {
67
67
  left: 0;
@@ -39,7 +39,7 @@ i {
39
39
  &.solid {
40
40
  color: var(--cTxtAccent2);
41
41
  background: var(--cBg);
42
- border-radius: @radius;
42
+ border-radius: 50%;
43
43
 
44
44
  // Normla size must fit inside a normal fit element
45
45
  width: @sizeComponent * 0.75;
@@ -105,6 +105,10 @@ strong.number {
105
105
  line-height: 1em;
106
106
  }
107
107
 
108
+ .nowrap {
109
+ white-space: nowrap;
110
+ }
111
+
108
112
  em {
109
113
  /*font-style: normal;
110
114
  position: relative;
@@ -12,4 +12,4 @@
12
12
  .bl-2, .bh-2 { border-left: solid 1px var(--cLine); }
13
13
 
14
14
  .b-0 { border: none; }
15
- .b-1 { border-top: solid 1px var(--cLine); }
15
+ .b-1 { border: solid 1px var(--cLine); }
@@ -31,6 +31,9 @@
31
31
  -ms-overflow-style: none; /* IE and Edge */
32
32
  scrollbar-width: none; /* Firefox */
33
33
 
34
+ // Don't fit scrollable containers to their content
35
+ min-height: 0;
36
+
34
37
  /* For Chrome, Safari, and other WebKit-based browsers */
35
38
  &::-webkit-scrollbar {
36
39
  display: none;
@@ -42,6 +45,11 @@
42
45
  display: flex;
43
46
  flex-wrap: nowrap;
44
47
 
48
+ > * {
49
+ // Avoids flexbox childrens to overflw parent
50
+ min-width: 0;
51
+ }
52
+
45
53
  &.scrollable {
46
54
  > * {
47
55
  min-width: fit-content;
@@ -176,11 +184,6 @@
176
184
  .row,
177
185
  .col {
178
186
 
179
- > * {
180
- // Avoids flexbox childrens to overflw parent
181
- min-width: 0;
182
- }
183
-
184
187
  &.sp-btw { justify-content: space-between; }
185
188
  &.sp-ar { justify-content: space-around; }
186
189
  &.wrap { flex-wrap: wrap; }
@@ -28,7 +28,7 @@ export type Props = {
28
28
 
29
29
  tag?: "a" | "button",
30
30
  type?: 'guide' | 'primary' | 'secondary' | 'link',
31
- shape?: 'default' | 'icon' | 'tile' | 'pill',
31
+ shape?: 'default' | 'icon' | 'tile' | 'pill' | 'custom',
32
32
  size?: TComponentSize,
33
33
  class?: string,
34
34
 
@@ -236,9 +236,19 @@ export default ({
236
236
  if (disabled)
237
237
  return false;
238
238
 
239
+ // Custom event
240
+ if (props.onClick !== undefined) {
241
+
242
+ const returned = props.onClick(e);
243
+ if (async && returned?.then) {
244
+ setLoading(true);
245
+ returned.finally(() => setLoading(false));
246
+ }
247
+ }
248
+
239
249
  // Link
240
250
  let nativeEvent: boolean = false;
241
- if ('link' in props) {
251
+ if (('link' in props) && !e.defaultPrevented) {
242
252
 
243
253
  // Nouvelle fenetre = event par defaut
244
254
  if (props.target === '_blank') {
@@ -257,27 +267,20 @@ export default ({
257
267
  }
258
268
  }
259
269
 
260
- // Custom event
261
- if (props.onClick !== undefined) {
262
-
263
- const returned = props.onClick(e);
264
- if (async && returned?.then) {
265
- setLoading(true);
266
- returned.finally(() => setLoading(false));
267
- }
268
- }
269
-
270
270
  if (!nativeEvent) {
271
271
  e.preventDefault();
272
272
  return false;
273
273
  }
274
274
  }}>
275
275
  {prefix}
276
- {children && (
277
- <span class={"label"}>
278
- {children}
279
- </span>
280
- )}
276
+ {children === undefined
277
+ ? null
278
+ : shape === 'custom'
279
+ ? children : (
280
+ <span class={"label"}>
281
+ {children}
282
+ </span>
283
+ )}
281
284
  {suffix}
282
285
  </Tag>
283
286
  )
@@ -26,7 +26,11 @@ export default (initProps: Props) => {
26
26
  - INIT
27
27
  ----------------------------------*/
28
28
 
29
- const [{ title, onChange }, { errors, required, ...props }] = useMantineInput<Props>(initProps);
29
+ const [{ title, onChange, value }, { errors, required, ...props }] = useMantineInput<Props>(initProps);
30
+
31
+ if (initProps.title === 'Exact match')
32
+ console.log("Checkbox", initProps, props);
33
+
30
34
 
31
35
  /*----------------------------------
32
36
  - RENDER
@@ -36,6 +40,7 @@ export default (initProps: Props) => {
36
40
  label={title}
37
41
  error={errors?.join(', ')}
38
42
  required={required}
43
+ checked={value}
39
44
  {...props}
40
45
  onChange={e => onChange?.(e.target.checked)}
41
46
  />
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+
3
+ import type { Choice } from '@client/components/Select';
4
+
5
+ const ConnectedInput = <TComponent extends React.ComponentType<any>>({
6
+ component: Component, data: dataInit, ...props
7
+ }: {
8
+ component: TComponent,
9
+ data?: Choice[] | ((search?: string) => Promise<Choice[]>),
10
+ } & Omit<React.ComponentProps<TComponent>, 'data' | 'onSearchChange'>) => {
11
+
12
+ const [data, setData] = React.useState<Choice[]>([]);
13
+ const [search, setSearch] = React.useState<string>('');
14
+
15
+ React.useEffect(() => {
16
+
17
+ if (!dataInit) return;
18
+ if (Array.isArray(dataInit))
19
+ setData(dataInit);
20
+ else
21
+ dataInit(search).then(setData);
22
+
23
+ }, [dataInit, search]);
24
+
25
+ return (
26
+ <Component
27
+ {...props}
28
+ data={data}
29
+ onSearchChange={setSearch}
30
+ />
31
+ )
32
+ }
33
+
34
+ export default ConnectedInput;
@@ -5,8 +5,9 @@
5
5
  // Npm
6
6
  import React from 'react';
7
7
  import { JSX, ComponentChild } from 'preact';
8
- import { Button, Menu, MenuProps } from '@mantine/core';
9
- import { Props as ButtonProps } from './Button';
8
+ import { Menu, MenuProps } from '@mantine/core';
9
+ import Button, { Props as ButtonProps } from './Button';
10
+ import Popover, { Props as PopoverProps } from './containers/Popover';
10
11
 
11
12
  // Core libs
12
13
  import { useMantineInput, InputBaseProps } from './utils';
@@ -16,16 +17,32 @@ import { useMantineInput, InputBaseProps } from './utils';
16
17
  ----------------------------------*/
17
18
  export type Props = ButtonProps & {
18
19
  menuProps?: MenuProps,
19
- label: ComponentChild,
20
+ label: ComponentChild,
21
+ popover?: PopoverProps,
20
22
  }
21
23
 
22
24
  /*----------------------------------
23
25
  - COMPOSANT
24
26
  ----------------------------------*/
25
27
  export default ({
26
- label, children,
28
+ label, children, popover = {},
27
29
  menuProps = {}, size, icon, ...btnProps
28
30
  }: Props) => {
31
+ return (
32
+ <Popover {...popover} content={(
33
+ <div class="card bg white col menu">
34
+ {children}
35
+ </div>
36
+ )}>
37
+ <Button {...btnProps}
38
+ size={size}
39
+ suffix={<i src="angle-down" />}
40
+ icon={icon}
41
+ >
42
+ {label}
43
+ </Button>
44
+ </Popover>
45
+ )
29
46
  return (
30
47
  <Menu {...menuProps} size={size}>
31
48
  <Menu.Target>
@@ -61,8 +61,8 @@ export default (initProps: Props) => {
61
61
  props.min = props.min ?? 0;
62
62
  } else if (props.type === 'longtext' && typeof document !== 'undefined') {
63
63
  Component = Textarea;
64
- props.autosize = true;
65
- props.minRows = 2;
64
+ props.autosize = props.autosize || true;
65
+ props.minRows = props.minRows || 2;
66
66
  } else {
67
67
  Component = TextInput;
68
68
  }
@@ -73,6 +73,7 @@ import YouTubePlugin from './plugins/YouTubePlugin';
73
73
  // Core libs
74
74
  import editorNodes from '@common/data/rte/nodes';
75
75
  import type { Props as TRteProps } from '.';
76
+ import type { LexicalState } from '@common/utils/rte';
76
77
 
77
78
  // Special componets
78
79
  import ExampleTheme from './themes/PlaygroundEditorTheme';
@@ -111,6 +112,8 @@ export default ({ value, setValue, props }: {
111
112
  let {
112
113
  // Decoration
113
114
  title,
115
+ toolbar,
116
+ decorateText = true,
114
117
  // Actions
115
118
  preview = true
116
119
  } = props;
@@ -145,7 +148,7 @@ export default ({ value, setValue, props }: {
145
148
  }
146
149
  }, [isPreview]);
147
150
 
148
- const renderPreview = async (value: {} | undefined) => {
151
+ const renderPreview = async (value: LexicalState | undefined) => {
149
152
 
150
153
  if (!value)
151
154
  return '';
@@ -165,7 +168,7 @@ export default ({ value, setValue, props }: {
165
168
  <i src="spin" />
166
169
  </div>
167
170
  ) : (
168
- <div class="preview reading h-1-4 scrollable col clickable"
171
+ <div class={"preview h-1-4 scrollable clickable" + (decorateText ? ' reading col' : '')}
169
172
  onClick={() => setIsPreview(false)}
170
173
  dangerouslySetInnerHTML={{ __html: html }} />
171
174
  )
@@ -240,13 +243,13 @@ export default ({ value, setValue, props }: {
240
243
  theme: ExampleTheme,
241
244
  }}>
242
245
  <div className="editor-container">
243
- <ToolbarPlugin setIsLinkEditMode={setIsLinkEditMode} />
246
+ <ToolbarPlugin setIsLinkEditMode={setIsLinkEditMode} display={toolbar} />
244
247
  <div className="editor-inner">
245
248
  <RichTextPlugin
246
249
  contentEditable={
247
250
  <div className="editor" ref={onRef}>
248
251
  <ContentEditable
249
- className="editor-input reading col"
252
+ className={"editor-input" + (decorateText ? ' reading col' : '')}
250
253
  aria-placeholder={"Type text here ..."}
251
254
  placeholder={
252
255
  <div className="editor-placeholder">Type text here ...</div>
@@ -277,7 +280,15 @@ export default ({ value, setValue, props }: {
277
280
  <SpeechToTextPlugin />
278
281
  <AutoLinkPlugin />
279
282
  <CodeHighlightPlugin />
280
- <ListPlugin />
283
+
284
+ {toolbar?.insert !== false && <>
285
+
286
+ {(toolbar?.insert === true || toolbar?.insert?.list !== false) && (
287
+ <ListPlugin />
288
+ )}
289
+
290
+ </>}
291
+
281
292
  <CheckListPlugin />
282
293
  <ListMaxIndentLevelPlugin maxDepth={7} />
283
294
  <TablePlugin
@@ -317,10 +328,13 @@ export default ({ value, setValue, props }: {
317
328
  cellMerge={true}
318
329
  />
319
330
  <TableHoverActionsPlugin anchorElem={floatingAnchorElem} />
320
- <FloatingTextFormatToolbarPlugin
321
- anchorElem={floatingAnchorElem}
322
- setIsLinkEditMode={setIsLinkEditMode}
323
- />
331
+
332
+ {toolbar?.formatting !== false && (
333
+ <FloatingTextFormatToolbarPlugin
334
+ anchorElem={floatingAnchorElem}
335
+ setIsLinkEditMode={setIsLinkEditMode}
336
+ />
337
+ )}
324
338
  </>
325
339
  )}
326
340
 
@@ -92,7 +92,7 @@ export default function ElementFormatDropdown({
92
92
  popover={{ tag: 'li' }}
93
93
  >
94
94
  {FormatOptions.map((option) => (
95
- <Button icon={isRTL ? option.iconRTL : option.icon}
95
+ <Button size="s" icon={isRTL ? option.iconRTL : option.icon}
96
96
  onClick={() => {
97
97
  if (option.value === 'indent')
98
98
  editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);