@tsiky/components-r19 1.0.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.
Files changed (61) hide show
  1. package/index.ts +35 -33
  2. package/package.json +1 -1
  3. package/src/components/AnnouncementPanel/FlexRowContainer.css +17 -17
  4. package/src/components/AnnouncementPanel/FlexRowContainer.stories.tsx +329 -329
  5. package/src/components/AnnouncementPanel/FlexRowContainer.tsx +24 -24
  6. package/src/components/AnnouncementPanel/ListBox/CounterListBox.css +56 -56
  7. package/src/components/AnnouncementPanel/ListBox/CounterListBox.stories.tsx +292 -292
  8. package/src/components/AnnouncementPanel/ListBox/CounterListBox.tsx +106 -106
  9. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.css +57 -57
  10. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.stories.tsx +189 -189
  11. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.tsx +138 -138
  12. package/src/components/AnnouncementPanel/ListBox/TrendListBox.css +61 -61
  13. package/src/components/AnnouncementPanel/ListBox/TrendListBox.stories.tsx +257 -257
  14. package/src/components/AnnouncementPanel/ListBox/TrendListBox.tsx +90 -90
  15. package/src/components/AnnouncementPanel/ListBox/index.ts +3 -3
  16. package/src/components/AnnouncementPanel/ListContentContainer.css +23 -23
  17. package/src/components/AnnouncementPanel/ListContentContainer.stories.tsx +212 -212
  18. package/src/components/AnnouncementPanel/ListContentContainer.tsx +33 -33
  19. package/src/components/AnnouncementPanel/index.ts +3 -3
  20. package/src/components/Charts/area-chart-admission/AreaChartAdmission.tsx +129 -89
  21. package/src/components/Charts/bar-chart/BarChart.tsx +171 -132
  22. package/src/components/Charts/boxplot-chart/BoxPlotChart.tsx +114 -114
  23. package/src/components/Charts/mixed-chart/MixedChart.tsx +65 -9
  24. package/src/components/Charts/sankey-adaptation/sankey.tsx +70 -70
  25. package/src/components/Charts/sankey-chart/SankeyChart.tsx +183 -155
  26. package/src/components/Confirmationpopup/ConfirmationPopup.module.css +88 -0
  27. package/src/components/Confirmationpopup/ConfirmationPopup.stories.tsx +94 -0
  28. package/src/components/Confirmationpopup/ConfirmationPopup.tsx +47 -0
  29. package/src/components/Confirmationpopup/index.ts +6 -0
  30. package/src/components/Confirmationpopup/useConfirmationPopup.ts +48 -0
  31. package/src/components/DayStatCard/DayStatCard.tsx +96 -69
  32. package/src/components/DraggableSwitcher/DraggableSwitcherButton.tsx +58 -58
  33. package/src/components/DraggableSwitcher/context/useDraggableSwitcher.tsx +45 -45
  34. package/src/components/DraggableSwitcher/index.ts +2 -2
  35. package/src/components/DynamicInput/input/SelectInput.tsx +75 -75
  36. package/src/components/DynamicInput/input/assets/SelectInput.module.css +95 -95
  37. package/src/components/DynamicTable/TableCell.tsx +38 -30
  38. package/src/components/DynamicTable/TableHeader.tsx +39 -34
  39. package/src/components/DynamicTable/TableauDynamique.module.css +1333 -1287
  40. package/src/components/DynamicTable/TableauDynamique.tsx +154 -154
  41. package/src/components/DynamicTable/tools/tableTypes.ts +63 -63
  42. package/src/components/Grid/Grid.tsx +5 -0
  43. package/src/components/Grid/grid.css +285 -285
  44. package/src/components/Header/Header.tsx +4 -2
  45. package/src/components/Header/header.css +61 -31
  46. package/src/components/MetricsPanel/MetricsPanel.module.css +688 -636
  47. package/src/components/MetricsPanel/MetricsPanel.tsx +220 -282
  48. package/src/components/MetricsPanel/renderers/CompactRenderer.tsx +148 -125
  49. package/src/components/NavBar/NavBar.tsx +1 -1
  50. package/src/components/NavItem/NavItem.tsx +58 -58
  51. package/src/components/PeriodRange/PeriodRange.module.css +158 -158
  52. package/src/components/PeriodRange/PeriodRange.tsx +130 -130
  53. package/src/components/SearchBar/SearchBar.css +40 -40
  54. package/src/components/SelectFilter/SelectFilter.module.css +249 -0
  55. package/src/components/SelectFilter/SelectFilter.stories.tsx +321 -0
  56. package/src/components/SelectFilter/SelectFilter.tsx +219 -0
  57. package/src/components/SelectFilter/index.ts +2 -0
  58. package/src/components/SelectFilter/types.ts +19 -0
  59. package/src/components/TranslationKey/TranslationKey.css +272 -272
  60. package/src/components/TranslationKey/TranslationKey.tsx +266 -245
  61. package/src/components/TrendList/TrendList.tsx +72 -45
@@ -1,69 +1,96 @@
1
- import React from 'react';
2
- import type { CSSProperties } from 'react';
3
- import './DayStatCard.css';
4
- import { CircularProgress } from '../CircularProgress/CircularProgress';
5
- import type { CircularProgressProps } from '../CircularProgress/CircularProgress';
6
-
7
- export type DayStatCardProps = {
8
- background?: string;
9
- headerTop: string;
10
- headerBottom?: string;
11
- headerTopStyle?: CSSProperties;
12
- headerBottomStyle?: CSSProperties;
13
- progress1: CircularProgressProps;
14
- progress2: CircularProgressProps;
15
- progress3: CircularProgressProps;
16
- style?: CSSProperties;
17
- size?: number;
18
- className?: string;
19
- };
20
-
21
- export const DayStatCard: React.FC<DayStatCardProps> = ({
22
- size = 200,
23
- background = '#fff',
24
- headerTop,
25
- headerBottom,
26
- headerTopStyle,
27
- headerBottomStyle,
28
- progress1,
29
- progress2,
30
- progress3,
31
- style,
32
- className = '',
33
- }) => {
34
- const progress1WithDefaults = { size: size * 0.5, ...progress1 };
35
- const progress2WithDefaults = { size: size * 0.4, ...progress2 };
36
- const progress3WithDefaults = { size: size * 0.4, ...progress3 };
37
-
38
- return (
39
- <div style={{ width: size, background, ...style }} className={`stat-card ${className}`}>
40
- <div className='stat-card-header'>
41
- <div className='stat-card-header-top' style={headerTopStyle}>
42
- {headerTop}
43
- </div>
44
- {headerBottom && (
45
- <div className='stat-card-header-bottom' style={headerBottomStyle}>
46
- {headerBottom}
47
- </div>
48
- )}
49
- </div>
50
-
51
- <div className='stat-card-body'>
52
- {/* Première ligne - Progress Centré */}
53
- <div className='progress-row-single'>
54
- <CircularProgress {...progress1WithDefaults} />
55
- </div>
56
-
57
- {/* Deuxième ligne - Deux Progress côte à côte */}
58
- <div className='progress-row-double'>
59
- <div className='progress-item'>
60
- <CircularProgress {...progress2WithDefaults} />
61
- </div>
62
- <div className='progress-item'>
63
- <CircularProgress {...progress3WithDefaults} />
64
- </div>
65
- </div>
66
- </div>
67
- </div>
68
- );
69
- };
1
+ import React from 'react';
2
+ import type { CSSProperties } from 'react';
3
+ import './DayStatCard.css';
4
+ import { CircularProgress } from '../CircularProgress/CircularProgress';
5
+ import type { CircularProgressProps } from '../CircularProgress/CircularProgress';
6
+ import { Move } from 'lucide-react';
7
+
8
+ export type DayStatCardProps = {
9
+ background?: string;
10
+ headerTop: string;
11
+ headerBottom?: string;
12
+ headerTopStyle?: CSSProperties;
13
+ headerBottomStyle?: CSSProperties;
14
+ progress1: CircularProgressProps;
15
+ progress2: CircularProgressProps;
16
+ progress3: CircularProgressProps;
17
+ style?: CSSProperties;
18
+ size?: number;
19
+ className?: string;
20
+ draggable?: boolean; // nouvelle prop
21
+ };
22
+
23
+ export const DayStatCard: React.FC<DayStatCardProps> = ({
24
+ size = 200,
25
+ background = '#fff',
26
+ headerTop,
27
+ headerBottom,
28
+ headerTopStyle,
29
+ headerBottomStyle,
30
+ progress1,
31
+ progress2,
32
+ progress3,
33
+ style,
34
+ className = '',
35
+ draggable = false,
36
+ }) => {
37
+ const progress1WithDefaults = { size: size * 0.5, ...progress1 };
38
+ const progress2WithDefaults = { size: size * 0.4, ...progress2 };
39
+ const progress3WithDefaults = { size: size * 0.4, ...progress3 };
40
+
41
+ return (
42
+ <div
43
+ style={{ width: size, background, position: 'relative', ...style }}
44
+ className={`stat-card ${className}`}
45
+ >
46
+ {/* Header toujours visible */}
47
+ <div className='stat-card-header'>
48
+ <div className='stat-card-header-top' style={headerTopStyle}>
49
+ {headerTop}
50
+ </div>
51
+ {headerBottom && (
52
+ <div className='stat-card-header-bottom' style={headerBottomStyle}>
53
+ {headerBottom}
54
+ </div>
55
+ )}
56
+ </div>
57
+
58
+ {/* Body */}
59
+ <div className='stat-card-body' style={{ opacity: draggable ? 0 : 1 }}>
60
+ {/* Première ligne - Progress Centré */}
61
+ <div className='progress-row-single'>
62
+ <CircularProgress {...progress1WithDefaults} />
63
+ </div>
64
+
65
+ {/* Deuxième ligne - Deux Progress côte à côte */}
66
+ <div className='progress-row-double'>
67
+ <div className='progress-item'>
68
+ <CircularProgress {...progress2WithDefaults} />
69
+ </div>
70
+ <div className='progress-item'>
71
+ <CircularProgress {...progress3WithDefaults} />
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ {/* Overlay Move */}
77
+ {draggable && (
78
+ <div
79
+ style={{
80
+ position: 'absolute',
81
+ top: 0,
82
+ left: 0,
83
+ width: '100%',
84
+ height: '100%',
85
+ display: 'flex',
86
+ alignItems: 'center',
87
+ justifyContent: 'center',
88
+ pointerEvents: 'none',
89
+ }}
90
+ >
91
+ <Move size={32} strokeWidth={1.5} style={{ opacity: 0.8 }} />
92
+ </div>
93
+ )}
94
+ </div>
95
+ );
96
+ };
@@ -1,58 +1,58 @@
1
- 'use client';
2
- import { useEffect, useState } from 'react';
3
- import { useDraggableSwitcher } from './context/useDraggableSwitcher';
4
- import { Switcher } from '../Switcher/Switcher';
5
-
6
- export interface DraggableSwitcherButtonProps {
7
- leftIcon?: string;
8
- rightIcon?: string;
9
- colors?: {
10
- bg?: string;
11
- activeBg?: string;
12
- border?: string;
13
- circle?: string;
14
- icon?: string;
15
- icon2?: string;
16
- };
17
- size?: number;
18
- }
19
-
20
- export const DraggableSwitcherButton = ({
21
- leftIcon = 'Move',
22
- rightIcon = 'MoveDiagonal',
23
- colors = {
24
- bg: '#e5e7eb',
25
- activeBg: '#10b981',
26
- border: '#ffffff',
27
- circle: '#ffffff',
28
- icon: '#10b981',
29
- icon2: '#ffffff',
30
- },
31
- size = 24,
32
- }: DraggableSwitcherButtonProps) => {
33
- const { isDraggable, switchDraggable } = useDraggableSwitcher();
34
- const [mounted, setMounted] = useState(false);
35
-
36
- useEffect(() => {
37
- setMounted(true);
38
- }, []);
39
-
40
- if (!mounted) return null;
41
-
42
- const handleToggle = (checked: boolean) => {
43
- switchDraggable(checked);
44
- };
45
-
46
- return (
47
- <Switcher
48
- leftIcon={leftIcon}
49
- rightIcon={rightIcon}
50
- checked={isDraggable}
51
- onToggle={handleToggle}
52
- colors={colors}
53
- size={size}
54
- />
55
- );
56
- };
57
-
58
- export default DraggableSwitcherButton;
1
+ 'use client';
2
+ import { useEffect, useState } from 'react';
3
+ import { useDraggableSwitcher } from './context/useDraggableSwitcher';
4
+ import { Switcher } from '../Switcher/Switcher';
5
+
6
+ export interface DraggableSwitcherButtonProps {
7
+ leftIcon?: string;
8
+ rightIcon?: string;
9
+ colors?: {
10
+ bg?: string;
11
+ activeBg?: string;
12
+ border?: string;
13
+ circle?: string;
14
+ icon?: string;
15
+ icon2?: string;
16
+ };
17
+ size?: number;
18
+ }
19
+
20
+ export const DraggableSwitcherButton = ({
21
+ leftIcon = 'Move',
22
+ rightIcon = 'MoveDiagonal',
23
+ colors = {
24
+ bg: '#e5e7eb',
25
+ activeBg: '#10b981',
26
+ border: '#ffffff',
27
+ circle: '#ffffff',
28
+ icon: '#10b981',
29
+ icon2: '#ffffff',
30
+ },
31
+ size = 24,
32
+ }: DraggableSwitcherButtonProps) => {
33
+ const { isDraggable, switchDraggable } = useDraggableSwitcher();
34
+ const [mounted, setMounted] = useState(false);
35
+
36
+ useEffect(() => {
37
+ setMounted(true);
38
+ }, []);
39
+
40
+ if (!mounted) return null;
41
+
42
+ const handleToggle = (checked: boolean) => {
43
+ switchDraggable(checked);
44
+ };
45
+
46
+ return (
47
+ <Switcher
48
+ leftIcon={leftIcon}
49
+ rightIcon={rightIcon}
50
+ checked={isDraggable}
51
+ onToggle={handleToggle}
52
+ colors={colors}
53
+ size={size}
54
+ />
55
+ );
56
+ };
57
+
58
+ export default DraggableSwitcherButton;
@@ -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
+ };