@contractspec/lib.contracts-runtime-client-react 3.8.4 → 3.8.6
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/browser/drivers/rn-reusables.js +1 -15
- package/dist/browser/drivers/shadcn.js +1 -15
- package/dist/browser/feature-render.js +1 -108
- package/dist/browser/form-render.impl.js +1 -367
- package/dist/browser/form-render.js +1 -367
- package/dist/browser/index.js +1 -480
- package/dist/browser/transform-engine.js +1 -66
- package/dist/drivers/rn-reusables.js +1 -9
- package/dist/drivers/shadcn.js +1 -9
- package/dist/feature-render.js +1 -102
- package/dist/form-render.impl.js +1 -361
- package/dist/form-render.js +1 -361
- package/dist/index.js +1 -474
- package/dist/node/drivers/rn-reusables.js +1 -10
- package/dist/node/drivers/shadcn.js +1 -10
- package/dist/node/feature-render.js +1 -103
- package/dist/node/form-render.impl.js +1 -362
- package/dist/node/form-render.js +1 -362
- package/dist/node/index.js +1 -475
- package/dist/node/transform-engine.js +1 -61
- package/dist/transform-engine.js +1 -60
- package/package.json +8 -8
package/dist/node/index.js
CHANGED
|
@@ -1,475 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/drivers/rn-reusables.ts
|
|
5
|
-
function rnReusablesDriver(slots) {
|
|
6
|
-
return slots;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// src/drivers/shadcn.ts
|
|
10
|
-
function shadcnDriver(slots) {
|
|
11
|
-
return slots;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// src/transform-engine.ts
|
|
15
|
-
import {
|
|
16
|
-
createDefaultTransformEngine,
|
|
17
|
-
htmlToMarkdown,
|
|
18
|
-
registerBasicValidation
|
|
19
|
-
} from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
20
|
-
import React from "react";
|
|
21
|
-
|
|
22
|
-
export * from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
23
|
-
function registerDefaultReactRenderer(engine) {
|
|
24
|
-
engine.register({
|
|
25
|
-
target: "react",
|
|
26
|
-
async render(desc) {
|
|
27
|
-
if (desc.source.type === "component") {
|
|
28
|
-
const props = desc.source.props ? desc.source.props.getZod().safeParse({}).success ? {} : undefined : undefined;
|
|
29
|
-
return {
|
|
30
|
-
kind: "react_component",
|
|
31
|
-
componentKey: desc.source.componentKey,
|
|
32
|
-
props
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
kind: "blocknotejs",
|
|
37
|
-
docJson: desc.source.docJson,
|
|
38
|
-
blockConfig: desc.source.blockConfig
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return engine;
|
|
43
|
-
}
|
|
44
|
-
function registerReactToMarkdownRenderer(engine, componentMap) {
|
|
45
|
-
engine.prependRegister({
|
|
46
|
-
target: "markdown",
|
|
47
|
-
async render(desc) {
|
|
48
|
-
if (desc.source.type !== "component") {
|
|
49
|
-
throw new Error("React-to-markdown renderer only handles component presentations");
|
|
50
|
-
}
|
|
51
|
-
const Component = componentMap[desc.source.componentKey];
|
|
52
|
-
if (!Component) {
|
|
53
|
-
throw new Error(`Component ${desc.source.componentKey} not found in componentMap`);
|
|
54
|
-
}
|
|
55
|
-
const { renderToStaticMarkup } = await import("react-dom/server");
|
|
56
|
-
const element = React.createElement(Component, desc.source.props ? {} : undefined);
|
|
57
|
-
const markdown = htmlToMarkdown(renderToStaticMarkup(element));
|
|
58
|
-
return {
|
|
59
|
-
mimeType: "text/markdown",
|
|
60
|
-
body: desc.policy?.pii?.length ? markdown.replace(/\[REDACTED\]/g, "[REDACTED]") : markdown
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
return engine;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// src/feature-render.ts
|
|
68
|
-
import React2 from "react";
|
|
69
|
-
function createEngineWithDefaults() {
|
|
70
|
-
return registerBasicValidation(registerDefaultReactRenderer(createDefaultTransformEngine()));
|
|
71
|
-
}
|
|
72
|
-
async function renderFeaturePresentation(engine, target, desc, options) {
|
|
73
|
-
if (target === "react") {
|
|
74
|
-
const rd = await engine.render("react", desc);
|
|
75
|
-
if (rd.kind === "react_component") {
|
|
76
|
-
const map = options?.componentMap ?? {};
|
|
77
|
-
const C = map[rd.componentKey];
|
|
78
|
-
if (!C)
|
|
79
|
-
return null;
|
|
80
|
-
const merged = {
|
|
81
|
-
...rd.props ?? {},
|
|
82
|
-
...options?.reactProps ?? {}
|
|
83
|
-
};
|
|
84
|
-
return React2.createElement(C, merged);
|
|
85
|
-
}
|
|
86
|
-
if (rd.kind === "blocknotejs") {
|
|
87
|
-
if (options?.renderBlockNote)
|
|
88
|
-
return options.renderBlockNote(rd.docJson, rd.blockConfig);
|
|
89
|
-
return React2.createElement("div", {}, "[BlockNote renderer not configured]");
|
|
90
|
-
}
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
if (target === "markdown")
|
|
94
|
-
return engine.render(target, desc);
|
|
95
|
-
if (target === "application/json")
|
|
96
|
-
return engine.render(target, desc);
|
|
97
|
-
if (target === "application/xml")
|
|
98
|
-
return engine.render(target, desc);
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
function createFeatureModule(meta, refs) {
|
|
102
|
-
return { meta, ...refs };
|
|
103
|
-
}
|
|
104
|
-
function registerFeature(registry, feature) {
|
|
105
|
-
registry.register(feature);
|
|
106
|
-
return registry;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// src/form-render.impl.tsx
|
|
110
|
-
import {
|
|
111
|
-
buildZodWithRelations,
|
|
112
|
-
evalPredicate
|
|
113
|
-
} from "@contractspec/lib.contracts-spec/forms";
|
|
114
|
-
import { zodResolver } from "@hookform/resolvers/zod";
|
|
115
|
-
import React3, { useEffect, useMemo, useState } from "react";
|
|
116
|
-
import {
|
|
117
|
-
Controller,
|
|
118
|
-
useFieldArray,
|
|
119
|
-
useForm
|
|
120
|
-
} from "react-hook-form";
|
|
121
|
-
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
122
|
-
"use client";
|
|
123
|
-
function toOptionsArray(src) {
|
|
124
|
-
if (!src)
|
|
125
|
-
return;
|
|
126
|
-
if (Array.isArray(src))
|
|
127
|
-
return { kind: "static", options: src };
|
|
128
|
-
return src;
|
|
129
|
-
}
|
|
130
|
-
function getAtPath(values, path) {
|
|
131
|
-
if (!path)
|
|
132
|
-
return;
|
|
133
|
-
const segs = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
134
|
-
let cur = values;
|
|
135
|
-
for (const s of segs) {
|
|
136
|
-
if (cur == null)
|
|
137
|
-
return;
|
|
138
|
-
cur = cur[s];
|
|
139
|
-
}
|
|
140
|
-
return cur;
|
|
141
|
-
}
|
|
142
|
-
function makeDepsKey(values, deps) {
|
|
143
|
-
if (!deps || deps.length === 0)
|
|
144
|
-
return "[]";
|
|
145
|
-
try {
|
|
146
|
-
return JSON.stringify(deps.map((d) => getAtPath(values, d)));
|
|
147
|
-
} catch {
|
|
148
|
-
return "[]";
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
function useResolvedOptions(values, source, resolvers) {
|
|
152
|
-
const [opts, setOpts] = useState([]);
|
|
153
|
-
const depKey = useMemo(() => {
|
|
154
|
-
if (!source)
|
|
155
|
-
return "nil";
|
|
156
|
-
if (source.kind === "static")
|
|
157
|
-
return JSON.stringify(source.options ?? []);
|
|
158
|
-
return makeDepsKey(values, source.deps);
|
|
159
|
-
}, [source, values]);
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
let mounted = true;
|
|
162
|
-
const run = async () => {
|
|
163
|
-
if (!source)
|
|
164
|
-
return setOpts([]);
|
|
165
|
-
if (source.kind === "static")
|
|
166
|
-
return setOpts([...source.options ?? []]);
|
|
167
|
-
const fn = resolvers?.[source.resolverKey];
|
|
168
|
-
if (!fn)
|
|
169
|
-
return setOpts([]);
|
|
170
|
-
const res = await fn(values, source.args);
|
|
171
|
-
if (mounted)
|
|
172
|
-
setOpts([...res ?? []]);
|
|
173
|
-
};
|
|
174
|
-
run();
|
|
175
|
-
return () => {
|
|
176
|
-
mounted = false;
|
|
177
|
-
};
|
|
178
|
-
}, [
|
|
179
|
-
depKey,
|
|
180
|
-
source && source.kind === "resolver" ? source.resolverKey : undefined
|
|
181
|
-
]);
|
|
182
|
-
return opts;
|
|
183
|
-
}
|
|
184
|
-
function fieldPath(parent, name, arrayIndex) {
|
|
185
|
-
if (!name)
|
|
186
|
-
return parent ?? "";
|
|
187
|
-
const child = typeof arrayIndex === "number" ? `${name.replace(/^\$index$/, String(arrayIndex))}` : name;
|
|
188
|
-
return parent ? `${parent}${typeof arrayIndex === "number" ? `.${arrayIndex}` : ""}.${child}`.replace(/\.+/g, ".") : child;
|
|
189
|
-
}
|
|
190
|
-
function createFormRenderer(base) {
|
|
191
|
-
const conf = base;
|
|
192
|
-
const { driver } = conf;
|
|
193
|
-
function InternalForm(props) {
|
|
194
|
-
const { spec, options, merged } = props;
|
|
195
|
-
const baseZod = useMemo(() => buildZodWithRelations(spec), [spec]);
|
|
196
|
-
const form = useForm({
|
|
197
|
-
...merged.formOptions,
|
|
198
|
-
resolver: zodResolver(baseZod),
|
|
199
|
-
defaultValues: options?.defaultValues
|
|
200
|
-
});
|
|
201
|
-
const values = form.watch();
|
|
202
|
-
const renderOne = (f, parent, arrayIndex) => {
|
|
203
|
-
const DriverField = driver.Field;
|
|
204
|
-
const DriverLabel = driver.FieldLabel;
|
|
205
|
-
const DriverDesc = driver.FieldDescription;
|
|
206
|
-
const DriverError = driver.FieldError;
|
|
207
|
-
const name = fieldPath(parent, f.name, arrayIndex);
|
|
208
|
-
const visible = evalPredicate(values, f.visibleWhen);
|
|
209
|
-
const enabled = evalPredicate(values, f.enabledWhen);
|
|
210
|
-
const invalid = Boolean(form.getFieldState(name)?.invalid);
|
|
211
|
-
if (!visible)
|
|
212
|
-
return null;
|
|
213
|
-
const id = name?.replace(/\./g, "-");
|
|
214
|
-
const commonWrapProps = {
|
|
215
|
-
"data-invalid": invalid,
|
|
216
|
-
hidden: !visible,
|
|
217
|
-
disabled: !enabled
|
|
218
|
-
};
|
|
219
|
-
const labelNode = f.labelI18n ? /* @__PURE__ */ jsxDEV(DriverLabel, {
|
|
220
|
-
htmlFor: id,
|
|
221
|
-
children: f.labelI18n
|
|
222
|
-
}, undefined, false, undefined, this) : null;
|
|
223
|
-
const descNode = f.descriptionI18n ? /* @__PURE__ */ jsxDEV(DriverDesc, {
|
|
224
|
-
children: f.descriptionI18n
|
|
225
|
-
}, undefined, false, undefined, this) : null;
|
|
226
|
-
if (f.kind === "group") {
|
|
227
|
-
const children = f.fields.map((c, i) => /* @__PURE__ */ jsxDEV(React3.Fragment, {
|
|
228
|
-
children: renderOne(c, name, arrayIndex)
|
|
229
|
-
}, `${name}-${i}`, false, undefined, this));
|
|
230
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
231
|
-
...commonWrapProps,
|
|
232
|
-
children: [
|
|
233
|
-
labelNode,
|
|
234
|
-
children,
|
|
235
|
-
descNode
|
|
236
|
-
]
|
|
237
|
-
}, undefined, true, undefined, this);
|
|
238
|
-
}
|
|
239
|
-
if (f.kind === "array") {
|
|
240
|
-
return renderArray(f, parent);
|
|
241
|
-
}
|
|
242
|
-
return /* @__PURE__ */ jsxDEV(Controller, {
|
|
243
|
-
name,
|
|
244
|
-
control: form.control,
|
|
245
|
-
render: ({ field, fieldState }) => {
|
|
246
|
-
const err = fieldState.error ? [fieldState.error] : [];
|
|
247
|
-
const ariaInvalid = fieldState.invalid || undefined;
|
|
248
|
-
if (f.kind === "text") {
|
|
249
|
-
const textField = f;
|
|
250
|
-
const Input = driver.Input;
|
|
251
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
252
|
-
...commonWrapProps,
|
|
253
|
-
children: [
|
|
254
|
-
labelNode,
|
|
255
|
-
/* @__PURE__ */ jsxDEV(Input, {
|
|
256
|
-
id,
|
|
257
|
-
"aria-invalid": ariaInvalid,
|
|
258
|
-
placeholder: f.placeholderI18n,
|
|
259
|
-
autoComplete: textField.autoComplete,
|
|
260
|
-
inputMode: textField.inputMode,
|
|
261
|
-
maxLength: textField.maxLength,
|
|
262
|
-
minLength: textField.minLength,
|
|
263
|
-
disabled: !enabled,
|
|
264
|
-
...field,
|
|
265
|
-
...f.uiProps
|
|
266
|
-
}, undefined, false, undefined, this),
|
|
267
|
-
descNode,
|
|
268
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
269
|
-
errors: err
|
|
270
|
-
}, undefined, false, undefined, this) : null
|
|
271
|
-
]
|
|
272
|
-
}, undefined, true, undefined, this);
|
|
273
|
-
}
|
|
274
|
-
if (f.kind === "textarea") {
|
|
275
|
-
const textareaField = f;
|
|
276
|
-
const Textarea = driver.Textarea;
|
|
277
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
278
|
-
...commonWrapProps,
|
|
279
|
-
children: [
|
|
280
|
-
labelNode,
|
|
281
|
-
/* @__PURE__ */ jsxDEV(Textarea, {
|
|
282
|
-
id,
|
|
283
|
-
"aria-invalid": ariaInvalid,
|
|
284
|
-
placeholder: f.placeholderI18n,
|
|
285
|
-
rows: textareaField.rows,
|
|
286
|
-
maxLength: textareaField.maxLength,
|
|
287
|
-
disabled: !enabled,
|
|
288
|
-
...field,
|
|
289
|
-
...f.uiProps
|
|
290
|
-
}, undefined, false, undefined, this),
|
|
291
|
-
descNode,
|
|
292
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
293
|
-
errors: err
|
|
294
|
-
}, undefined, false, undefined, this) : null
|
|
295
|
-
]
|
|
296
|
-
}, undefined, true, undefined, this);
|
|
297
|
-
}
|
|
298
|
-
if (f.kind === "select") {
|
|
299
|
-
const selectField = f;
|
|
300
|
-
const Select = driver.Select;
|
|
301
|
-
const src = toOptionsArray(selectField.options);
|
|
302
|
-
const opts = useResolvedOptions(values, src, merged.resolvers);
|
|
303
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
304
|
-
...commonWrapProps,
|
|
305
|
-
children: [
|
|
306
|
-
labelNode,
|
|
307
|
-
/* @__PURE__ */ jsxDEV(Select, {
|
|
308
|
-
id,
|
|
309
|
-
name,
|
|
310
|
-
"aria-invalid": ariaInvalid,
|
|
311
|
-
disabled: !enabled,
|
|
312
|
-
value: field.value,
|
|
313
|
-
onChange: (v) => field.onChange(v),
|
|
314
|
-
options: opts,
|
|
315
|
-
...f.uiProps
|
|
316
|
-
}, undefined, false, undefined, this),
|
|
317
|
-
descNode,
|
|
318
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
319
|
-
errors: err
|
|
320
|
-
}, undefined, false, undefined, this) : null
|
|
321
|
-
]
|
|
322
|
-
}, undefined, true, undefined, this);
|
|
323
|
-
}
|
|
324
|
-
if (f.kind === "checkbox") {
|
|
325
|
-
const Checkbox = driver.Checkbox;
|
|
326
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
327
|
-
...commonWrapProps,
|
|
328
|
-
children: [
|
|
329
|
-
labelNode,
|
|
330
|
-
/* @__PURE__ */ jsxDEV(Checkbox, {
|
|
331
|
-
id,
|
|
332
|
-
name,
|
|
333
|
-
disabled: !enabled,
|
|
334
|
-
checked: !!field.value,
|
|
335
|
-
onCheckedChange: (v) => field.onChange(v),
|
|
336
|
-
...f.uiProps
|
|
337
|
-
}, undefined, false, undefined, this),
|
|
338
|
-
descNode,
|
|
339
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
340
|
-
errors: err
|
|
341
|
-
}, undefined, false, undefined, this) : null
|
|
342
|
-
]
|
|
343
|
-
}, undefined, true, undefined, this);
|
|
344
|
-
}
|
|
345
|
-
if (f.kind === "radio") {
|
|
346
|
-
const radioField = f;
|
|
347
|
-
const RadioGroup = driver.RadioGroup;
|
|
348
|
-
const src = toOptionsArray(radioField.options);
|
|
349
|
-
const opts = useResolvedOptions(values, src, merged.resolvers);
|
|
350
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
351
|
-
...commonWrapProps,
|
|
352
|
-
children: [
|
|
353
|
-
labelNode,
|
|
354
|
-
/* @__PURE__ */ jsxDEV(RadioGroup, {
|
|
355
|
-
id,
|
|
356
|
-
name,
|
|
357
|
-
disabled: !enabled,
|
|
358
|
-
value: field.value,
|
|
359
|
-
onValueChange: (v) => field.onChange(v),
|
|
360
|
-
options: opts,
|
|
361
|
-
...f.uiProps
|
|
362
|
-
}, undefined, false, undefined, this),
|
|
363
|
-
descNode,
|
|
364
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
365
|
-
errors: err
|
|
366
|
-
}, undefined, false, undefined, this) : null
|
|
367
|
-
]
|
|
368
|
-
}, undefined, true, undefined, this);
|
|
369
|
-
}
|
|
370
|
-
if (f.kind === "switch") {
|
|
371
|
-
const Switch = driver.Switch;
|
|
372
|
-
return /* @__PURE__ */ jsxDEV(DriverField, {
|
|
373
|
-
...commonWrapProps,
|
|
374
|
-
children: [
|
|
375
|
-
labelNode,
|
|
376
|
-
/* @__PURE__ */ jsxDEV(Switch, {
|
|
377
|
-
id,
|
|
378
|
-
name,
|
|
379
|
-
disabled: !enabled,
|
|
380
|
-
checked: !!field.value,
|
|
381
|
-
onCheckedChange: (v) => field.onChange(v),
|
|
382
|
-
...f.uiProps
|
|
383
|
-
}, undefined, false, undefined, this),
|
|
384
|
-
descNode,
|
|
385
|
-
fieldState.invalid ? /* @__PURE__ */ jsxDEV(DriverError, {
|
|
386
|
-
errors: err
|
|
387
|
-
}, undefined, false, undefined, this) : null
|
|
388
|
-
]
|
|
389
|
-
}, undefined, true, undefined, this);
|
|
390
|
-
}
|
|
391
|
-
return /* @__PURE__ */ jsxDEV(Fragment, {}, undefined, false, undefined, this);
|
|
392
|
-
}
|
|
393
|
-
}, name, false, undefined, this);
|
|
394
|
-
};
|
|
395
|
-
const renderArray = (f, parent) => {
|
|
396
|
-
const name = fieldPath(parent, f.name);
|
|
397
|
-
const { fields, append, remove } = useFieldArray({
|
|
398
|
-
control: form.control,
|
|
399
|
-
name
|
|
400
|
-
});
|
|
401
|
-
const canAdd = f.max == null || fields.length < f.max;
|
|
402
|
-
const canRemove = (idx) => (f.min == null ? fields.length > 0 : fields.length > f.min) && idx >= 0;
|
|
403
|
-
const Button2 = driver.Button;
|
|
404
|
-
const Label = driver.FieldLabel;
|
|
405
|
-
return /* @__PURE__ */ jsxDEV("div", {
|
|
406
|
-
children: [
|
|
407
|
-
f.labelI18n ? /* @__PURE__ */ jsxDEV(Label, {
|
|
408
|
-
children: f.labelI18n
|
|
409
|
-
}, undefined, false, undefined, this) : null,
|
|
410
|
-
fields.map((row, idx) => /* @__PURE__ */ jsxDEV("div", {
|
|
411
|
-
children: [
|
|
412
|
-
renderOne(f.of, name, idx),
|
|
413
|
-
canRemove(idx) ? /* @__PURE__ */ jsxDEV(Button2, {
|
|
414
|
-
type: "button",
|
|
415
|
-
variant: "ghost",
|
|
416
|
-
size: "sm",
|
|
417
|
-
onClick: () => remove(idx),
|
|
418
|
-
children: "Remove"
|
|
419
|
-
}, undefined, false, undefined, this) : null
|
|
420
|
-
]
|
|
421
|
-
}, row.id ?? idx, true, undefined, this)),
|
|
422
|
-
canAdd ? /* @__PURE__ */ jsxDEV(Button2, {
|
|
423
|
-
type: "button",
|
|
424
|
-
variant: "outline",
|
|
425
|
-
size: "sm",
|
|
426
|
-
onClick: () => append({}),
|
|
427
|
-
children: "Add"
|
|
428
|
-
}, undefined, false, undefined, this) : null
|
|
429
|
-
]
|
|
430
|
-
}, name, true, undefined, this);
|
|
431
|
-
};
|
|
432
|
-
const onSubmit = async (data) => {
|
|
433
|
-
const actionKey = spec.actions?.[0]?.key ?? "submit";
|
|
434
|
-
if (merged.onSubmitOverride) {
|
|
435
|
-
return merged.onSubmitOverride(data, actionKey);
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
const Button = driver.Button;
|
|
439
|
-
return /* @__PURE__ */ jsxDEV("form", {
|
|
440
|
-
onSubmit: form.handleSubmit(onSubmit),
|
|
441
|
-
children: [
|
|
442
|
-
(spec.fields || []).map((f, i) => /* @__PURE__ */ jsxDEV(React3.Fragment, {
|
|
443
|
-
children: renderOne(f)
|
|
444
|
-
}, i, false, undefined, this)),
|
|
445
|
-
spec.actions && spec.actions.length ? /* @__PURE__ */ jsxDEV("div", {
|
|
446
|
-
children: spec.actions.map((a) => /* @__PURE__ */ jsxDEV(Button, {
|
|
447
|
-
type: "submit",
|
|
448
|
-
children: a.labelI18n
|
|
449
|
-
}, a.key, false, undefined, this))
|
|
450
|
-
}, undefined, false, undefined, this) : null
|
|
451
|
-
]
|
|
452
|
-
}, undefined, true, undefined, this);
|
|
453
|
-
}
|
|
454
|
-
return {
|
|
455
|
-
render: (spec, options) => /* @__PURE__ */ jsxDEV(InternalForm, {
|
|
456
|
-
spec,
|
|
457
|
-
options,
|
|
458
|
-
merged: {
|
|
459
|
-
...conf,
|
|
460
|
-
...options?.overrides ?? {}
|
|
461
|
-
}
|
|
462
|
-
}, undefined, false, undefined, this)
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
// src/index.ts
|
|
466
|
-
"use client";
|
|
467
|
-
export {
|
|
468
|
-
shadcnDriver,
|
|
469
|
-
rnReusablesDriver,
|
|
470
|
-
renderFeaturePresentation,
|
|
471
|
-
registerFeature,
|
|
472
|
-
createFormRenderer,
|
|
473
|
-
createFeatureModule,
|
|
474
|
-
createEngineWithDefaults
|
|
475
|
-
};
|
|
1
|
+
import{createRequire as s}from"node:module";var r=s(import.meta.url);function Zq(J){return J}function Tq(J){return J}import{createDefaultTransformEngine as x,htmlToMarkdown as e,registerBasicValidation as u}from"@contractspec/lib.presentation-runtime-core/transform-engine";import qq from"react";export*from"@contractspec/lib.presentation-runtime-core/transform-engine";function m(J){return J.register({target:"react",async render(q){if(q.source.type==="component"){let Q=q.source.props?q.source.props.getZod().safeParse({}).success?{}:void 0:void 0;return{kind:"react_component",componentKey:q.source.componentKey,props:Q}}return{kind:"blocknotejs",docJson:q.source.docJson,blockConfig:q.source.blockConfig}}}),J}function Cq(J,q){return J.prependRegister({target:"markdown",async render(Q){if(Q.source.type!=="component")throw Error("React-to-markdown renderer only handles component presentations");let X=q[Q.source.componentKey];if(!X)throw Error(`Component ${Q.source.componentKey} not found in componentMap`);let{renderToStaticMarkup:Y}=await import("react-dom/server"),_=qq.createElement(X,Q.source.props?{}:void 0),T=e(Y(_));return{mimeType:"text/markdown",body:Q.policy?.pii?.length?T.replace(/\[REDACTED\]/g,"[REDACTED]"):T}}}),J}import p from"react";function Eq(){return u(m(x()))}async function Oq(J,q,Q,X){if(q==="react"){let Y=await J.render("react",Q);if(Y.kind==="react_component"){let T=(X?.componentMap??{})[Y.componentKey];if(!T)return null;let A={...Y.props??{},...X?.reactProps??{}};return p.createElement(T,A)}if(Y.kind==="blocknotejs"){if(X?.renderBlockNote)return X.renderBlockNote(Y.docJson,Y.blockConfig);return p.createElement("div",{},"[BlockNote renderer not configured]")}return null}if(q==="markdown")return J.render(q,Q);if(q==="application/json")return J.render(q,Q);if(q==="application/xml")return J.render(q,Q);return null}function Pq(J,q){return{meta:J,...q}}function hq(J,q){return J.register(q),J}import{buildZodWithRelations as Hq,evalPredicate as l}from"@contractspec/lib.contracts-spec/forms";import{zodResolver as Jq}from"@hookform/resolvers/zod";import f,{useEffect as Qq,useMemo as i,useState as Uq}from"react";import{Controller as Xq,useFieldArray as Yq,useForm as _q}from"react-hook-form";import{jsx as U,jsxs as B,Fragment as zq}from"react/jsx-runtime";function c(J){if(!J)return;if(Array.isArray(J))return{kind:"static",options:J};return J}function $q(J,q){if(!q)return;let Q=q.replace(/\[(\d+)\]/g,".$1").split(".").filter(Boolean),X=J;for(let Y of Q){if(X==null)return;X=X[Y]}return X}function Gq(J,q){if(!q||q.length===0)return"[]";try{return JSON.stringify(q.map((Q)=>$q(J,Q)))}catch{return"[]"}}function o(J,q,Q){let[X,Y]=Uq([]),_=i(()=>{if(!q)return"nil";if(q.kind==="static")return JSON.stringify(q.options??[]);return Gq(J,q.deps)},[q,J]);return Qq(()=>{let T=!0;return(async()=>{if(!q)return Y([]);if(q.kind==="static")return Y([...q.options??[]]);let N=Q?.[q.resolverKey];if(!N)return Y([]);let k=await N(J,q.args);if(T)Y([...k??[]])})(),()=>{T=!1}},[_,q&&q.kind==="resolver"?q.resolverKey:void 0]),X}function n(J,q,Q){if(!q)return J??"";let X=typeof Q==="number"?`${q.replace(/^\$index$/,String(Q))}`:q;return J?`${J}${typeof Q==="number"?`.${Q}`:""}.${X}`.replace(/\.+/g,"."):X}function bq(J){let q=J,{driver:Q}=q;function X(Y){let{spec:_,options:T,merged:A}=Y,N=i(()=>Hq(_),[_]),k=_q({...A.formOptions,resolver:Jq(N),defaultValues:T?.defaultValues}),y=k.watch(),S=(H,C,O)=>{let{Field:G,FieldLabel:I,FieldDescription:F,FieldError:M}=Q,z=n(C,H.name,O),P=l(y,H.visibleWhen),w=l(y,H.enabledWhen),h=Boolean(k.getFieldState(z)?.invalid);if(!P)return null;let L=z?.replace(/\./g,"-"),D={"data-invalid":h,hidden:!P,disabled:!w},W=H.labelI18n?U(I,{htmlFor:L,children:H.labelI18n}):null,E=H.descriptionI18n?U(F,{children:H.descriptionI18n}):null;if(H.kind==="group"){let V=H.fields.map((Z,R)=>U(f.Fragment,{children:S(Z,z,O)},`${z}-${R}`));return B(G,{...D,children:[W,V,E]})}if(H.kind==="array")return t(H,C);return U(Xq,{name:z,control:k.control,render:({field:V,fieldState:Z})=>{let R=Z.error?[Z.error]:[],b=Z.invalid||void 0;if(H.kind==="text"){let $=H,K=Q.Input;return B(G,{...D,children:[W,U(K,{id:L,"aria-invalid":b,placeholder:H.placeholderI18n,autoComplete:$.autoComplete,inputMode:$.inputMode,maxLength:$.maxLength,minLength:$.minLength,disabled:!w,...V,...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}if(H.kind==="textarea"){let $=H,K=Q.Textarea;return B(G,{...D,children:[W,U(K,{id:L,"aria-invalid":b,placeholder:H.placeholderI18n,rows:$.rows,maxLength:$.maxLength,disabled:!w,...V,...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}if(H.kind==="select"){let $=H,K=Q.Select,j=c($.options),g=o(y,j,A.resolvers);return B(G,{...D,children:[W,U(K,{id:L,name:z,"aria-invalid":b,disabled:!w,value:V.value,onChange:(v)=>V.onChange(v),options:g,...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}if(H.kind==="checkbox"){let $=Q.Checkbox;return B(G,{...D,children:[W,U($,{id:L,name:z,disabled:!w,checked:!!V.value,onCheckedChange:(K)=>V.onChange(K),...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}if(H.kind==="radio"){let $=H,K=Q.RadioGroup,j=c($.options),g=o(y,j,A.resolvers);return B(G,{...D,children:[W,U(K,{id:L,name:z,disabled:!w,value:V.value,onValueChange:(v)=>V.onChange(v),options:g,...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}if(H.kind==="switch"){let $=Q.Switch;return B(G,{...D,children:[W,U($,{id:L,name:z,disabled:!w,checked:!!V.value,onCheckedChange:(K)=>V.onChange(K),...H.uiProps}),E,Z.invalid?U(M,{errors:R}):null]})}return U(zq,{})}},z)},t=(H,C)=>{let O=n(C,H.name),{fields:G,append:I,remove:F}=Yq({control:k.control,name:O}),M=H.max==null||G.length<H.max,z=(h)=>(H.min==null?G.length>0:G.length>H.min)&&h>=0,P=Q.Button,w=Q.FieldLabel;return B("div",{children:[H.labelI18n?U(w,{children:H.labelI18n}):null,G.map((h,L)=>B("div",{children:[S(H.of,O,L),z(L)?U(P,{type:"button",variant:"ghost",size:"sm",onClick:()=>F(L),children:"Remove"}):null]},h.id??L)),M?U(P,{type:"button",variant:"outline",size:"sm",onClick:()=>I({}),children:"Add"}):null]},O)},d=async(H)=>{let C=_.actions?.[0]?.key??"submit";if(A.onSubmitOverride)return A.onSubmitOverride(H,C)},a=Q.Button;return B("form",{onSubmit:k.handleSubmit(d),children:[(_.fields||[]).map((H,C)=>U(f.Fragment,{children:S(H)},C)),_.actions&&_.actions.length?U("div",{children:_.actions.map((H)=>U(a,{type:"submit",children:H.labelI18n},H.key))}):null]})}return{render:(Y,_)=>U(X,{spec:Y,options:_,merged:{...q,..._?.overrides??{}}})}}export{Tq as shadcnDriver,Zq as rnReusablesDriver,Oq as renderFeaturePresentation,hq as registerFeature,bq as createFormRenderer,Pq as createFeatureModule,Eq as createEngineWithDefaults};
|
|
@@ -1,61 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/transform-engine.ts
|
|
5
|
-
import {
|
|
6
|
-
createDefaultTransformEngine,
|
|
7
|
-
htmlToMarkdown,
|
|
8
|
-
registerBasicValidation
|
|
9
|
-
} from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
10
|
-
import React from "react";
|
|
11
|
-
|
|
12
|
-
export * from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
13
|
-
function registerDefaultReactRenderer(engine) {
|
|
14
|
-
engine.register({
|
|
15
|
-
target: "react",
|
|
16
|
-
async render(desc) {
|
|
17
|
-
if (desc.source.type === "component") {
|
|
18
|
-
const props = desc.source.props ? desc.source.props.getZod().safeParse({}).success ? {} : undefined : undefined;
|
|
19
|
-
return {
|
|
20
|
-
kind: "react_component",
|
|
21
|
-
componentKey: desc.source.componentKey,
|
|
22
|
-
props
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return {
|
|
26
|
-
kind: "blocknotejs",
|
|
27
|
-
docJson: desc.source.docJson,
|
|
28
|
-
blockConfig: desc.source.blockConfig
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
return engine;
|
|
33
|
-
}
|
|
34
|
-
function registerReactToMarkdownRenderer(engine, componentMap) {
|
|
35
|
-
engine.prependRegister({
|
|
36
|
-
target: "markdown",
|
|
37
|
-
async render(desc) {
|
|
38
|
-
if (desc.source.type !== "component") {
|
|
39
|
-
throw new Error("React-to-markdown renderer only handles component presentations");
|
|
40
|
-
}
|
|
41
|
-
const Component = componentMap[desc.source.componentKey];
|
|
42
|
-
if (!Component) {
|
|
43
|
-
throw new Error(`Component ${desc.source.componentKey} not found in componentMap`);
|
|
44
|
-
}
|
|
45
|
-
const { renderToStaticMarkup } = await import("react-dom/server");
|
|
46
|
-
const element = React.createElement(Component, desc.source.props ? {} : undefined);
|
|
47
|
-
const markdown = htmlToMarkdown(renderToStaticMarkup(element));
|
|
48
|
-
return {
|
|
49
|
-
mimeType: "text/markdown",
|
|
50
|
-
body: desc.policy?.pii?.length ? markdown.replace(/\[REDACTED\]/g, "[REDACTED]") : markdown
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
return engine;
|
|
55
|
-
}
|
|
56
|
-
export {
|
|
57
|
-
registerReactToMarkdownRenderer,
|
|
58
|
-
registerDefaultReactRenderer,
|
|
59
|
-
registerBasicValidation,
|
|
60
|
-
createDefaultTransformEngine
|
|
61
|
-
};
|
|
1
|
+
import{createRequire as G}from"node:module";var H=G(import.meta.url);import{createDefaultTransformEngine as O,htmlToMarkdown as I,registerBasicValidation as P}from"@contractspec/lib.presentation-runtime-core/transform-engine";import J from"react";export*from"@contractspec/lib.presentation-runtime-core/transform-engine";function U(x){return x.register({target:"react",async render(j){if(j.source.type==="component"){let q=j.source.props?j.source.props.getZod().safeParse({}).success?{}:void 0:void 0;return{kind:"react_component",componentKey:j.source.componentKey,props:q}}return{kind:"blocknotejs",docJson:j.source.docJson,blockConfig:j.source.blockConfig}}}),x}function W(x,j){return x.prependRegister({target:"markdown",async render(q){if(q.source.type!=="component")throw Error("React-to-markdown renderer only handles component presentations");let y=j[q.source.componentKey];if(!y)throw Error(`Component ${q.source.componentKey} not found in componentMap`);let{renderToStaticMarkup:A}=await import("react-dom/server"),F=J.createElement(y,q.source.props?{}:void 0),z=I(A(F));return{mimeType:"text/markdown",body:q.policy?.pii?.length?z.replace(/\[REDACTED\]/g,"[REDACTED]"):z}}}),x}export{W as registerReactToMarkdownRenderer,U as registerDefaultReactRenderer,P as registerBasicValidation,O as createDefaultTransformEngine};
|
package/dist/transform-engine.js
CHANGED
|
@@ -1,61 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
// src/transform-engine.ts
|
|
5
|
-
import {
|
|
6
|
-
createDefaultTransformEngine,
|
|
7
|
-
htmlToMarkdown,
|
|
8
|
-
registerBasicValidation
|
|
9
|
-
} from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
10
|
-
import React from "react";
|
|
11
|
-
|
|
12
|
-
export * from "@contractspec/lib.presentation-runtime-core/transform-engine";
|
|
13
|
-
function registerDefaultReactRenderer(engine) {
|
|
14
|
-
engine.register({
|
|
15
|
-
target: "react",
|
|
16
|
-
async render(desc) {
|
|
17
|
-
if (desc.source.type === "component") {
|
|
18
|
-
const props = desc.source.props ? desc.source.props.getZod().safeParse({}).success ? {} : undefined : undefined;
|
|
19
|
-
return {
|
|
20
|
-
kind: "react_component",
|
|
21
|
-
componentKey: desc.source.componentKey,
|
|
22
|
-
props
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
return {
|
|
26
|
-
kind: "blocknotejs",
|
|
27
|
-
docJson: desc.source.docJson,
|
|
28
|
-
blockConfig: desc.source.blockConfig
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
return engine;
|
|
33
|
-
}
|
|
34
|
-
function registerReactToMarkdownRenderer(engine, componentMap) {
|
|
35
|
-
engine.prependRegister({
|
|
36
|
-
target: "markdown",
|
|
37
|
-
async render(desc) {
|
|
38
|
-
if (desc.source.type !== "component") {
|
|
39
|
-
throw new Error("React-to-markdown renderer only handles component presentations");
|
|
40
|
-
}
|
|
41
|
-
const Component = componentMap[desc.source.componentKey];
|
|
42
|
-
if (!Component) {
|
|
43
|
-
throw new Error(`Component ${desc.source.componentKey} not found in componentMap`);
|
|
44
|
-
}
|
|
45
|
-
const { renderToStaticMarkup } = await import("react-dom/server");
|
|
46
|
-
const element = React.createElement(Component, desc.source.props ? {} : undefined);
|
|
47
|
-
const markdown = htmlToMarkdown(renderToStaticMarkup(element));
|
|
48
|
-
return {
|
|
49
|
-
mimeType: "text/markdown",
|
|
50
|
-
body: desc.policy?.pii?.length ? markdown.replace(/\[REDACTED\]/g, "[REDACTED]") : markdown
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
return engine;
|
|
55
|
-
}
|
|
56
|
-
export {
|
|
57
|
-
registerReactToMarkdownRenderer,
|
|
58
|
-
registerDefaultReactRenderer,
|
|
59
|
-
registerBasicValidation,
|
|
60
|
-
createDefaultTransformEngine
|
|
61
|
-
};
|
|
2
|
+
var G=import.meta.require;import{createDefaultTransformEngine as L,htmlToMarkdown as H,registerBasicValidation as N}from"@contractspec/lib.presentation-runtime-core/transform-engine";import I from"react";export*from"@contractspec/lib.presentation-runtime-core/transform-engine";function P(x){return x.register({target:"react",async render(j){if(j.source.type==="component"){let q=j.source.props?j.source.props.getZod().safeParse({}).success?{}:void 0:void 0;return{kind:"react_component",componentKey:j.source.componentKey,props:q}}return{kind:"blocknotejs",docJson:j.source.docJson,blockConfig:j.source.blockConfig}}}),x}function Q(x,j){return x.prependRegister({target:"markdown",async render(q){if(q.source.type!=="component")throw Error("React-to-markdown renderer only handles component presentations");let y=j[q.source.componentKey];if(!y)throw Error(`Component ${q.source.componentKey} not found in componentMap`);let{renderToStaticMarkup:A}=await import("react-dom/server"),F=I.createElement(y,q.source.props?{}:void 0),z=H(A(F));return{mimeType:"text/markdown",body:q.policy?.pii?.length?z.replace(/\[REDACTED\]/g,"[REDACTED]"):z}}}),x}export{Q as registerReactToMarkdownRenderer,P as registerDefaultReactRenderer,N as registerBasicValidation,L as createDefaultTransformEngine};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/lib.contracts-runtime-client-react",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.6",
|
|
4
4
|
"description": "React runtime adapters for ContractSpec contracts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"publish:pkg:canary": "bun publish:pkg --tag canary",
|
|
10
10
|
"clean": "rm -rf dist",
|
|
11
11
|
"lint": "bun run lint:fix",
|
|
12
|
-
"lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
|
|
13
|
-
"lint:check": "biome check .",
|
|
12
|
+
"lint:fix": "node ../../../scripts/biome.cjs check --write --unsafe --only=nursery/useSortedClasses . && node ../../../scripts/biome.cjs check --write .",
|
|
13
|
+
"lint:check": "node ../../../scripts/biome.cjs check .",
|
|
14
14
|
"build": "bun run build:bundle && bun run build:types",
|
|
15
15
|
"build:bundle": "contractspec-bun-build transpile",
|
|
16
16
|
"build:types": "contractspec-bun-build types",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"react-hook-form": "^7.72.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@contractspec/lib.contracts-spec": "5.0
|
|
34
|
-
"@contractspec/lib.schema": "3.7.
|
|
35
|
-
"@contractspec/lib.presentation-runtime-core": "3.9.
|
|
33
|
+
"@contractspec/lib.contracts-spec": "5.2.0",
|
|
34
|
+
"@contractspec/lib.schema": "3.7.14",
|
|
35
|
+
"@contractspec/lib.presentation-runtime-core": "3.9.6"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@contractspec/tool.typescript": "3.7.
|
|
38
|
+
"@contractspec/tool.typescript": "3.7.13",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
|
-
"@contractspec/tool.bun": "3.7.
|
|
40
|
+
"@contractspec/tool.bun": "3.7.14"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
43
43
|
"dist",
|