5htp-core 0.4.7 → 0.4.8

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 (38) hide show
  1. package/package.json +6 -1
  2. package/src/client/assets/css/text/titres.less +1 -1
  3. package/src/client/assets/css/utils/layouts.less +8 -2
  4. package/src/client/components/Dialog/Manager.tsx +65 -29
  5. package/src/client/components/Dialog/card.tsx +3 -1
  6. package/src/client/components/Dialog/index.less +1 -2
  7. package/src/client/components/Select/ChoiceSelector.tsx +7 -5
  8. package/src/client/components/Select/index.tsx +162 -130
  9. package/src/client/components/index.ts +2 -1
  10. package/src/client/components/inputv3/Rte/ExampleTheme.tsx +42 -0
  11. package/src/client/components/inputv3/Rte/ToolbarPlugin.tsx +167 -0
  12. package/src/client/components/inputv3/Rte/icons/LICENSE.md +5 -0
  13. package/src/client/components/inputv3/Rte/icons/arrow-clockwise.svg +4 -0
  14. package/src/client/components/inputv3/Rte/icons/arrow-counterclockwise.svg +4 -0
  15. package/src/client/components/inputv3/Rte/icons/journal-text.svg +5 -0
  16. package/src/client/components/inputv3/Rte/icons/justify.svg +3 -0
  17. package/src/client/components/inputv3/Rte/icons/text-center.svg +3 -0
  18. package/src/client/components/inputv3/Rte/icons/text-left.svg +3 -0
  19. package/src/client/components/inputv3/Rte/icons/text-paragraph.svg +3 -0
  20. package/src/client/components/inputv3/Rte/icons/text-right.svg +3 -0
  21. package/src/client/components/inputv3/Rte/icons/type-bold.svg +3 -0
  22. package/src/client/components/inputv3/Rte/icons/type-italic.svg +3 -0
  23. package/src/client/components/inputv3/Rte/icons/type-strikethrough.svg +3 -0
  24. package/src/client/components/inputv3/Rte/icons/type-underline.svg +3 -0
  25. package/src/client/components/inputv3/Rte/index.tsx +163 -0
  26. package/src/client/components/inputv3/Rte/style.less +428 -0
  27. package/src/client/components/inputv3/base.less +20 -33
  28. package/src/client/components/inputv3/base.tsx +36 -2
  29. package/src/client/components/inputv3/index.tsx +45 -44
  30. package/src/common/data/rte/index.ts +66 -0
  31. package/src/common/data/rte/nodes.ts +20 -0
  32. package/src/common/validation/validators.ts +46 -1
  33. package/src/server/services/auth/index.ts +0 -2
  34. package/src/server/services/database/index.ts +1 -1
  35. package/src/client/components/input/Rte/index.less +0 -13
  36. package/src/client/components/input/Rte/index.tsx +0 -143
  37. package/src/client/components/input/Rte/selection.ts +0 -34
  38. package/src/common/data/rte.tsx +0 -11
@@ -0,0 +1,428 @@
1
+ .input.rte {
2
+ .other h2 {
3
+ font-size: 18px;
4
+ color: #444;
5
+ margin-bottom: 7px;
6
+ }
7
+
8
+ .other a {
9
+ color: #777;
10
+ text-decoration: underline;
11
+ font-size: 14px;
12
+ }
13
+
14
+ .other ul {
15
+ padding: 0;
16
+ margin: 0;
17
+ list-style-type: none;
18
+ }
19
+
20
+ .App {
21
+ font-family: sans-serif;
22
+ text-align: center;
23
+ }
24
+
25
+ h1 {
26
+ font-size: 24px;
27
+ color: #333;
28
+ }
29
+
30
+ .ltr {
31
+ text-align: left;
32
+ }
33
+
34
+ .rtl {
35
+ text-align: right;
36
+ }
37
+
38
+ .editor-container {
39
+ margin: 0;
40
+ color: #000;
41
+ position: relative;
42
+ line-height: 20px;
43
+ font-weight: 400;
44
+ text-align: left;
45
+ border-top-left-radius: 10px;
46
+ border-top-right-radius: 10px;
47
+ }
48
+
49
+ .editor-inner {
50
+ background: #fff;
51
+ position: relative;
52
+ }
53
+
54
+ .editor-input {
55
+ min-height: 150px;
56
+ resize: none;
57
+ font-size: 15px;
58
+ caret-color: rgb(5, 5, 5);
59
+ position: relative;
60
+ tab-size: 1;
61
+ outline: 0;
62
+ caret-color: #444;
63
+ }
64
+
65
+ .editor-placeholder {
66
+ color: #999;
67
+ overflow: hidden;
68
+ position: absolute;
69
+ text-overflow: ellipsis;
70
+ top: 3px;
71
+ left: 0px;
72
+ font-size: 15px;
73
+ user-select: none;
74
+ display: inline-block;
75
+ pointer-events: none;
76
+ }
77
+
78
+ .editor-text-bold {
79
+ font-weight: bold;
80
+ }
81
+
82
+ .editor-text-italic {
83
+ font-style: italic;
84
+ }
85
+
86
+ .editor-text-underline {
87
+ text-decoration: underline;
88
+ }
89
+
90
+ .editor-text-strikethrough {
91
+ text-decoration: line-through;
92
+ }
93
+
94
+ .editor-text-underlineStrikethrough {
95
+ text-decoration: underline line-through;
96
+ }
97
+
98
+ .editor-text-code {
99
+ background-color: rgb(240, 242, 245);
100
+ padding: 1px 0.25rem;
101
+ font-family: Menlo, Consolas, Monaco, monospace;
102
+ font-size: 94%;
103
+ }
104
+
105
+ .editor-link {
106
+ color: rgb(33, 111, 219);
107
+ text-decoration: none;
108
+ }
109
+
110
+ .tree-view-output {
111
+ display: block;
112
+ background: #222;
113
+ color: #fff;
114
+ padding: 5px;
115
+ font-size: 12px;
116
+ white-space: pre-wrap;
117
+ margin: 1px auto 10px auto;
118
+ max-height: 250px;
119
+ position: relative;
120
+ border-bottom-left-radius: 10px;
121
+ border-bottom-right-radius: 10px;
122
+ overflow: auto;
123
+ line-height: 14px;
124
+ }
125
+
126
+ .editor-code {
127
+ background-color: rgb(240, 242, 245);
128
+ font-family: Menlo, Consolas, Monaco, monospace;
129
+ display: block;
130
+ padding: 8px 8px 8px 52px;
131
+ line-height: 1.53;
132
+ font-size: 13px;
133
+ margin: 0;
134
+ margin-top: 8px;
135
+ margin-bottom: 8px;
136
+ tab-size: 2;
137
+ /* white-space: pre; */
138
+ overflow-x: auto;
139
+ position: relative;
140
+ }
141
+
142
+ .editor-code:before {
143
+ content: attr(data-gutter);
144
+ position: absolute;
145
+ background-color: #eee;
146
+ left: 0;
147
+ top: 0;
148
+ border-right: 1px solid #ccc;
149
+ padding: 8px;
150
+ color: #777;
151
+ white-space: pre-wrap;
152
+ text-align: right;
153
+ min-width: 25px;
154
+ }
155
+
156
+ .editor-code:after {
157
+ content: attr(data-highlight-language);
158
+ top: 0;
159
+ right: 3px;
160
+ padding: 3px;
161
+ font-size: 10px;
162
+ text-transform: uppercase;
163
+ position: absolute;
164
+ color: rgba(0, 0, 0, 0.5);
165
+ }
166
+
167
+ .editor-tokenComment {
168
+ color: slategray;
169
+ }
170
+
171
+ .editor-tokenPunctuation {
172
+ color: #999;
173
+ }
174
+
175
+ .editor-tokenProperty {
176
+ color: #905;
177
+ }
178
+
179
+ .editor-tokenSelector {
180
+ color: #690;
181
+ }
182
+
183
+ .editor-tokenOperator {
184
+ color: #9a6e3a;
185
+ }
186
+
187
+ .editor-tokenAttr {
188
+ color: #07a;
189
+ }
190
+
191
+ .editor-tokenVariable {
192
+ color: #e90;
193
+ }
194
+
195
+ .editor-tokenFunction {
196
+ color: #dd4a68;
197
+ }
198
+
199
+ .editor-paragraph {
200
+ margin: 0;
201
+ margin-bottom: 8px;
202
+ position: relative;
203
+ }
204
+
205
+ .editor-paragraph:last-child {
206
+ margin-bottom: 0;
207
+ }
208
+
209
+ .editor-heading-h1 {
210
+ font-size: 24px;
211
+ color: rgb(5, 5, 5);
212
+ font-weight: 400;
213
+ margin: 0;
214
+ margin-bottom: 12px;
215
+ padding: 0;
216
+ }
217
+
218
+ .editor-heading-h2 {
219
+ font-size: 15px;
220
+ color: rgb(101, 103, 107);
221
+ font-weight: 700;
222
+ margin: 0;
223
+ margin-top: 10px;
224
+ padding: 0;
225
+ text-transform: uppercase;
226
+ }
227
+
228
+ .editor-quote {
229
+ margin: 0;
230
+ margin-left: 20px;
231
+ font-size: 15px;
232
+ color: rgb(101, 103, 107);
233
+ border-left-color: rgb(206, 208, 212);
234
+ border-left-width: 4px;
235
+ border-left-style: solid;
236
+ padding-left: 16px;
237
+ }
238
+
239
+ .editor-list-ol {
240
+ padding: 0;
241
+ margin: 0;
242
+ margin-left: 16px;
243
+ }
244
+
245
+ .editor-list-ul {
246
+ padding: 0;
247
+ margin: 0;
248
+ margin-left: 16px;
249
+ }
250
+
251
+ .editor-listitem {
252
+ margin: 8px 32px 8px 32px;
253
+ }
254
+
255
+ .editor-nested-listitem {
256
+ list-style-type: none;
257
+ }
258
+
259
+ pre::-webkit-scrollbar {
260
+ background: transparent;
261
+ width: 10px;
262
+ }
263
+
264
+ pre::-webkit-scrollbar-thumb {
265
+ background: #999;
266
+ }
267
+
268
+ .debug-timetravel-panel {
269
+ overflow: hidden;
270
+ padding: 0 0 10px 0;
271
+ margin: auto;
272
+ display: flex;
273
+ }
274
+
275
+ .debug-timetravel-panel-slider {
276
+ padding: 0;
277
+ flex: 8;
278
+ }
279
+
280
+ .debug-timetravel-panel-button {
281
+ padding: 0;
282
+ border: 0;
283
+ background: none;
284
+ flex: 1;
285
+ color: #fff;
286
+ font-size: 12px;
287
+ }
288
+
289
+ .debug-timetravel-panel-button:hover {
290
+ text-decoration: underline;
291
+ }
292
+
293
+ .debug-timetravel-button {
294
+ border: 0;
295
+ padding: 0;
296
+ font-size: 12px;
297
+ top: 10px;
298
+ right: 15px;
299
+ position: absolute;
300
+ background: none;
301
+ color: #fff;
302
+ }
303
+
304
+ .debug-timetravel-button:hover {
305
+ text-decoration: underline;
306
+ }
307
+
308
+ .toolbar {
309
+ display: flex;
310
+ background: #fff;
311
+ vertical-align: middle;
312
+ }
313
+
314
+ .toolbar button.toolbar-item {
315
+ border: 0;
316
+ display: flex;
317
+ background: none;
318
+ border-radius: 10px;
319
+ padding: 8px;
320
+ cursor: pointer;
321
+ vertical-align: middle;
322
+ }
323
+
324
+ .toolbar button.toolbar-item:disabled {
325
+ cursor: not-allowed;
326
+ }
327
+
328
+ .toolbar button.toolbar-item.spaced {
329
+ margin-right: 2px;
330
+ }
331
+
332
+ .toolbar button.toolbar-item i.format {
333
+ background-size: contain;
334
+ display: inline-block;
335
+ height: 18px;
336
+ width: 18px;
337
+ margin-top: 2px;
338
+ vertical-align: -0.25em;
339
+ display: flex;
340
+ opacity: 0.6;
341
+ }
342
+
343
+ .toolbar button.toolbar-item:disabled i.format {
344
+ opacity: 0.2;
345
+ }
346
+
347
+ .toolbar button.toolbar-item.active {
348
+ background-color: rgba(223, 232, 250, 0.3);
349
+ }
350
+
351
+ .toolbar button.toolbar-item.active i {
352
+ opacity: 1;
353
+ }
354
+
355
+ .toolbar .toolbar-item:hover:not([disabled]) {
356
+ background-color: #eee;
357
+ }
358
+
359
+ .toolbar .divider {
360
+ width: 1px;
361
+ background-color: #eee;
362
+ margin: 0 4px;
363
+ }
364
+
365
+ .toolbar .toolbar-item .text {
366
+ display: flex;
367
+ line-height: 20px;
368
+ width: 200px;
369
+ vertical-align: middle;
370
+ font-size: 14px;
371
+ color: #777;
372
+ text-overflow: ellipsis;
373
+ width: 70px;
374
+ overflow: hidden;
375
+ height: 20px;
376
+ text-align: left;
377
+ }
378
+
379
+ .toolbar .toolbar-item .icon {
380
+ display: flex;
381
+ width: 20px;
382
+ height: 20px;
383
+ user-select: none;
384
+ margin-right: 8px;
385
+ line-height: 16px;
386
+ background-size: contain;
387
+ }
388
+
389
+ i.undo {
390
+ background-image: url(icons/arrow-counterclockwise.svg);
391
+ }
392
+
393
+ i.redo {
394
+ background-image: url(icons/arrow-clockwise.svg);
395
+ }
396
+
397
+ i.bold {
398
+ background-image: url(icons/type-bold.svg);
399
+ }
400
+
401
+ i.italic {
402
+ background-image: url(icons/type-italic.svg);
403
+ }
404
+
405
+ i.underline {
406
+ background-image: url(icons/type-underline.svg);
407
+ }
408
+
409
+ i.strikethrough {
410
+ background-image: url(icons/type-strikethrough.svg);
411
+ }
412
+
413
+ i.left-align {
414
+ background-image: url(icons/text-left.svg);
415
+ }
416
+
417
+ i.center-align {
418
+ background-image: url(icons/text-center.svg);
419
+ }
420
+
421
+ i.right-align {
422
+ background-image: url(icons/text-right.svg);
423
+ }
424
+
425
+ i.justify-align {
426
+ background-image: url(icons/justify.svg);
427
+ }
428
+ }
@@ -1,7 +1,6 @@
1
1
  @import (reference) "@/client/assets/vars.less";
2
2
 
3
3
  @hInput: @sizeComponent;
4
- @labelH: 0.6em;
5
4
 
6
5
  // TODO: Adapter textarea à input/basev2
7
6
  .contChamp textarea {
@@ -12,6 +11,22 @@
12
11
  padding-top: @spacing * 2 !important;
13
12
  }
14
13
 
14
+ .inputWrapper {
15
+ display: flex;
16
+ flex-direction: column;
17
+ gap: 0.5em;
18
+ align-items: stretch;
19
+
20
+ > label {
21
+ font-weight: 700;
22
+ }
23
+
24
+ > p.hint {
25
+ text-align: left;
26
+ color: var(--cTxtDesc);
27
+ }
28
+ }
29
+
15
30
  .input {
16
31
  &.text,
17
32
  &.select {
@@ -22,15 +37,6 @@
22
37
  > i {
23
38
  color: var(--cTxtDesc);
24
39
  }
25
-
26
- label {
27
- display: flex;
28
- align-items: center;
29
- color: var(--cTxtImportant);
30
- font-size: 0.9em;
31
- font-weight: 600;
32
- transition: all .1s ease-out;
33
- }
34
40
  }
35
41
 
36
42
  // Error bubble
@@ -72,28 +78,9 @@
72
78
  --cBg2: #eee;
73
79
  //box-shadow: 1px 3px 0 fade(#000,4%), 0 1px 2px 0 fade(#000,2%);
74
80
 
75
- @gapAround: (@hInput - @labelH) / 2;
81
+ @gapAround: @spacing;
76
82
  > .btn:first-child { margin-left: 0 - @gapAround / 2; }
77
83
 
78
- label {
79
- position: absolute;
80
- left: 0; width: 100%;
81
- top: 0;
82
- height: @labelH;
83
- font-size: 0.8em;
84
- line-height: 0.8em;
85
-
86
- color: var(--cTxtImportant);
87
- }
88
-
89
- &.empty:not(.focus) {
90
- label {
91
- height: 100%;
92
- font-size: 1em;
93
- color: var(--cTxtBase);
94
- }
95
- }
96
-
97
84
  .contValue {
98
85
  position: relative;
99
86
  flex: 1;
@@ -114,7 +101,7 @@
114
101
  border: none;
115
102
  font-family: inherit;
116
103
  width: 100%;
117
- padding: @labelH 0 0 0;
104
+ padding: 0;
118
105
  font-size: 1rem;
119
106
  color: inherit;
120
107
  }
@@ -128,7 +115,7 @@
128
115
  }
129
116
 
130
117
  textarea {
131
- padding: @labelH + @spacing 0 @spacing 0;
132
- min-height: 4em;
118
+ padding: 0;
119
+ min-height: 6em;
133
120
  }
134
121
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  // Npm
6
6
  import React from 'react';
7
+ import type { ComponentChild } from 'preact';
7
8
  import type { StateUpdater } from 'preact/hooks';
8
9
 
9
10
  // Core libs
@@ -16,10 +17,13 @@ import { useState } from '@client/hooks';
16
17
  export type InputBaseProps<TValue> = {
17
18
 
18
19
  title: string, // Now mandatory
20
+ hint?: ComponentChild,
19
21
  required?: boolean,
20
22
  errors?: string[],
21
23
  size?: TComponentSize,
22
24
 
25
+ wrapper?: boolean,
26
+
23
27
  value: TValue,
24
28
  onChange?: (value: TValue) => void,
25
29
  }
@@ -64,7 +68,7 @@ export function useInput<TValue>(
64
68
  if (state.changed === false)
65
69
  return;
66
70
 
67
- console.log(`[input] Commit value:`, state.value, externalValue);
71
+ //console.log(`[input] Commit value:`, state.value, externalValue);
68
72
  if (onChange !== undefined)
69
73
  onChange(state.value);
70
74
  }
@@ -73,7 +77,7 @@ export function useInput<TValue>(
73
77
  React.useEffect(() => {
74
78
 
75
79
  if (externalValue !== undefined && externalValue !== state.value) {
76
- console.log("External value change", externalValue);
80
+ //console.log("External value change", externalValue);
77
81
  setState({ value: externalValue, valueSource: 'external', changed: true })
78
82
  }
79
83
 
@@ -91,4 +95,34 @@ export function useInput<TValue>(
91
95
  /*----------------------------------
92
96
  - COMPONENT
93
97
  ----------------------------------*/
98
+ export const InputWrapper = ({ children, wrapper = true, title, hint, required }: InputBaseProps<unknown> & {
99
+ children: ComponentChild
100
+ }) => {
101
+
102
+ /*----------------------------------
103
+ - INIT
104
+ ----------------------------------*/
105
+
106
+ /*----------------------------------
107
+ - ACTIONS
108
+ ----------------------------------*/
109
+
110
+ /*----------------------------------
111
+ - RENDER
112
+ ----------------------------------*/
113
+ return wrapper === false ? <>{children}</> : (
114
+ <div class="inputWrapper">
115
+
116
+ <label>{title}{required && (
117
+ <span class="fg error">&nbsp;*</span>
118
+ )}</label>
119
+
120
+ {hint && <p class="hint">{hint}</p>}
121
+
122
+ {children}
123
+
124
+ </div>
125
+ )
126
+ }
127
+
94
128
  import './base.less';
@@ -8,7 +8,7 @@ import { VNode, JSX } from 'preact';
8
8
  import TextareaAutosize from 'react-textarea-autosize';
9
9
 
10
10
  // Core libs
11
- import { useInput, InputBaseProps } from './base';
11
+ import { useInput, InputBaseProps, InputWrapper } from './base';
12
12
  import { default as Validator } from '../../../common/validation/validator';
13
13
  import type SchemaValidators from '@common/validation/validators';
14
14
 
@@ -47,17 +47,18 @@ type TInputElementProps = Omit<(
47
47
  /*----------------------------------
48
48
  - COMPOSANT
49
49
  ----------------------------------*/
50
- export default ({
51
- // Decoration
52
- icon, prefix, suffix, iconR, required, size, className = '',
53
- // State
54
- inputRef, errors,
55
- // Behavior
56
- type, choice, validator,
57
- // Actions
58
- onPressEnter,
59
- ...props
60
- }: Props & InputBaseProps<string> & TInputElementProps) => {
50
+ export default (props: Props & InputBaseProps<string> & TInputElementProps) => {
51
+
52
+ let {
53
+ // Decoration
54
+ icon, prefix, suffix, iconR, placeholder, size, className = '',
55
+ // State
56
+ inputRef, errors,
57
+ // Behavior
58
+ type, validator,
59
+ // Actions
60
+ onPressEnter
61
+ } = props;
61
62
 
62
63
  /*----------------------------------
63
64
  - INIT
@@ -128,7 +129,7 @@ export default ({
128
129
 
129
130
  } else if (type === 'longtext') {
130
131
 
131
- prefix = prefix || <i src="text" />;
132
+ // No icon because not good looking ane we want as much space as possible
132
133
  Tag = 'textarea';
133
134
  className += ' multiline';
134
135
 
@@ -170,43 +171,43 @@ export default ({
170
171
  /*----------------------------------
171
172
  - RENDER
172
173
  ----------------------------------*/
173
- return <>
174
- <div class={className} onClick={() => refInput.current?.focus()}>
174
+ return (
175
+ <InputWrapper {...props}>
176
+ <div class={className} onClick={() => refInput.current?.focus()}>
175
177
 
176
- {prefix}
178
+ {prefix}
177
179
 
178
- <div class="contValue">
180
+ <div class="contValue">
179
181
 
180
- <Tag {...fieldProps}
181
- // @ts-ignore: Property 'ref' does not exist on type 'IntrinsicAttributes'
182
- ref={refInput}
183
- value={value}
184
- onFocus={() => setState({ focus: true })}
185
- onBlur={() => setState({ focus: false })}
186
- onChange={(e) => updateValue(e.target.value)}
182
+ <Tag {...fieldProps}
187
183
 
188
- onKeyDown={(e: KeyboardEvent) => {
184
+ placeholder={placeholder || props.title}
189
185
 
190
- if (onPressEnter && e.key === 'Enter' && value !== undefined) {
191
- commitValue();
192
- onPressEnter(value)
193
- }
194
- }}
195
- />
186
+ // @ts-ignore: Property 'ref' does not exist on type 'IntrinsicAttributes'
187
+ ref={refInput}
188
+ value={value}
189
+ onFocus={() => setState({ focus: true })}
190
+ onBlur={() => setState({ focus: false })}
191
+ onChange={(e) => updateValue(e.target.value)}
192
+ onKeyDown={(e: KeyboardEvent) => {
196
193
 
197
- <label>{props.title}{required && (
198
- <span class="fg error">&nbsp;*</span>
199
- )}</label>
200
- </div>
194
+ if (onPressEnter && e.key === 'Enter' && value !== undefined) {
195
+ commitValue();
196
+ onPressEnter(value)
197
+ }
198
+ }}
199
+ />
200
+ </div>
201
201
 
202
- {suffix}
202
+ {suffix}
203
+
204
+ {errors?.length && (
205
+ <div class="bubble bg error bottom">
206
+ {errors.join('. ')}
207
+ </div>
208
+ )}
203
209
 
204
- {errors?.length && (
205
- <div class="bubble bg error bottom">
206
- {errors.join('. ')}
207
- </div>
208
- )}
209
-
210
- </div>
211
- </>
210
+ </div>
211
+ </InputWrapper>
212
+ )
212
213
  }