@rsuci/shared-form-components 1.0.16 → 1.0.17

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.
@@ -19,6 +19,7 @@ export interface RosterVariable {
19
19
  valeurDefaut?: string;
20
20
  ordre: number;
21
21
  estObligatoire?: boolean;
22
+ conditionsAffichage?: string;
22
23
  }
23
24
  export interface RosterPanelProps {
24
25
  option: RosterOption;
@@ -1 +1 @@
1
- {"version":3,"file":"RosterPanel.d.ts","sourceRoot":"","sources":["../../../src/components/roster/RosterPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAuI3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"RosterPanel.d.ts","sourceRoot":"","sources":["../../../src/components/roster/RosterPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAOvC,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+J3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -7,12 +7,33 @@
7
7
  */
8
8
  'use client';
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ import { useMemo } from 'react';
10
11
  import VariableRenderer from '../VariableRenderer';
11
12
  import { cn } from '../../lib/utils/cn';
13
+ import { RosterConditionEngine } from '../../lib/roster-condition-engine';
12
14
  const RosterPanel = ({ option, rosterVariables, value, onChange, disabled, showCheckbox = false, isChecked = true, onCheckChange }) => {
13
15
  // Trier les variables par ordre
14
16
  const sortedVariables = [...rosterVariables].sort((a, b) => a.ordre - b.ordre);
15
- return (_jsxs("div", { className: cn('border border-gray-200 rounded-lg p-4 bg-white', 'shadow-sm hover:shadow-md transition-shadow', disabled && 'opacity-60'), children: [_jsx("div", { className: "border-b border-gray-100 pb-3 mb-4", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center flex-1", children: [showCheckbox && (_jsx("input", { type: "checkbox", checked: isChecked, onChange: (e) => onCheckChange?.(e.target.checked), disabled: disabled, className: cn('w-5 h-5 mr-3 text-green-600 border-gray-300 rounded focus:ring-green-500', disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer') })), _jsxs("div", { children: [_jsxs("h3", { className: "font-semibold text-lg text-gray-800 flex items-center", children: [_jsx("span", { className: "mr-2", children: "\uD83D\uDCCC" }), option.designation] }), _jsxs("p", { className: "text-xs text-blue-600 font-mono mt-1", children: ["(", option.code, ")"] })] })] }) }) }), !showCheckbox || isChecked ? (_jsx("div", { className: "space-y-4", children: sortedVariables.map(rosterVar => {
17
+ // Calculer les variables masquées par les jumps
18
+ const jumpedVariables = useMemo(() => {
19
+ return RosterConditionEngine.computeJumpedVariables(sortedVariables.map(v => ({ code: v.code, ordre: v.ordre, conditionsAffichage: v.conditionsAffichage })), value);
20
+ }, [sortedVariables, value]);
21
+ // Filtrer les variables visibles (conditions + jumps)
22
+ const visibleVariables = useMemo(() => {
23
+ return sortedVariables.filter(rosterVar => {
24
+ // Variable masquée par un jump actif
25
+ if (jumpedVariables.has(rosterVar.code)) {
26
+ return false;
27
+ }
28
+ // Pas de condition = visible
29
+ if (!rosterVar.conditionsAffichage) {
30
+ return true;
31
+ }
32
+ // Évaluer la condition avec les valeurs de cette ligne
33
+ return RosterConditionEngine.evaluate(rosterVar.conditionsAffichage, value);
34
+ });
35
+ }, [sortedVariables, jumpedVariables, value]);
36
+ return (_jsxs("div", { className: cn('border border-gray-200 rounded-lg p-4 bg-white', 'shadow-sm hover:shadow-md transition-shadow', disabled && 'opacity-60'), children: [_jsx("div", { className: "border-b border-gray-100 pb-3 mb-4", children: _jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center flex-1", children: [showCheckbox && (_jsx("input", { type: "checkbox", checked: isChecked, onChange: (e) => onCheckChange?.(e.target.checked), disabled: disabled, className: cn('w-5 h-5 mr-3 text-green-600 border-gray-300 rounded focus:ring-green-500', disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer') })), _jsxs("div", { children: [_jsxs("h3", { className: "font-semibold text-lg text-gray-800 flex items-center", children: [_jsx("span", { className: "mr-2", children: "\uD83D\uDCCC" }), option.designation] }), _jsxs("p", { className: "text-xs text-blue-600 font-mono mt-1", children: ["(", option.code, ")"] })] })] }) }) }), !showCheckbox || isChecked ? (_jsx("div", { className: "space-y-4", children: visibleVariables.map(rosterVar => {
16
37
  // Créer un objet VariableFormulaire compatible avec VariableRenderer
17
38
  // Rendre le code unique par panel pour éviter les conflits de radios/checkboxes
18
39
  const uniqueCode = `${option.code}_${rosterVar.code}`;
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@ export type { VariableNodeState, GroupNodeState, JumpRange, JumpError, IFormTree
38
38
  export { VariableValueConverter } from './lib/utils/variableValueConverter';
39
39
  export { interpolateVariableLabel } from './lib/utils/interpolateVariableLabel';
40
40
  export { ConditionEngine } from './lib/condition-engine';
41
+ export { RosterConditionEngine, type RosterConditionError, type RosterConditionErrorType, type RosterConditionValidationResult, type RosterVariableRef } from './lib/roster-condition-engine';
41
42
  export { FormTree } from './lib/form-tree';
42
43
  export { useFormTree, type UseFormTreeOptions, type UseFormTreeReturn } from './hooks/useFormTree';
43
44
  export { cn } from './lib/utils/cn';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,EACL,OAAO,IAAI,gBAAgB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACL,OAAO,IAAI,eAAe,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAOzC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAG3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAM5E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAM/E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAO9E,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,UAAU,EACV,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,SAAS,EACT,SAAS,EACT,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAG5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAGhF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,EACpC,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAO3C,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGnG,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -58,6 +58,8 @@ export { VariableValueConverter } from './lib/utils/variableValueConverter';
58
58
  export { interpolateVariableLabel } from './lib/utils/interpolateVariableLabel';
59
59
  // Moteur de conditions
60
60
  export { ConditionEngine } from './lib/condition-engine';
61
+ // Moteur de conditions scopées pour les ROSTER
62
+ export { RosterConditionEngine } from './lib/roster-condition-engine';
61
63
  // FormTree (arbre virtuel du formulaire)
62
64
  export { FormTree } from './lib/form-tree';
63
65
  // ========================================
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Moteur d'évaluation des conditions scopées pour les variables ROSTER
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ *
5
+ * Ce moteur est ISOLÉ du ConditionEngine principal.
6
+ * Les conditions sont évaluées PAR LIGNE (par option de roster) indépendamment.
7
+ * Le scope est limité aux variables du même ROSTER uniquement.
8
+ */
9
+ export type RosterConditionErrorType = 'variable_not_in_scope' | 'jump_out_of_scope' | 'backward_jump' | 'self_reference' | 'syntax_error';
10
+ export interface RosterConditionError {
11
+ type: RosterConditionErrorType;
12
+ variableCode: string;
13
+ message: string;
14
+ }
15
+ export interface RosterConditionValidationResult {
16
+ isValid: boolean;
17
+ errors: RosterConditionError[];
18
+ }
19
+ export interface RosterVariableRef {
20
+ code: string;
21
+ ordre: number;
22
+ }
23
+ /**
24
+ * Moteur de conditions scopées pour les ROSTER
25
+ * Toutes les méthodes sont statiques pour une utilisation sans état
26
+ */
27
+ export declare class RosterConditionEngine {
28
+ /**
29
+ * Valide une condition au moment du design (admin)
30
+ * Vérifie que les références sont dans le scope et que les jumps sont valides
31
+ */
32
+ static validateCondition(condition: string, availableVariables: RosterVariableRef[], currentVariableCode: string, currentVariableOrdre: number): RosterConditionValidationResult;
33
+ /**
34
+ * Évalue une condition au runtime (rendu)
35
+ * Utilise les valeurs de la ligne courante du roster
36
+ */
37
+ static evaluate(condition: string, lineValues: Record<string, any>): boolean;
38
+ /**
39
+ * Extrait toutes les références de variables d'une condition
40
+ * Format: ${VAR_CODE}
41
+ */
42
+ static extractVariableReferences(condition: string): string[];
43
+ /**
44
+ * Extrait la cible d'un jump s'il existe dans la condition
45
+ * Format: jump(condition, ${TARGET})
46
+ */
47
+ static extractJumpTarget(condition: string): string | null;
48
+ /**
49
+ * Calcule les variables qui doivent être masquées à cause des jumps actifs
50
+ */
51
+ static computeJumpedVariables(sortedVariables: RosterVariableRef[], lineValues: Record<string, any>): Set<string>;
52
+ /**
53
+ * Valide la syntaxe de base d'une condition
54
+ */
55
+ private static validateSyntax;
56
+ }
57
+ //# sourceMappingURL=roster-condition-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roster-condition-engine.d.ts","sourceRoot":"","sources":["../../src/lib/roster-condition-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,wBAAwB,GAChC,uBAAuB,GACvB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,GAChB,cAAc,CAAC;AAEnB,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,qBAAa,qBAAqB;IAEhC;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CACtB,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,iBAAiB,EAAE,EACvC,mBAAmB,EAAE,MAAM,EAC3B,oBAAoB,EAAE,MAAM,GAC3B,+BAA+B;IAgElC;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAyB5E;;;OAGG;IACH,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAO7D;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO1D;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAC3B,eAAe,EAAE,iBAAiB,EAAE,EACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9B,GAAG,CAAC,MAAM,CAAC;IA2Bd;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;CA0B9B"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Moteur d'évaluation des conditions scopées pour les variables ROSTER
3
+ * RSU v2 - Moteur de Rendu des Formulaires d'Enquête
4
+ *
5
+ * Ce moteur est ISOLÉ du ConditionEngine principal.
6
+ * Les conditions sont évaluées PAR LIGNE (par option de roster) indépendamment.
7
+ * Le scope est limité aux variables du même ROSTER uniquement.
8
+ */
9
+ import { ConditionEngine } from './condition-engine';
10
+ /**
11
+ * Moteur de conditions scopées pour les ROSTER
12
+ * Toutes les méthodes sont statiques pour une utilisation sans état
13
+ */
14
+ export class RosterConditionEngine {
15
+ /**
16
+ * Valide une condition au moment du design (admin)
17
+ * Vérifie que les références sont dans le scope et que les jumps sont valides
18
+ */
19
+ static validateCondition(condition, availableVariables, currentVariableCode, currentVariableOrdre) {
20
+ const errors = [];
21
+ if (!condition?.trim()) {
22
+ return { isValid: true, errors: [] };
23
+ }
24
+ const availableCodes = new Set(availableVariables.map(v => v.code));
25
+ // 1. Vérifier les références de variables
26
+ const refs = this.extractVariableReferences(condition);
27
+ for (const ref of refs) {
28
+ if (ref === currentVariableCode) {
29
+ errors.push({
30
+ type: 'self_reference',
31
+ variableCode: ref,
32
+ message: 'Une variable ne peut pas se référencer elle-même'
33
+ });
34
+ }
35
+ else if (!availableCodes.has(ref)) {
36
+ errors.push({
37
+ type: 'variable_not_in_scope',
38
+ variableCode: ref,
39
+ message: `La variable \${${ref}} n'existe pas dans ce Roster`
40
+ });
41
+ }
42
+ }
43
+ // 2. Vérifier le jump s'il existe
44
+ const jumpTarget = this.extractJumpTarget(condition);
45
+ if (jumpTarget) {
46
+ if (!availableCodes.has(jumpTarget)) {
47
+ errors.push({
48
+ type: 'jump_out_of_scope',
49
+ variableCode: jumpTarget,
50
+ message: `La variable cible \${${jumpTarget}} n'existe pas dans ce Roster`
51
+ });
52
+ }
53
+ else {
54
+ const targetVar = availableVariables.find(v => v.code === jumpTarget);
55
+ if (targetVar && targetVar.ordre <= currentVariableOrdre) {
56
+ errors.push({
57
+ type: 'backward_jump',
58
+ variableCode: jumpTarget,
59
+ message: 'Le jump ne peut pas cibler une variable précédente'
60
+ });
61
+ }
62
+ }
63
+ }
64
+ // 3. Valider la syntaxe générale
65
+ const syntaxError = this.validateSyntax(condition);
66
+ if (syntaxError) {
67
+ errors.push({
68
+ type: 'syntax_error',
69
+ variableCode: '',
70
+ message: syntaxError
71
+ });
72
+ }
73
+ return {
74
+ isValid: errors.length === 0,
75
+ errors
76
+ };
77
+ }
78
+ /**
79
+ * Évalue une condition au runtime (rendu)
80
+ * Utilise les valeurs de la ligne courante du roster
81
+ */
82
+ static evaluate(condition, lineValues) {
83
+ if (!condition?.trim()) {
84
+ return true;
85
+ }
86
+ try {
87
+ // Construire un contexte isolé pour cette ligne du roster
88
+ const responses = {};
89
+ for (const [code, value] of Object.entries(lineValues)) {
90
+ responses[code] = {
91
+ variableCode: code,
92
+ valeur: value,
93
+ dateModification: new Date()
94
+ };
95
+ }
96
+ // Utiliser le ConditionEngine en composition (pas héritage)
97
+ const engine = new ConditionEngine(responses);
98
+ return engine.evaluate(condition);
99
+ }
100
+ catch (error) {
101
+ console.warn('[RosterConditionEngine] Erreur évaluation:', condition, error);
102
+ return true; // En cas d'erreur, afficher par défaut
103
+ }
104
+ }
105
+ /**
106
+ * Extrait toutes les références de variables d'une condition
107
+ * Format: ${VAR_CODE}
108
+ */
109
+ static extractVariableReferences(condition) {
110
+ if (!condition)
111
+ return [];
112
+ const matches = condition.match(/\$\{([A-Z_][A-Z0-9_]*)\}/g) || [];
113
+ return matches.map(m => m.slice(2, -1));
114
+ }
115
+ /**
116
+ * Extrait la cible d'un jump s'il existe dans la condition
117
+ * Format: jump(condition, ${TARGET})
118
+ */
119
+ static extractJumpTarget(condition) {
120
+ if (!condition)
121
+ return null;
122
+ const match = condition.match(/jump\s*\([^,]+,\s*\$\{([A-Z_][A-Z0-9_]*)\}\s*\)/);
123
+ return match ? match[1] : null;
124
+ }
125
+ /**
126
+ * Calcule les variables qui doivent être masquées à cause des jumps actifs
127
+ */
128
+ static computeJumpedVariables(sortedVariables, lineValues) {
129
+ const jumped = new Set();
130
+ for (const rosterVar of sortedVariables) {
131
+ const condition = rosterVar.conditionsAffichage;
132
+ if (!condition)
133
+ continue;
134
+ const jumpTarget = this.extractJumpTarget(condition);
135
+ if (!jumpTarget)
136
+ continue;
137
+ // Évaluer si le jump doit s'activer
138
+ if (this.evaluate(condition, lineValues)) {
139
+ const targetVar = sortedVariables.find(v => v.code === jumpTarget);
140
+ if (targetVar) {
141
+ // Masquer toutes les variables entre la source et la cible
142
+ for (const v of sortedVariables) {
143
+ if (v.ordre > rosterVar.ordre && v.ordre < targetVar.ordre) {
144
+ jumped.add(v.code);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+ return jumped;
151
+ }
152
+ /**
153
+ * Valide la syntaxe de base d'une condition
154
+ */
155
+ static validateSyntax(condition) {
156
+ try {
157
+ // Vérifier les parenthèses équilibrées
158
+ let depth = 0;
159
+ for (const char of condition) {
160
+ if (char === '(')
161
+ depth++;
162
+ if (char === ')')
163
+ depth--;
164
+ if (depth < 0) {
165
+ return 'Parenthèses non équilibrées';
166
+ }
167
+ }
168
+ if (depth !== 0) {
169
+ return 'Parenthèses non équilibrées';
170
+ }
171
+ // Vérifier les fonctions reconnues
172
+ const functionMatch = condition.match(/^(showMe|hideMe|jump)\s*\(/);
173
+ if (!functionMatch && !condition.includes('${')) {
174
+ return 'Condition invalide: utilisez showMe(), hideMe() ou jump()';
175
+ }
176
+ return null;
177
+ }
178
+ catch (error) {
179
+ return `Erreur de syntaxe: ${error instanceof Error ? error.message : 'Erreur inconnue'}`;
180
+ }
181
+ }
182
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsuci/shared-form-components",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Composants partagés de rendu de formulaires RSU v2 - Package local pour frontend Admin et Public",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",