@rsuci/shared-form-components 1.0.29 → 1.0.32

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 (48) hide show
  1. package/dist/components/form-renderer/ConfirmationModal.d.ts +20 -0
  2. package/dist/components/form-renderer/ConfirmationModal.d.ts.map +1 -0
  3. package/dist/components/form-renderer/ConfirmationModal.js +79 -0
  4. package/dist/components/form-renderer/FormActions.d.ts +21 -0
  5. package/dist/components/form-renderer/FormActions.d.ts.map +1 -0
  6. package/dist/components/form-renderer/FormActions.js +81 -0
  7. package/dist/components/form-renderer/FormNavigationButtons.d.ts +23 -0
  8. package/dist/components/form-renderer/FormNavigationButtons.d.ts.map +1 -0
  9. package/dist/components/form-renderer/FormNavigationButtons.js +35 -0
  10. package/dist/components/form-renderer/FormProgress.d.ts +19 -0
  11. package/dist/components/form-renderer/FormProgress.d.ts.map +1 -0
  12. package/dist/components/form-renderer/FormProgress.js +26 -0
  13. package/dist/components/form-renderer/FormRenderer.d.ts +39 -0
  14. package/dist/components/form-renderer/FormRenderer.d.ts.map +1 -0
  15. package/dist/components/form-renderer/FormRenderer.js +113 -0
  16. package/dist/components/form-renderer/FormRendererContext.d.ts +109 -0
  17. package/dist/components/form-renderer/FormRendererContext.d.ts.map +1 -0
  18. package/dist/components/form-renderer/FormRendererContext.js +114 -0
  19. package/dist/components/form-renderer/GroupeInstanceTabs.d.ts +18 -0
  20. package/dist/components/form-renderer/GroupeInstanceTabs.d.ts.map +1 -0
  21. package/dist/components/form-renderer/GroupeInstanceTabs.js +174 -0
  22. package/dist/components/form-renderer/index.d.ts +17 -0
  23. package/dist/components/form-renderer/index.d.ts.map +1 -0
  24. package/dist/components/form-renderer/index.js +23 -0
  25. package/dist/hooks/useFormInstances.d.ts +87 -0
  26. package/dist/hooks/useFormInstances.d.ts.map +1 -0
  27. package/dist/hooks/useFormInstances.js +197 -0
  28. package/dist/hooks/useFormNavigation.d.ts +72 -0
  29. package/dist/hooks/useFormNavigation.d.ts.map +1 -0
  30. package/dist/hooks/useFormNavigation.js +147 -0
  31. package/dist/hooks/useFormRenderer.d.ts +87 -0
  32. package/dist/hooks/useFormRenderer.d.ts.map +1 -0
  33. package/dist/hooks/useFormRenderer.js +177 -0
  34. package/dist/hooks/useFormValidation.d.ts +50 -0
  35. package/dist/hooks/useFormValidation.d.ts.map +1 -0
  36. package/dist/hooks/useFormValidation.js +175 -0
  37. package/dist/index.d.ts +13 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +20 -0
  40. package/dist/lib/__tests__/date-functions.test.d.ts +5 -0
  41. package/dist/lib/__tests__/date-functions.test.d.ts.map +1 -0
  42. package/dist/lib/__tests__/date-functions.test.js +184 -0
  43. package/dist/lib/utils/groupeInstanceManager.d.ts +88 -0
  44. package/dist/lib/utils/groupeInstanceManager.d.ts.map +1 -0
  45. package/dist/lib/utils/groupeInstanceManager.js +606 -0
  46. package/dist/types/form-renderer.d.ts +115 -1
  47. package/dist/types/form-renderer.d.ts.map +1 -1
  48. package/package.json +5 -1
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Composant Modal de Confirmation
3
+ * RSU v2 - Composant partagé pour les confirmations utilisateur
4
+ */
5
+ import React from 'react';
6
+ export type ConfirmationModalType = 'danger' | 'warning' | 'info' | 'success';
7
+ export interface ConfirmationModalProps {
8
+ isOpen: boolean;
9
+ title: string;
10
+ message: string;
11
+ confirmText?: string;
12
+ cancelText?: string;
13
+ onConfirm: () => void;
14
+ onCancel: () => void;
15
+ type?: ConfirmationModalType;
16
+ isProcessing?: boolean;
17
+ }
18
+ declare const ConfirmationModal: React.FC<ConfirmationModalProps>;
19
+ export default ConfirmationModal;
20
+ //# sourceMappingURL=ConfirmationModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmationModal.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/ConfirmationModal.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAA4B,MAAM,OAAO,CAAC;AAGjD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA8JvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Composant Modal de Confirmation
3
+ * RSU v2 - Composant partagé pour les confirmations utilisateur
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ import { useEffect, useRef } from 'react';
8
+ import { AlertTriangle, Info, AlertCircle, CheckCircle } from 'lucide-react';
9
+ const ConfirmationModal = ({ isOpen, title, message, confirmText = 'Confirmer', cancelText = 'Annuler', onConfirm, onCancel, type = 'warning', isProcessing = false }) => {
10
+ const modalRef = useRef(null);
11
+ const confirmButtonRef = useRef(null);
12
+ // Focus sur le bouton de confirmation à l'ouverture
13
+ useEffect(() => {
14
+ if (isOpen && confirmButtonRef.current) {
15
+ confirmButtonRef.current.focus();
16
+ }
17
+ }, [isOpen]);
18
+ // Gérer la fermeture avec Escape
19
+ useEffect(() => {
20
+ const handleEscape = (e) => {
21
+ if (e.key === 'Escape' && isOpen && !isProcessing) {
22
+ onCancel();
23
+ }
24
+ };
25
+ document.addEventListener('keydown', handleEscape);
26
+ return () => document.removeEventListener('keydown', handleEscape);
27
+ }, [isOpen, isProcessing, onCancel]);
28
+ if (!isOpen)
29
+ return null;
30
+ // Configuration du style selon le type
31
+ const getTypeConfig = () => {
32
+ switch (type) {
33
+ case 'danger':
34
+ return {
35
+ icon: _jsx(AlertTriangle, { className: "h-6 w-6 text-red-500" }),
36
+ iconBg: 'bg-red-100',
37
+ confirmBg: 'bg-red-600 hover:bg-red-700 focus:ring-red-500',
38
+ confirmText: 'text-white'
39
+ };
40
+ case 'warning':
41
+ return {
42
+ icon: _jsx(AlertCircle, { className: "h-6 w-6 text-yellow-500" }),
43
+ iconBg: 'bg-yellow-100',
44
+ confirmBg: 'bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500',
45
+ confirmText: 'text-white'
46
+ };
47
+ case 'info':
48
+ return {
49
+ icon: _jsx(Info, { className: "h-6 w-6 text-blue-500" }),
50
+ iconBg: 'bg-blue-100',
51
+ confirmBg: 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500',
52
+ confirmText: 'text-white'
53
+ };
54
+ case 'success':
55
+ return {
56
+ icon: _jsx(CheckCircle, { className: "h-6 w-6 text-green-500" }),
57
+ iconBg: 'bg-green-100',
58
+ confirmBg: 'bg-green-600 hover:bg-green-700 focus:ring-green-500',
59
+ confirmText: 'text-white'
60
+ };
61
+ default:
62
+ return {
63
+ icon: _jsx(AlertCircle, { className: "h-6 w-6 text-yellow-500" }),
64
+ iconBg: 'bg-yellow-100',
65
+ confirmBg: 'bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500',
66
+ confirmText: 'text-white'
67
+ };
68
+ }
69
+ };
70
+ const config = getTypeConfig();
71
+ // Empêcher le clic sur l'overlay de fermer le modal pendant le traitement
72
+ const handleOverlayClick = (e) => {
73
+ if (e.target === e.currentTarget && !isProcessing) {
74
+ onCancel();
75
+ }
76
+ };
77
+ return (_jsxs("div", { className: "fixed inset-0 z-50 overflow-y-auto", "aria-labelledby": "modal-title", role: "dialog", "aria-modal": "true", children: [_jsx("div", { className: "fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity", onClick: handleOverlayClick }), _jsx("div", { className: "flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0", children: _jsxs("div", { ref: modalRef, className: "relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg", children: [_jsx("div", { className: "bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4", children: _jsxs("div", { className: "sm:flex sm:items-start", children: [_jsx("div", { className: `mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full ${config.iconBg} sm:mx-0 sm:h-10 sm:w-10`, children: config.icon }), _jsxs("div", { className: "mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left", children: [_jsx("h3", { className: "text-base font-semibold leading-6 text-gray-900", id: "modal-title", children: title }), _jsx("div", { className: "mt-2", children: _jsx("p", { className: "text-sm text-gray-500", children: message }) })] })] }) }), _jsxs("div", { className: "bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6", children: [_jsx("button", { ref: confirmButtonRef, type: "button", disabled: isProcessing, onClick: onConfirm, className: `inline-flex w-full justify-center rounded-md px-3 py-2 text-sm font-semibold shadow-sm ${config.confirmBg} ${config.confirmText} sm:ml-3 sm:w-auto focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed`, children: isProcessing ? (_jsxs("span", { className: "flex items-center", children: [_jsx("span", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" }), "Traitement..."] })) : (confirmText) }), _jsx("button", { type: "button", disabled: isProcessing, onClick: onCancel, className: "mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto disabled:opacity-50 disabled:cursor-not-allowed", children: cancelText })] })] }) })] }));
78
+ };
79
+ export default ConfirmationModal;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Composant des actions du formulaire (Soumettre, Brouillon, Annuler, Validation DR)
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ import React from 'react';
6
+ export interface FormActionsProps {
7
+ /** Classes CSS additionnelles */
8
+ className?: string;
9
+ /** Callback personnalisé pour la soumission */
10
+ onSubmit?: () => Promise<void>;
11
+ /** Callback personnalisé pour le brouillon */
12
+ onSaveDraft?: () => Promise<void>;
13
+ /** Callback personnalisé pour l'annulation */
14
+ onCancel?: () => void;
15
+ }
16
+ /**
17
+ * Boutons d'action du formulaire
18
+ */
19
+ export declare const FormActions: React.FC<FormActionsProps>;
20
+ export default FormActions;
21
+ //# sourceMappingURL=FormActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormActions.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormActions.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4JlD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Composant des actions du formulaire (Soumettre, Brouillon, Annuler, Validation DR)
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ import { useState } from 'react';
8
+ import { useFormRendererContext } from './FormRendererContext';
9
+ /**
10
+ * Boutons d'action du formulaire
11
+ */
12
+ export const FormActions = ({ className = '', onSubmit: customOnSubmit, onSaveDraft: customOnSaveDraft, onCancel: customOnCancel }) => {
13
+ const { navigation, validation, responses, config, callbacks, formulaire, isSubmitting, setIsSubmitting, hasUnsavedChanges, effectiveDisabled, groupesWithInstances } = useFormRendererContext();
14
+ const { isLastGroup } = navigation;
15
+ const { mode, features } = config;
16
+ const labels = config.labels || {};
17
+ // État local pour les actions
18
+ const [isSavingDraft, setIsSavingDraft] = useState(false);
19
+ // Textes des boutons
20
+ const submitText = labels.submitButton || (mode === 'admin' ? 'Valider' : 'Soumettre');
21
+ const draftText = labels.draftButton || 'Enregistrer brouillon';
22
+ const cancelText = labels.cancelButton || 'Annuler';
23
+ // Validation complète du formulaire
24
+ const groupes = groupesWithInstances.length > 0 ? groupesWithInstances : formulaire?.groupes || [];
25
+ const isFormValid = validation.validateAllGroups(groupes, responses).isValid;
26
+ // Handlers
27
+ const handleSubmit = async () => {
28
+ if (customOnSubmit) {
29
+ await customOnSubmit();
30
+ return;
31
+ }
32
+ if (effectiveDisabled || isSubmitting)
33
+ return;
34
+ // Valider tout le formulaire
35
+ const result = validation.validateAllGroups(groupes, responses);
36
+ if (!result.isValid) {
37
+ if (callbacks.onValidationError) {
38
+ callbacks.onValidationError(result.errors);
39
+ }
40
+ return;
41
+ }
42
+ setIsSubmitting(true);
43
+ try {
44
+ await callbacks.onSubmit(responses);
45
+ }
46
+ finally {
47
+ setIsSubmitting(false);
48
+ }
49
+ };
50
+ const handleSaveDraft = async () => {
51
+ if (customOnSaveDraft) {
52
+ await customOnSaveDraft();
53
+ return;
54
+ }
55
+ if (!callbacks.onSaveDraft || effectiveDisabled || isSavingDraft)
56
+ return;
57
+ setIsSavingDraft(true);
58
+ try {
59
+ await callbacks.onSaveDraft(responses);
60
+ }
61
+ finally {
62
+ setIsSavingDraft(false);
63
+ }
64
+ };
65
+ const handleCancel = () => {
66
+ if (customOnCancel) {
67
+ customOnCancel();
68
+ return;
69
+ }
70
+ callbacks.onCancel();
71
+ };
72
+ // Ne pas afficher les boutons si on n'est pas sur le dernier groupe
73
+ // (sauf pour le bouton annuler et brouillon qui sont toujours disponibles)
74
+ const showSubmitButton = isLastGroup;
75
+ return (_jsxs("div", { className: `flex flex-wrap gap-2 justify-end ${className}`, children: [_jsx("button", { type: "button", onClick: handleCancel, disabled: isSubmitting || isSavingDraft, className: "px-4 py-2 rounded-lg font-medium transition-colors bg-red-500 text-white hover:bg-red-600 disabled:opacity-50 disabled:cursor-not-allowed", children: cancelText }), mode === 'admin' && features?.saveDraft && callbacks.onSaveDraft && (_jsx("button", { type: "button", onClick: handleSaveDraft, disabled: effectiveDisabled || isSavingDraft || isSubmitting || !hasUnsavedChanges, className: `px-4 py-2 rounded-lg font-medium transition-colors ${hasUnsavedChanges && !effectiveDisabled
76
+ ? 'bg-yellow-500 text-white hover:bg-yellow-600'
77
+ : 'bg-gray-300 text-gray-500 cursor-not-allowed'}`, children: isSavingDraft ? (_jsxs("span", { className: "flex items-center", children: [_jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "Enregistrement..."] })) : (draftText) })), showSubmitButton && (_jsx("button", { type: "button", onClick: handleSubmit, disabled: effectiveDisabled || isSubmitting || !isFormValid, className: `px-4 py-2 rounded-lg font-medium transition-colors ${isFormValid && !effectiveDisabled
78
+ ? 'bg-blue-600 text-white hover:bg-blue-700'
79
+ : 'bg-gray-400 text-gray-200 cursor-not-allowed'}`, title: !isFormValid ? 'Veuillez remplir tous les champs obligatoires' : '', children: isSubmitting ? (_jsxs("span", { className: "flex items-center", children: [_jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "Envoi en cours..."] })) : (submitText) }))] }));
80
+ };
81
+ export default FormActions;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Composant de navigation du formulaire (boutons Précédent/Suivant)
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ import React from 'react';
6
+ export interface FormNavigationButtonsProps {
7
+ /** Classes CSS additionnelles */
8
+ className?: string;
9
+ /** Texte personnalisé pour le bouton Précédent */
10
+ previousLabel?: string;
11
+ /** Texte personnalisé pour le bouton Suivant */
12
+ nextLabel?: string;
13
+ /** Afficher le bouton Précédent */
14
+ showPrevious?: boolean;
15
+ /** Afficher le bouton Suivant */
16
+ showNext?: boolean;
17
+ }
18
+ /**
19
+ * Boutons de navigation entre les groupes du formulaire
20
+ */
21
+ export declare const FormNavigationButtons: React.FC<FormNavigationButtonsProps>;
22
+ export default FormNavigationButtons;
23
+ //# sourceMappingURL=FormNavigationButtons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormNavigationButtons.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormNavigationButtons.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAyFtE,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Composant de navigation du formulaire (boutons Précédent/Suivant)
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ import { useFormRendererContext } from './FormRendererContext';
8
+ /**
9
+ * Boutons de navigation entre les groupes du formulaire
10
+ */
11
+ export const FormNavigationButtons = ({ className = '', previousLabel, nextLabel, showPrevious = true, showNext = true }) => {
12
+ const { navigation, validation, currentGroup, responses, config, effectiveDisabled } = useFormRendererContext();
13
+ const { isFirstGroup, isLastGroup, goToNextGroup, goToPreviousGroup } = navigation;
14
+ const labels = config.labels || {};
15
+ const prevText = previousLabel || labels.previousButton || 'Précédent';
16
+ const nextText = nextLabel || labels.nextButton || 'Suivant';
17
+ // Validation avant navigation
18
+ const canGoNext = validation.validateCurrentGroupRequiredFields(currentGroup, responses);
19
+ const handleNext = () => {
20
+ if (canGoNext && !isLastGroup) {
21
+ goToNextGroup();
22
+ }
23
+ };
24
+ const handlePrevious = () => {
25
+ if (!isFirstGroup) {
26
+ goToPreviousGroup();
27
+ }
28
+ };
29
+ return (_jsxs("div", { className: `flex justify-between items-center ${className}`, children: [showPrevious && (_jsxs("button", { type: "button", onClick: handlePrevious, disabled: isFirstGroup || effectiveDisabled, className: `flex items-center px-4 py-2 rounded-lg font-medium transition-colors ${!isFirstGroup && !effectiveDisabled
30
+ ? 'bg-orange-500 text-white hover:bg-orange-600'
31
+ : 'bg-gray-100 text-gray-400 cursor-not-allowed'}`, children: [_jsx("svg", { className: "h-4 w-4 mr-2", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }), _jsx("span", { className: "hidden sm:inline", children: prevText }), _jsx("span", { className: "sm:hidden", children: "Pr\u00E9c." })] })), (!showPrevious || !showNext) && _jsx("div", {}), showNext && !isLastGroup && (_jsxs("button", { type: "button", onClick: handleNext, disabled: !canGoNext || effectiveDisabled, className: `flex items-center px-4 py-2 rounded-lg font-medium transition-colors ${canGoNext && !effectiveDisabled
32
+ ? 'bg-green-600 text-white hover:bg-green-700'
33
+ : 'bg-gray-400 text-gray-200 cursor-not-allowed'}`, title: !canGoNext ? 'Veuillez remplir tous les champs obligatoires' : 'Passer au groupe suivant', children: [_jsx("span", { className: "hidden sm:inline", children: nextText }), _jsx("span", { className: "sm:hidden", children: "Suiv." }), _jsx("svg", { className: "h-4 w-4 ml-2", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })] }))] }));
34
+ };
35
+ export default FormNavigationButtons;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Composant de barre de progression du formulaire
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ import React from 'react';
6
+ export interface FormProgressProps {
7
+ /** Afficher les labels des groupes */
8
+ showLabels?: boolean;
9
+ /** Afficher le pourcentage */
10
+ showPercentage?: boolean;
11
+ /** Classes CSS additionnelles */
12
+ className?: string;
13
+ }
14
+ /**
15
+ * Barre de progression indiquant l'avancement dans le formulaire
16
+ */
17
+ export declare const FormProgress: React.FC<FormProgressProps>;
18
+ export default FormProgress;
19
+ //# sourceMappingURL=FormProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormProgress.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormProgress.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA8EpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Composant de barre de progression du formulaire
3
+ * RSU v2 - Package Partagé
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ import { useFormRendererContext } from './FormRendererContext';
8
+ /**
9
+ * Barre de progression indiquant l'avancement dans le formulaire
10
+ */
11
+ export const FormProgress = ({ showLabels = false, showPercentage = true, className = '' }) => {
12
+ const { navigation, groupesWithInstances, formulaire } = useFormRendererContext();
13
+ const { navigationState, progressPercent } = navigation;
14
+ const groupes = groupesWithInstances.length > 0 ? groupesWithInstances : formulaire?.groupes || [];
15
+ const currentIndex = navigationState.groupeIndex;
16
+ const totalGroupes = groupes.length;
17
+ if (totalGroupes === 0) {
18
+ return null;
19
+ }
20
+ return (_jsxs("div", { className: `w-full ${className}`, children: [_jsxs("div", { className: "relative", children: [_jsx("div", { className: "w-full bg-gray-200 rounded-full h-2.5", children: _jsx("div", { className: "bg-blue-600 h-2.5 rounded-full transition-all duration-300 ease-out", style: { width: `${progressPercent}%` } }) }), _jsx("div", { className: "flex justify-between mt-1", children: groupes.map((groupe, index) => (_jsxs("div", { className: `flex flex-col items-center ${index <= currentIndex ? 'text-blue-600' : 'text-gray-400'}`, style: { width: `${100 / totalGroupes}%` }, children: [_jsx("div", { className: `w-3 h-3 rounded-full -mt-3 border-2 ${index < currentIndex
21
+ ? 'bg-blue-600 border-blue-600'
22
+ : index === currentIndex
23
+ ? 'bg-white border-blue-600'
24
+ : 'bg-white border-gray-300'}` }), showLabels && (_jsx("span", { className: "text-xs mt-1 truncate max-w-full text-center", children: groupe.designation }))] }, groupe.code))) })] }), _jsxs("div", { className: "flex justify-between items-center mt-2 text-sm text-gray-600", children: [_jsxs("span", { children: ["Groupe ", currentIndex + 1, " sur ", totalGroupes] }), showPercentage && (_jsxs("span", { className: "font-medium text-blue-600", children: [progressPercent, "%"] }))] })] }));
25
+ };
26
+ export default FormProgress;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Composant principal FormRenderer unifié
3
+ * Supporte les modes admin et public via configuration
4
+ * RSU v2 - Package Partagé
5
+ */
6
+ import React from 'react';
7
+ import { FormulaireComplet, EnqueteInstance, EnqueteReponse } from '../../types/enquete';
8
+ import { FormRendererConfig, FormRendererCallbacks } from '../../types/form-renderer';
9
+ import { FormRendererServices, GeographicComponents } from '../../types/services';
10
+ /**
11
+ * Props simplifiées pour FormRenderer
12
+ */
13
+ export interface FormRendererProps {
14
+ /** Le formulaire à rendre */
15
+ formulaire: FormulaireComplet;
16
+ /** L'instance d'enquête (optionnel pour nouvelle enquête) */
17
+ enquete?: EnqueteInstance;
18
+ /** Réponses initiales */
19
+ initialResponses?: Record<string, EnqueteReponse>;
20
+ /** Configuration du FormRenderer */
21
+ config: FormRendererConfig;
22
+ /** Callbacks pour les actions */
23
+ callbacks: FormRendererCallbacks;
24
+ /** Services injectés */
25
+ services?: FormRendererServices;
26
+ /** Composants géographiques injectés */
27
+ geographicComponents?: GeographicComponents;
28
+ /** Désactiver tous les inputs */
29
+ disabled?: boolean;
30
+ /** État de soumission externe */
31
+ isSubmitting?: boolean;
32
+ }
33
+ /**
34
+ * Composant principal FormRenderer
35
+ * Encapsule le Provider et le composant interne
36
+ */
37
+ export declare const FormRenderer: React.FC<FormRendererProps>;
38
+ export default FormRenderer;
39
+ //# sourceMappingURL=FormRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAmBlF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,iCAAiC;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAwOD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgBpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Composant principal FormRenderer unifié
3
+ * Supporte les modes admin et public via configuration
4
+ * RSU v2 - Package Partagé
5
+ */
6
+ 'use client';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ import { useMemo, useCallback, useState } from 'react';
9
+ // Contexte et Provider
10
+ import { FormRendererProvider, useFormRendererContext } from './FormRendererContext';
11
+ // Sous-composants
12
+ import FormProgress from './FormProgress';
13
+ import FormNavigationButtons from './FormNavigationButtons';
14
+ import FormActions from './FormActions';
15
+ import GroupeInstanceTabs from './GroupeInstanceTabs';
16
+ import ConfirmationModal from './ConfirmationModal';
17
+ // Composants de rendu
18
+ import VariableRenderer from '../VariableRenderer';
19
+ // Hooks et utilitaires
20
+ import { useFormTree } from '../../hooks/useFormTree';
21
+ /**
22
+ * Composant interne qui utilise le contexte
23
+ */
24
+ const FormRendererInner = () => {
25
+ const context = useFormRendererContext();
26
+ const { formulaire, enquete, config, callbacks, services, geographicComponents, navigation, validation, instances, responses, updateResponse, hasUnsavedChanges, isSubmitting, effectiveDisabled, currentGroup, currentInstance, groupesWithInstances } = context;
27
+ const { mode, features } = config;
28
+ // État local pour les modals
29
+ const [showCancelModal, setShowCancelModal] = useState(false);
30
+ // FormTree pour la visibilité des variables
31
+ const { formTree, getVisibleVariables } = useFormTree(groupesWithInstances.length > 0 ? groupesWithInstances : formulaire?.groupes || [], responses, { debug: false });
32
+ // Vérifier si une variable est visible
33
+ const isVariableVisible = useCallback((variable) => {
34
+ if (!currentGroup?.code)
35
+ return true;
36
+ const visibleVars = getVisibleVariables(currentGroup.code);
37
+ return visibleVars.some(v => v.code === variable.code);
38
+ }, [currentGroup?.code, getVisibleVariables]);
39
+ // Filtrer les variables selon le mode
40
+ const getFilteredVariables = useCallback((variables) => {
41
+ if (!variables)
42
+ return [];
43
+ // En mode public, filtrer les variables MENAGE et ENQUETE
44
+ if (mode === 'public' && !features?.showMenageVariables && !features?.showEnqueteVariables) {
45
+ return variables.filter(v => v.typeCode !== 'MENAGE' && v.typeCode !== 'ENQUETE');
46
+ }
47
+ return variables;
48
+ }, [mode, features]);
49
+ // Obtenir les variables visibles du groupe actuel
50
+ const visibleVariables = useMemo(() => {
51
+ if (!currentGroup?.variables)
52
+ return [];
53
+ const filtered = getFilteredVariables(currentGroup.variables);
54
+ return filtered.filter(v => isVariableVisible(v));
55
+ }, [currentGroup, getFilteredVariables, isVariableVisible]);
56
+ // Handler pour le changement de variable
57
+ const handleVariableChange = useCallback((variable, value) => {
58
+ const numeroMembre = currentGroup?.estMultiple
59
+ ? currentInstance?.numeroInstance
60
+ : undefined;
61
+ updateResponse(variable.code, value, variable, numeroMembre);
62
+ }, [currentGroup, currentInstance, updateResponse]);
63
+ // Handler pour l'annulation
64
+ const handleCancelClick = () => {
65
+ if (hasUnsavedChanges) {
66
+ setShowCancelModal(true);
67
+ }
68
+ else {
69
+ callbacks.onCancel();
70
+ }
71
+ };
72
+ const handleConfirmCancel = () => {
73
+ setShowCancelModal(false);
74
+ callbacks.onCancel();
75
+ };
76
+ // Handler pour le changement d'instance
77
+ const handleInstanceChange = (instanceIndex) => {
78
+ navigation.changeInstance(instanceIndex);
79
+ };
80
+ // Handler pour l'ajout d'instance
81
+ const handleInstanceAdded = (instance) => {
82
+ navigation.updateTotalInstances(currentGroup?.instances?.length || 1);
83
+ // Naviguer vers la nouvelle instance
84
+ if (currentGroup?.instances) {
85
+ navigation.changeInstance(currentGroup.instances.length - 1);
86
+ }
87
+ };
88
+ // Handler pour la suppression d'instance
89
+ const handleInstanceRemoved = (instanceNumber) => {
90
+ navigation.updateTotalInstances(currentGroup?.instances?.length || 1);
91
+ // Revenir à la première instance
92
+ navigation.changeInstance(0);
93
+ };
94
+ // Vérification de la présence de groupes
95
+ if (!formulaire || !formulaire.groupes || formulaire.groupes.length === 0) {
96
+ return (_jsx("div", { className: "min-h-screen bg-gray-50 flex items-center justify-center", children: _jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-8 text-center max-w-md", children: [_jsx("div", { className: "text-red-500 mb-4", children: _jsx("svg", { className: "w-12 h-12 mx-auto", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z" }) }) }), _jsx("h3", { className: "text-lg font-medium text-gray-900 mb-2", children: "Formulaire non configur\u00E9" }), _jsx("p", { className: "text-gray-600 mb-4", children: "Ce formulaire ne contient aucun groupe de variables." }), _jsx("button", { onClick: callbacks.onCancel, className: "inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", children: "Retour" })] }) }));
97
+ }
98
+ return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsxs("div", { className: "max-w-4xl mx-auto px-4 py-6", children: [_jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6", children: [_jsx("h1", { className: "text-xl font-semibold text-gray-900 mb-4", children: formulaire.designation }), _jsx(FormProgress, { showPercentage: true })] }), _jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6", children: [_jsxs("div", { className: "mb-6", children: [_jsx("h2", { className: "text-lg font-medium text-gray-900", children: currentGroup?.designation }), currentGroup?.estMultiple && (_jsx("p", { className: "text-sm text-gray-500 mt-1", children: "Groupe \u00E0 instances multiples" }))] }), currentGroup?.estMultiple && currentGroup.instances && (_jsx("div", { className: "mb-6", children: _jsx(GroupeInstanceTabs, { groupe: currentGroup, currentInstanceIndex: navigation.navigationState.instanceIndex, responses: responses, onInstanceChange: handleInstanceChange, onInstanceAdded: handleInstanceAdded, onInstanceRemoved: handleInstanceRemoved, disabled: effectiveDisabled }) })), _jsx("div", { className: "space-y-6", children: visibleVariables.map(variable => {
99
+ const responseKey = currentGroup?.estMultiple && currentInstance?.numeroInstance
100
+ ? `${variable.code}_${currentInstance.numeroInstance}`
101
+ : variable.code;
102
+ const currentValue = responses[responseKey]?.valeur;
103
+ return (_jsx(VariableRenderer, { variable: variable, value: currentValue, onChange: (value) => handleVariableChange(variable, value), disabled: effectiveDisabled, numeroMembre: currentGroup?.estMultiple ? currentInstance?.numeroInstance : undefined, services: services, geographicComponents: geographicComponents, formulaireVariables: formulaire.variables, allResponses: responses, reponses: responses }, variable.id));
104
+ }) })] }), _jsx("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4", children: _jsxs("div", { className: "flex flex-col sm:flex-row justify-between items-center gap-4", children: [_jsx(FormNavigationButtons, {}), _jsx(FormActions, { onCancel: handleCancelClick })] }) })] }), _jsx(ConfirmationModal, { isOpen: showCancelModal, title: "Annuler les modifications", message: "Vous avez des modifications non sauvegard\u00E9es. \u00CAtes-vous s\u00FBr de vouloir quitter ?", confirmText: "Quitter", cancelText: "Continuer", onConfirm: handleConfirmCancel, onCancel: () => setShowCancelModal(false), type: "danger" })] }));
105
+ };
106
+ /**
107
+ * Composant principal FormRenderer
108
+ * Encapsule le Provider et le composant interne
109
+ */
110
+ export const FormRenderer = (props) => {
111
+ return (_jsx(FormRendererProvider, { formulaire: props.formulaire, enquete: props.enquete, initialResponses: props.initialResponses, config: props.config, callbacks: props.callbacks, services: props.services, geographicComponents: props.geographicComponents, disabled: props.disabled, isSubmitting: props.isSubmitting, children: _jsx(FormRendererInner, {}) }));
112
+ };
113
+ export default FormRenderer;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Contexte React pour le FormRenderer
3
+ * Partage l'état et les fonctions entre tous les sous-composants
4
+ * RSU v2 - Package Partagé
5
+ */
6
+ import React, { ReactNode } from 'react';
7
+ import { FormulaireComplet, EnqueteInstance, EnqueteReponse, VariableFormulaire, VariableValue } from '../../types/enquete';
8
+ import { FormRendererConfig, FormRendererMode, FormRendererFeatures, FormRendererCallbacks } from '../../types/form-renderer';
9
+ import { FormRendererServices, GeographicComponents } from '../../types/services';
10
+ import { UseFormRendererResult } from '../../hooks/useFormRenderer';
11
+ import { UseFormNavigationResult } from '../../hooks/useFormNavigation';
12
+ import { UseFormValidationResult } from '../../hooks/useFormValidation';
13
+ import { UseFormInstancesResult } from '../../hooks/useFormInstances';
14
+ /**
15
+ * Valeur du contexte FormRenderer
16
+ */
17
+ export interface FormRendererContextValue extends UseFormRendererResult {
18
+ /** Le formulaire complet */
19
+ formulaire: FormulaireComplet;
20
+ /** L'instance d'enquête */
21
+ enquete?: EnqueteInstance;
22
+ /** Configuration complète */
23
+ config: FormRendererConfig;
24
+ /** Callbacks pour les actions */
25
+ callbacks: FormRendererCallbacks;
26
+ /** Services pour les composants */
27
+ services?: FormRendererServices;
28
+ /** Composants géographiques */
29
+ geographicComponents?: GeographicComponents;
30
+ }
31
+ declare const FormRendererContext: React.Context<FormRendererContextValue>;
32
+ /**
33
+ * Props du Provider
34
+ */
35
+ export interface FormRendererProviderProps {
36
+ children: ReactNode;
37
+ /** Le formulaire à rendre */
38
+ formulaire: FormulaireComplet;
39
+ /** L'instance d'enquête (optionnel pour nouvelle enquête) */
40
+ enquete?: EnqueteInstance;
41
+ /** Réponses initiales */
42
+ initialResponses?: Record<string, EnqueteReponse>;
43
+ /** Configuration */
44
+ config: FormRendererConfig;
45
+ /** Callbacks */
46
+ callbacks: FormRendererCallbacks;
47
+ /** Services injectés */
48
+ services?: FormRendererServices;
49
+ /** Composants géographiques */
50
+ geographicComponents?: GeographicComponents;
51
+ /** Désactiver tous les inputs */
52
+ disabled?: boolean;
53
+ /** État de soumission externe */
54
+ isSubmitting?: boolean;
55
+ /** Fonction pour vérifier si une variable est visible */
56
+ isVariableVisible?: (variable: VariableFormulaire) => boolean;
57
+ /** Mode debug */
58
+ debug?: boolean;
59
+ }
60
+ /**
61
+ * Provider pour le contexte FormRenderer
62
+ * Encapsule useFormRenderer et fournit l'état à tous les enfants
63
+ */
64
+ export declare const FormRendererProvider: React.FC<FormRendererProviderProps>;
65
+ /**
66
+ * Hook pour accéder au contexte FormRenderer
67
+ * Doit être utilisé à l'intérieur d'un FormRendererProvider
68
+ */
69
+ export declare function useFormRendererContext(): FormRendererContextValue;
70
+ /**
71
+ * Hook pour accéder uniquement à la navigation
72
+ */
73
+ export declare function useFormRendererNavigation(): UseFormNavigationResult;
74
+ /**
75
+ * Hook pour accéder uniquement à la validation
76
+ */
77
+ export declare function useFormRendererValidation(): UseFormValidationResult;
78
+ /**
79
+ * Hook pour accéder uniquement aux instances
80
+ */
81
+ export declare function useFormRendererInstances(): UseFormInstancesResult;
82
+ /**
83
+ * Hook pour accéder à la configuration
84
+ */
85
+ export declare function useFormRendererConfig(): {
86
+ mode: FormRendererMode;
87
+ features: FormRendererFeatures;
88
+ config: FormRendererConfig;
89
+ };
90
+ /**
91
+ * Hook pour accéder aux réponses
92
+ */
93
+ export declare function useFormRendererResponses(): {
94
+ responses: Record<string, EnqueteReponse>;
95
+ updateResponse: (variableCode: string, value: VariableValue, variable: VariableFormulaire, numeroMembre?: number) => void;
96
+ getResponseValue: (variableCode: string, numeroMembre?: number) => VariableValue;
97
+ };
98
+ /**
99
+ * Hook pour accéder à l'état global
100
+ */
101
+ export declare function useFormRendererState(): {
102
+ hasUnsavedChanges: boolean;
103
+ isSubmitting: boolean;
104
+ effectiveDisabled: boolean;
105
+ isReadOnly: boolean;
106
+ isConsultationMode: boolean;
107
+ };
108
+ export default FormRendererContext;
109
+ //# sourceMappingURL=FormRendererContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRendererContext.d.ts","sourceRoot":"","sources":["../../../src/components/form-renderer/FormRendererContext.tsx"],"names":[],"mappings":"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"}