@streamline-pulse/formkrafter-core 0.34.0 → 0.37.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.
@@ -0,0 +1,39 @@
1
+ import type { BrickType } from "../utils/brick-type.js";
2
+ /**
3
+ * The bricks a language model may write, with the configs each one reads. The
4
+ * strict schema (schema/form-spec.strict.schema.json) is generated from this
5
+ * list and fromStrictSpec reads it back, so a brick or a config a model can use
6
+ * is declared once, here. The web components test that every registered brick
7
+ * is either listed here or in AI_EXCLUDED_BRICKS, with the configs it reads.
8
+ */
9
+ export type CatalogConfig = {
10
+ kind: "text";
11
+ description: string;
12
+ } | {
13
+ kind: "string";
14
+ description: string;
15
+ } | {
16
+ kind: "number";
17
+ description: string;
18
+ } | {
19
+ kind: "options";
20
+ description: string;
21
+ };
22
+ export type CatalogDataType = "string" | "number" | "boolean" | "array" | "void";
23
+ export interface CatalogBrick {
24
+ id: string;
25
+ type: BrickType;
26
+ dataType: CatalogDataType;
27
+ /** What the brick is for, written for the model. */
28
+ description: string;
29
+ /** Configs besides key, label and description, which every field has. */
30
+ configs: Record<string, CatalogConfig>;
31
+ /** Whether the brick holds a value under configs.key. */
32
+ field: boolean;
33
+ /** "bricks": any brick; "fields": the fields of one row of a collection. */
34
+ children?: "bricks" | "fields";
35
+ }
36
+ export declare const BRICK_CATALOG: readonly CatalogBrick[];
37
+ /** Registered bricks a model does not write, and why. */
38
+ export declare const AI_EXCLUDED_BRICKS: Readonly<Record<string, string>>;
39
+ export declare const catalogBrick: (id: string) => CatalogBrick | undefined;
@@ -0,0 +1,9 @@
1
+ import type { BrickSpec } from "../utils/brick-spec.js";
2
+ /**
3
+ * Turns what a model wrote against schema/form-spec.strict.schema.json into a
4
+ * canonical spec that fk-form-render and validateFormData take unchanged: it
5
+ * unwraps { form }, drops the nulls strict mode fills absent properties with,
6
+ * restores type, dataType and name from the brick id, and expands hiddenWhen /
7
+ * disabledWhen into rules. A form whose root is not a panel gets a column.
8
+ */
9
+ export declare function fromStrictSpec(output: unknown): BrickSpec;
package/dist/index.d.ts CHANGED
@@ -3,9 +3,11 @@ export { BrickMold } from "./utils/brick-mold.js";
3
3
  export { DropType, BrickMoldDropType, BrickSpecDropType } from "./utils/drop-type.js";
4
4
  export { BrickStyles } from "./utils/brick-styles.js";
5
5
  export { BrickBaseConfigs, CommonBrickProps, WithBrickBaseConfigs } from "./utils/common-brick-props.js";
6
- export { BrickLayout, BrickSpec, buildValidationSchema, iterateBricks, iterateSchemaBricks, defaultFormData, } from "./utils/brick-spec.js";
6
+ export { BrickLayout, BrickSpec, RowTrack, buildValidationSchema, iterateBricks, iterateSchemaBricks, defaultFormData, } from "./utils/brick-spec.js";
7
7
  export { getBrickData, wrapBrickData } from "./utils/brick-data.js";
8
8
  export { SelectOption, normalizeOptions } from "./utils/options.js";
9
+ export { BRICK_CATALOG, AI_EXCLUDED_BRICKS, CatalogBrick, CatalogConfig, CatalogDataType, catalogBrick } from "./ai/brick-catalog.js";
10
+ export { fromStrictSpec } from "./ai/from-strict-spec.js";
9
11
  export { RecapItem, collectRecapItems } from "./utils/recap.js";
10
12
  export { FieldDescriptor, CollectFieldsOptions, collectFields } from "./utils/fields.js";
11
13
  export { IdentityFormat, IDENTITY_FORMATS, checkIdentity, checkFrNir, checkBjNpi, checkDigits, checkLuhn, checkFrSiren, checkFrSiret, checkBjIfu, checkIban, formatIban } from "./utils/identity.js";
package/dist/index.js CHANGED
@@ -7130,6 +7130,154 @@ function normalizeOptions(raw, labelKey = "label", valueKey = "value") {
7130
7130
  return String(raw ?? "").split(`
7131
7131
  `).map((line) => line.trim()).filter(Boolean).map((line) => ({ label: line, value: line }));
7132
7132
  }
7133
+ // lib/ai/brick-catalog.ts
7134
+ var placeholder = { kind: "text", description: "Example shown in the empty control." };
7135
+ var options = { kind: "options", description: "The choices, in display order: label shown, value stored." };
7136
+ var field = (id, dataType, description, configs = {}) => ({ id, type: "input", dataType, description, configs, field: true });
7137
+ var BRICK_CATALOG = [
7138
+ field("text", "string", "One line of free text.", {
7139
+ placeholder,
7140
+ mask: { kind: "string", description: "Input mask: 9 a digit, a a letter, A a letter in capitals, * either; other characters are inserted as they are." }
7141
+ }),
7142
+ field("textarea", "string", "Several lines of free text.", { placeholder }),
7143
+ field("email", "string", "An email address.", { placeholder }),
7144
+ field("url", "string", "A web address (https://…).", { placeholder }),
7145
+ field("phone", "string", "A phone number.", {
7146
+ placeholder,
7147
+ mask: { kind: "string", description: "Input mask: 9 a digit, other characters inserted as they are, for example +228 99 99 99 99." }
7148
+ }),
7149
+ field("number", "number", "A number.", {
7150
+ placeholder,
7151
+ prefix: { kind: "text", description: "Shown before the control, for example a currency." },
7152
+ suffix: { kind: "text", description: "Shown after the control, for example a unit." }
7153
+ }),
7154
+ field("date", "string", "A date, stored as YYYY-MM-DD."),
7155
+ field("time", "string", "A time of day, stored as HH:MM."),
7156
+ field("datetime", "string", "A date and a time."),
7157
+ field("checkbox", "boolean", "A yes/no box; the label sits beside it. Use it for each item of a list someone ticks."),
7158
+ field("select", "string", "One choice in a drop-down list. Prefer radio for 2 to 4 short choices.", { placeholder, options }),
7159
+ field("radio", "string", "One choice among a few options, all visible.", { options }),
7160
+ field("multi-select", "array", "Several choices in a drop-down list.", { placeholder, options }),
7161
+ field("select-boxes", "array", "Several choices, one box each, all visible.", { options }),
7162
+ {
7163
+ id: "data-grid",
7164
+ type: "collection",
7165
+ dataType: "array",
7166
+ description: "A table whose rows the person adds; children are the fields of one row.",
7167
+ configs: {},
7168
+ field: true,
7169
+ children: "fields"
7170
+ },
7171
+ {
7172
+ id: "content",
7173
+ type: "output",
7174
+ dataType: "void",
7175
+ description: "Fixed text shown to the person, not a question. Put it above or below a row, not in it.",
7176
+ configs: { content: { kind: "text", description: "The text, one paragraph per line." } },
7177
+ field: false
7178
+ },
7179
+ {
7180
+ id: "group",
7181
+ type: "panel",
7182
+ dataType: "void",
7183
+ description: "A titled box around related bricks.",
7184
+ configs: { label: { kind: "text", description: "The group's title." } },
7185
+ field: false,
7186
+ children: "bricks"
7187
+ },
7188
+ {
7189
+ id: "row",
7190
+ type: "panel",
7191
+ dataType: "void",
7192
+ description: "Bricks side by side; they stack on narrow screens. Put in one row only questions shown together.",
7193
+ configs: {},
7194
+ field: false,
7195
+ children: "bricks"
7196
+ },
7197
+ {
7198
+ id: "column",
7199
+ type: "panel",
7200
+ dataType: "void",
7201
+ description: "Bricks one under the other; the usual root of a form.",
7202
+ configs: {},
7203
+ field: false,
7204
+ children: "bricks"
7205
+ }
7206
+ ];
7207
+ var AI_EXCLUDED_BRICKS = {
7208
+ password: "a form written by a model must not ask for a password",
7209
+ hidden: "carries a value the host sets, not one a person enters",
7210
+ tags: "free list of words; select-boxes or textarea cover what a model needs",
7211
+ signature: "legal capture belongs in forms a person designs",
7212
+ "geo-point": "needs the host's map tiles",
7213
+ "geo-area": "needs the host's map tiles",
7214
+ "geo-address": "needs the host's search and map services",
7215
+ "geo-layer": "needs the host's layers",
7216
+ "national-id": "country identifier formats are a design decision",
7217
+ mrz: "identity documents belong in forms a person designs",
7218
+ "tax-id": "country identifier formats are a design decision",
7219
+ iban: "bank details belong in forms a person designs",
7220
+ money: "currency lists are a design decision",
7221
+ appointment: "needs the host's slot provider",
7222
+ document: "needs the host's document reader",
7223
+ measure: "unit families are a design decision",
7224
+ "vehicle-plate": "country plate formats are a design decision",
7225
+ "company-registry": "country registry formats are a design decision",
7226
+ "date-range": "two dates cover it",
7227
+ tabs: "navigation belongs in forms a person designs",
7228
+ stepper: "navigation belongs in forms a person designs",
7229
+ address: "the host's address model is a design decision",
7230
+ file: "needs the host's upload service",
7231
+ "key-value": "free-form object, not a question",
7232
+ recap: "a summary page, not a question",
7233
+ code: "a code editor is not a question for a person",
7234
+ "nested-form": "references the host's stored forms"
7235
+ };
7236
+ var byId = new Map(BRICK_CATALOG.map((brick) => [brick.id, brick]));
7237
+ var catalogBrick = (id) => byId.get(id);
7238
+ // lib/ai/from-strict-spec.ts
7239
+ var isNode = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7240
+ var present = (record) => Object.fromEntries(Object.entries(record).filter(([, value]) => value !== null));
7241
+ var RULE_TARGETS = { hiddenWhen: "hidden", disabledWhen: "disabled" };
7242
+ var rulesOf = (node) => Object.keys(RULE_TARGETS).filter((name) => isNode(node[name])).map((name) => ({
7243
+ name,
7244
+ type: "jsonLogic",
7245
+ logic: node[name],
7246
+ effects: [{ property: { target: RULE_TARGETS[name], type: "boolean" }, boolean: true }]
7247
+ }));
7248
+ var toBrick = (node, path) => {
7249
+ if (!isNode(node))
7250
+ throw new Error(`fromStrictSpec: ${path} is not a brick`);
7251
+ const id = String(node.id);
7252
+ const entry = catalogBrick(id);
7253
+ if (!entry)
7254
+ throw new Error(`fromStrictSpec: ${path} has an unknown brick id "${id}"`);
7255
+ const configs = isNode(node.configs) ? present(node.configs) : {};
7256
+ if ("options" in configs && (id === "select" || id === "multi-select"))
7257
+ configs.optionsSource = "static";
7258
+ const validations = Array.isArray(node.validations) ? node.validations.filter(isNode).map((validation2) => present(validation2)) : [];
7259
+ const rules = rulesOf(node);
7260
+ const layout = isNode(node.layout) ? present(node.layout) : {};
7261
+ const children = Array.isArray(node.children) ? node.children.map((child, index) => toBrick(child, `${path}.${index}`)) : [];
7262
+ return {
7263
+ type: entry.type,
7264
+ dataType: entry.dataType,
7265
+ id,
7266
+ name: String(configs.label ?? configs.key ?? id),
7267
+ configs,
7268
+ ...validations.length ? { validations } : {},
7269
+ ...rules.length ? { rules } : {},
7270
+ ...Object.keys(layout).length ? { layout } : {},
7271
+ ...children.length ? { children } : {}
7272
+ };
7273
+ };
7274
+ function fromStrictSpec(output) {
7275
+ const root = isNode(output) && "form" in output ? output.form : output;
7276
+ const spec = toBrick(root, "form");
7277
+ if (spec.type === "panel")
7278
+ return spec;
7279
+ return { type: "panel", dataType: "void", id: "column", name: "Form", configs: {}, children: [spec] };
7280
+ }
7133
7281
  // lib/i18n.ts
7134
7282
  var en = {
7135
7283
  "palette.search": "Search bricks…",
@@ -10077,6 +10225,8 @@ async function expandSpec(spec, options = {}) {
10077
10225
  return expandBrick(structuredClone(spec), []);
10078
10226
  }
10079
10227
  export {
10228
+ AI_EXCLUDED_BRICKS,
10229
+ BRICK_CATALOG,
10080
10230
  Base64FileUploadService,
10081
10231
  Brick,
10082
10232
  FetchDataSourceService,
@@ -10094,6 +10244,7 @@ export {
10094
10244
  addBrick,
10095
10245
  appendSearchParam,
10096
10246
  buildValidationSchema,
10247
+ catalogBrick,
10097
10248
  checkBjIfu,
10098
10249
  checkBjNpi,
10099
10250
  checkCompanyRegistry,
@@ -10125,6 +10276,7 @@ export {
10125
10276
  formatMeasure,
10126
10277
  formatPlate,
10127
10278
  frFkTranslations,
10279
+ fromStrictSpec,
10128
10280
  generateSlots,
10129
10281
  getAffectedProperties,
10130
10282
  getBrickAt,
@@ -10171,5 +10323,5 @@ export {
10171
10323
  wrapBrickData
10172
10324
  };
10173
10325
 
10174
- //# debugId=4C946517E957968D64756E2164756E21
10326
+ //# debugId=4A8FDDA420C6F9E564756E2164756E21
10175
10327
  //# sourceMappingURL=index.js.map