@tsiky/components-r19 1.1.0 → 1.2.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/package.json +1 -1
- package/src/components/AnnouncementPanel/FlexRowContainer.css +17 -17
- package/src/components/AnnouncementPanel/FlexRowContainer.stories.tsx +329 -329
- package/src/components/AnnouncementPanel/FlexRowContainer.tsx +24 -24
- package/src/components/AnnouncementPanel/ListBox/CounterListBox.css +56 -56
- package/src/components/AnnouncementPanel/ListBox/CounterListBox.stories.tsx +292 -292
- package/src/components/AnnouncementPanel/ListBox/CounterListBox.tsx +106 -106
- package/src/components/AnnouncementPanel/ListBox/SimpleListBox.css +57 -57
- package/src/components/AnnouncementPanel/ListBox/SimpleListBox.stories.tsx +189 -189
- package/src/components/AnnouncementPanel/ListBox/SimpleListBox.tsx +138 -138
- package/src/components/AnnouncementPanel/ListBox/TrendListBox.css +61 -61
- package/src/components/AnnouncementPanel/ListBox/TrendListBox.stories.tsx +257 -257
- package/src/components/AnnouncementPanel/ListBox/TrendListBox.tsx +90 -90
- package/src/components/AnnouncementPanel/ListBox/index.ts +3 -3
- package/src/components/AnnouncementPanel/ListContentContainer.css +23 -23
- package/src/components/AnnouncementPanel/ListContentContainer.stories.tsx +212 -212
- package/src/components/AnnouncementPanel/ListContentContainer.tsx +33 -33
- package/src/components/AnnouncementPanel/index.ts +3 -3
- package/src/components/Charts/area-chart-admission/AreaChartAdmission.tsx +7 -1
- package/src/components/Charts/bar-chart/BarChart.tsx +6 -2
- package/src/components/Charts/boxplot-chart/BoxPlotChart.tsx +114 -114
- package/src/components/Charts/mixed-chart/MixedChart.tsx +1 -1
- package/src/components/Charts/sankey-adaptation/sankey.tsx +70 -70
- package/src/components/DraggableSwitcher/DraggableSwitcherButton.tsx +58 -58
- package/src/components/DraggableSwitcher/context/useDraggableSwitcher.tsx +45 -45
- package/src/components/DraggableSwitcher/index.ts +2 -2
- package/src/components/DynamicInput/input/SelectInput.tsx +75 -75
- package/src/components/DynamicInput/input/assets/SelectInput.module.css +95 -95
- package/src/components/DynamicTable/AdvancedFilters.tsx +196 -196
- package/src/components/DynamicTable/ColumnSorter.tsx +185 -185
- package/src/components/DynamicTable/Pagination.tsx +115 -115
- package/src/components/DynamicTable/TableCell.tsx +38 -30
- package/src/components/DynamicTable/TableHeader.tsx +39 -34
- package/src/components/DynamicTable/TableauDynamique.module.css +79 -33
- package/src/components/DynamicTable/TableauDynamique.tsx +154 -154
- package/src/components/DynamicTable/filters/SelectFilter.tsx +69 -69
- package/src/components/DynamicTable/tools/tableTypes.ts +63 -63
- package/src/components/EntryControl/EntryControl.tsx +117 -117
- package/src/components/Grid/grid.css +285 -285
- package/src/components/MetricsPanel/MetricsPanel.tsx +37 -37
- package/src/components/MetricsPanel/renderers/CompactRenderer.tsx +1 -1
- package/src/components/NavItem/NavItem.tsx +58 -58
- package/src/components/PeriodRange/PeriodRange.module.css +158 -158
- package/src/components/PeriodRange/PeriodRange.tsx +130 -130
- package/src/components/SearchBar/SearchBar.css +40 -40
- package/src/components/TranslationKey/TranslationKey.css +272 -272
- package/src/components/TranslationKey/TranslationKey.tsx +8 -7
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { createContext, useContext, useState, useEffect } from 'react';
|
|
3
|
-
import type { ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
interface DraggableContextType {
|
|
6
|
-
isDraggable: boolean;
|
|
7
|
-
switchDraggable: (value: boolean) => void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const DraggableContext = createContext<DraggableContextType | undefined>(undefined);
|
|
11
|
-
|
|
12
|
-
export const DraggableProvider = ({ children }: { children: ReactNode }) => {
|
|
13
|
-
const [isDraggable, setIsDraggable] = useState(false);
|
|
14
|
-
|
|
15
|
-
// Charger depuis localStorage au premier rendu
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const stored = localStorage.getItem('isDraggable');
|
|
18
|
-
if (stored !== null) {
|
|
19
|
-
setIsDraggable(stored === 'true'); // localStorage stocke toujours des strings
|
|
20
|
-
}
|
|
21
|
-
}, []);
|
|
22
|
-
|
|
23
|
-
// Sauvegarder dans localStorage quand ça change
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
localStorage.setItem('isDraggable', String(isDraggable));
|
|
26
|
-
}, [isDraggable]);
|
|
27
|
-
|
|
28
|
-
const switchDraggable = (value: boolean) => {
|
|
29
|
-
setIsDraggable(value);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<DraggableContext.Provider value={{ isDraggable, switchDraggable }}>
|
|
34
|
-
{children}
|
|
35
|
-
</DraggableContext.Provider>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const useDraggableSwitcher = () => {
|
|
40
|
-
const context = useContext(DraggableContext);
|
|
41
|
-
if (!context) {
|
|
42
|
-
throw new Error('useDraggableSwitcher must be used inside a DraggableProvider');
|
|
43
|
-
}
|
|
44
|
-
return context;
|
|
45
|
-
};
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext, useState, useEffect } from 'react';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface DraggableContextType {
|
|
6
|
+
isDraggable: boolean;
|
|
7
|
+
switchDraggable: (value: boolean) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DraggableContext = createContext<DraggableContextType | undefined>(undefined);
|
|
11
|
+
|
|
12
|
+
export const DraggableProvider = ({ children }: { children: ReactNode }) => {
|
|
13
|
+
const [isDraggable, setIsDraggable] = useState(false);
|
|
14
|
+
|
|
15
|
+
// Charger depuis localStorage au premier rendu
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const stored = localStorage.getItem('isDraggable');
|
|
18
|
+
if (stored !== null) {
|
|
19
|
+
setIsDraggable(stored === 'true'); // localStorage stocke toujours des strings
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
// Sauvegarder dans localStorage quand ça change
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
localStorage.setItem('isDraggable', String(isDraggable));
|
|
26
|
+
}, [isDraggable]);
|
|
27
|
+
|
|
28
|
+
const switchDraggable = (value: boolean) => {
|
|
29
|
+
setIsDraggable(value);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<DraggableContext.Provider value={{ isDraggable, switchDraggable }}>
|
|
34
|
+
{children}
|
|
35
|
+
</DraggableContext.Provider>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const useDraggableSwitcher = () => {
|
|
40
|
+
const context = useContext(DraggableContext);
|
|
41
|
+
if (!context) {
|
|
42
|
+
throw new Error('useDraggableSwitcher must be used inside a DraggableProvider');
|
|
43
|
+
}
|
|
44
|
+
return context;
|
|
45
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './DraggableSwitcherButton';
|
|
2
|
-
export * from './context/useDraggableSwitcher';
|
|
1
|
+
export * from './DraggableSwitcherButton';
|
|
2
|
+
export * from './context/useDraggableSwitcher';
|
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import styles from './assets/SelectInput.module.css';
|
|
4
|
-
|
|
5
|
-
interface SelectInputProps {
|
|
6
|
-
field: any;
|
|
7
|
-
value: any;
|
|
8
|
-
onChange: (value: any) => void;
|
|
9
|
-
onBlur: () => void;
|
|
10
|
-
error?: string;
|
|
11
|
-
touched?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const SelectInput: React.FC<SelectInputProps> = ({
|
|
15
|
-
field,
|
|
16
|
-
value,
|
|
17
|
-
onChange,
|
|
18
|
-
onBlur,
|
|
19
|
-
error,
|
|
20
|
-
touched,
|
|
21
|
-
}) => {
|
|
22
|
-
const hasError = Boolean(touched && error);
|
|
23
|
-
const displayLabel = field.label || '';
|
|
24
|
-
const placeholder = field.placeholder || '';
|
|
25
|
-
|
|
26
|
-
// Trouve le label de l'option sélectionnée si présente
|
|
27
|
-
const selectedOptionLabel =
|
|
28
|
-
field.options?.find((o: any) => String(o.value) === String(value))?.label ?? '';
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div
|
|
32
|
-
className={`${styles.wrapper} ${hasError ? styles.wrapperInvalid : ''} ${
|
|
33
|
-
value ? styles.wrapperHasValue : ''
|
|
34
|
-
}`}
|
|
35
|
-
>
|
|
36
|
-
{/* Select natif (masqué visuellement mais accessible) */}
|
|
37
|
-
<select
|
|
38
|
-
id={field.name}
|
|
39
|
-
name={field.name}
|
|
40
|
-
className={styles.nativeSelect}
|
|
41
|
-
value={value ?? ''}
|
|
42
|
-
onChange={(e) => onChange(e.target.value)}
|
|
43
|
-
onBlur={onBlur}
|
|
44
|
-
aria-invalid={hasError}
|
|
45
|
-
aria-label={displayLabel}
|
|
46
|
-
>
|
|
47
|
-
{/* Placeholder : visible quand le select est fermé, caché dans la liste */}
|
|
48
|
-
<option value='' disabled hidden>
|
|
49
|
-
{placeholder || `Sélectionnez ${displayLabel?.toLowerCase() || ''}`}
|
|
50
|
-
</option>
|
|
51
|
-
|
|
52
|
-
{field.options?.map((option: any, idx: number) => (
|
|
53
|
-
<option key={idx} value={option.value} className={styles.optionStyle}>
|
|
54
|
-
{option.label}
|
|
55
|
-
</option>
|
|
56
|
-
))}
|
|
57
|
-
</select>
|
|
58
|
-
|
|
59
|
-
{/* Couche visuelle */}
|
|
60
|
-
<div className={styles.display}>
|
|
61
|
-
{displayLabel && <span className={styles.topLabel}>{displayLabel}</span>}
|
|
62
|
-
<span
|
|
63
|
-
className={`${styles.valueLine} ${value ? styles.valueActive : styles.valuePlaceholder}`}
|
|
64
|
-
>
|
|
65
|
-
{value ? selectedOptionLabel : placeholder}
|
|
66
|
-
</span>
|
|
67
|
-
|
|
68
|
-
{/* caret (SVG) */}
|
|
69
|
-
<span className={styles.caret} aria-hidden='true'></span>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
{hasError && <span className={styles.error}>{error}</span>}
|
|
73
|
-
</div>
|
|
74
|
-
);
|
|
75
|
-
};
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styles from './assets/SelectInput.module.css';
|
|
4
|
+
|
|
5
|
+
interface SelectInputProps {
|
|
6
|
+
field: any;
|
|
7
|
+
value: any;
|
|
8
|
+
onChange: (value: any) => void;
|
|
9
|
+
onBlur: () => void;
|
|
10
|
+
error?: string;
|
|
11
|
+
touched?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const SelectInput: React.FC<SelectInputProps> = ({
|
|
15
|
+
field,
|
|
16
|
+
value,
|
|
17
|
+
onChange,
|
|
18
|
+
onBlur,
|
|
19
|
+
error,
|
|
20
|
+
touched,
|
|
21
|
+
}) => {
|
|
22
|
+
const hasError = Boolean(touched && error);
|
|
23
|
+
const displayLabel = field.label || '';
|
|
24
|
+
const placeholder = field.placeholder || '';
|
|
25
|
+
|
|
26
|
+
// Trouve le label de l'option sélectionnée si présente
|
|
27
|
+
const selectedOptionLabel =
|
|
28
|
+
field.options?.find((o: any) => String(o.value) === String(value))?.label ?? '';
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
className={`${styles.wrapper} ${hasError ? styles.wrapperInvalid : ''} ${
|
|
33
|
+
value ? styles.wrapperHasValue : ''
|
|
34
|
+
}`}
|
|
35
|
+
>
|
|
36
|
+
{/* Select natif (masqué visuellement mais accessible) */}
|
|
37
|
+
<select
|
|
38
|
+
id={field.name}
|
|
39
|
+
name={field.name}
|
|
40
|
+
className={styles.nativeSelect}
|
|
41
|
+
value={value ?? ''}
|
|
42
|
+
onChange={(e) => onChange(e.target.value)}
|
|
43
|
+
onBlur={onBlur}
|
|
44
|
+
aria-invalid={hasError}
|
|
45
|
+
aria-label={displayLabel}
|
|
46
|
+
>
|
|
47
|
+
{/* Placeholder : visible quand le select est fermé, caché dans la liste */}
|
|
48
|
+
<option value='' disabled hidden>
|
|
49
|
+
{placeholder || `Sélectionnez ${displayLabel?.toLowerCase() || ''}`}
|
|
50
|
+
</option>
|
|
51
|
+
|
|
52
|
+
{field.options?.map((option: any, idx: number) => (
|
|
53
|
+
<option key={idx} value={option.value} className={styles.optionStyle}>
|
|
54
|
+
{option.label}
|
|
55
|
+
</option>
|
|
56
|
+
))}
|
|
57
|
+
</select>
|
|
58
|
+
|
|
59
|
+
{/* Couche visuelle */}
|
|
60
|
+
<div className={styles.display}>
|
|
61
|
+
{displayLabel && <span className={styles.topLabel}>{displayLabel}</span>}
|
|
62
|
+
<span
|
|
63
|
+
className={`${styles.valueLine} ${value ? styles.valueActive : styles.valuePlaceholder}`}
|
|
64
|
+
>
|
|
65
|
+
{value ? selectedOptionLabel : placeholder}
|
|
66
|
+
</span>
|
|
67
|
+
|
|
68
|
+
{/* caret (SVG) */}
|
|
69
|
+
<span className={styles.caret} aria-hidden='true'></span>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{hasError && <span className={styles.error}>{error}</span>}
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
.wrapper {
|
|
2
|
-
position: relative;
|
|
3
|
-
width: 100%;
|
|
4
|
-
border: 1px solid #d3d6db;
|
|
5
|
-
border-radius: 10px;
|
|
6
|
-
padding: 12px 44px 12px 14px;
|
|
7
|
-
box-sizing: border-box;
|
|
8
|
-
cursor: pointer;
|
|
9
|
-
transition:
|
|
10
|
-
border-color 0.15s ease,
|
|
11
|
-
box-shadow 0.15s ease;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.wrapper:focus-within {
|
|
15
|
-
border-color: #2684ff;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.wrapperInvalid {
|
|
19
|
-
border-color: #dc3545;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.nativeSelect {
|
|
23
|
-
position: absolute;
|
|
24
|
-
inset: 0;
|
|
25
|
-
width: 100%;
|
|
26
|
-
height: 100%;
|
|
27
|
-
opacity: 0;
|
|
28
|
-
border: none;
|
|
29
|
-
background: transparent;
|
|
30
|
-
cursor: pointer;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.display {
|
|
34
|
-
display: flex;
|
|
35
|
-
flex-direction: column;
|
|
36
|
-
pointer-events: none;
|
|
37
|
-
user-select: none;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.topLabel {
|
|
41
|
-
font-size: 0.8rem;
|
|
42
|
-
color: #8b9094;
|
|
43
|
-
font-weight: 500;
|
|
44
|
-
line-height: 1;
|
|
45
|
-
margin-bottom: 6px;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.valueLine {
|
|
49
|
-
font-size: 1rem;
|
|
50
|
-
line-height: 1.1;
|
|
51
|
-
white-space: nowrap;
|
|
52
|
-
overflow: hidden;
|
|
53
|
-
text-overflow: ellipsis;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.valuePlaceholder {
|
|
57
|
-
color: #99a0a6;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.valueActive {
|
|
61
|
-
color: var(--color-text, #222);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.caret {
|
|
65
|
-
position: absolute;
|
|
66
|
-
right: 12px;
|
|
67
|
-
top: 50%;
|
|
68
|
-
transform: translateY(-50%);
|
|
69
|
-
width: 16px;
|
|
70
|
-
height: 16px;
|
|
71
|
-
pointer-events: none;
|
|
72
|
-
background-image: url("data:image/svg+xml;utf8,<svg fill='%23888' height='16' viewBox='0 0 24 24' width='16' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/></svg>");
|
|
73
|
-
background-repeat: no-repeat;
|
|
74
|
-
background-position: center;
|
|
75
|
-
background-size: 16px;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.error {
|
|
79
|
-
display: block;
|
|
80
|
-
margin-top: 8px;
|
|
81
|
-
font-size: 0.85rem;
|
|
82
|
-
color: #dc3545;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
@media (prefers-reduced-motion: reduce) {
|
|
86
|
-
.wrapper,
|
|
87
|
-
.wrapper:focus-within {
|
|
88
|
-
transition: none;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.optionStyle {
|
|
93
|
-
background-color: var(--color-card-background);
|
|
94
|
-
color: var(--color-text);
|
|
95
|
-
}
|
|
1
|
+
.wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
border: 1px solid #d3d6db;
|
|
5
|
+
border-radius: 10px;
|
|
6
|
+
padding: 12px 44px 12px 14px;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
transition:
|
|
10
|
+
border-color 0.15s ease,
|
|
11
|
+
box-shadow 0.15s ease;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.wrapper:focus-within {
|
|
15
|
+
border-color: #2684ff;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.wrapperInvalid {
|
|
19
|
+
border-color: #dc3545;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.nativeSelect {
|
|
23
|
+
position: absolute;
|
|
24
|
+
inset: 0;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
opacity: 0;
|
|
28
|
+
border: none;
|
|
29
|
+
background: transparent;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.display {
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
user-select: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.topLabel {
|
|
41
|
+
font-size: 0.8rem;
|
|
42
|
+
color: #8b9094;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
line-height: 1;
|
|
45
|
+
margin-bottom: 6px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.valueLine {
|
|
49
|
+
font-size: 1rem;
|
|
50
|
+
line-height: 1.1;
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
text-overflow: ellipsis;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.valuePlaceholder {
|
|
57
|
+
color: #99a0a6;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.valueActive {
|
|
61
|
+
color: var(--color-text, #222);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.caret {
|
|
65
|
+
position: absolute;
|
|
66
|
+
right: 12px;
|
|
67
|
+
top: 50%;
|
|
68
|
+
transform: translateY(-50%);
|
|
69
|
+
width: 16px;
|
|
70
|
+
height: 16px;
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
background-image: url("data:image/svg+xml;utf8,<svg fill='%23888' height='16' viewBox='0 0 24 24' width='16' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/></svg>");
|
|
73
|
+
background-repeat: no-repeat;
|
|
74
|
+
background-position: center;
|
|
75
|
+
background-size: 16px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.error {
|
|
79
|
+
display: block;
|
|
80
|
+
margin-top: 8px;
|
|
81
|
+
font-size: 0.85rem;
|
|
82
|
+
color: #dc3545;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (prefers-reduced-motion: reduce) {
|
|
86
|
+
.wrapper,
|
|
87
|
+
.wrapper:focus-within {
|
|
88
|
+
transition: none;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.optionStyle {
|
|
93
|
+
background-color: var(--color-card-background);
|
|
94
|
+
color: var(--color-text);
|
|
95
|
+
}
|