datakeen-session-react 1.1.140-rc.75 → 1.1.140-rc.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/legal-consent/LegalConsentNode.js +6 -11
- package/dist/cjs/components/legal-consent/LegalConsentNode.js.map +1 -1
- package/dist/cjs/components/session/UserInputForm/LegalRepFields.js +45 -0
- package/dist/cjs/components/session/UserInputForm/LegalRepFields.js.map +1 -0
- package/dist/cjs/components/session/UserInputForm.js +2 -1
- package/dist/cjs/components/session/UserInputForm.js.map +1 -1
- package/dist/cjs/constants/userInputForm.js +2 -2
- package/dist/cjs/constants/userInputForm.js.map +1 -1
- package/dist/cjs/hooks/useUserInputForm.js +17 -1
- package/dist/cjs/hooks/useUserInputForm.js.map +1 -1
- package/dist/cjs/i18n/documents/documents.en.json.js +3 -0
- package/dist/cjs/i18n/documents/documents.en.json.js.map +1 -1
- package/dist/cjs/i18n/documents/documents.fr.json.js +3 -0
- package/dist/cjs/i18n/documents/documents.fr.json.js.map +1 -1
- package/dist/cjs/i18n/en.json.js +4 -1
- package/dist/cjs/i18n/en.json.js.map +1 -1
- package/dist/cjs/i18n/fr.json.js +4 -1
- package/dist/cjs/i18n/fr.json.js.map +1 -1
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/cjs/utils/renderInlineMarkdown.js +75 -0
- package/dist/cjs/utils/renderInlineMarkdown.js.map +1 -0
- package/dist/cjs/utils/userInputForm.js +1 -0
- package/dist/cjs/utils/userInputForm.js.map +1 -1
- package/dist/esm/components/legal-consent/LegalConsentNode.js +6 -11
- package/dist/esm/components/legal-consent/LegalConsentNode.js.map +1 -1
- package/dist/esm/components/session/UserInputForm/LegalRepFields.js +22 -0
- package/dist/esm/components/session/UserInputForm/LegalRepFields.js.map +1 -0
- package/dist/esm/components/session/UserInputForm.js +2 -1
- package/dist/esm/components/session/UserInputForm.js.map +1 -1
- package/dist/esm/constants/userInputForm.js +2 -2
- package/dist/esm/constants/userInputForm.js.map +1 -1
- package/dist/esm/hooks/useUserInputForm.js +17 -1
- package/dist/esm/hooks/useUserInputForm.js.map +1 -1
- package/dist/esm/i18n/documents/documents.en.json.js +3 -1
- package/dist/esm/i18n/documents/documents.en.json.js.map +1 -1
- package/dist/esm/i18n/documents/documents.fr.json.js +3 -1
- package/dist/esm/i18n/documents/documents.fr.json.js.map +1 -1
- package/dist/esm/i18n/en.json.js +4 -1
- package/dist/esm/i18n/en.json.js.map +1 -1
- package/dist/esm/i18n/fr.json.js +4 -1
- package/dist/esm/i18n/fr.json.js.map +1 -1
- package/dist/esm/types/session.js.map +1 -1
- package/dist/esm/utils/renderInlineMarkdown.js +73 -0
- package/dist/esm/utils/renderInlineMarkdown.js.map +1 -0
- package/dist/esm/utils/userInputForm.js +1 -0
- package/dist/esm/utils/userInputForm.js.map +1 -1
- package/package.json +1 -1
|
@@ -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, skipHistory?: boolean) => void;\n goBack: () => void;\n /** Retour arrière vers un nœud précis (ex: \"Corriger ma saisie\") :\n * tronque l'historique jusqu'à `targetStep` au lieu de l'empiler. */\n goBackToStep: (targetStep: number) => 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 editableIfMissing?: boolean; // soft lock — éditable si la valeur API est absente\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 nfcEnabled?: boolean;\n // \"nfcAndApi\" reste accepté pour rétrocompat (parcours legacy) ; à normaliser à la lecture.\n nfcMode?: \"nfcOnly\" | \"nfcOrPhoto\" | \"nfcAndApi\";\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Résultat forcé par le nœud `end` (configuré dans le builder). Sert au SDK à\n // afficher la variante « erreur conservée » de l'écran de fin quand la branche\n // fausse d'une condition pointe directement vers un end non_compliant.\n expectedResult?: string;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n // Undefined is treated as \"loop\" by the SDK for legacy templates.\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 */\n/** Clé du catalogue d'icônes des écrans de fin (mappée vers lucide-react au rendu). */\nexport type EndScreenIcon =\n | \"thanks\"\n | \"send\"\n | \"mail\"\n | \"check\"\n | \"clock\"\n | \"shield\"\n | \"user\"\n | \"info\";\n\nexport interface EndScreenItem {\n icon: EndScreenIcon;\n text: string;\n}\n\nexport interface EndScreenCase {\n title?: string;\n items: EndScreenItem[];\n}\n\n/** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\nexport interface EndScreenConfig {\n compliant?: EndScreenCase;\n nonCompliant?: EndScreenCase;\n}\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 endScreenConfig?: EndScreenConfig;\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 nfcStatus?: \"pending\" | \"opened\" | \"completed\" | \"skipped\" | \"failed\";\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":"AAiEO,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, skipHistory?: boolean) => void;\n goBack: () => void;\n /** Retour arrière vers un nœud précis (ex: \"Corriger ma saisie\") :\n * tronque l'historique jusqu'à `targetStep` au lieu de l'empiler. */\n goBackToStep: (targetStep: number) => 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 editableIfMissing?: boolean; // soft lock — éditable si la valeur API est absente\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 cguLinkLabel?: string;\n privacyLinkLabel?: string;\n checkboxText?: string;\n // Identity control specific properties\n automaticPhotoCapture?: boolean;\n nfcEnabled?: boolean;\n // \"nfcAndApi\" reste accepté pour rétrocompat (parcours legacy) ; à normaliser à la lecture.\n nfcMode?: \"nfcOnly\" | \"nfcOrPhoto\" | \"nfcAndApi\";\n acceptedCountries?: AcceptedCountry[];\n // End node specific properties\n callbackURL?: string | null;\n // Résultat forcé par le nœud `end` (configuré dans le builder). Sert au SDK à\n // afficher la variante « erreur conservée » de l'écran de fin quand la branche\n // fausse d'une condition pointe directement vers un end non_compliant.\n expectedResult?: string;\n // Condition node specific properties\n conditionExpression?: string;\n conditionTokens?: ConditionToken[];\n conditionFalseErrorMessage?: string;\n conditionMaxRetries?: number;\n conditionMaxRetryAction?: \"end-journey\" | \"force-true\";\n // Undefined is treated as \"loop\" by the SDK for legacy templates.\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 */\n/** Clé du catalogue d'icônes des écrans de fin (mappée vers lucide-react au rendu). */\nexport type EndScreenIcon =\n | \"thanks\"\n | \"send\"\n | \"mail\"\n | \"check\"\n | \"clock\"\n | \"shield\"\n | \"user\"\n | \"info\";\n\nexport interface EndScreenItem {\n icon: EndScreenIcon;\n text: string;\n}\n\nexport interface EndScreenCase {\n title?: string;\n items: EndScreenItem[];\n}\n\n/** Textes de fin personnalisés (config globale du journey). Vide → fallback standard. */\nexport interface EndScreenConfig {\n compliant?: EndScreenCase;\n nonCompliant?: EndScreenCase;\n}\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 endScreenConfig?: EndScreenConfig;\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 nfcStatus?: \"pending\" | \"opened\" | \"completed\" | \"skipped\" | \"failed\";\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":"AAiEO,IAAM,2BAA2B,GAAsB;;;;"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mini-renderer Markdown *inline* et sûr, pour les textes de consentement.
|
|
5
|
+
*
|
|
6
|
+
* Volontairement limité (pas de lib externe, SDK publié npm) :
|
|
7
|
+
* - liens `[libellé](url)` — uniquement http(s) et mailto, ouverts en nouvel onglet ;
|
|
8
|
+
* - gras `**texte**` ;
|
|
9
|
+
* - paragraphes (lignes vides) et sauts de ligne simples.
|
|
10
|
+
*
|
|
11
|
+
* Aucune injection de HTML brut : on ne produit que des éléments React, le texte
|
|
12
|
+
* reste du texte. Les URLs non http(s)/mailto sont rendues en texte (pas de lien).
|
|
13
|
+
*/
|
|
14
|
+
var SAFE_URL = /^(https?:|mailto:)/i;
|
|
15
|
+
// Capture **gras** ou [libellé](url) ; le reste est du texte simple.
|
|
16
|
+
var INLINE_PATTERN = /(\*\*([^*]+)\*\*)|(\[([^\]]+)\]\(([^)\s]+)\))/g;
|
|
17
|
+
function renderInlineSegments(text, keyPrefix) {
|
|
18
|
+
var nodes = [];
|
|
19
|
+
var lastIndex = 0;
|
|
20
|
+
var match;
|
|
21
|
+
var i = 0;
|
|
22
|
+
INLINE_PATTERN.lastIndex = 0;
|
|
23
|
+
while ((match = INLINE_PATTERN.exec(text)) !== null) {
|
|
24
|
+
if (match.index > lastIndex) {
|
|
25
|
+
nodes.push(text.slice(lastIndex, match.index));
|
|
26
|
+
}
|
|
27
|
+
if (match[2] !== undefined) {
|
|
28
|
+
// **gras**
|
|
29
|
+
nodes.push(jsx("strong", { children: match[2] }, "".concat(keyPrefix, "-b-").concat(i)));
|
|
30
|
+
}
|
|
31
|
+
else if (match[4] !== undefined && match[5] !== undefined) {
|
|
32
|
+
// [libellé](url)
|
|
33
|
+
var label = match[4];
|
|
34
|
+
var url = match[5];
|
|
35
|
+
if (SAFE_URL.test(url)) {
|
|
36
|
+
nodes.push(jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "underline text-blue-600 hover:text-blue-800", children: label }, "".concat(keyPrefix, "-a-").concat(i)));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// URL non sûre : on retombe sur le libellé en texte simple.
|
|
40
|
+
nodes.push(label);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
lastIndex = INLINE_PATTERN.lastIndex;
|
|
44
|
+
i += 1;
|
|
45
|
+
}
|
|
46
|
+
if (lastIndex < text.length) {
|
|
47
|
+
nodes.push(text.slice(lastIndex));
|
|
48
|
+
}
|
|
49
|
+
return nodes;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Rend une chaîne markdown en paragraphes React. Les blocs séparés par une ligne
|
|
53
|
+
* vide deviennent des `<p>` ; les sauts de ligne simples deviennent des `<br/>`.
|
|
54
|
+
*/
|
|
55
|
+
function renderInlineMarkdown(text) {
|
|
56
|
+
if (!text)
|
|
57
|
+
return null;
|
|
58
|
+
var blocks = text.split(/\n\s*\n/);
|
|
59
|
+
return blocks.map(function (block, blockIndex) {
|
|
60
|
+
var lines = block.split("\n");
|
|
61
|
+
var content = [];
|
|
62
|
+
lines.forEach(function (line, lineIndex) {
|
|
63
|
+
if (lineIndex > 0) {
|
|
64
|
+
content.push(jsx("br", {}, "br-".concat(blockIndex, "-").concat(lineIndex)));
|
|
65
|
+
}
|
|
66
|
+
content.push.apply(content, renderInlineSegments(line, "".concat(blockIndex, "-").concat(lineIndex)));
|
|
67
|
+
});
|
|
68
|
+
return jsx("p", { children: content }, "p-".concat(blockIndex));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { renderInlineMarkdown };
|
|
73
|
+
//# sourceMappingURL=renderInlineMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderInlineMarkdown.js","sources":["../../../../src/utils/renderInlineMarkdown.tsx"],"sourcesContent":["import React from \"react\";\n\n/**\n * Mini-renderer Markdown *inline* et sûr, pour les textes de consentement.\n *\n * Volontairement limité (pas de lib externe, SDK publié npm) :\n * - liens `[libellé](url)` — uniquement http(s) et mailto, ouverts en nouvel onglet ;\n * - gras `**texte**` ;\n * - paragraphes (lignes vides) et sauts de ligne simples.\n *\n * Aucune injection de HTML brut : on ne produit que des éléments React, le texte\n * reste du texte. Les URLs non http(s)/mailto sont rendues en texte (pas de lien).\n */\n\nconst SAFE_URL = /^(https?:|mailto:)/i;\n\n// Capture **gras** ou [libellé](url) ; le reste est du texte simple.\nconst INLINE_PATTERN = /(\\*\\*([^*]+)\\*\\*)|(\\[([^\\]]+)\\]\\(([^)\\s]+)\\))/g;\n\nfunction renderInlineSegments(text: string, keyPrefix: string): React.ReactNode[] {\n const nodes: React.ReactNode[] = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n let i = 0;\n\n INLINE_PATTERN.lastIndex = 0;\n while ((match = INLINE_PATTERN.exec(text)) !== null) {\n if (match.index > lastIndex) {\n nodes.push(text.slice(lastIndex, match.index));\n }\n\n if (match[2] !== undefined) {\n // **gras**\n nodes.push(<strong key={`${keyPrefix}-b-${i}`}>{match[2]}</strong>);\n } else if (match[4] !== undefined && match[5] !== undefined) {\n // [libellé](url)\n const label = match[4];\n const url = match[5];\n if (SAFE_URL.test(url)) {\n nodes.push(\n <a\n key={`${keyPrefix}-a-${i}`}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline text-blue-600 hover:text-blue-800\"\n >\n {label}\n </a>,\n );\n } else {\n // URL non sûre : on retombe sur le libellé en texte simple.\n nodes.push(label);\n }\n }\n\n lastIndex = INLINE_PATTERN.lastIndex;\n i += 1;\n }\n\n if (lastIndex < text.length) {\n nodes.push(text.slice(lastIndex));\n }\n\n return nodes;\n}\n\n/**\n * Rend une chaîne markdown en paragraphes React. Les blocs séparés par une ligne\n * vide deviennent des `<p>` ; les sauts de ligne simples deviennent des `<br/>`.\n */\nexport function renderInlineMarkdown(\n text: string | undefined,\n): React.ReactNode {\n if (!text) return null;\n\n const blocks = text.split(/\\n\\s*\\n/);\n\n return blocks.map((block, blockIndex) => {\n const lines = block.split(\"\\n\");\n const content: React.ReactNode[] = [];\n\n lines.forEach((line, lineIndex) => {\n if (lineIndex > 0) {\n content.push(<br key={`br-${blockIndex}-${lineIndex}`} />);\n }\n content.push(\n ...renderInlineSegments(line, `${blockIndex}-${lineIndex}`),\n );\n });\n\n return <p key={`p-${blockIndex}`}>{content}</p>;\n });\n}\n"],"names":["_jsx"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import '../node_modules/tslib/tslib.es6.js';
|
|
|
3
3
|
var resolveInformationType = function (informationType, fallback) {
|
|
4
4
|
if (informationType === "identity" ||
|
|
5
5
|
informationType === "identity-legal" ||
|
|
6
|
+
informationType === "identity-legal-rep" ||
|
|
6
7
|
informationType === "contact" ||
|
|
7
8
|
informationType === "address" ||
|
|
8
9
|
informationType === "nationality" ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userInputForm.js","sources":["../../../../src/utils/userInputForm.ts"],"sourcesContent":["import type {\n AddressParts,\n BirthDateParts,\n InformationType,\n} from \"../types/userInputForm\";\n\nexport const resolveInformationType = (\n informationType?: string,\n fallback: InformationType = \"identity\"\n): InformationType => {\n if (\n informationType === \"identity\" ||\n informationType === \"identity-legal\" ||\n informationType === \"contact\" ||\n informationType === \"address\" ||\n informationType === \"nationality\" ||\n informationType === \"custom\"\n ) {\n return informationType;\n }\n return fallback;\n};\n\nexport const parseBirthDate = (value: string): BirthDateParts => {\n if (!value) {\n return { day: \"\", month: \"\", year: \"\" };\n }\n\n try {\n if (value.includes(\"-\")) {\n const parts = value.split(\"-\");\n if (parts.length === 3) {\n if (Number(parts[0]) <= 31) {\n const [day, month, year] = parts;\n return {\n day,\n month,\n year,\n };\n }\n }\n }\n\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) {\n return {\n day: String(date.getDate()).padStart(2, \"0\"),\n month: String(date.getMonth() + 1).padStart(2, \"0\"),\n year: String(date.getFullYear()),\n };\n }\n } catch (error) {\n console.error(\"Error parsing birth date:\", error);\n }\n\n return { day: \"\", month: \"\", year: \"\" };\n};\n\nexport const checkIsMajor = (birthDate: string): boolean => {\n if (!birthDate) {\n return false;\n }\n\n const today = new Date();\n let birthDateObj: Date | undefined;\n\n if (birthDate.includes(\"-\") && birthDate.split(\"-\").length === 3) {\n const parts = birthDate.split(\"-\");\n if (Number(parts[0]) <= 31) {\n const [day, month, year] = parts;\n birthDateObj = new Date(Number(year), Number(month) - 1, Number(day));\n } else {\n birthDateObj = new Date(birthDate);\n }\n } else {\n birthDateObj = new Date(birthDate);\n }\n\n if (!birthDateObj || Number.isNaN(birthDateObj.getTime())) {\n return false;\n }\n\n const age = today.getFullYear() - birthDateObj.getFullYear();\n const monthDiff = today.getMonth() - birthDateObj.getMonth();\n const dayDiff = today.getDate() - birthDateObj.getDate();\n\n return (\n age > 18 ||\n (age === 18 && (monthDiff > 0 || (monthDiff === 0 && dayDiff >= 0)))\n );\n};\n\nexport const parseAddress = (\n value: string,\n fallback: AddressParts\n): AddressParts => {\n if (!value) {\n return fallback;\n }\n\n const parts = value.split(\",\");\n if (parts.length < 2) {\n return {\n ...fallback,\n addressLine1: value.trim(),\n };\n }\n\n const addressLine1 = (parts[0] || \"\").trim();\n const cityPostalPart = (parts[1] || \"\").trim();\n const country = (parts[2] || \"\").trim();\n\n const cityPostalMatch = cityPostalPart.match(/^(\\d{4,6})\\s+(.*)$/);\n\n if (cityPostalMatch) {\n return {\n addressLine1,\n postalCode: cityPostalMatch[1],\n city: cityPostalMatch[2],\n country,\n };\n }\n\n return {\n addressLine1,\n postalCode: fallback.postalCode,\n city: cityPostalPart || fallback.city,\n country: country || fallback.country,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"userInputForm.js","sources":["../../../../src/utils/userInputForm.ts"],"sourcesContent":["import type {\n AddressParts,\n BirthDateParts,\n InformationType,\n} from \"../types/userInputForm\";\n\nexport const resolveInformationType = (\n informationType?: string,\n fallback: InformationType = \"identity\"\n): InformationType => {\n if (\n informationType === \"identity\" ||\n informationType === \"identity-legal\" ||\n informationType === \"identity-legal-rep\" ||\n informationType === \"contact\" ||\n informationType === \"address\" ||\n informationType === \"nationality\" ||\n informationType === \"custom\"\n ) {\n return informationType;\n }\n return fallback;\n};\n\nexport const parseBirthDate = (value: string): BirthDateParts => {\n if (!value) {\n return { day: \"\", month: \"\", year: \"\" };\n }\n\n try {\n if (value.includes(\"-\")) {\n const parts = value.split(\"-\");\n if (parts.length === 3) {\n if (Number(parts[0]) <= 31) {\n const [day, month, year] = parts;\n return {\n day,\n month,\n year,\n };\n }\n }\n }\n\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) {\n return {\n day: String(date.getDate()).padStart(2, \"0\"),\n month: String(date.getMonth() + 1).padStart(2, \"0\"),\n year: String(date.getFullYear()),\n };\n }\n } catch (error) {\n console.error(\"Error parsing birth date:\", error);\n }\n\n return { day: \"\", month: \"\", year: \"\" };\n};\n\nexport const checkIsMajor = (birthDate: string): boolean => {\n if (!birthDate) {\n return false;\n }\n\n const today = new Date();\n let birthDateObj: Date | undefined;\n\n if (birthDate.includes(\"-\") && birthDate.split(\"-\").length === 3) {\n const parts = birthDate.split(\"-\");\n if (Number(parts[0]) <= 31) {\n const [day, month, year] = parts;\n birthDateObj = new Date(Number(year), Number(month) - 1, Number(day));\n } else {\n birthDateObj = new Date(birthDate);\n }\n } else {\n birthDateObj = new Date(birthDate);\n }\n\n if (!birthDateObj || Number.isNaN(birthDateObj.getTime())) {\n return false;\n }\n\n const age = today.getFullYear() - birthDateObj.getFullYear();\n const monthDiff = today.getMonth() - birthDateObj.getMonth();\n const dayDiff = today.getDate() - birthDateObj.getDate();\n\n return (\n age > 18 ||\n (age === 18 && (monthDiff > 0 || (monthDiff === 0 && dayDiff >= 0)))\n );\n};\n\nexport const parseAddress = (\n value: string,\n fallback: AddressParts\n): AddressParts => {\n if (!value) {\n return fallback;\n }\n\n const parts = value.split(\",\");\n if (parts.length < 2) {\n return {\n ...fallback,\n addressLine1: value.trim(),\n };\n }\n\n const addressLine1 = (parts[0] || \"\").trim();\n const cityPostalPart = (parts[1] || \"\").trim();\n const country = (parts[2] || \"\").trim();\n\n const cityPostalMatch = cityPostalPart.match(/^(\\d{4,6})\\s+(.*)$/);\n\n if (cityPostalMatch) {\n return {\n addressLine1,\n postalCode: cityPostalMatch[1],\n city: cityPostalMatch[2],\n country,\n };\n }\n\n return {\n addressLine1,\n postalCode: fallback.postalCode,\n city: cityPostalPart || fallback.city,\n country: country || fallback.country,\n };\n};\n"],"names":[],"mappings":"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"}
|