@streamline-pulse/formkrafter-core 0.34.0 → 0.36.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.
- package/dist/ai/brick-catalog.d.ts +39 -0
- package/dist/ai/from-strict-spec.d.ts +9 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +153 -1
- package/dist/index.js.map +6 -4
- package/dist/utils/brick-spec.d.ts +13 -3
- package/package.json +3 -2
- package/schema/form-spec.schema.json +24 -3
- package/schema/form-spec.strict.schema.json +2040 -0
|
@@ -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=
|
|
10326
|
+
//# debugId=4A8FDDA420C6F9E564756E2164756E21
|
|
10175
10327
|
//# sourceMappingURL=index.js.map
|