@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.
- package/dist/components/form-renderer/ConfirmationModal.d.ts +20 -0
- package/dist/components/form-renderer/ConfirmationModal.d.ts.map +1 -0
- package/dist/components/form-renderer/ConfirmationModal.js +79 -0
- package/dist/components/form-renderer/FormActions.d.ts +21 -0
- package/dist/components/form-renderer/FormActions.d.ts.map +1 -0
- package/dist/components/form-renderer/FormActions.js +81 -0
- package/dist/components/form-renderer/FormNavigationButtons.d.ts +23 -0
- package/dist/components/form-renderer/FormNavigationButtons.d.ts.map +1 -0
- package/dist/components/form-renderer/FormNavigationButtons.js +35 -0
- package/dist/components/form-renderer/FormProgress.d.ts +19 -0
- package/dist/components/form-renderer/FormProgress.d.ts.map +1 -0
- package/dist/components/form-renderer/FormProgress.js +26 -0
- package/dist/components/form-renderer/FormRenderer.d.ts +39 -0
- package/dist/components/form-renderer/FormRenderer.d.ts.map +1 -0
- package/dist/components/form-renderer/FormRenderer.js +113 -0
- package/dist/components/form-renderer/FormRendererContext.d.ts +109 -0
- package/dist/components/form-renderer/FormRendererContext.d.ts.map +1 -0
- package/dist/components/form-renderer/FormRendererContext.js +114 -0
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts +18 -0
- package/dist/components/form-renderer/GroupeInstanceTabs.d.ts.map +1 -0
- package/dist/components/form-renderer/GroupeInstanceTabs.js +174 -0
- package/dist/components/form-renderer/index.d.ts +17 -0
- package/dist/components/form-renderer/index.d.ts.map +1 -0
- package/dist/components/form-renderer/index.js +23 -0
- package/dist/hooks/useFormInstances.d.ts +87 -0
- package/dist/hooks/useFormInstances.d.ts.map +1 -0
- package/dist/hooks/useFormInstances.js +197 -0
- package/dist/hooks/useFormNavigation.d.ts +72 -0
- package/dist/hooks/useFormNavigation.d.ts.map +1 -0
- package/dist/hooks/useFormNavigation.js +147 -0
- package/dist/hooks/useFormRenderer.d.ts +87 -0
- package/dist/hooks/useFormRenderer.d.ts.map +1 -0
- package/dist/hooks/useFormRenderer.js +177 -0
- package/dist/hooks/useFormValidation.d.ts +50 -0
- package/dist/hooks/useFormValidation.d.ts.map +1 -0
- package/dist/hooks/useFormValidation.js +175 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/lib/__tests__/date-functions.test.d.ts +5 -0
- package/dist/lib/__tests__/date-functions.test.d.ts.map +1 -0
- package/dist/lib/__tests__/date-functions.test.js +184 -0
- package/dist/lib/utils/groupeInstanceManager.d.ts +88 -0
- package/dist/lib/utils/groupeInstanceManager.d.ts.map +1 -0
- package/dist/lib/utils/groupeInstanceManager.js +606 -0
- package/dist/types/form-renderer.d.ts +115 -1
- package/dist/types/form-renderer.d.ts.map +1 -1
- 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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"}
|