@tsiky/components-r19 1.1.0 → 1.3.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.
Files changed (50) hide show
  1. package/package.json +1 -1
  2. package/src/components/AnnouncementPanel/FlexRowContainer.css +17 -17
  3. package/src/components/AnnouncementPanel/FlexRowContainer.stories.tsx +329 -329
  4. package/src/components/AnnouncementPanel/FlexRowContainer.tsx +24 -24
  5. package/src/components/AnnouncementPanel/ListBox/CounterListBox.css +56 -56
  6. package/src/components/AnnouncementPanel/ListBox/CounterListBox.stories.tsx +292 -292
  7. package/src/components/AnnouncementPanel/ListBox/CounterListBox.tsx +106 -106
  8. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.css +57 -57
  9. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.stories.tsx +189 -189
  10. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.tsx +138 -138
  11. package/src/components/AnnouncementPanel/ListBox/TrendListBox.css +61 -61
  12. package/src/components/AnnouncementPanel/ListBox/TrendListBox.stories.tsx +257 -257
  13. package/src/components/AnnouncementPanel/ListBox/TrendListBox.tsx +90 -90
  14. package/src/components/AnnouncementPanel/ListBox/index.ts +3 -3
  15. package/src/components/AnnouncementPanel/ListContentContainer.css +23 -23
  16. package/src/components/AnnouncementPanel/ListContentContainer.stories.tsx +212 -212
  17. package/src/components/AnnouncementPanel/ListContentContainer.tsx +33 -33
  18. package/src/components/AnnouncementPanel/index.ts +3 -3
  19. package/src/components/Charts/area-chart-admission/AreaChartAdmission.tsx +7 -1
  20. package/src/components/Charts/bar-chart/BarChart.tsx +6 -2
  21. package/src/components/Charts/boxplot-chart/BoxPlotChart.tsx +114 -114
  22. package/src/components/Charts/mixed-chart/MixedChart.tsx +1 -1
  23. package/src/components/Charts/sankey-adaptation/sankey.tsx +70 -70
  24. package/src/components/DraggableSwitcher/DraggableSwitcherButton.tsx +58 -58
  25. package/src/components/DraggableSwitcher/context/useDraggableSwitcher.tsx +45 -45
  26. package/src/components/DraggableSwitcher/index.ts +2 -2
  27. package/src/components/DynamicInput/DynamicInput.module.css +125 -126
  28. package/src/components/DynamicInput/input/SelectInput.tsx +75 -75
  29. package/src/components/DynamicInput/input/assets/SelectInput.module.css +95 -95
  30. package/src/components/DynamicTable/AdvancedFilters.tsx +196 -196
  31. package/src/components/DynamicTable/ColumnSorter.tsx +185 -185
  32. package/src/components/DynamicTable/Pagination.tsx +115 -115
  33. package/src/components/DynamicTable/TableCell.tsx +38 -30
  34. package/src/components/DynamicTable/TableHeader.tsx +39 -34
  35. package/src/components/DynamicTable/TableauDynamique.module.css +77 -70
  36. package/src/components/DynamicTable/TableauDynamique.tsx +154 -154
  37. package/src/components/DynamicTable/filters/SelectFilter.tsx +69 -69
  38. package/src/components/DynamicTable/tools/tableTypes.ts +63 -63
  39. package/src/components/EntryControl/EntryControl.tsx +117 -117
  40. package/src/components/Grid/grid.css +285 -285
  41. package/src/components/MetricsPanel/MetricsPanel.tsx +37 -37
  42. package/src/components/MetricsPanel/renderers/CompactRenderer.tsx +1 -1
  43. package/src/components/NavItem/NavItem.tsx +58 -58
  44. package/src/components/PeriodRange/PeriodRange.module.css +158 -158
  45. package/src/components/PeriodRange/PeriodRange.tsx +130 -130
  46. package/src/components/PeriodSelect/PeriodSelect.module.css +64 -65
  47. package/src/components/PeriodSelect/PeriodSelect.tsx +48 -42
  48. package/src/components/SearchBar/SearchBar.css +40 -40
  49. package/src/components/TranslationKey/TranslationKey.css +272 -272
  50. package/src/components/TranslationKey/TranslationKey.tsx +8 -7
@@ -1,130 +1,130 @@
1
- /* File: components/PeriodRange/PeriodRange.tsx */
2
- 'use client';
3
- import { useEffect, useRef, useState } from 'react';
4
- import styles from './PeriodRange.module.css';
5
-
6
- export type Sampling = 'Par jour' | 'Par semaine' | 'Par mois' | 'Par heure';
7
-
8
- export interface PeriodRangeProps {
9
- start?: string; // 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:mm'
10
- end?: string;
11
- onChange?: (range: { start: string; end: string }) => void;
12
- sampling?: Sampling;
13
- onSamplingChange?: (s: Sampling) => void;
14
- className?: string;
15
- }
16
-
17
- export default function PeriodRange({
18
- start = '',
19
- end = '',
20
- onChange,
21
- sampling = 'Par jour',
22
- onSamplingChange,
23
- className = '',
24
- }: PeriodRangeProps) {
25
- const [from, setFrom] = useState<string>(start);
26
- const [to, setTo] = useState<string>(end);
27
- const [localSampling, setLocalSampling] = useState<Sampling>(sampling);
28
- const containerRef = useRef<HTMLDivElement | null>(null);
29
-
30
- // keep local state in sync if parent changes props
31
- useEffect(() => setFrom(start), [start]);
32
- useEffect(() => setTo(end), [end]);
33
- useEffect(() => setLocalSampling(sampling), [sampling]);
34
-
35
- useEffect(() => {
36
- function handleClickOutside(e: MouseEvent) {
37
- const t = e.target as Node | null;
38
- if (containerRef.current && t && !containerRef.current.contains(t)) {
39
- // keep behaviour simple: we don't show custom popovers here
40
- }
41
- }
42
- document.addEventListener('mousedown', handleClickOutside);
43
- return () => document.removeEventListener('mousedown', handleClickOutside);
44
- }, []);
45
-
46
- useEffect(() => {
47
- onChange?.({ start: from, end: to });
48
- }, [from, to, onChange]);
49
-
50
- const handleSamplingChange = (s: Sampling) => {
51
- setLocalSampling(s);
52
- onSamplingChange?.(s);
53
- };
54
-
55
- return (
56
- <div className={`${styles.wrapper} ${className}`} ref={containerRef}>
57
- <label className={styles.label} aria-hidden>
58
- <svg
59
- className={styles.calendarIcon}
60
- xmlns='http://www.w3.org/2000/svg'
61
- viewBox='0 0 24 24'
62
- width='18'
63
- height='18'
64
- aria-hidden
65
- >
66
- <path fill='currentColor' d='M7 10h5v5H7z' opacity='0' />
67
- <path
68
- fill='currentColor'
69
- d='M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zM5 20V9h14l.002 11H5z'
70
- />
71
- </svg>
72
- <span className={styles.labelText}>Période</span>
73
- </label>
74
-
75
- <div className={styles.rangeRow}>
76
- <div className={styles.dateWrap}>
77
- <label className={styles.innerLabel} htmlFor='period-from'>
78
- Début
79
- </label>
80
- <input
81
- id='period-from'
82
- className={styles.dateInput}
83
- type='date'
84
- value={from}
85
- onChange={(e) => setFrom(e.target.value)}
86
- aria-label='Date de début'
87
- />
88
- </div>
89
-
90
- <div className={styles.sepWrap} aria-hidden>
91
- <span className={styles.separator}>—</span>
92
- </div>
93
-
94
- <div className={styles.dateWrap}>
95
- <label className={styles.innerLabel} htmlFor='period-to'>
96
- Fin
97
- </label>
98
- <div className={styles.inputWithIcon}>
99
- <input
100
- id='period-to'
101
- className={styles.dateInput}
102
- type='date'
103
- value={to}
104
- onChange={(e) => setTo(e.target.value)}
105
- aria-label='Date de fin'
106
- />
107
- </div>
108
- </div>
109
-
110
- <div className={styles.samplingWrap}>
111
- <label className={styles.samplingLabel} htmlFor='period-sampling'>
112
- Échantillonnage
113
- </label>
114
- <select
115
- id='period-sampling'
116
- className={styles.samplingSelect}
117
- value={localSampling}
118
- onChange={(e) => handleSamplingChange(e.target.value as Sampling)}
119
- aria-label='Échantillonnage'
120
- >
121
- <option>Par jour</option>
122
- <option>Par semaine</option>
123
- <option>Par mois</option>
124
- <option>Par heure</option>
125
- </select>
126
- </div>
127
- </div>
128
- </div>
129
- );
130
- }
1
+ /* File: components/PeriodRange/PeriodRange.tsx */
2
+ 'use client';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import styles from './PeriodRange.module.css';
5
+
6
+ export type Sampling = 'Par jour' | 'Par semaine' | 'Par mois' | 'Par heure';
7
+
8
+ export interface PeriodRangeProps {
9
+ start?: string; // 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:mm'
10
+ end?: string;
11
+ onChange?: (range: { start: string; end: string }) => void;
12
+ sampling?: Sampling;
13
+ onSamplingChange?: (s: Sampling) => void;
14
+ className?: string;
15
+ }
16
+
17
+ export default function PeriodRange({
18
+ start = '',
19
+ end = '',
20
+ onChange,
21
+ sampling = 'Par jour',
22
+ onSamplingChange,
23
+ className = '',
24
+ }: PeriodRangeProps) {
25
+ const [from, setFrom] = useState<string>(start);
26
+ const [to, setTo] = useState<string>(end);
27
+ const [localSampling, setLocalSampling] = useState<Sampling>(sampling);
28
+ const containerRef = useRef<HTMLDivElement | null>(null);
29
+
30
+ // keep local state in sync if parent changes props
31
+ useEffect(() => setFrom(start), [start]);
32
+ useEffect(() => setTo(end), [end]);
33
+ useEffect(() => setLocalSampling(sampling), [sampling]);
34
+
35
+ useEffect(() => {
36
+ function handleClickOutside(e: MouseEvent) {
37
+ const t = e.target as Node | null;
38
+ if (containerRef.current && t && !containerRef.current.contains(t)) {
39
+ // keep behaviour simple: we don't show custom popovers here
40
+ }
41
+ }
42
+ document.addEventListener('mousedown', handleClickOutside);
43
+ return () => document.removeEventListener('mousedown', handleClickOutside);
44
+ }, []);
45
+
46
+ useEffect(() => {
47
+ onChange?.({ start: from, end: to });
48
+ }, [from, to, onChange]);
49
+
50
+ const handleSamplingChange = (s: Sampling) => {
51
+ setLocalSampling(s);
52
+ onSamplingChange?.(s);
53
+ };
54
+
55
+ return (
56
+ <div className={`${styles.wrapper} ${className}`} ref={containerRef}>
57
+ <label className={styles.label} aria-hidden>
58
+ <svg
59
+ className={styles.calendarIcon}
60
+ xmlns='http://www.w3.org/2000/svg'
61
+ viewBox='0 0 24 24'
62
+ width='18'
63
+ height='18'
64
+ aria-hidden
65
+ >
66
+ <path fill='currentColor' d='M7 10h5v5H7z' opacity='0' />
67
+ <path
68
+ fill='currentColor'
69
+ d='M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zM5 20V9h14l.002 11H5z'
70
+ />
71
+ </svg>
72
+ <span className={styles.labelText}>Période</span>
73
+ </label>
74
+
75
+ <div className={styles.rangeRow}>
76
+ <div className={styles.dateWrap}>
77
+ <label className={styles.innerLabel} htmlFor='period-from'>
78
+ Début
79
+ </label>
80
+ <input
81
+ id='period-from'
82
+ className={styles.dateInput}
83
+ type='date'
84
+ value={from}
85
+ onChange={(e) => setFrom(e.target.value)}
86
+ aria-label='Date de début'
87
+ />
88
+ </div>
89
+
90
+ <div className={styles.sepWrap} aria-hidden>
91
+ <span className={styles.separator}>—</span>
92
+ </div>
93
+
94
+ <div className={styles.dateWrap}>
95
+ <label className={styles.innerLabel} htmlFor='period-to'>
96
+ Fin
97
+ </label>
98
+ <div className={styles.inputWithIcon}>
99
+ <input
100
+ id='period-to'
101
+ className={styles.dateInput}
102
+ type='date'
103
+ value={to}
104
+ onChange={(e) => setTo(e.target.value)}
105
+ aria-label='Date de fin'
106
+ />
107
+ </div>
108
+ </div>
109
+
110
+ <div className={styles.samplingWrap}>
111
+ <label className={styles.samplingLabel} htmlFor='period-sampling'>
112
+ Échantillonnage
113
+ </label>
114
+ <select
115
+ id='period-sampling'
116
+ className={styles.samplingSelect}
117
+ value={localSampling}
118
+ onChange={(e) => handleSamplingChange(e.target.value as Sampling)}
119
+ aria-label='Échantillonnage'
120
+ >
121
+ <option>Par jour</option>
122
+ <option>Par semaine</option>
123
+ <option>Par mois</option>
124
+ <option>Par heure</option>
125
+ </select>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ );
130
+ }
@@ -1,65 +1,64 @@
1
- .container {
2
- display: flex;
3
- align-items: center;
4
- gap: 8px;
5
- border-radius: 8px;
6
- height: 100%;
7
- }
8
-
9
- .icon {
10
- color: #6b7280; /* gris doux */
11
- display: flex;
12
- flex-wrap: wrap;
13
- align-items: center;
14
- gap: 5px;
15
- }
16
-
17
- .icon p {
18
- margin: 0;
19
- padding: 0;
20
- line-height: 1; /* évite décalage vertical dû au line-height */
21
- font-size: 14px;
22
- }
23
-
24
- .selectWrapper {
25
- display: flex;
26
- align-items: center; /* centre verticalement */
27
- height: 100%;
28
- /* margin-top: 10px; */
29
- width: 20%;
30
- }
31
-
32
- /* Large desktop */
33
- @media (max-width: 1200px) {
34
- .selectWrapper {
35
- width: 35%;
36
- }
37
- }
38
-
39
- /* Tablet landscape */
40
- @media (max-width: 992px) {
41
- .selectWrapper {
42
- width: 45%;
43
- }
44
- }
45
-
46
- /* Tablet portrait */
47
- @media (max-width: 768px) {
48
- .selectWrapper {
49
- width: 55%;
50
- }
51
- }
52
-
53
- /* Small mobile */
54
- @media (max-width: 576px) {
55
- .selectWrapper {
56
- width: 70%;
57
- }
58
- }
59
-
60
- /* Extra small mobile */
61
- @media (max-width: 400px) {
62
- .selectWrapper {
63
- width: 85%;
64
- }
65
- }
1
+ .container {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 8px;
5
+ border-radius: 8px;
6
+ height: 100%;
7
+ }
8
+
9
+ .icon {
10
+ display: flex;
11
+ flex-wrap: wrap;
12
+ align-items: center;
13
+ gap: 5px;
14
+ }
15
+
16
+ .icon p {
17
+ margin: 0;
18
+ padding: 0;
19
+ line-height: 1; /* évite décalage vertical dû au line-height */
20
+ font-size: 14px;
21
+ }
22
+
23
+ .selectWrapper {
24
+ display: flex;
25
+ align-items: center; /* centre verticalement */
26
+ height: 100%;
27
+ /* margin-top: 10px; */
28
+ width: 20%;
29
+ }
30
+
31
+ /* Large desktop */
32
+ @media (max-width: 1200px) {
33
+ .selectWrapper {
34
+ width: 35%;
35
+ }
36
+ }
37
+
38
+ /* Tablet landscape */
39
+ @media (max-width: 992px) {
40
+ .selectWrapper {
41
+ width: 45%;
42
+ }
43
+ }
44
+
45
+ /* Tablet portrait */
46
+ @media (max-width: 768px) {
47
+ .selectWrapper {
48
+ width: 55%;
49
+ }
50
+ }
51
+
52
+ /* Small mobile */
53
+ @media (max-width: 576px) {
54
+ .selectWrapper {
55
+ width: 70%;
56
+ }
57
+ }
58
+
59
+ /* Extra small mobile */
60
+ @media (max-width: 400px) {
61
+ .selectWrapper {
62
+ width: 85%;
63
+ }
64
+ }
@@ -1,42 +1,48 @@
1
- import React, { useState } from 'react';
2
- import styles from './PeriodSelect.module.css';
3
- import { Calendar } from 'lucide-react';
4
- import { SelectInput } from '../DynamicInput';
5
-
6
- export interface Option {
7
- label: string;
8
- value: string;
9
- }
10
-
11
- interface PeriodSelectProps {
12
- options: Option[];
13
- defaultValue?: string;
14
- onChange?: (value: string) => void;
15
- }
16
-
17
- export const PeriodSelect: React.FC<PeriodSelectProps> = ({ options, defaultValue, onChange }) => {
18
- const [value, setValue] = useState(defaultValue || options[0]?.value || '');
19
-
20
- const handleChange = (val: string) => {
21
- setValue(val);
22
- onChange?.(val);
23
- };
24
-
25
- return (
26
- <div className={styles.container}>
27
- <div className={styles.icon}>
28
- <Calendar size={18} />
29
- <p> Période: </p>
30
- </div>
31
-
32
- <div className={styles.selectWrapper}>
33
- <SelectInput
34
- field={{ name: 'periode', label: '', options }}
35
- value={value}
36
- onChange={handleChange}
37
- onBlur={() => {}}
38
- />
39
- </div>
40
- </div>
41
- );
42
- };
1
+ import React, { useState } from 'react';
2
+ import styles from './PeriodSelect.module.css';
3
+ import { Calendar } from 'lucide-react';
4
+ import { SelectInput } from '../DynamicInput';
5
+
6
+ export interface Option {
7
+ label: string;
8
+ value: string;
9
+ }
10
+
11
+ interface PeriodSelectProps {
12
+ options: Option[];
13
+ defaultValue?: string;
14
+ onChange?: (value: string) => void;
15
+ label?: string;
16
+ }
17
+
18
+ export const PeriodSelect: React.FC<PeriodSelectProps> = ({
19
+ options,
20
+ defaultValue,
21
+ onChange,
22
+ label,
23
+ }) => {
24
+ const [value, setValue] = useState(defaultValue || options[0]?.value || '');
25
+
26
+ const handleChange = (val: string) => {
27
+ setValue(val);
28
+ onChange?.(val);
29
+ };
30
+
31
+ return (
32
+ <div className={styles.container}>
33
+ <div className={styles.icon}>
34
+ <Calendar size={18} />
35
+ <p>{label}</p>
36
+ </div>
37
+
38
+ <div className={styles.selectWrapper}>
39
+ <SelectInput
40
+ field={{ name: 'periode', label: '', options }}
41
+ value={value}
42
+ onChange={handleChange}
43
+ onBlur={() => {}}
44
+ />
45
+ </div>
46
+ </div>
47
+ );
48
+ };
@@ -1,40 +1,40 @@
1
- .search-container {
2
- position: relative;
3
- width: 100%;
4
- }
5
-
6
- .search-icon {
7
- position: absolute;
8
- left: 1rem;
9
- top: 50%;
10
- transform: translateY(-50%);
11
- width: 1.25rem;
12
- height: 1.25rem;
13
- color: #9ca3af;
14
- pointer-events: none;
15
- }
16
-
17
- .search-input {
18
- width: 100%;
19
- padding: 1rem 1rem 1rem 3rem; /* top right bottom left */
20
- border: 1px solid #d1d5db;
21
- border-radius: 0.5rem;
22
- outline: none;
23
- background-color: white;
24
- color: var(--color-text);
25
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26
- box-sizing: border-box;
27
- border: 1px solid var(--color-border);
28
- background-color: var(--color-card-background);
29
- }
30
-
31
- .search-input::placeholder {
32
- color: #9ca3af;
33
- font-family: var(--font-primary);
34
- font-size: var(--text-paragraph);
35
- font-weight: var(--font-normal);
36
- }
37
-
38
- .search-input:focus {
39
- border-color: #d1d5db;
40
- }
1
+ .search-container {
2
+ position: relative;
3
+ width: 100%;
4
+ }
5
+
6
+ .search-icon {
7
+ position: absolute;
8
+ left: 1rem;
9
+ top: 50%;
10
+ transform: translateY(-50%);
11
+ width: 1.25rem;
12
+ height: 1.25rem;
13
+ color: #9ca3af;
14
+ pointer-events: none;
15
+ }
16
+
17
+ .search-input {
18
+ width: 100%;
19
+ padding: 1rem 1rem 1rem 3rem; /* top right bottom left */
20
+ border: 1px solid #d1d5db;
21
+ border-radius: 0.5rem;
22
+ outline: none;
23
+ background-color: white;
24
+ color: var(--color-text);
25
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26
+ box-sizing: border-box;
27
+ border: 1px solid var(--color-border);
28
+ background-color: var(--color-card-background);
29
+ }
30
+
31
+ .search-input::placeholder {
32
+ color: #9ca3af;
33
+ font-family: var(--font-primary);
34
+ font-size: var(--text-paragraph);
35
+ font-weight: var(--font-normal);
36
+ }
37
+
38
+ .search-input:focus {
39
+ border-color: #d1d5db;
40
+ }