kelt-ui-kit-react 1.9.9 → 2.0.0
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/dist/form/Form.d.ts +2 -1
- package/dist/form/form.enum.d.ts +2 -1
- package/dist/form/form.interface.d.ts +4 -0
- package/dist/grid/col/Col.d.ts +3 -6
- package/dist/grid/col/colStyled/ColStyled.d.ts +7 -5
- package/dist/grid/grid.interface.d.ts +9 -5
- package/dist/header/header.interface.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1892 -1827
- package/dist/menus/menu/Menu.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/toaster/store/useToasterStore.d.ts +1 -0
- package/index.html +1 -2
- package/package.json +2 -2
- package/src/button/button.css +2 -2
- package/src/card/card.css +2 -2
- package/src/dataTable/dataTable.css +3 -3
- package/src/expands/expands.css +1 -1
- package/src/form/Form.tsx +113 -10
- package/src/form/Form.view.tsx +9 -1
- package/src/form/form.css +17 -0
- package/src/form/form.enum.ts +1 -0
- package/src/form/form.interface.tsx +7 -0
- package/src/grid/col/Col.tsx +5 -7
- package/src/grid/col/colStyled/ColStyled.tsx +16 -4
- package/src/grid/grid.interface.tsx +11 -5
- package/src/header/Header.tsx +1 -1
- package/src/header/header.interface.tsx +1 -1
- package/src/index.css +58 -12
- package/src/index.ts +1 -0
- package/src/menus/Menus.tsx +1 -0
- package/src/menus/menu/Menu.tsx +2 -1
- package/src/sidebar/Sidebar.tsx +1 -0
- package/src/tabs/tabs.css +9 -3
- package/src/toaster/Toaster.tsx +7 -2
- package/src/toaster/Toaster.view.tsx +1 -0
- package/src/toaster/store/useToasterStore.tsx +2 -0
- package/src/toaster/toaster.css +7 -2
package/index.html
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
7
7
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
8
|
-
<link href="https://fonts.googleapis.com/css2?family=
|
|
9
|
-
rel="stylesheet">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@100..900&display=swap" rel="stylesheet">
|
|
10
9
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
11
10
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
12
11
|
<title>Vite + React + TS</title>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kelt-ui-kit-react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -53,4 +53,4 @@
|
|
|
53
53
|
"typescript": "^4.9.5",
|
|
54
54
|
"vite-plugin-checker": "^0.8.0"
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
}
|
package/src/button/button.css
CHANGED
|
@@ -5,7 +5,7 @@ button {
|
|
|
5
5
|
padding: 10px;
|
|
6
6
|
border-radius: 5px;
|
|
7
7
|
cursor: pointer;
|
|
8
|
-
font-size:
|
|
8
|
+
font-size: 18px;
|
|
9
9
|
font-weight: 500;
|
|
10
10
|
transition: background-color 0.3s;
|
|
11
11
|
display: flex;
|
|
@@ -14,7 +14,7 @@ button {
|
|
|
14
14
|
position: relative;
|
|
15
15
|
align-items: center;
|
|
16
16
|
justify-content: center;
|
|
17
|
-
font-family: "
|
|
17
|
+
font-family: "Lexend", sans-serif;
|
|
18
18
|
.badge {
|
|
19
19
|
position: absolute;
|
|
20
20
|
right: 10px;
|
package/src/card/card.css
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
.data-table {
|
|
55
55
|
width: 100%;
|
|
56
56
|
border-spacing: 0;
|
|
57
|
-
font-size:
|
|
57
|
+
font-size: 16px;
|
|
58
58
|
color: #333;
|
|
59
59
|
|
|
60
60
|
.select-cell {
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
top: 0;
|
|
85
85
|
z-index: 2;
|
|
86
86
|
background-color: #fff;
|
|
87
|
-
color:
|
|
87
|
+
color: var(--tertiary-color);
|
|
88
88
|
min-width: 100px;
|
|
89
89
|
padding: .5rem;
|
|
90
90
|
}
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
border: 1px solid #dcdcdc;
|
|
126
126
|
background-color: #f8f9fa;
|
|
127
127
|
color: #333;
|
|
128
|
-
font-size:
|
|
128
|
+
font-size: 16px;
|
|
129
129
|
line-height: 1;
|
|
130
130
|
cursor: pointer;
|
|
131
131
|
transition: background-color 0.15s, border-color 0.15s;
|
package/src/expands/expands.css
CHANGED
package/src/form/Form.tsx
CHANGED
|
@@ -9,9 +9,35 @@ import { Button } from "../button/Button";
|
|
|
9
9
|
import { Icon } from "../icon/Icon";
|
|
10
10
|
import { Select } from "../select/Select"; // <--- ton composant
|
|
11
11
|
import "./form.css";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
FormInterface,
|
|
14
|
+
FormMode,
|
|
15
|
+
FormValuesInterface,
|
|
16
|
+
} from "./form.interface";
|
|
13
17
|
import { Input } from "./input/Input";
|
|
18
|
+
import { InputPrice } from "./inputPrice/InputPrice";
|
|
14
19
|
import { TextArea } from "./textArea/TextArea";
|
|
20
|
+
import { Col } from "../grid/col/Col";
|
|
21
|
+
import { Row } from "../grid/row/Row";
|
|
22
|
+
import { TypeInputEnum } from "./form.enum";
|
|
23
|
+
|
|
24
|
+
const euroFormatter = new Intl.NumberFormat("fr-FR", {
|
|
25
|
+
style: "currency",
|
|
26
|
+
currency: "EUR",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
type FormFieldContainerProps = {
|
|
30
|
+
field: FormInterface;
|
|
31
|
+
gridEnabled: boolean;
|
|
32
|
+
children: React.ReactNode;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const FormFieldContainer = ({
|
|
36
|
+
field,
|
|
37
|
+
gridEnabled,
|
|
38
|
+
children,
|
|
39
|
+
}: FormFieldContainerProps) =>
|
|
40
|
+
gridEnabled ? <Col {...field.col}>{children}</Col> : <>{children}</>;
|
|
15
41
|
|
|
16
42
|
export type FormProps<
|
|
17
43
|
T extends { [key: string]: string | number | boolean | Date | string[] }
|
|
@@ -24,6 +50,7 @@ export type FormProps<
|
|
|
24
50
|
children?: React.ReactNode;
|
|
25
51
|
initialForm: FormInterface[];
|
|
26
52
|
disabledSubmit?: boolean;
|
|
53
|
+
mode?: FormMode;
|
|
27
54
|
onSubmit?: (values: FormValuesInterface<T>) => void;
|
|
28
55
|
onChange?: (values: FormValuesInterface<T>) => void;
|
|
29
56
|
};
|
|
@@ -40,6 +67,7 @@ export const DynamicForm = forwardRef(
|
|
|
40
67
|
onChange,
|
|
41
68
|
hideSubmit,
|
|
42
69
|
disabledSubmit = false,
|
|
70
|
+
mode = "edit",
|
|
43
71
|
className,
|
|
44
72
|
}: FormProps<T>,
|
|
45
73
|
ref: React.Ref<{
|
|
@@ -179,6 +207,52 @@ export const DynamicForm = forwardRef(
|
|
|
179
207
|
setBtnDisabledSubmit,
|
|
180
208
|
}));
|
|
181
209
|
|
|
210
|
+
const gridEnabled = initialForm.some((field) => field.col !== undefined);
|
|
211
|
+
const FieldsContainer = gridEnabled ? Row : React.Fragment;
|
|
212
|
+
const getReadValue = (field: FormInterface): React.ReactNode => {
|
|
213
|
+
const value = values[field.name];
|
|
214
|
+
|
|
215
|
+
if (field.formatReadValue) {
|
|
216
|
+
return field.formatReadValue(value ?? "");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (field.type === TypeInputEnum.SELECT) {
|
|
220
|
+
const selectedValues = Array.isArray(value) ? value : [value];
|
|
221
|
+
const labels = selectedValues
|
|
222
|
+
.map(
|
|
223
|
+
(selectedValue) =>
|
|
224
|
+
field.options?.find((option) => option.value === selectedValue)
|
|
225
|
+
?.label ?? selectedValue,
|
|
226
|
+
)
|
|
227
|
+
.filter((selectedValue) => selectedValue !== undefined);
|
|
228
|
+
|
|
229
|
+
return labels.join(", ") || "-";
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (field.type === TypeInputEnum.PRICE) {
|
|
233
|
+
const amount = Number(value);
|
|
234
|
+
return value === "" || value === undefined || Number.isNaN(amount)
|
|
235
|
+
? "-"
|
|
236
|
+
: euroFormatter.format(amount);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (typeof value === "boolean") {
|
|
240
|
+
return value ? "Oui" : "Non";
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (value instanceof Date) {
|
|
244
|
+
return value.toLocaleDateString();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (Array.isArray(value)) {
|
|
248
|
+
return value.join(", ") || "-";
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return value === undefined || value === null || value === ""
|
|
252
|
+
? "-"
|
|
253
|
+
: String(value);
|
|
254
|
+
};
|
|
255
|
+
|
|
182
256
|
return (
|
|
183
257
|
<form
|
|
184
258
|
autoComplete={autoComplete ?? "off"}
|
|
@@ -186,6 +260,7 @@ export const DynamicForm = forwardRef(
|
|
|
186
260
|
className={className ?? ""}
|
|
187
261
|
>
|
|
188
262
|
<div className="form-content">
|
|
263
|
+
<FieldsContainer>
|
|
189
264
|
{initialForm.map((v, key) => {
|
|
190
265
|
const required = v.onRequired
|
|
191
266
|
? v.onRequired(v.value)
|
|
@@ -195,16 +270,26 @@ export const DynamicForm = forwardRef(
|
|
|
195
270
|
: v.disabled ?? false;
|
|
196
271
|
|
|
197
272
|
return (
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
273
|
+
<FormFieldContainer key={key} field={v} gridEnabled={gridEnabled}>
|
|
274
|
+
<div
|
|
275
|
+
className={`d-flex flex-column ${
|
|
276
|
+
v.className ?? ""
|
|
277
|
+
} form-group form-group-${v.type}`}
|
|
278
|
+
>
|
|
204
279
|
{v.label && <label>{v.label}</label>}
|
|
205
280
|
{v.icon && <Icon classIcon={v.icon} />}
|
|
206
281
|
|
|
207
|
-
{
|
|
282
|
+
{mode === "read" ? (
|
|
283
|
+
<div
|
|
284
|
+
className={`form-read-value ${
|
|
285
|
+
v.type === TypeInputEnum.TEXTAREA
|
|
286
|
+
? "form-read-value--textarea"
|
|
287
|
+
: ""
|
|
288
|
+
}`}
|
|
289
|
+
>
|
|
290
|
+
{getReadValue(v)}
|
|
291
|
+
</div>
|
|
292
|
+
) : v.type === "select" ? (
|
|
208
293
|
<Select
|
|
209
294
|
id={v.id ?? v.name}
|
|
210
295
|
label={undefined}
|
|
@@ -236,6 +321,22 @@ export const DynamicForm = forwardRef(
|
|
|
236
321
|
handleChangeTextArea(name, value, v)
|
|
237
322
|
}
|
|
238
323
|
/>
|
|
324
|
+
) : v.type === TypeInputEnum.PRICE ? (
|
|
325
|
+
<InputPrice
|
|
326
|
+
id={v.id ?? v.name}
|
|
327
|
+
ref={(el) => (inputRefs.current[v.name] = el)}
|
|
328
|
+
name={v.name}
|
|
329
|
+
placeholder={v.placeholder ?? ""}
|
|
330
|
+
autoComplete={v.autoComplete}
|
|
331
|
+
tabIndex={0}
|
|
332
|
+
disabled={disabled}
|
|
333
|
+
autoFocus={v.focus ?? false}
|
|
334
|
+
required={required}
|
|
335
|
+
value={String(values[v.name] ?? "")}
|
|
336
|
+
onChange={(value) =>
|
|
337
|
+
handleChangeTextArea(v.name, value, v)
|
|
338
|
+
}
|
|
339
|
+
/>
|
|
239
340
|
) : (
|
|
240
341
|
<Input
|
|
241
342
|
id={v.id ?? v.name}
|
|
@@ -259,13 +360,15 @@ export const DynamicForm = forwardRef(
|
|
|
259
360
|
onInvalid={v.onInvalid ? v.onInvalid : undefined}
|
|
260
361
|
/>
|
|
261
362
|
)}
|
|
262
|
-
|
|
363
|
+
</div>
|
|
364
|
+
</FormFieldContainer>
|
|
263
365
|
);
|
|
264
366
|
})}
|
|
265
367
|
{children}
|
|
368
|
+
</FieldsContainer>
|
|
266
369
|
</div>
|
|
267
370
|
<div className="d-flex justify-content-end form-footer">
|
|
268
|
-
{!hideSubmit && (
|
|
371
|
+
{mode === "edit" && !hideSubmit && (
|
|
269
372
|
<Button
|
|
270
373
|
id={`button-${id}`}
|
|
271
374
|
disabled={btnDisabledSubmit}
|
package/src/form/Form.view.tsx
CHANGED
|
@@ -18,12 +18,14 @@ export const FormView = (): JSX.Element => {
|
|
|
18
18
|
name: "nom",
|
|
19
19
|
type: TypeInputEnum.PASSWORD,
|
|
20
20
|
required: true,
|
|
21
|
+
col: { xs: 12, md: 6 },
|
|
21
22
|
},
|
|
22
23
|
{
|
|
23
24
|
value: 30,
|
|
24
25
|
label: "Age",
|
|
25
26
|
name: "age",
|
|
26
27
|
type: TypeInputEnum.NUMBER,
|
|
28
|
+
col: { xs: 12, md: 6 },
|
|
27
29
|
},
|
|
28
30
|
{
|
|
29
31
|
value: false,
|
|
@@ -55,5 +57,11 @@ export const FormView = (): JSX.Element => {
|
|
|
55
57
|
const handleSubmit = (values: FormValuesInterface<FormData>) => {
|
|
56
58
|
console.log("Form Submitted: ", values);
|
|
57
59
|
};
|
|
58
|
-
return
|
|
60
|
+
return (
|
|
61
|
+
<DynamicForm
|
|
62
|
+
mode="edit"
|
|
63
|
+
onSubmit={handleSubmit}
|
|
64
|
+
initialForm={initialValues}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
59
67
|
};
|
package/src/form/form.css
CHANGED
|
@@ -59,4 +59,21 @@ form {
|
|
|
59
59
|
button {
|
|
60
60
|
margin-top: 1rem;
|
|
61
61
|
}
|
|
62
|
+
.form-read-value {
|
|
63
|
+
width: 100%;
|
|
64
|
+
min-width: 250px;
|
|
65
|
+
min-height: calc(1em + 1rem + 2px);
|
|
66
|
+
box-sizing: border-box;
|
|
67
|
+
border: 1px solid transparent;
|
|
68
|
+
border-radius: 4px;
|
|
69
|
+
margin: 0.25rem 0;
|
|
70
|
+
padding: 0.5rem 1rem;
|
|
71
|
+
font-size: 0.8rem;
|
|
72
|
+
line-height: normal;
|
|
73
|
+
overflow-wrap: anywhere;
|
|
74
|
+
}
|
|
75
|
+
.form-read-value--textarea {
|
|
76
|
+
min-height: 3.25rem;
|
|
77
|
+
white-space: pre-wrap;
|
|
78
|
+
}
|
|
62
79
|
}
|
package/src/form/form.enum.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { TypeInputEnum } from "./form.enum";
|
|
2
|
+
import { GridBreakpoints } from "../grid/grid.interface";
|
|
3
|
+
|
|
4
|
+
export type FormMode = "read" | "edit";
|
|
2
5
|
|
|
3
6
|
export type FormValuesInterface<
|
|
4
7
|
T extends { [key: string]: string | number | boolean | Date | string[] }
|
|
@@ -25,6 +28,10 @@ export interface FormInterface {
|
|
|
25
28
|
multiple?: boolean;
|
|
26
29
|
options?: { value: string; label: string }[]; // <--- pour les <option>
|
|
27
30
|
className?: string;
|
|
31
|
+
col?: GridBreakpoints;
|
|
32
|
+
formatReadValue?: (
|
|
33
|
+
value: string | number | boolean | Date | string[]
|
|
34
|
+
) => React.ReactNode;
|
|
28
35
|
autoComplete?: string;
|
|
29
36
|
step?: string;
|
|
30
37
|
onChange?: (
|
package/src/grid/col/Col.tsx
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { ColStyled } from "./colStyled/ColStyled";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
md?: number;
|
|
6
|
-
lg?: number;
|
|
2
|
+
import { GridBreakpoints } from "../grid.interface";
|
|
3
|
+
|
|
4
|
+
type ColProps = GridBreakpoints & {
|
|
7
5
|
children: React.ReactNode;
|
|
8
6
|
};
|
|
9
|
-
export const Col: React.FC<ColProps> = ({ xs, sm, md, lg, children }) => {
|
|
7
|
+
export const Col: React.FC<ColProps> = ({ xs, sm, md, lg, xl, children }) => {
|
|
10
8
|
return (
|
|
11
|
-
<ColStyled $xs={xs} $sm={sm} $md={md} $lg={lg}>
|
|
9
|
+
<ColStyled $xs={xs} $sm={sm} $md={md} $lg={lg} $xl={xl}>
|
|
12
10
|
{children}
|
|
13
11
|
</ColStyled>
|
|
14
12
|
);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import styled, { css } from "styled-components";
|
|
2
|
+
import { GridColumnSpan } from "../../grid.interface";
|
|
3
|
+
|
|
2
4
|
const getColWidth = (size = 12) => `${(size / 12) * 100}%`;
|
|
3
5
|
type ColStyledProps = {
|
|
4
|
-
$xs?:
|
|
5
|
-
$sm?:
|
|
6
|
-
$md?:
|
|
7
|
-
$lg?:
|
|
6
|
+
$xs?: GridColumnSpan;
|
|
7
|
+
$sm?: GridColumnSpan;
|
|
8
|
+
$md?: GridColumnSpan;
|
|
9
|
+
$lg?: GridColumnSpan;
|
|
10
|
+
$xl?: GridColumnSpan;
|
|
8
11
|
};
|
|
9
12
|
export const ColStyled = styled.div<ColStyledProps>`
|
|
10
13
|
padding: 0 15px;
|
|
@@ -38,4 +41,13 @@ export const ColStyled = styled.div<ColStyledProps>`
|
|
|
38
41
|
max-width: ${getColWidth($lg)};
|
|
39
42
|
}
|
|
40
43
|
`}
|
|
44
|
+
|
|
45
|
+
${({ $xl }) =>
|
|
46
|
+
$xl &&
|
|
47
|
+
css`
|
|
48
|
+
@container (min-width: 1200px) {
|
|
49
|
+
flex: 0 0 ${getColWidth($xl)};
|
|
50
|
+
max-width: ${getColWidth($xl)};
|
|
51
|
+
}
|
|
52
|
+
`}
|
|
41
53
|
`;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export type GridColumnSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
2
|
+
|
|
3
|
+
export interface GridBreakpoints {
|
|
4
|
+
xs?: GridColumnSpan;
|
|
5
|
+
sm?: GridColumnSpan;
|
|
6
|
+
md?: GridColumnSpan;
|
|
7
|
+
lg?: GridColumnSpan;
|
|
8
|
+
xl?: GridColumnSpan;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface GridInterface extends GridBreakpoints {
|
|
6
12
|
children: React.ReactNode;
|
|
7
13
|
}
|
package/src/header/Header.tsx
CHANGED