datakeen-session-react 1.1.140-dev.70 → 1.1.140-dev.71

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,16 +19,29 @@ var unisseyStrings = require('../utils/unisseyStrings.js');
19
19
 
20
20
  var SelfieRecorder = function (_a) {
21
21
  var _b;
22
- var handleSelfie = _a.handleSelfie, _c = _a.onBeginCapture, onBeginCapture = _c === void 0 ? function () { } : _c; _a.isCapturing; var btnBg = _a.btnBg, btnText = _a.btnText;
22
+ var handleSelfie = _a.handleSelfie, _c = _a.onBeginCapture, onBeginCapture = _c === void 0 ? function () { } : _c, btnBg = _a.btnBg, btnText = _a.btnText;
23
23
  var t = useI18n.useI18n().t;
24
24
  var isMobile = useIsMobile.default(768);
25
25
  var recorderRef = React.useRef(null);
26
- var _e = React.useState(false), disableButton = _e[0], setDisableButton = _e[1];
27
- var _f = React.useState(false), recorderReady = _f[0], setRecorderReady = _f[1];
28
- var _g = React.useState("idle"), recordingState = _g[0], setRecordingState = _g[1];
26
+ var _d = React.useState(false), disableButton = _d[0], setDisableButton = _d[1];
27
+ var _e = React.useState(false), recorderReady = _e[0], setRecorderReady = _e[1];
28
+ var _f = React.useState("idle"), recordingState = _f[0], setRecordingState = _f[1];
29
+ var recordingStateRef = React.useRef("idle");
30
+ var lastRecorderStatusRef = React.useRef();
29
31
  var capturedThumbnailRef = React.useRef(null);
30
- var _h = useLiveFrameCapture.useLiveFrameCapture(), captureFrame = _h.captureFrame, cleanup = _h.cleanup;
32
+ var _g = useLiveFrameCapture.useLiveFrameCapture(), captureFrame = _g.captureFrame, cleanup = _g.cleanup;
31
33
  useVideoRecorderStyles.default(btnBg, btnText);
34
+ var updateRecordingState = React.useCallback(function (state) {
35
+ recordingStateRef.current = state;
36
+ setRecordingState(state);
37
+ }, []);
38
+ var resetCaptureControls = React.useCallback(function () {
39
+ if (recordingStateRef.current === "processing")
40
+ return;
41
+ capturedThumbnailRef.current = null;
42
+ updateRecordingState("idle");
43
+ setDisableButton(false);
44
+ }, [updateRecordingState]);
32
45
  React.useEffect(function () {
33
46
  document.body.classList.add("recording-selfie");
34
47
  var cleanupObserver = videoElementStyles.setupVideoElementsObserver();
@@ -84,7 +97,7 @@ var SelfieRecorder = function (_a) {
84
97
  if (!recorderReady || recordingState !== "idle")
85
98
  return;
86
99
  onBeginCapture();
87
- setRecordingState("preparing");
100
+ updateRecordingState("preparing");
88
101
  setDisableButton(true);
89
102
  var triggerCapture = function () { return tslib_es6.__awaiter(void 0, void 0, void 0, function () {
90
103
  var error_1;
@@ -99,7 +112,7 @@ var SelfieRecorder = function (_a) {
99
112
  return [4 /*yield*/, selfieCaptureUtils.delay(200)];
100
113
  case 2:
101
114
  _b.sent();
102
- setRecordingState("recording");
115
+ updateRecordingState("recording");
103
116
  // Capture a frame from the live video during recording (after a short delay)
104
117
  setTimeout(function () {
105
118
  var videoElement = selfieCaptureUtils.getRecorderVideoElement(recorderRef.current);
@@ -113,7 +126,7 @@ var SelfieRecorder = function (_a) {
113
126
  case 3:
114
127
  error_1 = _b.sent();
115
128
  console.error("SelfieRecorder: failed to capture frame", error_1);
116
- setRecordingState("idle");
129
+ updateRecordingState("idle");
117
130
  setDisableButton(false);
118
131
  return [3 /*break*/, 4];
119
132
  case 4: return [2 /*return*/];
@@ -128,9 +141,24 @@ var SelfieRecorder = function (_a) {
128
141
  var status = (_a = recorderRef.current) === null || _a === void 0 ? void 0 : _a.sdkJsStatus;
129
142
  var isReady = status === "ready" || status === "running";
130
143
  setRecorderReady(function (prev) { return (prev !== isReady ? isReady : prev); });
144
+ var previousStatus = lastRecorderStatusRef.current;
145
+ var wasReady = previousStatus === "ready" || previousStatus === "running";
146
+ if (status !== previousStatus) {
147
+ lastRecorderStatusRef.current = status;
148
+ if (isReady && previousStatus !== undefined && !wasReady) {
149
+ resetCaptureControls();
150
+ }
151
+ }
131
152
  }, 500);
132
153
  return function () { return clearInterval(interval); };
133
- }, []);
154
+ }, [resetCaptureControls]);
155
+ var handleRecorderReady = function () {
156
+ setRecorderReady(true);
157
+ resetCaptureControls();
158
+ };
159
+ var handleRecordInterrupted = function () {
160
+ resetCaptureControls();
161
+ };
134
162
  var handleRecordCompleted = function (e) {
135
163
  var _a;
136
164
  var customEvent = e;
@@ -148,7 +176,7 @@ var SelfieRecorder = function (_a) {
148
176
  });
149
177
  });
150
178
  }
151
- setRecordingState("idle");
179
+ updateRecordingState("idle");
152
180
  setDisableButton(false);
153
181
  return;
154
182
  }
@@ -160,7 +188,7 @@ var SelfieRecorder = function (_a) {
160
188
  thumbnail: capturedThumbnailRef.current || undefined,
161
189
  }
162
190
  });
163
- setRecordingState("processing");
191
+ updateRecordingState("processing");
164
192
  handleSelfie(enhancedEvent);
165
193
  };
166
194
  return (jsxRuntime.jsxs("div", { className: "selfie selfie-recorder-root flex flex-col", style: (_b = {},
@@ -171,7 +199,7 @@ var SelfieRecorder = function (_a) {
171
199
  _b.zIndex = isMobile ? 50 : "auto",
172
200
  _b.height = "100%",
173
201
  _b.width = "100%",
174
- _b), children: [jsxRuntime.jsxs("div", { className: "p-4 text-center bg-white shrink-0", children: [jsxRuntime.jsx(Title.default, { className: "text-lg md:text-xl mb-1", children: t("selfie.recorder.title") }), jsxRuntime.jsx(Subtitle.default, { className: "text-xs text-gray-600 md:text-sm", children: t("selfie.recorder.subtitle") })] }), jsxRuntime.jsx("div", { className: "video-container flex-1 relative overflow-hidden", children: jsxRuntime.jsx(sdkReact.VideoRecorder, tslib_es6.__assign({ ref: recorderRef, preset: sdkReact.AcquisitionPreset.SELFIE_OPTIMIZED, hideCaptureBtn: true, faceChecker: (typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled', disableDebugMode: true, onRecordCompleted: handleRecordCompleted, onRecord: recordStarting, style: { width: "100%", height: "100%" }, className: "video-recorder-no-radius w-full h-full" }, (selfieCaptureUtils.isIOS() && {
202
+ _b), children: [jsxRuntime.jsxs("div", { className: "p-4 text-center bg-white shrink-0", children: [jsxRuntime.jsx(Title.default, { className: "text-lg md:text-xl mb-1", children: t("selfie.recorder.title") }), jsxRuntime.jsx(Subtitle.default, { className: "text-xs text-gray-600 md:text-sm", children: t("selfie.recorder.subtitle") })] }), jsxRuntime.jsx("div", { className: "video-container flex-1 relative overflow-hidden", children: jsxRuntime.jsx(sdkReact.VideoRecorder, tslib_es6.__assign({ ref: recorderRef, preset: sdkReact.AcquisitionPreset.SELFIE_OPTIMIZED, hideCaptureBtn: true, faceChecker: (typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled', disableDebugMode: true, onRecorderReady: handleRecorderReady, onRecordInterrupted: handleRecordInterrupted, onRecordCompleted: handleRecordCompleted, onRecord: recordStarting, style: { width: "100%", height: "100%" }, className: "video-recorder-no-radius w-full h-full" }, (selfieCaptureUtils.isIOS() && {
175
203
  "data-playsinline": "true",
176
204
  "data-autoplay": "true",
177
205
  "data-muted": "true"
@@ -1 +1 @@
1
- {"version":3,"file":"SelfieRecorder.js","sources":["../../../../../../src/components/selfie/selfie-flow/SelfieRecorder.tsx"],"sourcesContent":["import { useRef, useState, useEffect } from \"react\";\nimport { AcquisitionPreset, VideoRecorder } from \"@unissey-web/sdk-react\";\nimport Button from \"../../ui/Button\";\nimport Title from \"../../ui/Title\";\nimport Subtitle from \"../../ui/Subtitle\";\nimport useVideoRecorderStyles from \"../hooks/useVideoRecorderStyles\";\nimport { setupVideoElementsObserver } from \"../utils/videoElementStyles\";\nimport { delay, isIOS, waitForVideoFrame, getRecorderVideoElement } from \"../utils/selfieCaptureUtils\";\nimport { useLiveFrameCapture } from \"../hooks/useLiveFrameCapture\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport { getUnisseyStrings } from \"../utils/unisseyStrings\";\n\ninterface SelfieRecorderProps {\n handleSelfie: (e: Event) => void;\n onBeginCapture?: () => void;\n isCapturing?: boolean;\n btnBg?: string;\n btnText?: string;\n}\n\ninterface VideoRecorderRef extends HTMLElement {\n capture: () => void;\n}\n\nconst SelfieRecorder = ({\n handleSelfie,\n onBeginCapture = () => { },\n isCapturing = false,\n btnBg,\n btnText,\n}: SelfieRecorderProps) => {\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n const recorderRef = useRef<VideoRecorderRef | null>(null);\n const [disableButton, setDisableButton] = useState(false);\n const [recorderReady, setRecorderReady] = useState(false);\n const [recordingState, setRecordingState] = useState<\n \"idle\" | \"preparing\" | \"recording\" | \"processing\"\n >(\"idle\");\n const capturedThumbnailRef = useRef<string | null>(null);\n const { captureFrame, cleanup } = useLiveFrameCapture();\n\n useVideoRecorderStyles(btnBg, btnText);\n\n useEffect(() => {\n document.body.classList.add(\"recording-selfie\");\n const cleanupObserver = setupVideoElementsObserver();\n\n // iOS-specific fix: Add required attributes to video elements after mount\n if (isIOS()) {\n const addIOSVideoAttributes = () => {\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder) => {\n // Try to access shadow DOM and video elements\n try {\n const shadowRoot = (recorder as any).shadowRoot;\n if (shadowRoot) {\n const videoElements = shadowRoot.querySelectorAll(\"video\");\n videoElements.forEach((video: HTMLVideoElement) => {\n video.setAttribute(\"playsinline\", \"true\");\n video.setAttribute(\"autoplay\", \"true\");\n video.setAttribute(\"muted\", \"true\");\n // Ensure video plays inline and autoplays\n video.playsInline = true;\n video.autoplay = true;\n video.muted = true;\n });\n }\n } catch (error) {\n console.log(\"Could not access shadow DOM:\", error);\n }\n\n // Also set attributes on the component itself\n recorder.setAttribute(\"playsinline\", \"true\");\n recorder.setAttribute(\"autoplay\", \"true\");\n recorder.setAttribute(\"muted\", \"true\");\n });\n };\n\n // Apply immediately and also after a delay to catch dynamically created elements\n addIOSVideoAttributes();\n const iosTimeout = setTimeout(addIOSVideoAttributes, 500);\n const iosInterval = setInterval(addIOSVideoAttributes, 1000);\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n clearTimeout(iosTimeout);\n clearInterval(iosInterval);\n };\n }\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n };\n }, [cleanup]);\n\n const recordStarting = () => {\n if (!recorderReady || recordingState !== \"idle\") return;\n onBeginCapture();\n setRecordingState(\"preparing\");\n setDisableButton(true);\n\n const triggerCapture = async () => {\n try {\n await waitForVideoFrame(recorderRef.current);\n await delay(200);\n setRecordingState(\"recording\");\n\n // Capture a frame from the live video during recording (after a short delay)\n setTimeout(() => {\n const videoElement = getRecorderVideoElement(recorderRef.current);\n if (videoElement) {\n const thumbnail = captureFrame(videoElement);\n capturedThumbnailRef.current = thumbnail;\n }\n }, 1000); // Capture frame 1 second into recording\n\n recorderRef.current?.capture();\n } catch (error) {\n console.error(\"SelfieRecorder: failed to capture frame\", error);\n setRecordingState(\"idle\");\n setDisableButton(false);\n }\n };\n\n void triggerCapture();\n };\n\n useEffect(() => {\n const interval = setInterval(() => {\n const status = (recorderRef.current as any)?.sdkJsStatus;\n const isReady = status === \"ready\" || status === \"running\";\n setRecorderReady((prev) => (prev !== isReady ? isReady : prev));\n }, 500);\n return () => clearInterval(interval);\n }, []);\n\n const handleRecordCompleted = (e: Event) => {\n const customEvent = e as CustomEvent<{ media?: Blob; metadata?: string }>;\n if (!customEvent.detail?.media || customEvent.detail.media.size === 0) {\n console.error(\"❌ No valid media captured\");\n\n // iOS-specific debugging\n if (isIOS()) {\n console.log(\"🍎 iOS detected - checking video elements for proper attributes\");\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder, index) => {\n console.log(`VideoRecorder ${index}:`, {\n playsinline: recorder.getAttribute(\"playsinline\"),\n autoplay: recorder.getAttribute(\"autoplay\"),\n muted: recorder.getAttribute(\"muted\")\n });\n });\n }\n\n setRecordingState(\"idle\");\n setDisableButton(false);\n return;\n }\n\n // Attach the captured thumbnail to the event\n const enhancedEvent = new CustomEvent('record-completed', {\n detail: {\n media: customEvent.detail.media,\n metadata: customEvent.detail.metadata || '',\n thumbnail: capturedThumbnailRef.current || undefined,\n }\n });\n\n setRecordingState(\"processing\");\n handleSelfie(enhancedEvent);\n };\n\n return (\n <div\n className=\"selfie selfie-recorder-root flex flex-col\"\n style={{\n [\"--dk-btn-bg\" as string]: btnBg ?? \"#11E5C5\",\n [\"--dk-btn-text\" as string]: btnText ?? \"#3C3C40\",\n position: isMobile ? \"fixed\" : \"relative\",\n inset: isMobile ? 0 : \"auto\",\n zIndex: isMobile ? 50 : \"auto\",\n height: \"100%\",\n width: \"100%\",\n }}\n >\n <div className=\"p-4 text-center bg-white shrink-0\">\n <Title className=\"text-lg md:text-xl mb-1\">{t(\"selfie.recorder.title\")}</Title>\n <Subtitle className=\"text-xs text-gray-600 md:text-sm\">{t(\"selfie.recorder.subtitle\")}</Subtitle>\n </div>\n\n <div className=\"video-container flex-1 relative overflow-hidden\">\n <VideoRecorder\n ref={recorderRef as any}\n preset={AcquisitionPreset.SELFIE_OPTIMIZED}\n hideCaptureBtn\n faceChecker={(typeof window !== 'undefined' && (window as any).__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled'}\n disableDebugMode\n onRecordCompleted={handleRecordCompleted}\n onRecord={recordStarting}\n style={{ width: \"100%\", height: \"100%\" }}\n className=\"video-recorder-no-radius w-full h-full\"\n {...(isIOS() && {\n \"data-playsinline\": \"true\",\n \"data-autoplay\": \"true\",\n \"data-muted\": \"true\"\n })}\n strings={getUnisseyStrings(t)}\n />\n </div>\n\n <div className=\"shrink-0 bg-white border-t border-gray-200 p-4 md:p-6 relative\" style={{ zIndex: 9999 }}>\n <div className=\"max-w-md mx-auto\">\n <div className=\"text-center text-xs text-gray-400 mt-3\">\n {t(\"selfie.recorder.note\")}\n </div>\n\n <Button\n onClick={recordStarting}\n className=\"w-full py-3 md:py-4 relative selfie-button\"\n disabled={disableButton || !recorderReady}\n style={{ backgroundColor: btnBg ?? \"#11E5C5\", color: btnText ?? \"#3C3C40\" }}\n >\n {recordingState === \"idle\" && t(\"selfie.recorder.start\")}\n {recordingState === \"preparing\" && t(\"selfie.recorder.preparing\")}\n {recordingState === \"recording\" && (\n <span className=\"flex items-center justify-center\">\n <span className=\"mr-2\">{t(\"selfie.recorder.recording_label\")}</span>\n <span className=\"flex space-x-1 loading-dots\">\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n </span>\n </span>\n )}\n {recordingState === \"processing\" && t(\"selfie.recorder.processing\")}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SelfieRecorder;\n"],"names":["useI18n","useIsMobile","useRef","useState","useLiveFrameCapture","useVideoRecorderStyles","useEffect","setupVideoElementsObserver","isIOS","__awaiter","waitForVideoFrame","delay","getRecorderVideoElement","_jsxs","_jsx","Title","Subtitle","VideoRecorder","__assign","AcquisitionPreset","getUnisseyStrings","Button"],"mappings":"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"}
1
+ {"version":3,"file":"SelfieRecorder.js","sources":["../../../../../../src/components/selfie/selfie-flow/SelfieRecorder.tsx"],"sourcesContent":["import {\n useCallback,\n useRef,\n useState,\n useEffect,\n type ElementRef,\n} from \"react\";\nimport { AcquisitionPreset, VideoRecorder } from \"@unissey-web/sdk-react\";\nimport Button from \"../../ui/Button\";\nimport Title from \"../../ui/Title\";\nimport Subtitle from \"../../ui/Subtitle\";\nimport useVideoRecorderStyles from \"../hooks/useVideoRecorderStyles\";\nimport { setupVideoElementsObserver } from \"../utils/videoElementStyles\";\nimport { delay, isIOS, waitForVideoFrame, getRecorderVideoElement } from \"../utils/selfieCaptureUtils\";\nimport { useLiveFrameCapture } from \"../hooks/useLiveFrameCapture\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport { getUnisseyStrings } from \"../utils/unisseyStrings\";\n\ntype RecordingState = \"idle\" | \"preparing\" | \"recording\" | \"processing\";\n\ninterface SelfieRecorderProps {\n handleSelfie: (e: Event) => void;\n onBeginCapture?: () => void;\n isCapturing?: boolean;\n btnBg?: string;\n btnText?: string;\n}\n\ntype VideoRecorderElement = ElementRef<typeof VideoRecorder>;\n\nconst SelfieRecorder = ({\n handleSelfie,\n onBeginCapture = () => { },\n btnBg,\n btnText,\n}: SelfieRecorderProps) => {\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n const recorderRef = useRef<VideoRecorderElement | null>(null);\n const [disableButton, setDisableButton] = useState(false);\n const [recorderReady, setRecorderReady] = useState(false);\n const [recordingState, setRecordingState] = useState<RecordingState>(\"idle\");\n const recordingStateRef = useRef<RecordingState>(\"idle\");\n const lastRecorderStatusRef = useRef<string | undefined>();\n const capturedThumbnailRef = useRef<string | null>(null);\n const { captureFrame, cleanup } = useLiveFrameCapture();\n\n useVideoRecorderStyles(btnBg, btnText);\n\n const updateRecordingState = useCallback((state: RecordingState) => {\n recordingStateRef.current = state;\n setRecordingState(state);\n }, []);\n\n const resetCaptureControls = useCallback(() => {\n if (recordingStateRef.current === \"processing\") return;\n capturedThumbnailRef.current = null;\n updateRecordingState(\"idle\");\n setDisableButton(false);\n }, [updateRecordingState]);\n\n useEffect(() => {\n document.body.classList.add(\"recording-selfie\");\n const cleanupObserver = setupVideoElementsObserver();\n\n // iOS-specific fix: Add required attributes to video elements after mount\n if (isIOS()) {\n const addIOSVideoAttributes = () => {\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder) => {\n // Try to access shadow DOM and video elements\n try {\n const shadowRoot = recorder.shadowRoot;\n if (shadowRoot) {\n const videoElements = shadowRoot.querySelectorAll(\"video\");\n videoElements.forEach((video: HTMLVideoElement) => {\n video.setAttribute(\"playsinline\", \"true\");\n video.setAttribute(\"autoplay\", \"true\");\n video.setAttribute(\"muted\", \"true\");\n // Ensure video plays inline and autoplays\n video.playsInline = true;\n video.autoplay = true;\n video.muted = true;\n });\n }\n } catch (error) {\n console.log(\"Could not access shadow DOM:\", error);\n }\n\n // Also set attributes on the component itself\n recorder.setAttribute(\"playsinline\", \"true\");\n recorder.setAttribute(\"autoplay\", \"true\");\n recorder.setAttribute(\"muted\", \"true\");\n });\n };\n\n // Apply immediately and also after a delay to catch dynamically created elements\n addIOSVideoAttributes();\n const iosTimeout = setTimeout(addIOSVideoAttributes, 500);\n const iosInterval = setInterval(addIOSVideoAttributes, 1000);\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n clearTimeout(iosTimeout);\n clearInterval(iosInterval);\n };\n }\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n };\n }, [cleanup]);\n\n const recordStarting = () => {\n if (!recorderReady || recordingState !== \"idle\") return;\n onBeginCapture();\n updateRecordingState(\"preparing\");\n setDisableButton(true);\n\n const triggerCapture = async () => {\n try {\n await waitForVideoFrame(recorderRef.current);\n await delay(200);\n updateRecordingState(\"recording\");\n\n // Capture a frame from the live video during recording (after a short delay)\n setTimeout(() => {\n const videoElement = getRecorderVideoElement(recorderRef.current);\n if (videoElement) {\n const thumbnail = captureFrame(videoElement);\n capturedThumbnailRef.current = thumbnail;\n }\n }, 1000); // Capture frame 1 second into recording\n\n recorderRef.current?.capture();\n } catch (error) {\n console.error(\"SelfieRecorder: failed to capture frame\", error);\n updateRecordingState(\"idle\");\n setDisableButton(false);\n }\n };\n\n void triggerCapture();\n };\n\n useEffect(() => {\n const interval = setInterval(() => {\n const status = recorderRef.current?.sdkJsStatus;\n const isReady = status === \"ready\" || status === \"running\";\n setRecorderReady((prev) => (prev !== isReady ? isReady : prev));\n\n const previousStatus = lastRecorderStatusRef.current;\n const wasReady = previousStatus === \"ready\" || previousStatus === \"running\";\n if (status !== previousStatus) {\n lastRecorderStatusRef.current = status;\n if (isReady && previousStatus !== undefined && !wasReady) {\n resetCaptureControls();\n }\n }\n }, 500);\n return () => clearInterval(interval);\n }, [resetCaptureControls]);\n\n const handleRecorderReady = () => {\n setRecorderReady(true);\n resetCaptureControls();\n };\n\n const handleRecordInterrupted = () => {\n resetCaptureControls();\n };\n\n const handleRecordCompleted = (e: Event) => {\n const customEvent = e as CustomEvent<{ media?: Blob; metadata?: string }>;\n if (!customEvent.detail?.media || customEvent.detail.media.size === 0) {\n console.error(\"❌ No valid media captured\");\n\n // iOS-specific debugging\n if (isIOS()) {\n console.log(\"🍎 iOS detected - checking video elements for proper attributes\");\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder, index) => {\n console.log(`VideoRecorder ${index}:`, {\n playsinline: recorder.getAttribute(\"playsinline\"),\n autoplay: recorder.getAttribute(\"autoplay\"),\n muted: recorder.getAttribute(\"muted\")\n });\n });\n }\n\n updateRecordingState(\"idle\");\n setDisableButton(false);\n return;\n }\n\n // Attach the captured thumbnail to the event\n const enhancedEvent = new CustomEvent('record-completed', {\n detail: {\n media: customEvent.detail.media,\n metadata: customEvent.detail.metadata || '',\n thumbnail: capturedThumbnailRef.current || undefined,\n }\n });\n\n updateRecordingState(\"processing\");\n handleSelfie(enhancedEvent);\n };\n\n return (\n <div\n className=\"selfie selfie-recorder-root flex flex-col\"\n style={{\n [\"--dk-btn-bg\" as string]: btnBg ?? \"#11E5C5\",\n [\"--dk-btn-text\" as string]: btnText ?? \"#3C3C40\",\n position: isMobile ? \"fixed\" : \"relative\",\n inset: isMobile ? 0 : \"auto\",\n zIndex: isMobile ? 50 : \"auto\",\n height: \"100%\",\n width: \"100%\",\n }}\n >\n <div className=\"p-4 text-center bg-white shrink-0\">\n <Title className=\"text-lg md:text-xl mb-1\">{t(\"selfie.recorder.title\")}</Title>\n <Subtitle className=\"text-xs text-gray-600 md:text-sm\">{t(\"selfie.recorder.subtitle\")}</Subtitle>\n </div>\n\n <div className=\"video-container flex-1 relative overflow-hidden\">\n <VideoRecorder\n ref={recorderRef}\n preset={AcquisitionPreset.SELFIE_OPTIMIZED}\n hideCaptureBtn\n faceChecker={(typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled'}\n disableDebugMode\n onRecorderReady={handleRecorderReady}\n onRecordInterrupted={handleRecordInterrupted}\n onRecordCompleted={handleRecordCompleted}\n onRecord={recordStarting}\n style={{ width: \"100%\", height: \"100%\" }}\n className=\"video-recorder-no-radius w-full h-full\"\n {...(isIOS() && {\n \"data-playsinline\": \"true\",\n \"data-autoplay\": \"true\",\n \"data-muted\": \"true\"\n })}\n strings={getUnisseyStrings(t)}\n />\n </div>\n\n <div className=\"shrink-0 bg-white border-t border-gray-200 p-4 md:p-6 relative\" style={{ zIndex: 9999 }}>\n <div className=\"max-w-md mx-auto\">\n <div className=\"text-center text-xs text-gray-400 mt-3\">\n {t(\"selfie.recorder.note\")}\n </div>\n\n <Button\n onClick={recordStarting}\n className=\"w-full py-3 md:py-4 relative selfie-button\"\n disabled={disableButton || !recorderReady}\n style={{ backgroundColor: btnBg ?? \"#11E5C5\", color: btnText ?? \"#3C3C40\" }}\n >\n {recordingState === \"idle\" && t(\"selfie.recorder.start\")}\n {recordingState === \"preparing\" && t(\"selfie.recorder.preparing\")}\n {recordingState === \"recording\" && (\n <span className=\"flex items-center justify-center\">\n <span className=\"mr-2\">{t(\"selfie.recorder.recording_label\")}</span>\n <span className=\"flex space-x-1 loading-dots\">\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n </span>\n </span>\n )}\n {recordingState === \"processing\" && t(\"selfie.recorder.processing\")}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SelfieRecorder;\n"],"names":["useI18n","useIsMobile","useRef","useState","useLiveFrameCapture","useVideoRecorderStyles","useCallback","useEffect","setupVideoElementsObserver","isIOS","__awaiter","waitForVideoFrame","delay","getRecorderVideoElement","_jsxs","_jsx","Title","Subtitle","VideoRecorder","__assign","AcquisitionPreset","getUnisseyStrings","Button"],"mappings":"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"}
@@ -192,7 +192,8 @@ var CustomFormFields = function (_a) {
192
192
  return null;
193
193
  }
194
194
  };
195
- return (jsxRuntime.jsx(React.Fragment, { children: customFields.map(function (field) { return (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsxs(Label__namespace.Root, { htmlFor: field.id, className: "block text-sm md:text-base font-semibold text-gray-900", children: [field.label, field.required && jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), field.description && field.valueType !== "boolean" && (jsxRuntime.jsx("p", { className: "text-xs text-gray-500 -mt-1", children: field.description })), renderField(field), (function () {
195
+ var visibleFields = customFields.filter(function (f) { return !f.lockedFromApi; });
196
+ return (jsxRuntime.jsx(React.Fragment, { children: visibleFields.map(function (field) { return (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsxs(Label__namespace.Root, { htmlFor: field.id, className: "block text-sm md:text-base font-semibold text-gray-900", children: [field.label, field.required && jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), field.description && field.valueType !== "boolean" && (jsxRuntime.jsx("p", { className: "text-xs text-gray-500 -mt-1", children: field.description })), renderField(field), (function () {
196
197
  var fieldErr = errors[field.id];
197
198
  if (!fieldErr)
198
199
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"CustomFormFields.js","sources":["../../../../../../src/components/session/UserInputForm/CustomFormFields.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport * as Label from \"@radix-ui/react-label\";\nimport clsx from \"clsx\";\nimport { Select } from \"../../ui/SelectComponent\";\nimport type { CustomField, ListColumn } from \"../../../types/session\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport AddressFields from \"./AddressFields\";\nimport type { AddressSuggestion } from \"../../../types/userInputForm\";\nimport {\n createEmptyListRow,\n ensureMinimumListRows,\n getListFieldMinRows,\n normalizeListColumns,\n} from \"../../../utils/listFieldUtils\";\nimport { cellErrorKey } from \"../../../utils/customFieldValidation\";\nimport { DatePickerField } from \"./DatePickerField\";\n\ntype CellErrorValue = string | boolean;\n\n/**\n * Sous-composant dédié au rendu d'une cellule du tableau dynamique.\n * Nécessaire pour que les hooks internes à Select soient toujours appelés\n * de façon stable (règle des hooks React).\n */\nconst ListCell = ({\n col,\n value,\n hasError,\n cellClasses,\n onChange,\n language,\n}: {\n col: ListColumn;\n value: string;\n hasError: boolean;\n cellClasses: string;\n onChange: (val: string) => void;\n language: string;\n}) => {\n if (col.type === \"enum\") {\n return (\n <Select\n options={(col.options ?? []).map((opt) => ({ value: opt, label: opt }))}\n value={value}\n onValueChange={onChange}\n placeholder={col.placeholder || col.label}\n error={hasError}\n compact\n />\n );\n }\n if (col.type === \"email\") {\n return (\n <input\n type=\"email\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n }\n if (col.type === \"date\") {\n return (\n <DatePickerField\n value={value}\n dateFormat={col.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={col.placeholder}\n hasError={hasError}\n language={language}\n onChange={onChange}\n className={cellClasses}\n />\n );\n }\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n />\n );\n};\n\ninterface CustomFormFieldsProps {\n customFields: CustomField[];\n formData: Record<string, any>;\n errors: Record<string, CellErrorValue>;\n cellErrors?: Record<string, Record<string, CellErrorValue>>;\n onFieldChange: (fieldId: string, value: any) => void;\n // Address autocomplete props (for address field type)\n addressSuggestions?: AddressSuggestion[];\n showSuggestions?: boolean;\n onAddressChange?: (fieldId: string, value: string) => void;\n onAddressFocus?: (fieldId: string) => void;\n onAddressBlur?: (fieldId: string) => void;\n onApplySuggestion?: (fieldId: string, suggestion: AddressSuggestion) => void;\n}\n\nconst CustomFormFields = ({\n customFields,\n formData,\n errors,\n cellErrors = {},\n onFieldChange,\n addressSuggestions = [],\n showSuggestions = false,\n onAddressChange,\n onAddressFocus,\n onAddressBlur,\n onApplySuggestion,\n}: CustomFormFieldsProps) => {\n const { t, currentLanguage } = useI18n();\n\n console.log(\"🎨 [CustomFormFields] Rendering with:\", {\n fieldsCount: customFields.length,\n fields: customFields.map((f) => ({\n id: f.id,\n label: f.label,\n type: f.valueType,\n })),\n formData,\n errors,\n });\n\n const renderField = (field: CustomField) => {\n const hasError = Boolean(errors[field.id]);\n const value = formData[field.id];\n\n // Classes communes (EXACTEMENT comme IdentityFields/ContactFields)\n const inputClasses = clsx(\n \"w-full px-3 py-3 md:py-4 border rounded-lg text-base transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n switch (field.valueType) {\n case \"text\":\n return (\n <input\n id={field.id}\n type=\"text\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n />\n );\n\n case \"number\":\n return (\n <input\n id={field.id}\n type=\"number\"\n inputMode=\"numeric\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n />\n );\n\n case \"date\":\n return (\n <DatePickerField\n id={field.id}\n value={value || \"\"}\n dateFormat={field.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={field.placeholder}\n hasError={hasError}\n language={currentLanguage}\n onChange={(v) => onFieldChange(field.id, v)}\n className={inputClasses}\n />\n );\n\n case \"boolean\":\n return (\n <div className=\"flex items-center gap-2\">\n <input\n id={field.id}\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => onFieldChange(field.id, e.target.checked)}\n className=\"h-4 w-4 text-[#11E5C5] border-gray-300 rounded focus:ring-[#11E5C5]\"\n />\n {field.description && (\n <span className=\"text-sm text-gray-600\">{field.description}</span>\n )}\n </div>\n );\n\n case \"enum\":\n return (\n <Select\n options={(field.enumOptions || []).map((opt) => ({\n value: opt,\n label: opt,\n }))}\n value={value || \"\"}\n onValueChange={(val) => onFieldChange(field.id, val)}\n placeholder={field.placeholder || t(\"custom_form.select_option\")}\n error={hasError}\n />\n );\n\n case \"email\":\n return (\n <input\n id={field.id}\n type=\"email\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n\n case \"address\":\n // For address, use the existing AddressFields component\n const addressValue = value || {};\n const addressForm = {\n lastName: \"\",\n firstName: \"\",\n birthDate: \"\",\n day: \"\",\n month: \"\",\n year: \"\",\n email: \"\",\n phoneNumber: \"\",\n sms: \"\",\n addressLine1: addressValue.addressLine1 || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: addressValue.postalCode || \"\",\n city: addressValue.city || \"\",\n countryCode: addressValue.countryCode || \"\",\n nationality: \"\",\n companyName: \"\",\n siret: \"\",\n tva: \"\",\n };\n\n return (\n <AddressFields\n form={addressForm}\n errors={{\n addressLine1: hasError,\n addressLine2: false,\n postalCode: hasError,\n city: hasError,\n country: hasError,\n }}\n requestedFields={new Set([\"adresse\"])}\n onFieldChange={(key, val) => {\n const updatedAddress = {\n ...addressValue,\n [key]: val,\n };\n onFieldChange(field.id, updatedAddress);\n }}\n addressSuggestions={addressSuggestions}\n showSuggestions={showSuggestions}\n onAddressChange={(val) => {\n const updatedAddress = {\n ...addressValue,\n addressLine1: val,\n };\n onFieldChange(field.id, updatedAddress);\n onAddressChange?.(field.id, val);\n }}\n onAddressFocus={() => onAddressFocus?.(field.id)}\n onAddressBlur={() => onAddressBlur?.(field.id)}\n onApplySuggestion={(suggestion) => {\n const updatedAddress = {\n addressLine1: suggestion.label || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: suggestion.postalCode || \"\",\n city: suggestion.city || \"\",\n countryCode: suggestion.countryCode || \"\",\n };\n onFieldChange(field.id, updatedAddress);\n onApplySuggestion?.(field.id, suggestion);\n }}\n />\n );\n\n case \"list\": {\n const persistedRows: Record<string, string>[] = Array.isArray(value)\n ? value\n : [];\n const columns: ListColumn[] = normalizeListColumns(field.listColumns);\n const minRows = getListFieldMinRows(field);\n const rows = ensureMinimumListRows(persistedRows, columns, minRows);\n const gridTemplateColumns = `repeat(${columns.length}, minmax(180px, 1fr)) 32px`;\n const gridMinWidth = `${columns.length * 180 + (columns.length - 1) * 8 + 32}px`;\n const fieldCellErrors = cellErrors[field.id] ?? {};\n\n if (columns.length === 0) {\n return (\n <p className=\"text-sm text-red-600\">\n {t(\n \"custom_form.list_missing_columns\",\n \"Ce tableau n'a pas de colonnes configurées.\",\n )}\n </p>\n );\n }\n\n const handleRowChange = (\n rowIndex: number,\n colName: string,\n colValue: string,\n ) => {\n const updated = [...rows];\n updated[rowIndex] = { ...updated[rowIndex], [colName]: colValue };\n onFieldChange(field.id, updated);\n };\n\n const handleAddRow = () => {\n const emptyRow = createEmptyListRow(columns);\n onFieldChange(field.id, [...rows, emptyRow]);\n };\n\n const handleRemoveRow = (rowIndex: number) => {\n if (rows.length <= minRows) {\n return;\n }\n\n onFieldChange(\n field.id,\n rows.filter((_, i) => i !== rowIndex),\n );\n };\n\n const cellClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n return (\n <div className=\"space-y-3 overflow-x-auto\">\n {columns.length > 0 && (\n <div\n className=\"grid gap-2 items-center w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => (\n <span\n key={col.label}\n className=\"text-xs font-semibold text-gray-600 uppercase tracking-wide truncate\"\n >\n {col.label}\n </span>\n ))}\n <span />\n </div>\n )}\n\n {rows.map((row, rowIndex) => (\n <div\n key={rowIndex}\n className=\"grid gap-2 items-start w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => {\n const cellErr =\n fieldCellErrors[cellErrorKey(rowIndex, col.label)];\n const cellHasError = Boolean(cellErr);\n const cellInputClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n cellHasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n return (\n <div\n key={col.label}\n className=\"flex flex-col gap-1 min-w-0\"\n >\n <ListCell\n col={col}\n value={row[col.label] || \"\"}\n hasError={cellHasError || hasError}\n cellClasses={cellInputClasses}\n onChange={(val) =>\n handleRowChange(rowIndex, col.label, val)\n }\n language={currentLanguage}\n />\n {typeof cellErr === \"string\" && (\n <span className=\"text-xs text-red-600\">\n {cellErr}\n </span>\n )}\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={() => handleRemoveRow(rowIndex)}\n className={clsx(\n \"flex items-center justify-center w-8 h-8 rounded-full transition-colors\",\n rows.length <= minRows\n ? \"text-gray-300 cursor-not-allowed\"\n : \"text-gray-400 hover:text-red-500 hover:bg-red-50\",\n )}\n aria-label={t(\"custom_form.remove_row\", \"Supprimer la ligne\")}\n disabled={rows.length <= minRows}\n >\n ✕\n </button>\n </div>\n ))}\n\n <button\n type=\"button\"\n onClick={handleAddRow}\n className=\"flex items-center gap-2 text-sm text-[#11E5C5] hover:underline font-medium\"\n >\n + {t(\"custom_form.add_row\", \"Ajouter une ligne\")}\n </button>\n </div>\n );\n }\n\n default:\n return null;\n }\n };\n\n return (\n <Fragment>\n {customFields.map((field) => (\n <div key={field.id} className=\"space-y-2\">\n <Label.Root\n htmlFor={field.id}\n className=\"block text-sm md:text-base font-semibold text-gray-900\"\n >\n {field.label}\n {field.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label.Root>\n\n {field.description && field.valueType !== \"boolean\" && (\n <p className=\"text-xs text-gray-500 -mt-1\">{field.description}</p>\n )}\n\n {renderField(field)}\n\n {(() => {\n const fieldErr = errors[field.id];\n if (!fieldErr) return null;\n const message =\n typeof fieldErr === \"string\"\n ? fieldErr\n : field.required && !formData[field.id]\n ? t(\"custom_form.required_field\")\n : t(\"custom_form.invalid_value\");\n return (\n <p className=\"text-red-600 text-sm flex items-center gap-1\">\n <span className=\"text-red-500\">⚠</span>\n {message}\n </p>\n );\n })()}\n </div>\n ))}\n </Fragment>\n );\n};\n\nexport default CustomFormFields;\n"],"names":["_jsx","Select","DatePickerField","useI18n","_jsxs","AddressFields","normalizeListColumns","getListFieldMinRows","ensureMinimumListRows","__spreadArray","__assign","createEmptyListRow","cellErrorKey","Fragment","Label"],"mappings":"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"}
1
+ {"version":3,"file":"CustomFormFields.js","sources":["../../../../../../src/components/session/UserInputForm/CustomFormFields.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport * as Label from \"@radix-ui/react-label\";\nimport clsx from \"clsx\";\nimport { Select } from \"../../ui/SelectComponent\";\nimport type { CustomField, ListColumn } from \"../../../types/session\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport AddressFields from \"./AddressFields\";\nimport type { AddressSuggestion } from \"../../../types/userInputForm\";\nimport {\n createEmptyListRow,\n ensureMinimumListRows,\n getListFieldMinRows,\n normalizeListColumns,\n} from \"../../../utils/listFieldUtils\";\nimport { cellErrorKey } from \"../../../utils/customFieldValidation\";\nimport { DatePickerField } from \"./DatePickerField\";\n\ntype CellErrorValue = string | boolean;\n\n/**\n * Sous-composant dédié au rendu d'une cellule du tableau dynamique.\n * Nécessaire pour que les hooks internes à Select soient toujours appelés\n * de façon stable (règle des hooks React).\n */\nconst ListCell = ({\n col,\n value,\n hasError,\n cellClasses,\n onChange,\n language,\n}: {\n col: ListColumn;\n value: string;\n hasError: boolean;\n cellClasses: string;\n onChange: (val: string) => void;\n language: string;\n}) => {\n if (col.type === \"enum\") {\n return (\n <Select\n options={(col.options ?? []).map((opt) => ({ value: opt, label: opt }))}\n value={value}\n onValueChange={onChange}\n placeholder={col.placeholder || col.label}\n error={hasError}\n compact\n />\n );\n }\n if (col.type === \"email\") {\n return (\n <input\n type=\"email\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n }\n if (col.type === \"date\") {\n return (\n <DatePickerField\n value={value}\n dateFormat={col.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={col.placeholder}\n hasError={hasError}\n language={language}\n onChange={onChange}\n className={cellClasses}\n />\n );\n }\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n />\n );\n};\n\ninterface CustomFormFieldsProps {\n customFields: CustomField[];\n formData: Record<string, any>;\n errors: Record<string, CellErrorValue>;\n cellErrors?: Record<string, Record<string, CellErrorValue>>;\n onFieldChange: (fieldId: string, value: any) => void;\n // Address autocomplete props (for address field type)\n addressSuggestions?: AddressSuggestion[];\n showSuggestions?: boolean;\n onAddressChange?: (fieldId: string, value: string) => void;\n onAddressFocus?: (fieldId: string) => void;\n onAddressBlur?: (fieldId: string) => void;\n onApplySuggestion?: (fieldId: string, suggestion: AddressSuggestion) => void;\n}\n\nconst CustomFormFields = ({\n customFields,\n formData,\n errors,\n cellErrors = {},\n onFieldChange,\n addressSuggestions = [],\n showSuggestions = false,\n onAddressChange,\n onAddressFocus,\n onAddressBlur,\n onApplySuggestion,\n}: CustomFormFieldsProps) => {\n const { t, currentLanguage } = useI18n();\n\n console.log(\"🎨 [CustomFormFields] Rendering with:\", {\n fieldsCount: customFields.length,\n fields: customFields.map((f) => ({\n id: f.id,\n label: f.label,\n type: f.valueType,\n })),\n formData,\n errors,\n });\n\n const renderField = (field: CustomField) => {\n const hasError = Boolean(errors[field.id]);\n const value = formData[field.id];\n\n // Classes communes (EXACTEMENT comme IdentityFields/ContactFields)\n const inputClasses = clsx(\n \"w-full px-3 py-3 md:py-4 border rounded-lg text-base transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n switch (field.valueType) {\n case \"text\":\n return (\n <input\n id={field.id}\n type=\"text\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n />\n );\n\n case \"number\":\n return (\n <input\n id={field.id}\n type=\"number\"\n inputMode=\"numeric\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n />\n );\n\n case \"date\":\n return (\n <DatePickerField\n id={field.id}\n value={value || \"\"}\n dateFormat={field.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={field.placeholder}\n hasError={hasError}\n language={currentLanguage}\n onChange={(v) => onFieldChange(field.id, v)}\n className={inputClasses}\n />\n );\n\n case \"boolean\":\n return (\n <div className=\"flex items-center gap-2\">\n <input\n id={field.id}\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => onFieldChange(field.id, e.target.checked)}\n className=\"h-4 w-4 text-[#11E5C5] border-gray-300 rounded focus:ring-[#11E5C5]\"\n />\n {field.description && (\n <span className=\"text-sm text-gray-600\">{field.description}</span>\n )}\n </div>\n );\n\n case \"enum\":\n return (\n <Select\n options={(field.enumOptions || []).map((opt) => ({\n value: opt,\n label: opt,\n }))}\n value={value || \"\"}\n onValueChange={(val) => onFieldChange(field.id, val)}\n placeholder={field.placeholder || t(\"custom_form.select_option\")}\n error={hasError}\n />\n );\n\n case \"email\":\n return (\n <input\n id={field.id}\n type=\"email\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n\n case \"address\":\n // For address, use the existing AddressFields component\n const addressValue = value || {};\n const addressForm = {\n lastName: \"\",\n firstName: \"\",\n birthDate: \"\",\n day: \"\",\n month: \"\",\n year: \"\",\n email: \"\",\n phoneNumber: \"\",\n sms: \"\",\n addressLine1: addressValue.addressLine1 || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: addressValue.postalCode || \"\",\n city: addressValue.city || \"\",\n countryCode: addressValue.countryCode || \"\",\n nationality: \"\",\n companyName: \"\",\n siret: \"\",\n tva: \"\",\n };\n\n return (\n <AddressFields\n form={addressForm}\n errors={{\n addressLine1: hasError,\n addressLine2: false,\n postalCode: hasError,\n city: hasError,\n country: hasError,\n }}\n requestedFields={new Set([\"adresse\"])}\n onFieldChange={(key, val) => {\n const updatedAddress = {\n ...addressValue,\n [key]: val,\n };\n onFieldChange(field.id, updatedAddress);\n }}\n addressSuggestions={addressSuggestions}\n showSuggestions={showSuggestions}\n onAddressChange={(val) => {\n const updatedAddress = {\n ...addressValue,\n addressLine1: val,\n };\n onFieldChange(field.id, updatedAddress);\n onAddressChange?.(field.id, val);\n }}\n onAddressFocus={() => onAddressFocus?.(field.id)}\n onAddressBlur={() => onAddressBlur?.(field.id)}\n onApplySuggestion={(suggestion) => {\n const updatedAddress = {\n addressLine1: suggestion.label || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: suggestion.postalCode || \"\",\n city: suggestion.city || \"\",\n countryCode: suggestion.countryCode || \"\",\n };\n onFieldChange(field.id, updatedAddress);\n onApplySuggestion?.(field.id, suggestion);\n }}\n />\n );\n\n case \"list\": {\n const persistedRows: Record<string, string>[] = Array.isArray(value)\n ? value\n : [];\n const columns: ListColumn[] = normalizeListColumns(field.listColumns);\n const minRows = getListFieldMinRows(field);\n const rows = ensureMinimumListRows(persistedRows, columns, minRows);\n const gridTemplateColumns = `repeat(${columns.length}, minmax(180px, 1fr)) 32px`;\n const gridMinWidth = `${columns.length * 180 + (columns.length - 1) * 8 + 32}px`;\n const fieldCellErrors = cellErrors[field.id] ?? {};\n\n if (columns.length === 0) {\n return (\n <p className=\"text-sm text-red-600\">\n {t(\n \"custom_form.list_missing_columns\",\n \"Ce tableau n'a pas de colonnes configurées.\",\n )}\n </p>\n );\n }\n\n const handleRowChange = (\n rowIndex: number,\n colName: string,\n colValue: string,\n ) => {\n const updated = [...rows];\n updated[rowIndex] = { ...updated[rowIndex], [colName]: colValue };\n onFieldChange(field.id, updated);\n };\n\n const handleAddRow = () => {\n const emptyRow = createEmptyListRow(columns);\n onFieldChange(field.id, [...rows, emptyRow]);\n };\n\n const handleRemoveRow = (rowIndex: number) => {\n if (rows.length <= minRows) {\n return;\n }\n\n onFieldChange(\n field.id,\n rows.filter((_, i) => i !== rowIndex),\n );\n };\n\n const cellClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n return (\n <div className=\"space-y-3 overflow-x-auto\">\n {columns.length > 0 && (\n <div\n className=\"grid gap-2 items-center w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => (\n <span\n key={col.label}\n className=\"text-xs font-semibold text-gray-600 uppercase tracking-wide truncate\"\n >\n {col.label}\n </span>\n ))}\n <span />\n </div>\n )}\n\n {rows.map((row, rowIndex) => (\n <div\n key={rowIndex}\n className=\"grid gap-2 items-start w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => {\n const cellErr =\n fieldCellErrors[cellErrorKey(rowIndex, col.label)];\n const cellHasError = Boolean(cellErr);\n const cellInputClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n cellHasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n return (\n <div\n key={col.label}\n className=\"flex flex-col gap-1 min-w-0\"\n >\n <ListCell\n col={col}\n value={row[col.label] || \"\"}\n hasError={cellHasError || hasError}\n cellClasses={cellInputClasses}\n onChange={(val) =>\n handleRowChange(rowIndex, col.label, val)\n }\n language={currentLanguage}\n />\n {typeof cellErr === \"string\" && (\n <span className=\"text-xs text-red-600\">\n {cellErr}\n </span>\n )}\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={() => handleRemoveRow(rowIndex)}\n className={clsx(\n \"flex items-center justify-center w-8 h-8 rounded-full transition-colors\",\n rows.length <= minRows\n ? \"text-gray-300 cursor-not-allowed\"\n : \"text-gray-400 hover:text-red-500 hover:bg-red-50\",\n )}\n aria-label={t(\"custom_form.remove_row\", \"Supprimer la ligne\")}\n disabled={rows.length <= minRows}\n >\n ✕\n </button>\n </div>\n ))}\n\n <button\n type=\"button\"\n onClick={handleAddRow}\n className=\"flex items-center gap-2 text-sm text-[#11E5C5] hover:underline font-medium\"\n >\n + {t(\"custom_form.add_row\", \"Ajouter une ligne\")}\n </button>\n </div>\n );\n }\n\n default:\n return null;\n }\n };\n\n const visibleFields = customFields.filter((f) => !f.lockedFromApi);\n\n return (\n <Fragment>\n {visibleFields.map((field) => (\n <div key={field.id} className=\"space-y-2\">\n <Label.Root\n htmlFor={field.id}\n className=\"block text-sm md:text-base font-semibold text-gray-900\"\n >\n {field.label}\n {field.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label.Root>\n\n {field.description && field.valueType !== \"boolean\" && (\n <p className=\"text-xs text-gray-500 -mt-1\">{field.description}</p>\n )}\n\n {renderField(field)}\n\n {(() => {\n const fieldErr = errors[field.id];\n if (!fieldErr) return null;\n const message =\n typeof fieldErr === \"string\"\n ? fieldErr\n : field.required && !formData[field.id]\n ? t(\"custom_form.required_field\")\n : t(\"custom_form.invalid_value\");\n return (\n <p className=\"text-red-600 text-sm flex items-center gap-1\">\n <span className=\"text-red-500\">⚠</span>\n {message}\n </p>\n );\n })()}\n </div>\n ))}\n </Fragment>\n );\n};\n\nexport default CustomFormFields;\n"],"names":["_jsx","Select","DatePickerField","useI18n","_jsxs","AddressFields","normalizeListColumns","getListFieldMinRows","ensureMinimumListRows","__spreadArray","__assign","createEmptyListRow","cellErrorKey","Fragment","Label"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number) => void;\n goBack: () => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\";\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":";;AA8DO,IAAM,2BAA2B,GAAsB;;;;"}
1
+ {"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number) => void;\n goBack: () => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n lockedFromApi?: boolean;\n userInputKey?: string;\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\";\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":";;AA8DO,IAAM,2BAA2B,GAAsB;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { __assign, __awaiter, __generator } from '../../../node_modules/tslib/tslib.es6.js';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { useRef, useState, useEffect } from 'react';
3
+ import { useRef, useState, useCallback, useEffect } from 'react';
4
4
  import { VideoRecorder, AcquisitionPreset } from '@unissey-web/sdk-react';
5
5
  import Button from '../../ui/Button.js';
6
6
  import Title from '../../ui/Title.js';
@@ -15,16 +15,29 @@ import { getUnisseyStrings } from '../utils/unisseyStrings.js';
15
15
 
16
16
  var SelfieRecorder = function (_a) {
17
17
  var _b;
18
- var handleSelfie = _a.handleSelfie, _c = _a.onBeginCapture, onBeginCapture = _c === void 0 ? function () { } : _c; _a.isCapturing; var btnBg = _a.btnBg, btnText = _a.btnText;
18
+ var handleSelfie = _a.handleSelfie, _c = _a.onBeginCapture, onBeginCapture = _c === void 0 ? function () { } : _c, btnBg = _a.btnBg, btnText = _a.btnText;
19
19
  var t = useI18n().t;
20
20
  var isMobile = useIsMobile(768);
21
21
  var recorderRef = useRef(null);
22
- var _e = useState(false), disableButton = _e[0], setDisableButton = _e[1];
23
- var _f = useState(false), recorderReady = _f[0], setRecorderReady = _f[1];
24
- var _g = useState("idle"), recordingState = _g[0], setRecordingState = _g[1];
22
+ var _d = useState(false), disableButton = _d[0], setDisableButton = _d[1];
23
+ var _e = useState(false), recorderReady = _e[0], setRecorderReady = _e[1];
24
+ var _f = useState("idle"), recordingState = _f[0], setRecordingState = _f[1];
25
+ var recordingStateRef = useRef("idle");
26
+ var lastRecorderStatusRef = useRef();
25
27
  var capturedThumbnailRef = useRef(null);
26
- var _h = useLiveFrameCapture(), captureFrame = _h.captureFrame, cleanup = _h.cleanup;
28
+ var _g = useLiveFrameCapture(), captureFrame = _g.captureFrame, cleanup = _g.cleanup;
27
29
  useVideoRecorderStyles(btnBg, btnText);
30
+ var updateRecordingState = useCallback(function (state) {
31
+ recordingStateRef.current = state;
32
+ setRecordingState(state);
33
+ }, []);
34
+ var resetCaptureControls = useCallback(function () {
35
+ if (recordingStateRef.current === "processing")
36
+ return;
37
+ capturedThumbnailRef.current = null;
38
+ updateRecordingState("idle");
39
+ setDisableButton(false);
40
+ }, [updateRecordingState]);
28
41
  useEffect(function () {
29
42
  document.body.classList.add("recording-selfie");
30
43
  var cleanupObserver = setupVideoElementsObserver();
@@ -80,7 +93,7 @@ var SelfieRecorder = function (_a) {
80
93
  if (!recorderReady || recordingState !== "idle")
81
94
  return;
82
95
  onBeginCapture();
83
- setRecordingState("preparing");
96
+ updateRecordingState("preparing");
84
97
  setDisableButton(true);
85
98
  var triggerCapture = function () { return __awaiter(void 0, void 0, void 0, function () {
86
99
  var error_1;
@@ -95,7 +108,7 @@ var SelfieRecorder = function (_a) {
95
108
  return [4 /*yield*/, delay(200)];
96
109
  case 2:
97
110
  _b.sent();
98
- setRecordingState("recording");
111
+ updateRecordingState("recording");
99
112
  // Capture a frame from the live video during recording (after a short delay)
100
113
  setTimeout(function () {
101
114
  var videoElement = getRecorderVideoElement(recorderRef.current);
@@ -109,7 +122,7 @@ var SelfieRecorder = function (_a) {
109
122
  case 3:
110
123
  error_1 = _b.sent();
111
124
  console.error("SelfieRecorder: failed to capture frame", error_1);
112
- setRecordingState("idle");
125
+ updateRecordingState("idle");
113
126
  setDisableButton(false);
114
127
  return [3 /*break*/, 4];
115
128
  case 4: return [2 /*return*/];
@@ -124,9 +137,24 @@ var SelfieRecorder = function (_a) {
124
137
  var status = (_a = recorderRef.current) === null || _a === void 0 ? void 0 : _a.sdkJsStatus;
125
138
  var isReady = status === "ready" || status === "running";
126
139
  setRecorderReady(function (prev) { return (prev !== isReady ? isReady : prev); });
140
+ var previousStatus = lastRecorderStatusRef.current;
141
+ var wasReady = previousStatus === "ready" || previousStatus === "running";
142
+ if (status !== previousStatus) {
143
+ lastRecorderStatusRef.current = status;
144
+ if (isReady && previousStatus !== undefined && !wasReady) {
145
+ resetCaptureControls();
146
+ }
147
+ }
127
148
  }, 500);
128
149
  return function () { return clearInterval(interval); };
129
- }, []);
150
+ }, [resetCaptureControls]);
151
+ var handleRecorderReady = function () {
152
+ setRecorderReady(true);
153
+ resetCaptureControls();
154
+ };
155
+ var handleRecordInterrupted = function () {
156
+ resetCaptureControls();
157
+ };
130
158
  var handleRecordCompleted = function (e) {
131
159
  var _a;
132
160
  var customEvent = e;
@@ -144,7 +172,7 @@ var SelfieRecorder = function (_a) {
144
172
  });
145
173
  });
146
174
  }
147
- setRecordingState("idle");
175
+ updateRecordingState("idle");
148
176
  setDisableButton(false);
149
177
  return;
150
178
  }
@@ -156,7 +184,7 @@ var SelfieRecorder = function (_a) {
156
184
  thumbnail: capturedThumbnailRef.current || undefined,
157
185
  }
158
186
  });
159
- setRecordingState("processing");
187
+ updateRecordingState("processing");
160
188
  handleSelfie(enhancedEvent);
161
189
  };
162
190
  return (jsxs("div", { className: "selfie selfie-recorder-root flex flex-col", style: (_b = {},
@@ -167,7 +195,7 @@ var SelfieRecorder = function (_a) {
167
195
  _b.zIndex = isMobile ? 50 : "auto",
168
196
  _b.height = "100%",
169
197
  _b.width = "100%",
170
- _b), children: [jsxs("div", { className: "p-4 text-center bg-white shrink-0", children: [jsx(Title, { className: "text-lg md:text-xl mb-1", children: t("selfie.recorder.title") }), jsx(Subtitle, { className: "text-xs text-gray-600 md:text-sm", children: t("selfie.recorder.subtitle") })] }), jsx("div", { className: "video-container flex-1 relative overflow-hidden", children: jsx(VideoRecorder, __assign({ ref: recorderRef, preset: AcquisitionPreset.SELFIE_OPTIMIZED, hideCaptureBtn: true, faceChecker: (typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled', disableDebugMode: true, onRecordCompleted: handleRecordCompleted, onRecord: recordStarting, style: { width: "100%", height: "100%" }, className: "video-recorder-no-radius w-full h-full" }, (isIOS() && {
198
+ _b), children: [jsxs("div", { className: "p-4 text-center bg-white shrink-0", children: [jsx(Title, { className: "text-lg md:text-xl mb-1", children: t("selfie.recorder.title") }), jsx(Subtitle, { className: "text-xs text-gray-600 md:text-sm", children: t("selfie.recorder.subtitle") })] }), jsx("div", { className: "video-container flex-1 relative overflow-hidden", children: jsx(VideoRecorder, __assign({ ref: recorderRef, preset: AcquisitionPreset.SELFIE_OPTIMIZED, hideCaptureBtn: true, faceChecker: (typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled', disableDebugMode: true, onRecorderReady: handleRecorderReady, onRecordInterrupted: handleRecordInterrupted, onRecordCompleted: handleRecordCompleted, onRecord: recordStarting, style: { width: "100%", height: "100%" }, className: "video-recorder-no-radius w-full h-full" }, (isIOS() && {
171
199
  "data-playsinline": "true",
172
200
  "data-autoplay": "true",
173
201
  "data-muted": "true"
@@ -1 +1 @@
1
- {"version":3,"file":"SelfieRecorder.js","sources":["../../../../../../src/components/selfie/selfie-flow/SelfieRecorder.tsx"],"sourcesContent":["import { useRef, useState, useEffect } from \"react\";\nimport { AcquisitionPreset, VideoRecorder } from \"@unissey-web/sdk-react\";\nimport Button from \"../../ui/Button\";\nimport Title from \"../../ui/Title\";\nimport Subtitle from \"../../ui/Subtitle\";\nimport useVideoRecorderStyles from \"../hooks/useVideoRecorderStyles\";\nimport { setupVideoElementsObserver } from \"../utils/videoElementStyles\";\nimport { delay, isIOS, waitForVideoFrame, getRecorderVideoElement } from \"../utils/selfieCaptureUtils\";\nimport { useLiveFrameCapture } from \"../hooks/useLiveFrameCapture\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport { getUnisseyStrings } from \"../utils/unisseyStrings\";\n\ninterface SelfieRecorderProps {\n handleSelfie: (e: Event) => void;\n onBeginCapture?: () => void;\n isCapturing?: boolean;\n btnBg?: string;\n btnText?: string;\n}\n\ninterface VideoRecorderRef extends HTMLElement {\n capture: () => void;\n}\n\nconst SelfieRecorder = ({\n handleSelfie,\n onBeginCapture = () => { },\n isCapturing = false,\n btnBg,\n btnText,\n}: SelfieRecorderProps) => {\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n const recorderRef = useRef<VideoRecorderRef | null>(null);\n const [disableButton, setDisableButton] = useState(false);\n const [recorderReady, setRecorderReady] = useState(false);\n const [recordingState, setRecordingState] = useState<\n \"idle\" | \"preparing\" | \"recording\" | \"processing\"\n >(\"idle\");\n const capturedThumbnailRef = useRef<string | null>(null);\n const { captureFrame, cleanup } = useLiveFrameCapture();\n\n useVideoRecorderStyles(btnBg, btnText);\n\n useEffect(() => {\n document.body.classList.add(\"recording-selfie\");\n const cleanupObserver = setupVideoElementsObserver();\n\n // iOS-specific fix: Add required attributes to video elements after mount\n if (isIOS()) {\n const addIOSVideoAttributes = () => {\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder) => {\n // Try to access shadow DOM and video elements\n try {\n const shadowRoot = (recorder as any).shadowRoot;\n if (shadowRoot) {\n const videoElements = shadowRoot.querySelectorAll(\"video\");\n videoElements.forEach((video: HTMLVideoElement) => {\n video.setAttribute(\"playsinline\", \"true\");\n video.setAttribute(\"autoplay\", \"true\");\n video.setAttribute(\"muted\", \"true\");\n // Ensure video plays inline and autoplays\n video.playsInline = true;\n video.autoplay = true;\n video.muted = true;\n });\n }\n } catch (error) {\n console.log(\"Could not access shadow DOM:\", error);\n }\n\n // Also set attributes on the component itself\n recorder.setAttribute(\"playsinline\", \"true\");\n recorder.setAttribute(\"autoplay\", \"true\");\n recorder.setAttribute(\"muted\", \"true\");\n });\n };\n\n // Apply immediately and also after a delay to catch dynamically created elements\n addIOSVideoAttributes();\n const iosTimeout = setTimeout(addIOSVideoAttributes, 500);\n const iosInterval = setInterval(addIOSVideoAttributes, 1000);\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n clearTimeout(iosTimeout);\n clearInterval(iosInterval);\n };\n }\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n };\n }, [cleanup]);\n\n const recordStarting = () => {\n if (!recorderReady || recordingState !== \"idle\") return;\n onBeginCapture();\n setRecordingState(\"preparing\");\n setDisableButton(true);\n\n const triggerCapture = async () => {\n try {\n await waitForVideoFrame(recorderRef.current);\n await delay(200);\n setRecordingState(\"recording\");\n\n // Capture a frame from the live video during recording (after a short delay)\n setTimeout(() => {\n const videoElement = getRecorderVideoElement(recorderRef.current);\n if (videoElement) {\n const thumbnail = captureFrame(videoElement);\n capturedThumbnailRef.current = thumbnail;\n }\n }, 1000); // Capture frame 1 second into recording\n\n recorderRef.current?.capture();\n } catch (error) {\n console.error(\"SelfieRecorder: failed to capture frame\", error);\n setRecordingState(\"idle\");\n setDisableButton(false);\n }\n };\n\n void triggerCapture();\n };\n\n useEffect(() => {\n const interval = setInterval(() => {\n const status = (recorderRef.current as any)?.sdkJsStatus;\n const isReady = status === \"ready\" || status === \"running\";\n setRecorderReady((prev) => (prev !== isReady ? isReady : prev));\n }, 500);\n return () => clearInterval(interval);\n }, []);\n\n const handleRecordCompleted = (e: Event) => {\n const customEvent = e as CustomEvent<{ media?: Blob; metadata?: string }>;\n if (!customEvent.detail?.media || customEvent.detail.media.size === 0) {\n console.error(\"❌ No valid media captured\");\n\n // iOS-specific debugging\n if (isIOS()) {\n console.log(\"🍎 iOS detected - checking video elements for proper attributes\");\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder, index) => {\n console.log(`VideoRecorder ${index}:`, {\n playsinline: recorder.getAttribute(\"playsinline\"),\n autoplay: recorder.getAttribute(\"autoplay\"),\n muted: recorder.getAttribute(\"muted\")\n });\n });\n }\n\n setRecordingState(\"idle\");\n setDisableButton(false);\n return;\n }\n\n // Attach the captured thumbnail to the event\n const enhancedEvent = new CustomEvent('record-completed', {\n detail: {\n media: customEvent.detail.media,\n metadata: customEvent.detail.metadata || '',\n thumbnail: capturedThumbnailRef.current || undefined,\n }\n });\n\n setRecordingState(\"processing\");\n handleSelfie(enhancedEvent);\n };\n\n return (\n <div\n className=\"selfie selfie-recorder-root flex flex-col\"\n style={{\n [\"--dk-btn-bg\" as string]: btnBg ?? \"#11E5C5\",\n [\"--dk-btn-text\" as string]: btnText ?? \"#3C3C40\",\n position: isMobile ? \"fixed\" : \"relative\",\n inset: isMobile ? 0 : \"auto\",\n zIndex: isMobile ? 50 : \"auto\",\n height: \"100%\",\n width: \"100%\",\n }}\n >\n <div className=\"p-4 text-center bg-white shrink-0\">\n <Title className=\"text-lg md:text-xl mb-1\">{t(\"selfie.recorder.title\")}</Title>\n <Subtitle className=\"text-xs text-gray-600 md:text-sm\">{t(\"selfie.recorder.subtitle\")}</Subtitle>\n </div>\n\n <div className=\"video-container flex-1 relative overflow-hidden\">\n <VideoRecorder\n ref={recorderRef as any}\n preset={AcquisitionPreset.SELFIE_OPTIMIZED}\n hideCaptureBtn\n faceChecker={(typeof window !== 'undefined' && (window as any).__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled'}\n disableDebugMode\n onRecordCompleted={handleRecordCompleted}\n onRecord={recordStarting}\n style={{ width: \"100%\", height: \"100%\" }}\n className=\"video-recorder-no-radius w-full h-full\"\n {...(isIOS() && {\n \"data-playsinline\": \"true\",\n \"data-autoplay\": \"true\",\n \"data-muted\": \"true\"\n })}\n strings={getUnisseyStrings(t)}\n />\n </div>\n\n <div className=\"shrink-0 bg-white border-t border-gray-200 p-4 md:p-6 relative\" style={{ zIndex: 9999 }}>\n <div className=\"max-w-md mx-auto\">\n <div className=\"text-center text-xs text-gray-400 mt-3\">\n {t(\"selfie.recorder.note\")}\n </div>\n\n <Button\n onClick={recordStarting}\n className=\"w-full py-3 md:py-4 relative selfie-button\"\n disabled={disableButton || !recorderReady}\n style={{ backgroundColor: btnBg ?? \"#11E5C5\", color: btnText ?? \"#3C3C40\" }}\n >\n {recordingState === \"idle\" && t(\"selfie.recorder.start\")}\n {recordingState === \"preparing\" && t(\"selfie.recorder.preparing\")}\n {recordingState === \"recording\" && (\n <span className=\"flex items-center justify-center\">\n <span className=\"mr-2\">{t(\"selfie.recorder.recording_label\")}</span>\n <span className=\"flex space-x-1 loading-dots\">\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n </span>\n </span>\n )}\n {recordingState === \"processing\" && t(\"selfie.recorder.processing\")}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SelfieRecorder;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"SelfieRecorder.js","sources":["../../../../../../src/components/selfie/selfie-flow/SelfieRecorder.tsx"],"sourcesContent":["import {\n useCallback,\n useRef,\n useState,\n useEffect,\n type ElementRef,\n} from \"react\";\nimport { AcquisitionPreset, VideoRecorder } from \"@unissey-web/sdk-react\";\nimport Button from \"../../ui/Button\";\nimport Title from \"../../ui/Title\";\nimport Subtitle from \"../../ui/Subtitle\";\nimport useVideoRecorderStyles from \"../hooks/useVideoRecorderStyles\";\nimport { setupVideoElementsObserver } from \"../utils/videoElementStyles\";\nimport { delay, isIOS, waitForVideoFrame, getRecorderVideoElement } from \"../utils/selfieCaptureUtils\";\nimport { useLiveFrameCapture } from \"../hooks/useLiveFrameCapture\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport useIsMobile from \"../../../hooks/useIsMobile\";\nimport { getUnisseyStrings } from \"../utils/unisseyStrings\";\n\ntype RecordingState = \"idle\" | \"preparing\" | \"recording\" | \"processing\";\n\ninterface SelfieRecorderProps {\n handleSelfie: (e: Event) => void;\n onBeginCapture?: () => void;\n isCapturing?: boolean;\n btnBg?: string;\n btnText?: string;\n}\n\ntype VideoRecorderElement = ElementRef<typeof VideoRecorder>;\n\nconst SelfieRecorder = ({\n handleSelfie,\n onBeginCapture = () => { },\n btnBg,\n btnText,\n}: SelfieRecorderProps) => {\n const { t } = useI18n();\n const isMobile = useIsMobile(768);\n const recorderRef = useRef<VideoRecorderElement | null>(null);\n const [disableButton, setDisableButton] = useState(false);\n const [recorderReady, setRecorderReady] = useState(false);\n const [recordingState, setRecordingState] = useState<RecordingState>(\"idle\");\n const recordingStateRef = useRef<RecordingState>(\"idle\");\n const lastRecorderStatusRef = useRef<string | undefined>();\n const capturedThumbnailRef = useRef<string | null>(null);\n const { captureFrame, cleanup } = useLiveFrameCapture();\n\n useVideoRecorderStyles(btnBg, btnText);\n\n const updateRecordingState = useCallback((state: RecordingState) => {\n recordingStateRef.current = state;\n setRecordingState(state);\n }, []);\n\n const resetCaptureControls = useCallback(() => {\n if (recordingStateRef.current === \"processing\") return;\n capturedThumbnailRef.current = null;\n updateRecordingState(\"idle\");\n setDisableButton(false);\n }, [updateRecordingState]);\n\n useEffect(() => {\n document.body.classList.add(\"recording-selfie\");\n const cleanupObserver = setupVideoElementsObserver();\n\n // iOS-specific fix: Add required attributes to video elements after mount\n if (isIOS()) {\n const addIOSVideoAttributes = () => {\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder) => {\n // Try to access shadow DOM and video elements\n try {\n const shadowRoot = recorder.shadowRoot;\n if (shadowRoot) {\n const videoElements = shadowRoot.querySelectorAll(\"video\");\n videoElements.forEach((video: HTMLVideoElement) => {\n video.setAttribute(\"playsinline\", \"true\");\n video.setAttribute(\"autoplay\", \"true\");\n video.setAttribute(\"muted\", \"true\");\n // Ensure video plays inline and autoplays\n video.playsInline = true;\n video.autoplay = true;\n video.muted = true;\n });\n }\n } catch (error) {\n console.log(\"Could not access shadow DOM:\", error);\n }\n\n // Also set attributes on the component itself\n recorder.setAttribute(\"playsinline\", \"true\");\n recorder.setAttribute(\"autoplay\", \"true\");\n recorder.setAttribute(\"muted\", \"true\");\n });\n };\n\n // Apply immediately and also after a delay to catch dynamically created elements\n addIOSVideoAttributes();\n const iosTimeout = setTimeout(addIOSVideoAttributes, 500);\n const iosInterval = setInterval(addIOSVideoAttributes, 1000);\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n clearTimeout(iosTimeout);\n clearInterval(iosInterval);\n };\n }\n\n return () => {\n document.body.classList.remove(\"recording-selfie\");\n cleanupObserver();\n cleanup();\n };\n }, [cleanup]);\n\n const recordStarting = () => {\n if (!recorderReady || recordingState !== \"idle\") return;\n onBeginCapture();\n updateRecordingState(\"preparing\");\n setDisableButton(true);\n\n const triggerCapture = async () => {\n try {\n await waitForVideoFrame(recorderRef.current);\n await delay(200);\n updateRecordingState(\"recording\");\n\n // Capture a frame from the live video during recording (after a short delay)\n setTimeout(() => {\n const videoElement = getRecorderVideoElement(recorderRef.current);\n if (videoElement) {\n const thumbnail = captureFrame(videoElement);\n capturedThumbnailRef.current = thumbnail;\n }\n }, 1000); // Capture frame 1 second into recording\n\n recorderRef.current?.capture();\n } catch (error) {\n console.error(\"SelfieRecorder: failed to capture frame\", error);\n updateRecordingState(\"idle\");\n setDisableButton(false);\n }\n };\n\n void triggerCapture();\n };\n\n useEffect(() => {\n const interval = setInterval(() => {\n const status = recorderRef.current?.sdkJsStatus;\n const isReady = status === \"ready\" || status === \"running\";\n setRecorderReady((prev) => (prev !== isReady ? isReady : prev));\n\n const previousStatus = lastRecorderStatusRef.current;\n const wasReady = previousStatus === \"ready\" || previousStatus === \"running\";\n if (status !== previousStatus) {\n lastRecorderStatusRef.current = status;\n if (isReady && previousStatus !== undefined && !wasReady) {\n resetCaptureControls();\n }\n }\n }, 500);\n return () => clearInterval(interval);\n }, [resetCaptureControls]);\n\n const handleRecorderReady = () => {\n setRecorderReady(true);\n resetCaptureControls();\n };\n\n const handleRecordInterrupted = () => {\n resetCaptureControls();\n };\n\n const handleRecordCompleted = (e: Event) => {\n const customEvent = e as CustomEvent<{ media?: Blob; metadata?: string }>;\n if (!customEvent.detail?.media || customEvent.detail.media.size === 0) {\n console.error(\"❌ No valid media captured\");\n\n // iOS-specific debugging\n if (isIOS()) {\n console.log(\"🍎 iOS detected - checking video elements for proper attributes\");\n const videoRecorders = document.querySelectorAll(\"uni-video-recorder\");\n videoRecorders.forEach((recorder, index) => {\n console.log(`VideoRecorder ${index}:`, {\n playsinline: recorder.getAttribute(\"playsinline\"),\n autoplay: recorder.getAttribute(\"autoplay\"),\n muted: recorder.getAttribute(\"muted\")\n });\n });\n }\n\n updateRecordingState(\"idle\");\n setDisableButton(false);\n return;\n }\n\n // Attach the captured thumbnail to the event\n const enhancedEvent = new CustomEvent('record-completed', {\n detail: {\n media: customEvent.detail.media,\n metadata: customEvent.detail.metadata || '',\n thumbnail: capturedThumbnailRef.current || undefined,\n }\n });\n\n updateRecordingState(\"processing\");\n handleSelfie(enhancedEvent);\n };\n\n return (\n <div\n className=\"selfie selfie-recorder-root flex flex-col\"\n style={{\n [\"--dk-btn-bg\" as string]: btnBg ?? \"#11E5C5\",\n [\"--dk-btn-text\" as string]: btnText ?? \"#3C3C40\",\n position: isMobile ? \"fixed\" : \"relative\",\n inset: isMobile ? 0 : \"auto\",\n zIndex: isMobile ? 50 : \"auto\",\n height: \"100%\",\n width: \"100%\",\n }}\n >\n <div className=\"p-4 text-center bg-white shrink-0\">\n <Title className=\"text-lg md:text-xl mb-1\">{t(\"selfie.recorder.title\")}</Title>\n <Subtitle className=\"text-xs text-gray-600 md:text-sm\">{t(\"selfie.recorder.subtitle\")}</Subtitle>\n </div>\n\n <div className=\"video-container flex-1 relative overflow-hidden\">\n <VideoRecorder\n ref={recorderRef}\n preset={AcquisitionPreset.SELFIE_OPTIMIZED}\n hideCaptureBtn\n faceChecker={(typeof window !== 'undefined' && window.__E2E_DISABLE_FACE_CHECKER__) ? 'disabled' : 'enabled'}\n disableDebugMode\n onRecorderReady={handleRecorderReady}\n onRecordInterrupted={handleRecordInterrupted}\n onRecordCompleted={handleRecordCompleted}\n onRecord={recordStarting}\n style={{ width: \"100%\", height: \"100%\" }}\n className=\"video-recorder-no-radius w-full h-full\"\n {...(isIOS() && {\n \"data-playsinline\": \"true\",\n \"data-autoplay\": \"true\",\n \"data-muted\": \"true\"\n })}\n strings={getUnisseyStrings(t)}\n />\n </div>\n\n <div className=\"shrink-0 bg-white border-t border-gray-200 p-4 md:p-6 relative\" style={{ zIndex: 9999 }}>\n <div className=\"max-w-md mx-auto\">\n <div className=\"text-center text-xs text-gray-400 mt-3\">\n {t(\"selfie.recorder.note\")}\n </div>\n\n <Button\n onClick={recordStarting}\n className=\"w-full py-3 md:py-4 relative selfie-button\"\n disabled={disableButton || !recorderReady}\n style={{ backgroundColor: btnBg ?? \"#11E5C5\", color: btnText ?? \"#3C3C40\" }}\n >\n {recordingState === \"idle\" && t(\"selfie.recorder.start\")}\n {recordingState === \"preparing\" && t(\"selfie.recorder.preparing\")}\n {recordingState === \"recording\" && (\n <span className=\"flex items-center justify-center\">\n <span className=\"mr-2\">{t(\"selfie.recorder.recording_label\")}</span>\n <span className=\"flex space-x-1 loading-dots\">\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n <span className=\"h-1 w-1 bg-white rounded-full\"></span>\n </span>\n </span>\n )}\n {recordingState === \"processing\" && t(\"selfie.recorder.processing\")}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SelfieRecorder;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -169,7 +169,8 @@ var CustomFormFields = function (_a) {
169
169
  return null;
170
170
  }
171
171
  };
172
- return (jsx(Fragment, { children: customFields.map(function (field) { return (jsxs("div", { className: "space-y-2", children: [jsxs(Label.Root, { htmlFor: field.id, className: "block text-sm md:text-base font-semibold text-gray-900", children: [field.label, field.required && jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), field.description && field.valueType !== "boolean" && (jsx("p", { className: "text-xs text-gray-500 -mt-1", children: field.description })), renderField(field), (function () {
172
+ var visibleFields = customFields.filter(function (f) { return !f.lockedFromApi; });
173
+ return (jsx(Fragment, { children: visibleFields.map(function (field) { return (jsxs("div", { className: "space-y-2", children: [jsxs(Label.Root, { htmlFor: field.id, className: "block text-sm md:text-base font-semibold text-gray-900", children: [field.label, field.required && jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), field.description && field.valueType !== "boolean" && (jsx("p", { className: "text-xs text-gray-500 -mt-1", children: field.description })), renderField(field), (function () {
173
174
  var fieldErr = errors[field.id];
174
175
  if (!fieldErr)
175
176
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"CustomFormFields.js","sources":["../../../../../../src/components/session/UserInputForm/CustomFormFields.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport * as Label from \"@radix-ui/react-label\";\nimport clsx from \"clsx\";\nimport { Select } from \"../../ui/SelectComponent\";\nimport type { CustomField, ListColumn } from \"../../../types/session\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport AddressFields from \"./AddressFields\";\nimport type { AddressSuggestion } from \"../../../types/userInputForm\";\nimport {\n createEmptyListRow,\n ensureMinimumListRows,\n getListFieldMinRows,\n normalizeListColumns,\n} from \"../../../utils/listFieldUtils\";\nimport { cellErrorKey } from \"../../../utils/customFieldValidation\";\nimport { DatePickerField } from \"./DatePickerField\";\n\ntype CellErrorValue = string | boolean;\n\n/**\n * Sous-composant dédié au rendu d'une cellule du tableau dynamique.\n * Nécessaire pour que les hooks internes à Select soient toujours appelés\n * de façon stable (règle des hooks React).\n */\nconst ListCell = ({\n col,\n value,\n hasError,\n cellClasses,\n onChange,\n language,\n}: {\n col: ListColumn;\n value: string;\n hasError: boolean;\n cellClasses: string;\n onChange: (val: string) => void;\n language: string;\n}) => {\n if (col.type === \"enum\") {\n return (\n <Select\n options={(col.options ?? []).map((opt) => ({ value: opt, label: opt }))}\n value={value}\n onValueChange={onChange}\n placeholder={col.placeholder || col.label}\n error={hasError}\n compact\n />\n );\n }\n if (col.type === \"email\") {\n return (\n <input\n type=\"email\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n }\n if (col.type === \"date\") {\n return (\n <DatePickerField\n value={value}\n dateFormat={col.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={col.placeholder}\n hasError={hasError}\n language={language}\n onChange={onChange}\n className={cellClasses}\n />\n );\n }\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n />\n );\n};\n\ninterface CustomFormFieldsProps {\n customFields: CustomField[];\n formData: Record<string, any>;\n errors: Record<string, CellErrorValue>;\n cellErrors?: Record<string, Record<string, CellErrorValue>>;\n onFieldChange: (fieldId: string, value: any) => void;\n // Address autocomplete props (for address field type)\n addressSuggestions?: AddressSuggestion[];\n showSuggestions?: boolean;\n onAddressChange?: (fieldId: string, value: string) => void;\n onAddressFocus?: (fieldId: string) => void;\n onAddressBlur?: (fieldId: string) => void;\n onApplySuggestion?: (fieldId: string, suggestion: AddressSuggestion) => void;\n}\n\nconst CustomFormFields = ({\n customFields,\n formData,\n errors,\n cellErrors = {},\n onFieldChange,\n addressSuggestions = [],\n showSuggestions = false,\n onAddressChange,\n onAddressFocus,\n onAddressBlur,\n onApplySuggestion,\n}: CustomFormFieldsProps) => {\n const { t, currentLanguage } = useI18n();\n\n console.log(\"🎨 [CustomFormFields] Rendering with:\", {\n fieldsCount: customFields.length,\n fields: customFields.map((f) => ({\n id: f.id,\n label: f.label,\n type: f.valueType,\n })),\n formData,\n errors,\n });\n\n const renderField = (field: CustomField) => {\n const hasError = Boolean(errors[field.id]);\n const value = formData[field.id];\n\n // Classes communes (EXACTEMENT comme IdentityFields/ContactFields)\n const inputClasses = clsx(\n \"w-full px-3 py-3 md:py-4 border rounded-lg text-base transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n switch (field.valueType) {\n case \"text\":\n return (\n <input\n id={field.id}\n type=\"text\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n />\n );\n\n case \"number\":\n return (\n <input\n id={field.id}\n type=\"number\"\n inputMode=\"numeric\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n />\n );\n\n case \"date\":\n return (\n <DatePickerField\n id={field.id}\n value={value || \"\"}\n dateFormat={field.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={field.placeholder}\n hasError={hasError}\n language={currentLanguage}\n onChange={(v) => onFieldChange(field.id, v)}\n className={inputClasses}\n />\n );\n\n case \"boolean\":\n return (\n <div className=\"flex items-center gap-2\">\n <input\n id={field.id}\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => onFieldChange(field.id, e.target.checked)}\n className=\"h-4 w-4 text-[#11E5C5] border-gray-300 rounded focus:ring-[#11E5C5]\"\n />\n {field.description && (\n <span className=\"text-sm text-gray-600\">{field.description}</span>\n )}\n </div>\n );\n\n case \"enum\":\n return (\n <Select\n options={(field.enumOptions || []).map((opt) => ({\n value: opt,\n label: opt,\n }))}\n value={value || \"\"}\n onValueChange={(val) => onFieldChange(field.id, val)}\n placeholder={field.placeholder || t(\"custom_form.select_option\")}\n error={hasError}\n />\n );\n\n case \"email\":\n return (\n <input\n id={field.id}\n type=\"email\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n\n case \"address\":\n // For address, use the existing AddressFields component\n const addressValue = value || {};\n const addressForm = {\n lastName: \"\",\n firstName: \"\",\n birthDate: \"\",\n day: \"\",\n month: \"\",\n year: \"\",\n email: \"\",\n phoneNumber: \"\",\n sms: \"\",\n addressLine1: addressValue.addressLine1 || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: addressValue.postalCode || \"\",\n city: addressValue.city || \"\",\n countryCode: addressValue.countryCode || \"\",\n nationality: \"\",\n companyName: \"\",\n siret: \"\",\n tva: \"\",\n };\n\n return (\n <AddressFields\n form={addressForm}\n errors={{\n addressLine1: hasError,\n addressLine2: false,\n postalCode: hasError,\n city: hasError,\n country: hasError,\n }}\n requestedFields={new Set([\"adresse\"])}\n onFieldChange={(key, val) => {\n const updatedAddress = {\n ...addressValue,\n [key]: val,\n };\n onFieldChange(field.id, updatedAddress);\n }}\n addressSuggestions={addressSuggestions}\n showSuggestions={showSuggestions}\n onAddressChange={(val) => {\n const updatedAddress = {\n ...addressValue,\n addressLine1: val,\n };\n onFieldChange(field.id, updatedAddress);\n onAddressChange?.(field.id, val);\n }}\n onAddressFocus={() => onAddressFocus?.(field.id)}\n onAddressBlur={() => onAddressBlur?.(field.id)}\n onApplySuggestion={(suggestion) => {\n const updatedAddress = {\n addressLine1: suggestion.label || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: suggestion.postalCode || \"\",\n city: suggestion.city || \"\",\n countryCode: suggestion.countryCode || \"\",\n };\n onFieldChange(field.id, updatedAddress);\n onApplySuggestion?.(field.id, suggestion);\n }}\n />\n );\n\n case \"list\": {\n const persistedRows: Record<string, string>[] = Array.isArray(value)\n ? value\n : [];\n const columns: ListColumn[] = normalizeListColumns(field.listColumns);\n const minRows = getListFieldMinRows(field);\n const rows = ensureMinimumListRows(persistedRows, columns, minRows);\n const gridTemplateColumns = `repeat(${columns.length}, minmax(180px, 1fr)) 32px`;\n const gridMinWidth = `${columns.length * 180 + (columns.length - 1) * 8 + 32}px`;\n const fieldCellErrors = cellErrors[field.id] ?? {};\n\n if (columns.length === 0) {\n return (\n <p className=\"text-sm text-red-600\">\n {t(\n \"custom_form.list_missing_columns\",\n \"Ce tableau n'a pas de colonnes configurées.\",\n )}\n </p>\n );\n }\n\n const handleRowChange = (\n rowIndex: number,\n colName: string,\n colValue: string,\n ) => {\n const updated = [...rows];\n updated[rowIndex] = { ...updated[rowIndex], [colName]: colValue };\n onFieldChange(field.id, updated);\n };\n\n const handleAddRow = () => {\n const emptyRow = createEmptyListRow(columns);\n onFieldChange(field.id, [...rows, emptyRow]);\n };\n\n const handleRemoveRow = (rowIndex: number) => {\n if (rows.length <= minRows) {\n return;\n }\n\n onFieldChange(\n field.id,\n rows.filter((_, i) => i !== rowIndex),\n );\n };\n\n const cellClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n return (\n <div className=\"space-y-3 overflow-x-auto\">\n {columns.length > 0 && (\n <div\n className=\"grid gap-2 items-center w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => (\n <span\n key={col.label}\n className=\"text-xs font-semibold text-gray-600 uppercase tracking-wide truncate\"\n >\n {col.label}\n </span>\n ))}\n <span />\n </div>\n )}\n\n {rows.map((row, rowIndex) => (\n <div\n key={rowIndex}\n className=\"grid gap-2 items-start w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => {\n const cellErr =\n fieldCellErrors[cellErrorKey(rowIndex, col.label)];\n const cellHasError = Boolean(cellErr);\n const cellInputClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n cellHasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n return (\n <div\n key={col.label}\n className=\"flex flex-col gap-1 min-w-0\"\n >\n <ListCell\n col={col}\n value={row[col.label] || \"\"}\n hasError={cellHasError || hasError}\n cellClasses={cellInputClasses}\n onChange={(val) =>\n handleRowChange(rowIndex, col.label, val)\n }\n language={currentLanguage}\n />\n {typeof cellErr === \"string\" && (\n <span className=\"text-xs text-red-600\">\n {cellErr}\n </span>\n )}\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={() => handleRemoveRow(rowIndex)}\n className={clsx(\n \"flex items-center justify-center w-8 h-8 rounded-full transition-colors\",\n rows.length <= minRows\n ? \"text-gray-300 cursor-not-allowed\"\n : \"text-gray-400 hover:text-red-500 hover:bg-red-50\",\n )}\n aria-label={t(\"custom_form.remove_row\", \"Supprimer la ligne\")}\n disabled={rows.length <= minRows}\n >\n ✕\n </button>\n </div>\n ))}\n\n <button\n type=\"button\"\n onClick={handleAddRow}\n className=\"flex items-center gap-2 text-sm text-[#11E5C5] hover:underline font-medium\"\n >\n + {t(\"custom_form.add_row\", \"Ajouter une ligne\")}\n </button>\n </div>\n );\n }\n\n default:\n return null;\n }\n };\n\n return (\n <Fragment>\n {customFields.map((field) => (\n <div key={field.id} className=\"space-y-2\">\n <Label.Root\n htmlFor={field.id}\n className=\"block text-sm md:text-base font-semibold text-gray-900\"\n >\n {field.label}\n {field.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label.Root>\n\n {field.description && field.valueType !== \"boolean\" && (\n <p className=\"text-xs text-gray-500 -mt-1\">{field.description}</p>\n )}\n\n {renderField(field)}\n\n {(() => {\n const fieldErr = errors[field.id];\n if (!fieldErr) return null;\n const message =\n typeof fieldErr === \"string\"\n ? fieldErr\n : field.required && !formData[field.id]\n ? t(\"custom_form.required_field\")\n : t(\"custom_form.invalid_value\");\n return (\n <p className=\"text-red-600 text-sm flex items-center gap-1\">\n <span className=\"text-red-500\">⚠</span>\n {message}\n </p>\n );\n })()}\n </div>\n ))}\n </Fragment>\n );\n};\n\nexport default CustomFormFields;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"CustomFormFields.js","sources":["../../../../../../src/components/session/UserInputForm/CustomFormFields.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport * as Label from \"@radix-ui/react-label\";\nimport clsx from \"clsx\";\nimport { Select } from \"../../ui/SelectComponent\";\nimport type { CustomField, ListColumn } from \"../../../types/session\";\nimport { useI18n } from \"../../../hooks/useI18n\";\nimport AddressFields from \"./AddressFields\";\nimport type { AddressSuggestion } from \"../../../types/userInputForm\";\nimport {\n createEmptyListRow,\n ensureMinimumListRows,\n getListFieldMinRows,\n normalizeListColumns,\n} from \"../../../utils/listFieldUtils\";\nimport { cellErrorKey } from \"../../../utils/customFieldValidation\";\nimport { DatePickerField } from \"./DatePickerField\";\n\ntype CellErrorValue = string | boolean;\n\n/**\n * Sous-composant dédié au rendu d'une cellule du tableau dynamique.\n * Nécessaire pour que les hooks internes à Select soient toujours appelés\n * de façon stable (règle des hooks React).\n */\nconst ListCell = ({\n col,\n value,\n hasError,\n cellClasses,\n onChange,\n language,\n}: {\n col: ListColumn;\n value: string;\n hasError: boolean;\n cellClasses: string;\n onChange: (val: string) => void;\n language: string;\n}) => {\n if (col.type === \"enum\") {\n return (\n <Select\n options={(col.options ?? []).map((opt) => ({ value: opt, label: opt }))}\n value={value}\n onValueChange={onChange}\n placeholder={col.placeholder || col.label}\n error={hasError}\n compact\n />\n );\n }\n if (col.type === \"email\") {\n return (\n <input\n type=\"email\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n }\n if (col.type === \"date\") {\n return (\n <DatePickerField\n value={value}\n dateFormat={col.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={col.placeholder}\n hasError={hasError}\n language={language}\n onChange={onChange}\n className={cellClasses}\n />\n );\n }\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={col.placeholder || col.label}\n className={cellClasses}\n autoComplete=\"off\"\n />\n );\n};\n\ninterface CustomFormFieldsProps {\n customFields: CustomField[];\n formData: Record<string, any>;\n errors: Record<string, CellErrorValue>;\n cellErrors?: Record<string, Record<string, CellErrorValue>>;\n onFieldChange: (fieldId: string, value: any) => void;\n // Address autocomplete props (for address field type)\n addressSuggestions?: AddressSuggestion[];\n showSuggestions?: boolean;\n onAddressChange?: (fieldId: string, value: string) => void;\n onAddressFocus?: (fieldId: string) => void;\n onAddressBlur?: (fieldId: string) => void;\n onApplySuggestion?: (fieldId: string, suggestion: AddressSuggestion) => void;\n}\n\nconst CustomFormFields = ({\n customFields,\n formData,\n errors,\n cellErrors = {},\n onFieldChange,\n addressSuggestions = [],\n showSuggestions = false,\n onAddressChange,\n onAddressFocus,\n onAddressBlur,\n onApplySuggestion,\n}: CustomFormFieldsProps) => {\n const { t, currentLanguage } = useI18n();\n\n console.log(\"🎨 [CustomFormFields] Rendering with:\", {\n fieldsCount: customFields.length,\n fields: customFields.map((f) => ({\n id: f.id,\n label: f.label,\n type: f.valueType,\n })),\n formData,\n errors,\n });\n\n const renderField = (field: CustomField) => {\n const hasError = Boolean(errors[field.id]);\n const value = formData[field.id];\n\n // Classes communes (EXACTEMENT comme IdentityFields/ContactFields)\n const inputClasses = clsx(\n \"w-full px-3 py-3 md:py-4 border rounded-lg text-base transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n switch (field.valueType) {\n case \"text\":\n return (\n <input\n id={field.id}\n type=\"text\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n />\n );\n\n case \"number\":\n return (\n <input\n id={field.id}\n type=\"number\"\n inputMode=\"numeric\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n />\n );\n\n case \"date\":\n return (\n <DatePickerField\n id={field.id}\n value={value || \"\"}\n dateFormat={field.dateFormat ?? \"dd/mm/yyyy\"}\n placeholder={field.placeholder}\n hasError={hasError}\n language={currentLanguage}\n onChange={(v) => onFieldChange(field.id, v)}\n className={inputClasses}\n />\n );\n\n case \"boolean\":\n return (\n <div className=\"flex items-center gap-2\">\n <input\n id={field.id}\n type=\"checkbox\"\n checked={value || false}\n onChange={(e) => onFieldChange(field.id, e.target.checked)}\n className=\"h-4 w-4 text-[#11E5C5] border-gray-300 rounded focus:ring-[#11E5C5]\"\n />\n {field.description && (\n <span className=\"text-sm text-gray-600\">{field.description}</span>\n )}\n </div>\n );\n\n case \"enum\":\n return (\n <Select\n options={(field.enumOptions || []).map((opt) => ({\n value: opt,\n label: opt,\n }))}\n value={value || \"\"}\n onValueChange={(val) => onFieldChange(field.id, val)}\n placeholder={field.placeholder || t(\"custom_form.select_option\")}\n error={hasError}\n />\n );\n\n case \"email\":\n return (\n <input\n id={field.id}\n type=\"email\"\n value={value || \"\"}\n onChange={(e) => onFieldChange(field.id, e.target.value)}\n placeholder={field.placeholder}\n className={inputClasses}\n autoComplete=\"off\"\n inputMode=\"email\"\n />\n );\n\n case \"address\":\n // For address, use the existing AddressFields component\n const addressValue = value || {};\n const addressForm = {\n lastName: \"\",\n firstName: \"\",\n birthDate: \"\",\n day: \"\",\n month: \"\",\n year: \"\",\n email: \"\",\n phoneNumber: \"\",\n sms: \"\",\n addressLine1: addressValue.addressLine1 || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: addressValue.postalCode || \"\",\n city: addressValue.city || \"\",\n countryCode: addressValue.countryCode || \"\",\n nationality: \"\",\n companyName: \"\",\n siret: \"\",\n tva: \"\",\n };\n\n return (\n <AddressFields\n form={addressForm}\n errors={{\n addressLine1: hasError,\n addressLine2: false,\n postalCode: hasError,\n city: hasError,\n country: hasError,\n }}\n requestedFields={new Set([\"adresse\"])}\n onFieldChange={(key, val) => {\n const updatedAddress = {\n ...addressValue,\n [key]: val,\n };\n onFieldChange(field.id, updatedAddress);\n }}\n addressSuggestions={addressSuggestions}\n showSuggestions={showSuggestions}\n onAddressChange={(val) => {\n const updatedAddress = {\n ...addressValue,\n addressLine1: val,\n };\n onFieldChange(field.id, updatedAddress);\n onAddressChange?.(field.id, val);\n }}\n onAddressFocus={() => onAddressFocus?.(field.id)}\n onAddressBlur={() => onAddressBlur?.(field.id)}\n onApplySuggestion={(suggestion) => {\n const updatedAddress = {\n addressLine1: suggestion.label || \"\",\n addressLine2: addressValue.addressLine2 || \"\",\n postalCode: suggestion.postalCode || \"\",\n city: suggestion.city || \"\",\n countryCode: suggestion.countryCode || \"\",\n };\n onFieldChange(field.id, updatedAddress);\n onApplySuggestion?.(field.id, suggestion);\n }}\n />\n );\n\n case \"list\": {\n const persistedRows: Record<string, string>[] = Array.isArray(value)\n ? value\n : [];\n const columns: ListColumn[] = normalizeListColumns(field.listColumns);\n const minRows = getListFieldMinRows(field);\n const rows = ensureMinimumListRows(persistedRows, columns, minRows);\n const gridTemplateColumns = `repeat(${columns.length}, minmax(180px, 1fr)) 32px`;\n const gridMinWidth = `${columns.length * 180 + (columns.length - 1) * 8 + 32}px`;\n const fieldCellErrors = cellErrors[field.id] ?? {};\n\n if (columns.length === 0) {\n return (\n <p className=\"text-sm text-red-600\">\n {t(\n \"custom_form.list_missing_columns\",\n \"Ce tableau n'a pas de colonnes configurées.\",\n )}\n </p>\n );\n }\n\n const handleRowChange = (\n rowIndex: number,\n colName: string,\n colValue: string,\n ) => {\n const updated = [...rows];\n updated[rowIndex] = { ...updated[rowIndex], [colName]: colValue };\n onFieldChange(field.id, updated);\n };\n\n const handleAddRow = () => {\n const emptyRow = createEmptyListRow(columns);\n onFieldChange(field.id, [...rows, emptyRow]);\n };\n\n const handleRemoveRow = (rowIndex: number) => {\n if (rows.length <= minRows) {\n return;\n }\n\n onFieldChange(\n field.id,\n rows.filter((_, i) => i !== rowIndex),\n );\n };\n\n const cellClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n hasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n\n return (\n <div className=\"space-y-3 overflow-x-auto\">\n {columns.length > 0 && (\n <div\n className=\"grid gap-2 items-center w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => (\n <span\n key={col.label}\n className=\"text-xs font-semibold text-gray-600 uppercase tracking-wide truncate\"\n >\n {col.label}\n </span>\n ))}\n <span />\n </div>\n )}\n\n {rows.map((row, rowIndex) => (\n <div\n key={rowIndex}\n className=\"grid gap-2 items-start w-full\"\n style={{\n gridTemplateColumns,\n minWidth: gridMinWidth,\n }}\n >\n {columns.map((col) => {\n const cellErr =\n fieldCellErrors[cellErrorKey(rowIndex, col.label)];\n const cellHasError = Boolean(cellErr);\n const cellInputClasses = clsx(\n \"w-full px-2 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-[#11E5C5] focus:border-transparent\",\n cellHasError\n ? \"border-red-500 bg-red-50\"\n : \"border-gray-300 hover:border-gray-400\",\n );\n return (\n <div\n key={col.label}\n className=\"flex flex-col gap-1 min-w-0\"\n >\n <ListCell\n col={col}\n value={row[col.label] || \"\"}\n hasError={cellHasError || hasError}\n cellClasses={cellInputClasses}\n onChange={(val) =>\n handleRowChange(rowIndex, col.label, val)\n }\n language={currentLanguage}\n />\n {typeof cellErr === \"string\" && (\n <span className=\"text-xs text-red-600\">\n {cellErr}\n </span>\n )}\n </div>\n );\n })}\n <button\n type=\"button\"\n onClick={() => handleRemoveRow(rowIndex)}\n className={clsx(\n \"flex items-center justify-center w-8 h-8 rounded-full transition-colors\",\n rows.length <= minRows\n ? \"text-gray-300 cursor-not-allowed\"\n : \"text-gray-400 hover:text-red-500 hover:bg-red-50\",\n )}\n aria-label={t(\"custom_form.remove_row\", \"Supprimer la ligne\")}\n disabled={rows.length <= minRows}\n >\n ✕\n </button>\n </div>\n ))}\n\n <button\n type=\"button\"\n onClick={handleAddRow}\n className=\"flex items-center gap-2 text-sm text-[#11E5C5] hover:underline font-medium\"\n >\n + {t(\"custom_form.add_row\", \"Ajouter une ligne\")}\n </button>\n </div>\n );\n }\n\n default:\n return null;\n }\n };\n\n const visibleFields = customFields.filter((f) => !f.lockedFromApi);\n\n return (\n <Fragment>\n {visibleFields.map((field) => (\n <div key={field.id} className=\"space-y-2\">\n <Label.Root\n htmlFor={field.id}\n className=\"block text-sm md:text-base font-semibold text-gray-900\"\n >\n {field.label}\n {field.required && <span className=\"text-red-500 ml-1\">*</span>}\n </Label.Root>\n\n {field.description && field.valueType !== \"boolean\" && (\n <p className=\"text-xs text-gray-500 -mt-1\">{field.description}</p>\n )}\n\n {renderField(field)}\n\n {(() => {\n const fieldErr = errors[field.id];\n if (!fieldErr) return null;\n const message =\n typeof fieldErr === \"string\"\n ? fieldErr\n : field.required && !formData[field.id]\n ? t(\"custom_form.required_field\")\n : t(\"custom_form.invalid_value\");\n return (\n <p className=\"text-red-600 text-sm flex items-center gap-1\">\n <span className=\"text-red-500\">⚠</span>\n {message}\n </p>\n );\n })()}\n </div>\n ))}\n </Fragment>\n );\n};\n\nexport default CustomFormFields;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number) => void;\n goBack: () => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\";\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":"AA8DO,IAAM,2BAA2B,GAAsB;;;;"}
1
+ {"version":3,"file":"session.js","sources":["../../../../src/types/session.ts"],"sourcesContent":["import type React from \"react\";\n\nexport interface SessionConfig {\n selfie?: boolean;\n requireMobile?: boolean;\n}\n\nexport interface DatakeenSessionProps {\n sessionId: string;\n sessionConfig?: SessionConfig;\n apiBaseUrl?: string; // Optional API base URL for dynamic environment configuration\n}\n\nexport interface UseSessionReturn {\n SessionComponent: React.ReactElement;\n}\n\nexport type stepObject = {\n setStep: (step: number) => void;\n goBack: () => void;\n goToNextStep: (\n currentNodeId: string,\n template: SessionTemplate,\n handle?: string,\n ) => void;\n step: number;\n canGoBack: boolean;\n};\n\nexport interface ProcessingStep {\n title: string;\n subtitle: string;\n hasError?: boolean;\n}\n\nexport type ConditionTokenType = \"variable\" | \"control\" | \"operator\" | \"input\";\n\nexport interface ConditionToken {\n type: ConditionTokenType;\n value: string;\n label?: string;\n sourceNodeId?: string;\n}\n\n/**\n * Type for custom field value types\n */\nexport type CustomFieldValueType =\n | \"text\"\n | \"enum\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"email\"\n | \"address\"\n | \"list\";\n\n/**\n * Display formats supported for date fields (top-level and list columns).\n */\nexport type DateDisplayFormat = \"dd/mm/yyyy\" | \"mm/dd/yyyy\" | \"yyyy-mm-dd\";\n\nexport const DEFAULT_DATE_DISPLAY_FORMAT: DateDisplayFormat = \"dd/mm/yyyy\";\n\n/**\n * Column definition for a list-type custom field\n */\nexport interface ListColumn {\n label: string;\n type: \"text\" | \"enum\" | \"date\" | \"email\";\n options?: string[]; // required when type === 'enum'\n placeholder?: string; // text/email/date — shown to the end user\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n}\n\n/**\n * Interface for custom field definition\n */\nexport interface CustomField {\n id: string;\n label: string;\n placeholder?: string;\n description?: string;\n valueType: CustomFieldValueType;\n enumOptions?: string[];\n listColumns?: ListColumn[]; // for list type: column definitions\n minRows?: number; // for list type: minimum rows expected\n required?: boolean;\n regex?: string; // text — JS regex source (without slashes)\n regexErrorMessage?: string; // text — message displayed when regex fails\n dateFormat?: DateDisplayFormat; // date — display format expected\n lockedFromApi?: boolean;\n userInputKey?: string;\n}\n\n/**\n * Interface for session template node\n */\nexport interface SessionTemplateNode {\n id: string;\n type: string;\n title: string;\n description: string;\n informationType?:\n | \"identity\"\n | \"identity-legal\"\n | \"contact\"\n | \"address\"\n | \"nationality\"\n | \"custom\";\n position: {\n x: number;\n y: number;\n };\n options: unknown[];\n selectedOptions: string[];\n requiredDocumentType?: string;\n isRequired: boolean;\n order: number;\n optionalFields?: string[];\n requiredFields?: string[];\n pageTitle?: string;\n pageDescription?: string;\n // Properties for document-collection node type\n allowedDocumentTypes?: Array<{\n id: string;\n name: string;\n /**\n * Optional side information coming from the template.\n * When provided and equals to two (\"two\", 2, \"double\", \"recto-verso\"),\n * consumers should allow uploading two sides (front/back).\n */\n side?: string | number;\n }>;\n allowedAddingMethods?: string[];\n introductionPage?: {\n title?: string;\n description?: string;\n };\n documentSelection?: {\n title?: string;\n description?: string;\n };\n // Start node specific properties\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n welcomeDescription?: string;\n welcomeImage?: string;\n qrCodeTitle?: string;\n qrCodeDescription?: string;\n showLegacyCGU?: boolean; // default: true — rétrocompatibilité\n\n // Legal consent node specific properties\n consentDescription?: string;\n consentDescription2?: string;\n cguUrl?: string;\n privacyPolicyUrl?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n conditionFalseMode?: \"retry\" | \"loop\";\n\n // External verification specific properties\n targetApi?: \"INSEE\";\n referenceNodeId?: string;\n referenceNodeType?:\n | \"information-input\"\n | \"document-collection\"\n | \"identity-control\";\n referenceField?: \"siren\" | \"siret\";\n referenceVariable?: string;\n // Custom form fields (for information-input with type 'custom')\n customFields?: CustomField[];\n\n // Electronic signature specific properties\n templateId?: string;\n external_id?: string;\n fieldMappings?: Array<{\n sourceFieldId: string;\n label: string;\n docusealType: string;\n readonly: boolean;\n role?: string;\n sourceNodeId?: string;\n }>;\n /** If set, the generated PDF from this upstream pdf-generation node will be used as the document to sign */\n sourcePdfNodeId?: string;\n\n // PDF generation node specific properties\n // Note: htmlTemplate is intentionally NOT included — it is server-side only and never sent to the client\n pdfMode?: \"upload\" | \"html-template\";\n sourceNodeIds?: string[];\n\n // retry properties\n allowResubmission: boolean;\n maxResubmissionAttempts?: number;\n}\n\n/**\n * Interface for accepted countries\n */\nexport interface AcceptedCountry {\n code: string;\n documents: {\n passport: string[];\n idCard: string[];\n driverLicense: string[];\n residencePermit: string[];\n pinkDriverLicense: string[];\n };\n}\n\n/**\n * Interface for session template edge\n */\nexport interface SessionTemplateEdge {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n conditionValue?: string;\n}\n\n/**\n * Interface for platform information\n */\nexport interface PlatformInfo {\n mobile: boolean;\n desktop: boolean;\n backoffice: boolean;\n}\n\n/**\n * Interface for session template\n */\nexport interface SessionTemplate {\n id: string;\n name: string;\n description: string;\n version: string;\n languages: string[];\n nodes: SessionTemplateNode[];\n edges: SessionTemplateEdge[];\n groupId: string;\n userId: string | null;\n created_at: string;\n updated_at: string;\n platforms?: PlatformInfo;\n logo?: string;\n showQRCode?: boolean;\n buttonBgColor?: string;\n buttonTextColor?: string;\n}\n\n/**\n * Interface for session data\n */\nexport interface SessionData {\n id: string;\n userId: string | null;\n token: string;\n templateId: string;\n templateKey: string;\n expireTime: number;\n status: string;\n result: Record<string, unknown>;\n landingPage: unknown;\n withSelfie: boolean | null;\n groupId: string | null;\n userInput: Record<string, unknown>;\n contactInfo?: {\n email: string;\n phoneNumber: string;\n };\n callbackURL?: string | null;\n webhookURL: string;\n analysisTemplateId: string | null;\n userAgent: unknown[];\n mobile: boolean;\n analysisId: string | null;\n currentStep?: number;\n createdAt: string;\n updatedAt: string;\n auditTrail: unknown[];\n user: unknown | null;\n analysis: unknown[];\n documents: unknown[];\n template: SessionTemplate;\n retryCounts?: Record<string, number>; // nodeId -> retry count\n}\n\nexport interface ClientInfo {\n ip?: string;\n location?: string;\n device: string;\n browser: string;\n os: string;\n}\n"],"names":[],"mappings":"AA8DO,IAAM,2BAA2B,GAAsB;;;;"}
@@ -127,6 +127,35 @@ Si un type est inconnu, le SDK affiche un écran "Étape non supportée" et perm
127
127
  - Test de navigation (step suivant, branch, fallback).
128
128
  - Test des cas d’erreur de configuration.
129
129
 
130
+ ## Champs verrouillés depuis l'API — nœud `information-input`
131
+
132
+ Le nœud `information-input` supporte des champs marqués `lockedFromApi: true` dans la configuration du journey. Ces champs sont pré-remplis par le partenaire à la création de session et **ne doivent jamais apparaître** dans le formulaire présenté au Mandataire.
133
+
134
+ ### Comportement dans le SDK
135
+
136
+ Dans `CustomFormFields.tsx`, les champs verrouillés sont filtrés **avant** le rendu :
137
+
138
+ ```tsx
139
+ const visibleFields = customFields.filter((f) => !f.lockedFromApi);
140
+ ```
141
+
142
+ Le champ n'est pas rendu du tout (pas de `disabled`, pas de `readOnly`) — il est complètement absent du DOM.
143
+
144
+ ### Types concernés
145
+
146
+ Dans `src/types/session.ts`, l'interface `CustomField` expose :
147
+
148
+ | Propriété | Type | Description |
149
+ |---|---|---|
150
+ | `lockedFromApi` | `boolean \| undefined` | Si `true`, le champ est exclu du formulaire |
151
+ | `userInputKey` | `string \| undefined` | Clé correspondante dans `session.userInput` côté backend |
152
+
153
+ ### Important
154
+
155
+ Le filtre côté SDK est une couche d'UX uniquement. La protection réelle est assurée côté backend via `stripLockedFields()` dans `session.service.ts` — qui réinjecte la valeur verrouillée sur chaque soumission SDK, même si un client malveillant tente de la modifier.
156
+
157
+ ---
158
+
130
159
  ## Point d'attention condition
131
160
 
132
161
  La logique détaillée du nœud condition est documentée dans:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datakeen-session-react",
3
- "version": "1.1.140-dev.70",
3
+ "version": "1.1.140-dev.71",
4
4
  "description": "React SDK component to manage and render Datakeen session experiences easily.",
5
5
  "publishConfig": {
6
6
  "access": "public",