@reformer/renderer-json 8.0.0 → 9.0.0-beta.2

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/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @reformer/renderer-json
2
+
3
+ Render [`@reformer/core`](https://www.npmjs.com/package/@reformer/core) forms from a **JSON schema**.
4
+ Field bindings, components and data sources are expressed as string operators
5
+ (`$model(...)`, `$component(...)`, `$dataSource(...)`), so an entire form can be described as data and
6
+ rendered through a component registry — no per-field React code.
7
+
8
+ ## Documentation
9
+
10
+ Full documentation is available at [https://alexandrbukhtatyy.github.io/ReFormer/](https://alexandrbukhtatyy.github.io/ReFormer/)
11
+
12
+ ## Features
13
+
14
+ - Describe forms declaratively as JSON (`JsonFormSchema`)
15
+ - String operators bind schema leaves to a reactive `FormModel` and to registered components
16
+ - Component registry (`defineRegistry`) maps operator names to your React components
17
+ - Optional schema validation against a meta-schema (ajv, loaded dynamically — dev only)
18
+ - TypeScript support, tree-shakable exports
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @reformer/renderer-json @reformer/core @reformer/renderer-react
24
+ ```
25
+
26
+ `@reformer/ui-kit` is an optional peer — use it (or your own components) to populate the registry.
27
+
28
+ ## Quick Start
29
+
30
+ ```tsx
31
+ import { useMemo } from 'react';
32
+ import { createModel } from '@reformer/core';
33
+ import { Input, Box, FormField } from '@reformer/ui-kit';
34
+ import {
35
+ JsonFormRenderer,
36
+ JsonRendererProvider,
37
+ defineRegistry,
38
+ FIELD_WRAPPER,
39
+ type JsonFormSchema,
40
+ } from '@reformer/renderer-json';
41
+
42
+ // Bindings are string operators: '$model(...)', '$component(...)', '$dataSource(...)'.
43
+ const schema: JsonFormSchema = {
44
+ version: '1.0',
45
+ root: {
46
+ component: '$component(Box)',
47
+ children: [
48
+ {
49
+ value: '$model(email)',
50
+ component: '$component(Input)',
51
+ componentProps: { label: 'Email' },
52
+ },
53
+ ],
54
+ },
55
+ };
56
+
57
+ type MyForm = { email: string };
58
+
59
+ export function MyFormPage() {
60
+ // M1: the model is the source of truth; schema leaves bind to its signals.
61
+ const model = useMemo(() => createModel<MyForm>({ email: '' }), []);
62
+ const registry = useMemo(
63
+ () =>
64
+ defineRegistry((reg) => {
65
+ reg.component('Input', Input);
66
+ reg.component('Box', Box);
67
+ reg.component(FIELD_WRAPPER, FormField); // system field wrapper
68
+ }),
69
+ []
70
+ );
71
+
72
+ // The model is provided through the provider (settings.model), not as a renderer prop.
73
+ return (
74
+ <JsonRendererProvider settings={{ registry, model }}>
75
+ <JsonFormRenderer<MyForm> schema={schema} validate={import.meta.env.DEV} />
76
+ </JsonRendererProvider>
77
+ );
78
+ }
79
+ ```
80
+
81
+ `JsonFormRenderer` accepts only `{ schema, renderBehavior?, onSchemaReady?, validate? }`. The
82
+ `FormModel` is supplied via `JsonRendererProvider` settings (`model`); schema leaves are bound to its
83
+ signals by the built-in converter.
84
+
85
+ ## License
86
+
87
+ MIT
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,51 @@
1
+ const s = /^\$(model|component|dataSource|fn|locale)\((.+)\)$/;
2
+ function o(e) {
3
+ if (typeof e != "string") return null;
4
+ const t = s.exec(e);
5
+ return t ? { op: t[1], arg: t[2] } : null;
6
+ }
7
+ const $ = (e) => o(e)?.op === "model", g = (e) => o(e)?.op === "component", b = (e) => o(e)?.op === "dataSource", S = (e) => o(e)?.op === "fn", O = (e) => o(e)?.op === "locale", p = "http://json-schema.org/draft-07/schema#", c = "https://reformer.dev/schemas/form-schema.schema.json", m = "ReFormer JSON form schema (M1, string-operator DSL)", d = "Base meta-schema: validates node structure + operator string syntax ($model/$component/$dataSource). Component-name enum is tightened per-app via buildFormSchemaMetaSchema; $dataSource names and $model paths are checked outside this schema.", l = "object", f = ["root"], u = !1, h = { $schema: { type: "string" }, version: { type: "string" }, root: { $ref: "#/definitions/node" } }, y = { modelOp: { type: "string", pattern: "^\\$model\\(.+\\)$", description: 'Model binding: "$model(path)" — path resolved at runtime (not validated here).' }, componentOp: { type: "string", pattern: "^\\$component\\(.+\\)$", description: 'Registry component: "$component(Name)". Name is tightened to a registry enum by buildFormSchemaMetaSchema.' }, node: { $comment: "Discriminated by which operator key is present (array→value→component), mirroring the isArrayNode/isFieldNode/isContainerNode runtime guards. Using oneOf here made ajv (allErrors) report failures against all three branches for any single mistake, burying the real cause; if/then/else surfaces only the relevant branch's errors.", if: { type: "object", required: ["array"] }, then: { $ref: "#/definitions/arrayNode" }, else: { if: { type: "object", required: ["value"] }, then: { $ref: "#/definitions/fieldNode" }, else: { $ref: "#/definitions/containerNode" } } }, fieldNode: { type: "object", required: ["value"], additionalProperties: !1, properties: { selector: { type: "string" }, value: { $ref: "#/definitions/modelOp" }, component: { $ref: "#/definitions/componentOp" }, componentProps: { type: "object" }, wrapper: { $ref: "#/definitions/node" } } }, arrayNode: { type: "object", required: ["array", "item"], additionalProperties: !1, properties: { selector: { type: "string" }, array: { $ref: "#/definitions/modelOp" }, item: { type: "object", required: ["$template"], additionalProperties: !1, properties: { $template: { $ref: "#/definitions/node" } } }, initialValue: { type: "object" }, componentProps: { type: "object" } } }, containerNode: { type: "object", required: ["component"], additionalProperties: !1, properties: { selector: { type: "string" }, component: { $ref: "#/definitions/componentOp" }, componentProps: { type: "object" }, children: { type: "array", items: { $ref: "#/definitions/node" } } } } }, a = {
8
+ $schema: p,
9
+ $id: c,
10
+ title: m,
11
+ description: d,
12
+ type: l,
13
+ required: f,
14
+ additionalProperties: u,
15
+ properties: h,
16
+ definitions: y
17
+ }, N = a;
18
+ function j(e) {
19
+ return e.names().filter((t) => e.get(t)?.type === "component");
20
+ }
21
+ function v(e) {
22
+ return e.names().filter((t) => e.get(t)?.type === "dataSource");
23
+ }
24
+ function P(e) {
25
+ return e.names().filter((t) => e.get(t)?.type === "fn");
26
+ }
27
+ function q(e) {
28
+ return e.getLocale?.()?.keys;
29
+ }
30
+ function F(e) {
31
+ const t = JSON.parse(JSON.stringify(a)), n = e?.componentNames;
32
+ if (n && n.length > 0) {
33
+ const r = t.definitions.componentOp;
34
+ delete r.pattern, r.enum = n.map((i) => `$component(${i})`);
35
+ }
36
+ return t;
37
+ }
38
+ export {
39
+ g as a,
40
+ b,
41
+ S as c,
42
+ O as d,
43
+ F as e,
44
+ N as f,
45
+ j as g,
46
+ v as h,
47
+ $ as i,
48
+ P as j,
49
+ q as k,
50
+ o as p
51
+ };
package/dist/index.d.ts CHANGED
@@ -11,12 +11,19 @@ export { SchemaErrorPanel } from './components/schema-error-panel';
11
11
  export type { SchemaErrorPanelProps } from './components/schema-error-panel';
12
12
  export type { JsonFormSchema, JsonNode, JsonFieldNode, JsonArrayNode, JsonContainerNode, } from './types/json-schema';
13
13
  export { isFieldNode, isArrayNode, isContainerNode } from './types/json-schema';
14
- export { parseOperator, isModelOp, isComponentOp, isDataSourceOp } from './operators';
15
- export type { ModelOp, ComponentOp, DataSourceOp, JsonOperator, ParsedOperator } from './operators';
14
+ export { parseOperator, isModelOp, isComponentOp, isDataSourceOp, isFnOp, isLocaleOp, } from './operators';
15
+ export type { ModelOp, ComponentOp, DataSourceOp, FnOp, LocaleOp, JsonOperator, ParsedOperator, } from './operators';
16
16
  export { defineRegistry } from './registry/component-registry';
17
- export { FIELD_WRAPPER } from './registry/constants';
17
+ export { FIELD_WRAPPER, LOCALE_SERVICE } from './registry/constants';
18
18
  export type { ComponentRegistry, ComponentMetadata, RegistryBuilder } from './registry/types';
19
+ export { createLocaleResolver, createLocaleService, defaultLocaleResolver, } from './locale/locale-service';
20
+ export type { LocaleResolver, LocaleService, LocaleParams } from './locale/locale-service';
21
+ export { LocaleProvider, useLocale } from './locale/locale-context';
22
+ export type { LocaleProviderProps } from './locale/locale-context';
23
+ export { I18n } from './locale/i18n';
24
+ export type { I18nProps } from './locale/i18n';
25
+ export { useSignalValues, unwrapSignalValues } from './locale/use-signal-value';
19
26
  export { JsonRendererProvider, useJsonRendererSettings } from './context/json-renderer-context';
20
27
  export type { JsonRendererSettings, JsonRendererProviderProps, } from './context/json-renderer-context';
21
28
  export { createRenderSchemaFromJsonM1, convertJsonToM1Tree, } from './converter/json-to-render-schema';
22
- export { formSchemaMetaSchema, buildFormSchemaMetaSchema, getComponentNames, getDataSourceNames, } from './schema';
29
+ export { formSchemaMetaSchema, buildFormSchemaMetaSchema, getComponentNames, getDataSourceNames, getFnNames, getLocaleKeys, } from './schema';