@streamline-pulse/formkrafter-core 0.28.0 → 0.29.0

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.
@@ -15,6 +15,8 @@ export interface BrickProps<DataType, Configs extends BrickBaseConfigs, Styles>
15
15
  dataMap?: Record<string, unknown>;
16
16
  rootSpec?: BrickSpec;
17
17
  onDataChange?: (value?: DataType) => void;
18
+ /** Sets several form keys at once (a brick that fills other fields, e.g. from a document). */
19
+ onDataPatch?: (patch: Record<string, unknown>) => void;
18
20
  onMove?: (from: string, to: string) => void;
19
21
  onDuplicate?: (path: string) => void;
20
22
  onDelete?: (path: string) => void;
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export { FieldDescriptor, CollectFieldsOptions, collectFields } from "./utils/fi
11
11
  export { IdentityFormat, IDENTITY_FORMATS, checkIdentity, checkFrNir, checkBjNpi, checkDigits, checkLuhn, checkFrSiren, checkFrSiret, checkBjIfu, checkIban, formatIban } from "./utils/identity.js";
12
12
  export { MrzResult, parseMrz, mrzLines, mrzCheckDigit } from "./utils/mrz.js";
13
13
  export { Slot, SlotRules, generateSlots, readSlots, groupSlotsByDay, slotDate } from "./utils/slots.js";
14
+ export { DocumentField, parseDocumentFields, parseDocumentFills, documentFillPatch } from "./utils/documents.js";
14
15
  export { FieldAnnotation, FieldAnnotations, flaggedKeys } from "./review.js";
15
16
  export { SpecIssue, SpecIssueCode, lintSpec } from "./utils/lint-spec.js";
16
17
  export { ensureBrickUids, stripBrickUids, stripUidsFromPatches } from "./ops/uids.js";
@@ -43,4 +44,5 @@ export type { ExpandSpecOptions } from "./utils/expand-spec.js";
43
44
  export { FetchSpecSourceService } from "./services/spec_source_service.js";
44
45
  export type { SpecSourceService, FetchSpecSourceDefaults } from "./services/spec_source_service.js";
45
46
  export { FetchOptionSourceService } from "./services/option_source_service.js";
47
+ export { DocumentReading, DocumentReadOptions, DocumentReaderService, FetchDocumentReaderDefaults, FetchDocumentReaderService, readDocumentReading, } from "./services/document_reader_service.js";
46
48
  export type { OptionSourceService, FetchOptionSourceDefaults } from "./services/option_source_service.js";
package/dist/index.js CHANGED
@@ -7309,6 +7309,26 @@ var en = {
7309
7309
  "slots.picked": "Chosen slot:",
7310
7310
  "range.from": "From",
7311
7311
  "range.to": "To",
7312
+ "category.Documents": "Documents",
7313
+ "brick.document.name": "Document reading",
7314
+ "document.choose": "Choose a document…",
7315
+ "document.capture": "Take a photo",
7316
+ "document.reading": "Reading the document…",
7317
+ "document.read": "Document read",
7318
+ "document.none": "No document",
7319
+ "document.text": "Text read",
7320
+ "document.fields": "Fields read",
7321
+ "document.notFound": "not found",
7322
+ "document.remove": "Remove document",
7323
+ "document.noReader": "No document reader configured",
7324
+ "document.failed": "The document could not be read",
7325
+ "document.filled": "Fields filled from the document:",
7326
+ "panel.readUrl": "Reader URL (empty = host default)",
7327
+ "panel.documentFields": "Fields to read (key|Label per line)",
7328
+ "panel.documentFills": "Fill the form (field=formKey per line)",
7329
+ "panel.documentLanguage": "Document language (fr, en…)",
7330
+ "panel.cfg.capture": "Offer the camera on mobile",
7331
+ "panel.cfg.keepFile": "Keep the file in the answer",
7312
7332
  "panel.slotsUrl": "Slots URL (empty = opening rules)",
7313
7333
  "panel.slotDays": "Open days (1 = Monday … 7 = Sunday)",
7314
7334
  "panel.slotFrom": "Opens at",
@@ -7514,6 +7534,26 @@ var frFkTranslations = {
7514
7534
  "slots.picked": "Créneau choisi :",
7515
7535
  "range.from": "Du",
7516
7536
  "range.to": "Au",
7537
+ "category.Documents": "Documents",
7538
+ "brick.document.name": "Lecture de document",
7539
+ "document.choose": "Choisir un document…",
7540
+ "document.capture": "Prendre une photo",
7541
+ "document.reading": "Lecture du document…",
7542
+ "document.read": "Document lu",
7543
+ "document.none": "Aucun document",
7544
+ "document.text": "Texte lu",
7545
+ "document.fields": "Champs lus",
7546
+ "document.notFound": "non trouvé",
7547
+ "document.remove": "Retirer le document",
7548
+ "document.noReader": "Aucun lecteur de document configuré",
7549
+ "document.failed": "Le document n’a pas pu être lu",
7550
+ "document.filled": "Champs remplis depuis le document :",
7551
+ "panel.readUrl": "URL du lecteur (vide = celle de l’hôte)",
7552
+ "panel.documentFields": "Champs à lire (clé|Libellé par ligne)",
7553
+ "panel.documentFills": "Remplir le formulaire (champ=cléFormulaire par ligne)",
7554
+ "panel.documentLanguage": "Langue du document (fr, en…)",
7555
+ "panel.cfg.capture": "Proposer l’appareil photo sur mobile",
7556
+ "panel.cfg.keepFile": "Conserver le fichier dans la réponse",
7517
7557
  "panel.slotsUrl": "URL des créneaux (vide = règles d’ouverture)",
7518
7558
  "panel.slotDays": "Jours ouverts (1 = lundi … 7 = dimanche)",
7519
7559
  "panel.slotFrom": "Ouverture",
@@ -8127,6 +8167,67 @@ class FetchOptionSourceService {
8127
8167
  }
8128
8168
  }
8129
8169
 
8170
+ // lib/services/document_reader_service.ts
8171
+ var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
8172
+ function readDocumentReading(payload) {
8173
+ const root = asRecord(payload) ?? {};
8174
+ const data = asRecord(root.data) ?? root;
8175
+ const text = typeof data.text === "string" ? data.text : typeof data.md_content === "string" ? data.md_content : typeof data.content === "string" ? data.content : undefined;
8176
+ const reading = {};
8177
+ if (text !== undefined)
8178
+ reading.text = text;
8179
+ const fields = asRecord(data.fields);
8180
+ if (fields)
8181
+ reading.fields = fields;
8182
+ if (typeof data.pages === "number")
8183
+ reading.pages = data.pages;
8184
+ if (typeof data.engine === "string")
8185
+ reading.engine = data.engine;
8186
+ if (typeof data.confidence === "number")
8187
+ reading.confidence = data.confidence;
8188
+ if (Array.isArray(data.warnings))
8189
+ reading.warnings = data.warnings.filter((w) => typeof w === "string");
8190
+ return reading;
8191
+ }
8192
+
8193
+ class FetchDocumentReaderService {
8194
+ defaults;
8195
+ constructor(defaults = {}) {
8196
+ this.defaults = defaults;
8197
+ }
8198
+ async read(file, options = {}) {
8199
+ const url = options.url || this.defaults.url;
8200
+ if (!url)
8201
+ throw new Error("No document reader URL configured");
8202
+ const body = new FormData;
8203
+ const blob = file instanceof Blob ? file : new Blob([await file.arrayBuffer()], { type: file.type });
8204
+ body.append(this.defaults.fieldName ?? "file", blob, file.name);
8205
+ if (options.fields?.length)
8206
+ body.append("fields", options.fields.map((field) => field.key).join(","));
8207
+ if (options.fields?.length)
8208
+ body.append("fieldLabels", JSON.stringify(Object.fromEntries(options.fields.map((f) => [f.key, f.label ?? f.key]))));
8209
+ if (options.language)
8210
+ body.append("language", options.language);
8211
+ const doFetch = this.defaults.fetch ?? globalThis.fetch.bind(globalThis);
8212
+ const response = await doFetch(url, {
8213
+ method: "POST",
8214
+ body,
8215
+ credentials: this.defaults.credentials,
8216
+ headers: { accept: "application/json", ...this.defaults.headers, ...options.headers }
8217
+ });
8218
+ if (!response.ok) {
8219
+ let message = `Document reading failed (${response.status})`;
8220
+ try {
8221
+ const payload = await response.json();
8222
+ if (payload?.message)
8223
+ message = payload.message;
8224
+ } catch {}
8225
+ throw new Error(message);
8226
+ }
8227
+ return readDocumentReading(await response.json());
8228
+ }
8229
+ }
8230
+
8130
8231
  // lib/services/index.ts
8131
8232
  var GLOBAL_KEY2 = Symbol.for("formkrafter.core.services");
8132
8233
  var globalStore2 = globalThis;
@@ -8135,10 +8236,12 @@ var services = globalStore2[GLOBAL_KEY2] ??= {
8135
8236
  dataSourceService: new FetchDataSourceService,
8136
8237
  fileUploadService: new Base64FileUploadService,
8137
8238
  specSourceService: new FetchSpecSourceService,
8138
- optionSourceService: new FetchOptionSourceService
8239
+ optionSourceService: new FetchOptionSourceService,
8240
+ documentReaderService: new FetchDocumentReaderService
8139
8241
  };
8140
8242
  services.specSourceService ??= new FetchSpecSourceService;
8141
8243
  services.optionSourceService ??= new FetchOptionSourceService;
8244
+ services.documentReaderService ??= new FetchDocumentReaderService;
8142
8245
 
8143
8246
  // lib/brick/utils.ts
8144
8247
  var evalBrickCode = (code, data) => {
@@ -8576,6 +8679,58 @@ function groupSlotsByDay(slots) {
8576
8679
  }
8577
8680
  return [...byDay.entries()].map(([day, list]) => ({ day, slots: list }));
8578
8681
  }
8682
+ // lib/utils/documents.ts
8683
+ function parseDocumentFields(source) {
8684
+ if (Array.isArray(source))
8685
+ return source.filter((item) => !!item && typeof item === "object" && typeof item.key === "string").map((item) => ({ key: item.key.trim(), ...item.label ? { label: item.label } : {} })).filter((item) => item.key);
8686
+ if (typeof source !== "string")
8687
+ return [];
8688
+ const out = [];
8689
+ const seen = new Set;
8690
+ for (const raw of source.split(/\r?\n/)) {
8691
+ const line = raw.trim();
8692
+ if (!line || line.startsWith("#"))
8693
+ continue;
8694
+ const [keyPart, ...labelParts] = line.split("|");
8695
+ const key = (keyPart ?? "").trim();
8696
+ if (!key || seen.has(key))
8697
+ continue;
8698
+ seen.add(key);
8699
+ const label = labelParts.join("|").trim();
8700
+ out.push(label ? { key, label } : { key });
8701
+ }
8702
+ return out;
8703
+ }
8704
+ function parseDocumentFills(source) {
8705
+ if (typeof source !== "string")
8706
+ return {};
8707
+ const out = {};
8708
+ for (const raw of source.split(/\r?\n/)) {
8709
+ const line = raw.trim();
8710
+ if (!line || line.startsWith("#"))
8711
+ continue;
8712
+ const index = line.indexOf("=");
8713
+ if (index === -1)
8714
+ continue;
8715
+ const field = line.slice(0, index).trim();
8716
+ const target = line.slice(index + 1).trim();
8717
+ if (field && target)
8718
+ out[field] = target;
8719
+ }
8720
+ return out;
8721
+ }
8722
+ function documentFillPatch(fields, fills) {
8723
+ const patch = {};
8724
+ if (!fields)
8725
+ return patch;
8726
+ for (const [field, target] of Object.entries(fills)) {
8727
+ const value = fields[field];
8728
+ if (value === undefined || value === null || value === "")
8729
+ continue;
8730
+ patch[target] = value;
8731
+ }
8732
+ return patch;
8733
+ }
8579
8734
  // lib/review.ts
8580
8735
  var flaggedKeys = (annotations) => Object.entries(annotations ?? {}).filter(([, annotation]) => annotation?.incorrect === true).map(([key]) => key);
8581
8736
  // lib/utils/lint-spec.ts
@@ -9682,6 +9837,7 @@ export {
9682
9837
  Base64FileUploadService,
9683
9838
  Brick,
9684
9839
  FetchDataSourceService,
9840
+ FetchDocumentReaderService,
9685
9841
  FetchOptionSourceService,
9686
9842
  FetchSpecSourceService,
9687
9843
  IDENTITY_FORMATS,
@@ -9706,6 +9862,7 @@ export {
9706
9862
  convertFormioForm,
9707
9863
  defaultFormData,
9708
9864
  defaultValidationMessage,
9865
+ documentFillPatch,
9709
9866
  duplicateBrick,
9710
9867
  ensureBrickUids,
9711
9868
  evalBrickCode,
@@ -9730,9 +9887,12 @@ export {
9730
9887
  mrzCheckDigit,
9731
9888
  mrzLines,
9732
9889
  normalizeOptions,
9890
+ parseDocumentFields,
9891
+ parseDocumentFills,
9733
9892
  parseHeaderLines,
9734
9893
  parseMrz,
9735
9894
  pointerFromPath,
9895
+ readDocumentReading,
9736
9896
  readSlots,
9737
9897
  registerValidationMessages,
9738
9898
  removeBrick,
@@ -9754,5 +9914,5 @@ export {
9754
9914
  wrapBrickData
9755
9915
  };
9756
9916
 
9757
- //# debugId=30A49B7E74D3EC6964756E2164756E21
9917
+ //# debugId=A730893582334E9064756E2164756E21
9758
9918
  //# sourceMappingURL=index.js.map