5htp-core 0.4.6 → 0.4.7-2
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.
- package/package.json +6 -1
- package/src/client/assets/css/components/table.less +70 -7
- package/src/client/components/Select/ChoiceSelector.tsx +6 -5
- package/src/client/components/Select/index.tsx +138 -131
- package/src/client/components/Table/index.tsx +67 -15
- package/src/client/components/index.ts +2 -1
- package/src/client/components/inputv3/Rte/ExampleTheme.tsx +42 -0
- package/src/client/components/inputv3/Rte/ToolbarPlugin.tsx +167 -0
- package/src/client/components/inputv3/Rte/icons/LICENSE.md +5 -0
- package/src/client/components/inputv3/Rte/icons/arrow-clockwise.svg +4 -0
- package/src/client/components/inputv3/Rte/icons/arrow-counterclockwise.svg +4 -0
- package/src/client/components/inputv3/Rte/icons/journal-text.svg +5 -0
- package/src/client/components/inputv3/Rte/icons/justify.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/text-center.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/text-left.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/text-paragraph.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/text-right.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/type-bold.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/type-italic.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/type-strikethrough.svg +3 -0
- package/src/client/components/inputv3/Rte/icons/type-underline.svg +3 -0
- package/src/client/components/inputv3/Rte/index.tsx +163 -0
- package/src/client/components/inputv3/Rte/style.less +428 -0
- package/src/client/components/inputv3/base.less +20 -33
- package/src/client/components/inputv3/base.tsx +36 -2
- package/src/client/components/inputv3/index.tsx +45 -44
- package/src/common/data/rte/index.ts +66 -0
- package/src/common/data/rte/nodes.ts +20 -0
- package/src/common/router/request/index.ts +4 -1
- package/src/common/validation/validators.ts +74 -1
- package/src/server/app/index.ts +0 -11
- package/src/server/services/auth/index.ts +86 -47
- package/src/server/services/auth/router/request.ts +9 -5
- package/src/server/services/database/index.ts +1 -1
- package/src/server/services/database/metas.ts +1 -1
- package/src/server/services/router/index.ts +2 -1
- package/src/server/services/router/response/index.ts +5 -2
- package/src/client/components/input/Rte/index.less +0 -13
- package/src/client/components/input/Rte/index.tsx +0 -143
- package/src/client/components/input/Rte/selection.ts +0 -34
- package/src/common/data/rte.tsx +0 -11
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.7-2",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"framework"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@lexical/headless": "^0.18.0",
|
|
17
|
+
"@lexical/html": "^0.18.0",
|
|
18
|
+
"@lexical/react": "^0.18.0",
|
|
16
19
|
"accepts": "^1.3.7",
|
|
17
20
|
"activity-detector": "^3.0.0",
|
|
18
21
|
"ansi-to-html": "^0.7.1",
|
|
@@ -44,7 +47,9 @@
|
|
|
44
47
|
"intl": "^1.2.5",
|
|
45
48
|
"iso-639-1": "^2.1.9",
|
|
46
49
|
"js-cookie": "^3.0.1",
|
|
50
|
+
"jsdom": "^25.0.1",
|
|
47
51
|
"jsonwebtoken": "^8.5.1",
|
|
52
|
+
"lexical": "^0.18.0",
|
|
48
53
|
"load-script": "^2.0.0",
|
|
49
54
|
"locale": "^0.1.0",
|
|
50
55
|
"markdown-it": "^13.0.1",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.table {
|
|
2
2
|
overflow: auto;
|
|
3
|
+
max-height: 90vh;
|
|
3
4
|
|
|
4
5
|
> table {
|
|
5
6
|
border-collapse: collapse;
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
&.card {
|
|
16
|
-
padding:
|
|
17
|
+
padding: 0;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -26,7 +27,7 @@ table {
|
|
|
26
27
|
|
|
27
28
|
// By default, chrome disables text inherits
|
|
28
29
|
line-height: inherit;
|
|
29
|
-
font-size:
|
|
30
|
+
font-size: 0.9em;
|
|
30
31
|
|
|
31
32
|
th {
|
|
32
33
|
font-weight: 500;
|
|
@@ -38,8 +39,8 @@ table {
|
|
|
38
39
|
padding: 1em 1em;
|
|
39
40
|
text-align: left;
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
border-
|
|
42
|
+
&:not(:last-child) {
|
|
43
|
+
border-right: solid 1px #F5F5F5;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
&:first-child {
|
|
@@ -50,6 +51,29 @@ table {
|
|
|
50
51
|
padding-right: 2em;
|
|
51
52
|
text-align: right;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
&.stickyColumn {
|
|
56
|
+
position: sticky;
|
|
57
|
+
background: var(--cBg);
|
|
58
|
+
white-space: break-spaces;
|
|
59
|
+
z-index: 1;
|
|
60
|
+
|
|
61
|
+
&:first-child {
|
|
62
|
+
left: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&:last-child {
|
|
66
|
+
right: 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
thead {
|
|
72
|
+
position: sticky;
|
|
73
|
+
top: 0;
|
|
74
|
+
background: var(--cBg);
|
|
75
|
+
white-space: break-spaces;
|
|
76
|
+
z-index: 5;
|
|
53
77
|
}
|
|
54
78
|
|
|
55
79
|
tbody {
|
|
@@ -57,11 +81,45 @@ table {
|
|
|
57
81
|
td, th {
|
|
58
82
|
vertical-align: middle;
|
|
59
83
|
border-top: solid 1px var(--cLine);
|
|
84
|
+
position: relative;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Rows: Crop when too long
|
|
88
|
+
td {
|
|
89
|
+
|
|
90
|
+
cursor: default;
|
|
91
|
+
|
|
92
|
+
&.extendable > .row {
|
|
93
|
+
|
|
94
|
+
max-width: 20em;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
justify-content: flex-start;
|
|
97
|
+
|
|
98
|
+
&::after {
|
|
99
|
+
content: ' ';
|
|
100
|
+
display: block;
|
|
101
|
+
position: absolute;
|
|
102
|
+
|
|
103
|
+
top: 0;
|
|
104
|
+
right: 0;
|
|
105
|
+
width: 30%;
|
|
106
|
+
height: 100%;
|
|
107
|
+
|
|
108
|
+
background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--cBg));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
> * {
|
|
112
|
+
flex-shrink: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
> .badge {
|
|
116
|
+
font-size: 0.8em;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
60
119
|
}
|
|
61
120
|
|
|
62
|
-
|
|
63
|
-
background:
|
|
64
|
-
color: #fff;
|
|
121
|
+
tr:hover > td {
|
|
122
|
+
background: #FAFAFA;
|
|
65
123
|
}
|
|
66
124
|
}
|
|
67
125
|
|
|
@@ -112,4 +170,9 @@ table {
|
|
|
112
170
|
}
|
|
113
171
|
}
|
|
114
172
|
}*/
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.modal .tableCellExtended .row {
|
|
176
|
+
flex-wrap: wrap;
|
|
177
|
+
justify-content: flex-start;
|
|
115
178
|
}
|
|
@@ -18,9 +18,7 @@ import type { TDialogControls } from '@client/components/dropdown';
|
|
|
18
18
|
|
|
19
19
|
export type Choice = { label: ComponentChild, value: string }
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
type ChoicesFunc = (search: string) => Promise<Choices>
|
|
21
|
+
type ChoicesFunc = (search: string) => Promise<Choice[]>
|
|
24
22
|
|
|
25
23
|
export type Props = (
|
|
26
24
|
{
|
|
@@ -37,10 +35,13 @@ export type Props = (
|
|
|
37
35
|
validator?: StringValidator
|
|
38
36
|
}
|
|
39
37
|
) & {
|
|
40
|
-
choices:
|
|
38
|
+
choices: Choice[] | ChoicesFunc | string[],
|
|
41
39
|
enableSearch?: boolean,
|
|
42
40
|
required?: boolean,
|
|
43
41
|
noneSelection?: false | string,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type SelectorProps = Props & {
|
|
44
45
|
currentList: Choice[],
|
|
45
46
|
refDropdown?: RefObject<TDialogControls>
|
|
46
47
|
}
|
|
@@ -67,7 +68,7 @@ export default React.forwardRef<HTMLDivElement, Props>(({
|
|
|
67
68
|
currentList,
|
|
68
69
|
refDropdown,
|
|
69
70
|
...otherProps
|
|
70
|
-
}:
|
|
71
|
+
}: SelectorProps, ref) => {
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
|
|
@@ -8,6 +8,7 @@ import React from 'react';
|
|
|
8
8
|
// Core
|
|
9
9
|
import { Props as DropdownProps } from '@client/components/dropdown';
|
|
10
10
|
import { Popover, Button, Input } from '@client/components';
|
|
11
|
+
import { InputWrapper, InputBaseProps } from '@client/components/inputv3/base';
|
|
11
12
|
|
|
12
13
|
// Specific
|
|
13
14
|
import {
|
|
@@ -21,10 +22,8 @@ import ChoiceElement from './ChoiceElement';
|
|
|
21
22
|
- TYPES
|
|
22
23
|
----------------------------------*/
|
|
23
24
|
|
|
24
|
-
export type Props = SelectorProps & {
|
|
25
|
-
dropdown
|
|
26
|
-
title: string,
|
|
27
|
-
errors?: string[],
|
|
25
|
+
export type Props = SelectorProps & Omit<InputBaseProps<Choice>, 'value'> & {
|
|
26
|
+
dropdown?: boolean | DropdownProps,
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
export type { Choice } from './ChoiceSelector';
|
|
@@ -51,24 +50,27 @@ const ensureChoice = (choice: Choice | string, choices: Choice[]): Choice => {
|
|
|
51
50
|
/*----------------------------------
|
|
52
51
|
- COMONENT
|
|
53
52
|
----------------------------------*/
|
|
54
|
-
export default ({
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
export default (props: Props) => {
|
|
54
|
+
|
|
55
|
+
let {
|
|
56
|
+
// Input basics
|
|
57
|
+
title,
|
|
58
|
+
errors,
|
|
59
|
+
icon,
|
|
60
|
+
required,
|
|
61
|
+
validator,
|
|
62
|
+
wrapper = true,
|
|
63
|
+
|
|
64
|
+
// Choice selection
|
|
65
|
+
choices: initChoices,
|
|
66
|
+
noneSelection,
|
|
67
|
+
enableSearch,
|
|
68
|
+
value: current,
|
|
69
|
+
onChange: onChangeCallback,
|
|
70
|
+
multiple,
|
|
71
|
+
dropdown,
|
|
72
|
+
...otherProps
|
|
73
|
+
} = props;
|
|
72
74
|
|
|
73
75
|
/*----------------------------------
|
|
74
76
|
- INIT
|
|
@@ -77,8 +79,10 @@ export default ({
|
|
|
77
79
|
const popoverState = React.useState(false);
|
|
78
80
|
|
|
79
81
|
const choicesViaFunc = typeof initChoices === 'function';
|
|
80
|
-
if (choicesViaFunc
|
|
82
|
+
if (choicesViaFunc)
|
|
81
83
|
enableSearch = true;
|
|
84
|
+
else if (typeof initChoices[0] === 'string')
|
|
85
|
+
initChoices = initChoices.map( c => ({ label: c, value: c }));
|
|
82
86
|
|
|
83
87
|
const refInputSearch = React.useRef<HTMLInputElement | null>(null);
|
|
84
88
|
|
|
@@ -159,119 +163,122 @@ export default ({
|
|
|
159
163
|
/>
|
|
160
164
|
)
|
|
161
165
|
|
|
162
|
-
return
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{selectedItems.
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
166
|
+
return (
|
|
167
|
+
<InputWrapper {...props}>
|
|
168
|
+
{dropdown ? (
|
|
169
|
+
<Popover {...(dropdown === true ? {
|
|
170
|
+
width: '200px'
|
|
171
|
+
} : dropdown)} content={(
|
|
172
|
+
<div class="card bg white col al-top">
|
|
173
|
+
|
|
174
|
+
{Search}
|
|
175
|
+
|
|
176
|
+
{selectedItems.length !== 0 && (
|
|
177
|
+
<ul class="row al-left wrap sp-05">
|
|
178
|
+
{selectedItems.map( choice => (
|
|
179
|
+
<ChoiceElement format='badge' choice={choice}
|
|
180
|
+
currentList={currentList}
|
|
181
|
+
onChange={onChange}
|
|
182
|
+
multiple={multiple}
|
|
183
|
+
includeCurrent
|
|
184
|
+
/>
|
|
185
|
+
))}
|
|
186
|
+
</ul>
|
|
187
|
+
)}
|
|
188
|
+
|
|
189
|
+
{search.loading ? (
|
|
190
|
+
<div class="row al-center h-2">
|
|
191
|
+
<i src="spin" />
|
|
192
|
+
</div>
|
|
193
|
+
) : (
|
|
194
|
+
<ul class="menu col">
|
|
195
|
+
{choices.map( choice => (
|
|
196
|
+
<ChoiceElement format='list' choice={choice}
|
|
197
|
+
currentList={currentList}
|
|
198
|
+
onChange={onChange}
|
|
199
|
+
multiple={multiple}
|
|
200
|
+
includeCurrent
|
|
201
|
+
/>
|
|
202
|
+
))}
|
|
203
|
+
</ul>
|
|
204
|
+
)}
|
|
186
205
|
</div>
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
{
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
206
|
+
)} state={popoverState}>
|
|
207
|
+
<Button type="secondary" icon={icon} iconR="chevron-down" {...otherProps}>
|
|
208
|
+
|
|
209
|
+
{currentList.length === 0 ? <>
|
|
210
|
+
{title}
|
|
211
|
+
</> : multiple ? <>
|
|
212
|
+
{title} <span class="badge s bg accent">{currentList.length}</span>
|
|
213
|
+
</> : <>
|
|
214
|
+
{currentList[0].label}
|
|
215
|
+
</>}
|
|
216
|
+
|
|
217
|
+
{errors?.length && (
|
|
218
|
+
<div class="bubble bg error bottom">
|
|
219
|
+
{errors.join('. ')}
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
|
|
223
|
+
</Button>
|
|
224
|
+
</Popover>
|
|
225
|
+
) : (
|
|
226
|
+
<div class="col sp-05">
|
|
227
|
+
<div class={className} onMouseDown={() => refInputSearch.current?.focus()}>
|
|
228
|
+
|
|
229
|
+
<div class="row al-left wrap pd-1">
|
|
230
|
+
|
|
231
|
+
{icon !== undefined && (
|
|
232
|
+
<i src={icon} />
|
|
233
|
+
)}
|
|
234
|
+
|
|
235
|
+
<div class="col al-left sp-05">
|
|
236
|
+
|
|
237
|
+
<label>{title}{isRequired && (
|
|
238
|
+
<span class="fg error"> *</span>
|
|
239
|
+
)}</label>
|
|
240
|
+
|
|
241
|
+
<div class="row al-left wrap sp-05">
|
|
242
|
+
|
|
243
|
+
{selectedItems.map( choice => (
|
|
244
|
+
<ChoiceElement format='badge' choice={choice}
|
|
245
|
+
currentList={currentList}
|
|
246
|
+
onChange={onChange}
|
|
247
|
+
multiple={multiple}
|
|
248
|
+
includeCurrent
|
|
249
|
+
/>
|
|
250
|
+
))}
|
|
251
|
+
|
|
252
|
+
{Search}
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
229
255
|
|
|
230
|
-
<div class="col al-left sp-05">
|
|
231
|
-
|
|
232
|
-
<label>{title}{isRequired && (
|
|
233
|
-
<span class="fg error"> *</span>
|
|
234
|
-
)}</label>
|
|
235
|
-
|
|
236
|
-
<div class="row al-left wrap sp-05">
|
|
237
|
-
|
|
238
|
-
{selectedItems.map( choice => (
|
|
239
|
-
<ChoiceElement format='badge' choice={choice}
|
|
240
|
-
currentList={currentList}
|
|
241
|
-
onChange={onChange}
|
|
242
|
-
multiple={multiple}
|
|
243
|
-
includeCurrent
|
|
244
|
-
/>
|
|
245
|
-
))}
|
|
246
|
-
|
|
247
|
-
{Search}
|
|
248
256
|
</div>
|
|
249
|
-
</div>
|
|
250
|
-
|
|
251
|
-
</div>
|
|
252
257
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
258
|
+
<div class="pd-1">
|
|
259
|
+
<ul class="row al-left wrap sp-05" style={{
|
|
260
|
+
maxHeight: '30vh',
|
|
261
|
+
overflowY: 'auto'
|
|
262
|
+
}}>
|
|
263
|
+
{choices.map( choice => (
|
|
264
|
+
<ChoiceElement format='badge' choice={choice}
|
|
265
|
+
currentList={currentList}
|
|
266
|
+
onChange={onChange}
|
|
267
|
+
multiple={multiple}
|
|
268
|
+
includeCurrent
|
|
269
|
+
/>
|
|
270
|
+
))}
|
|
271
|
+
</ul>
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
</div>
|
|
275
|
+
{errors?.length && (
|
|
276
|
+
<div class="bubble bg error bottom">
|
|
277
|
+
{errors.join('. ')}
|
|
278
|
+
</div>
|
|
279
|
+
)}
|
|
273
280
|
</div>
|
|
274
281
|
)}
|
|
275
|
-
</
|
|
282
|
+
</InputWrapper>
|
|
276
283
|
)
|
|
277
284
|
}
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
/*----------------------------------
|
|
3
3
|
- DEPENDANCES
|
|
4
4
|
----------------------------------*/
|
|
5
|
+
|
|
5
6
|
// Libs
|
|
6
7
|
import React from 'react';
|
|
7
|
-
import { ComponentChild } from 'preact';
|
|
8
|
+
import { JSX, ComponentChild } from 'preact';
|
|
8
9
|
|
|
9
10
|
// Composants
|
|
11
|
+
import useContext from '@/client/context';
|
|
10
12
|
import Button, { Props as TButtonProps } from '@client/components/button';
|
|
11
13
|
import Popover from '../containers/Popover';
|
|
12
14
|
import Checkbox from '../inputv3/Checkbox';
|
|
@@ -21,6 +23,7 @@ export type Props<TRow> = {
|
|
|
21
23
|
|
|
22
24
|
data: TRow[],
|
|
23
25
|
columns: (row: TRow, rows: TRow[], index: number) => TColumn[];
|
|
26
|
+
stickyHeader?: boolean,
|
|
24
27
|
|
|
25
28
|
setData?: (rows: TRow[]) => void,
|
|
26
29
|
empty?: ComponentChild | false,
|
|
@@ -29,11 +32,11 @@ export type Props<TRow> = {
|
|
|
29
32
|
actions?: TAction<TRow>[]
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
export type TColumn = {
|
|
35
|
+
export type TColumn = JSX.HTMLAttributes<HTMLElement> & {
|
|
33
36
|
label: ComponentChild,
|
|
34
37
|
cell: ComponentChild,
|
|
35
38
|
raw?: number | string | boolean,
|
|
36
|
-
|
|
39
|
+
stick?: boolean,
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export type TAction<TRow> = Omit<TButtonProps, 'onClick'> & {
|
|
@@ -47,13 +50,16 @@ export type TAction<TRow> = Omit<TButtonProps, 'onClick'> & {
|
|
|
47
50
|
- COMPOSANTS
|
|
48
51
|
----------------------------------*/
|
|
49
52
|
export default function Liste<TRow extends TDonneeInconnue>({
|
|
53
|
+
stickyHeader,
|
|
50
54
|
data: rows, setData, empty,
|
|
51
55
|
columns, actions, ...props
|
|
52
56
|
}: Props<TRow>) {
|
|
53
57
|
|
|
58
|
+
const { modal } = useContext();
|
|
59
|
+
|
|
54
60
|
if (rows.length === 0)
|
|
55
61
|
return empty === false ? null : (
|
|
56
|
-
<div class="pd-2 col al-center">
|
|
62
|
+
<div class={"pd-2 col al-center " + (props.className || '')}>
|
|
57
63
|
{empty || <>
|
|
58
64
|
<i src="meh-rolling-eyes" class="xl" />
|
|
59
65
|
Uh ... No rows here.
|
|
@@ -92,29 +98,75 @@ export default function Liste<TRow extends TDonneeInconnue>({
|
|
|
92
98
|
</td>
|
|
93
99
|
)}
|
|
94
100
|
|
|
95
|
-
{columns(row, rows, iDonnee).map((
|
|
101
|
+
{columns(row, rows, iDonnee).map(({
|
|
102
|
+
label, cell, class: className, raw,
|
|
103
|
+
stick, width, ...cellProps
|
|
104
|
+
}) => {
|
|
105
|
+
|
|
106
|
+
let classe = className || '';
|
|
107
|
+
if (typeof raw === 'number')
|
|
108
|
+
classe += 'txtRight';
|
|
109
|
+
|
|
110
|
+
if (stick) {
|
|
111
|
+
classe += ' stickyColumn';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (width) {
|
|
115
|
+
|
|
116
|
+
if (cellProps.style === undefined)
|
|
117
|
+
cellProps.style = {};
|
|
118
|
+
|
|
119
|
+
cellProps.style = {
|
|
120
|
+
...cellProps.style,
|
|
121
|
+
minWidth: width,
|
|
122
|
+
width: width,
|
|
123
|
+
maxWidth: width,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
96
126
|
|
|
97
127
|
if (iDonnee === 0) renduColonnes.push(
|
|
98
|
-
<th>
|
|
99
|
-
{
|
|
128
|
+
<th class={classe} {...cellProps}>
|
|
129
|
+
{label}
|
|
100
130
|
</th>
|
|
101
131
|
);
|
|
102
132
|
|
|
103
|
-
|
|
133
|
+
let render: ComponentChild;
|
|
134
|
+
if (Array.isArray(cell)) {
|
|
104
135
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
136
|
+
classe += ' extendable';
|
|
137
|
+
|
|
138
|
+
render = (
|
|
139
|
+
<div class="row sp-05">
|
|
140
|
+
{cell.map((item, i) => (
|
|
141
|
+
<span class={"badge bg light" + ((i % 7) + 1)}>
|
|
142
|
+
{item}
|
|
143
|
+
</span>
|
|
144
|
+
))}
|
|
145
|
+
</div>
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
// Extension
|
|
149
|
+
cellProps.onClick = () => modal.show(() => (
|
|
150
|
+
<div class="card col tableCellExtended">
|
|
151
|
+
<h3>{label}</h3>
|
|
152
|
+
{render}
|
|
153
|
+
</div>
|
|
154
|
+
));
|
|
155
|
+
|
|
156
|
+
} else if (['number', 'string'].includes(typeof cell) || React.isValidElement(cell)) {
|
|
157
|
+
render = cell;
|
|
158
|
+
} else
|
|
159
|
+
render = JSON.stringify(cell);
|
|
108
160
|
|
|
109
161
|
return (
|
|
110
|
-
<td class={classe}>
|
|
111
|
-
{
|
|
162
|
+
<td class={classe} {...cellProps}>
|
|
163
|
+
{render}
|
|
112
164
|
</td>
|
|
113
165
|
)
|
|
114
166
|
})}
|
|
115
167
|
|
|
116
168
|
{actions !== undefined && (
|
|
117
|
-
<td>
|
|
169
|
+
<td class="stickyColumn">
|
|
118
170
|
<Popover content={(
|
|
119
171
|
<ul class="col menu card bg white">
|
|
120
172
|
{actions.map(({ label, onClick, ...props }: TAction<TRow>) => (
|
|
@@ -148,7 +200,7 @@ export default function Liste<TRow extends TDonneeInconnue>({
|
|
|
148
200
|
return <>
|
|
149
201
|
<div {...props}>
|
|
150
202
|
<table>
|
|
151
|
-
<thead>
|
|
203
|
+
<thead className={stickyHeader ? 'stickyHeader' : undefined}>
|
|
152
204
|
<tr>
|
|
153
205
|
{selectionMultiple && (
|
|
154
206
|
<th>
|
|
@@ -27,4 +27,5 @@ export { default as Select } from './Select';
|
|
|
27
27
|
export { default as Input } from './inputv3';
|
|
28
28
|
export { default as Checkbox } from './inputv3/Checkbox';
|
|
29
29
|
export { default as File } from './inputv3/file';
|
|
30
|
-
export { default as DateRangeInput } from './inputv3/Date';
|
|
30
|
+
export { default as DateRangeInput } from './inputv3/Date';
|
|
31
|
+
export { default as Rte } from './inputv3/Rte';
|