@playfast/reform-forms-react 0.0.7
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 +53 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# `@playfast/forms-react`
|
|
4
|
+
|
|
5
|
+
**Typed JSX mapping for [`@playfast/forms`](https://www.npmjs.com/package/@playfast/forms) — turn a form view into scoped field/array/variant helpers, no bundled widgets.**
|
|
6
|
+
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
`FormUi.make` wires a [`@playfast/forms`](https://www.npmjs.com/package/@playfast/forms) view (provided in a
|
|
12
|
+
[`@playfast/reform`](https://www.npmjs.com/package/@playfast/reform) contract's `form` prop) to your own React
|
|
13
|
+
components. It owns no state and ships no DOM widgets — it maps the typed schema to JSX so your layout cannot
|
|
14
|
+
drift from it.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { FormUi } from '@playfast/reform-forms-react'
|
|
18
|
+
|
|
19
|
+
export const CheckoutUi = FormUi.make(CheckoutContract, CheckoutForm, ({ field, array, variant, form }) => (
|
|
20
|
+
<Screen>
|
|
21
|
+
{field('email').as(EmailInput, { label: 'Email' })}
|
|
22
|
+
{array('items', ({ items, append }) => (
|
|
23
|
+
<Stack>
|
|
24
|
+
{items.map((item) => (
|
|
25
|
+
<Row key={item.key}>
|
|
26
|
+
{item.field('name').as(TextInput)}
|
|
27
|
+
<IconButton onPress={item.remove} />
|
|
28
|
+
</Row>
|
|
29
|
+
))}
|
|
30
|
+
<Button onPress={() => append()}>Add</Button>
|
|
31
|
+
</Stack>
|
|
32
|
+
))}
|
|
33
|
+
{variant('payment', {
|
|
34
|
+
Card: ({ field }) => field('cardNumber').as(CardNumberInput),
|
|
35
|
+
Paypal: ({ field }) => field('email').as(EmailInput),
|
|
36
|
+
})}
|
|
37
|
+
<Button disabled={!form.canSubmit} onPress={form.submit}>Submit</Button>
|
|
38
|
+
</Screen>
|
|
39
|
+
))
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The render callback receives scoped helpers (`field` / `array` / `variant`), the underlying `form` view, and the
|
|
43
|
+
contract `props`. `field(path).as(Component, props?)` returns a `ReactNode` whose component gets a typed
|
|
44
|
+
`field: FieldBinding<A>` prop. `array` and `variant` scopes expose the same helpers relative to that scope.
|
|
45
|
+
|
|
46
|
+
Full API: [playbook/api.doc.md](./playbook/api.doc.md). Pairs with core
|
|
47
|
+
[`@playfast/reform`](https://www.npmjs.com/package/@playfast/reform), form state
|
|
48
|
+
[`@playfast/forms`](https://www.npmjs.com/package/@playfast/forms), and the React host
|
|
49
|
+
[`@playfast/react`](https://www.npmjs.com/package/@playfast/react).
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
import { type UiClass, type UiContract, type ViewImpl } from '@playfast/reform';
|
|
3
|
+
import type { ArrayItem, ArrayPath, FieldBinding, FieldPath, PathValue, Values, VariantBody, VariantPath, VariantTag, VariantValue, View, AnyForm } from '@playfast/reform-forms';
|
|
4
|
+
export type FieldComponent<A, P extends object = {}> = ComponentType<{
|
|
5
|
+
readonly field: FieldBinding<A>;
|
|
6
|
+
} & P>;
|
|
7
|
+
export interface FieldHandle<A> {
|
|
8
|
+
as(component: FieldComponent<A>): ReactNode;
|
|
9
|
+
as<P extends object>(component: FieldComponent<A, P>, props: P): ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface ArrayItemScope<Item> extends ScopeHelpers<Item> {
|
|
12
|
+
readonly key: string;
|
|
13
|
+
readonly index: number;
|
|
14
|
+
readonly value: Item;
|
|
15
|
+
readonly remove: () => void;
|
|
16
|
+
readonly move: (to: number) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface ArrayRenderArgs<Item> {
|
|
19
|
+
readonly items: ReadonlyArray<ArrayItemScope<Item>>;
|
|
20
|
+
readonly append: (value?: Item) => void;
|
|
21
|
+
readonly remove: (index: number) => void;
|
|
22
|
+
readonly move: (from: number, to: number) => void;
|
|
23
|
+
readonly swap: (a: number, b: number) => void;
|
|
24
|
+
}
|
|
25
|
+
type VariantCases<V> = {
|
|
26
|
+
readonly [Tag in VariantTag<V>]: (scope: ScopeHelpers<VariantBody<V, Tag>>) => ReactNode;
|
|
27
|
+
};
|
|
28
|
+
export interface ScopeHelpers<ScopeValues> {
|
|
29
|
+
readonly field: <P extends FieldPath<ScopeValues>>(path: P) => FieldHandle<PathValue<ScopeValues, P>>;
|
|
30
|
+
readonly array: <P extends ArrayPath<ScopeValues>>(path: P, render: (args: ArrayRenderArgs<ArrayItem<ScopeValues, P>>) => ReactNode) => ReactNode;
|
|
31
|
+
readonly variant: <P extends VariantPath<ScopeValues>>(path: P, cases: VariantCases<VariantValue<ScopeValues, P>>) => ReactNode;
|
|
32
|
+
}
|
|
33
|
+
export interface RootHelpers<F extends AnyForm> extends ScopeHelpers<Values<F>> {
|
|
34
|
+
readonly form: View<F>;
|
|
35
|
+
}
|
|
36
|
+
type ContractWithForm<F extends AnyForm> = UiContract & {
|
|
37
|
+
readonly props: {
|
|
38
|
+
readonly form: View<F>;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare const make: <F extends AnyForm, C extends ContractWithForm<F>>(contract: UiClass<C>, _form: F, render: (helpers: RootHelpers<F> & {
|
|
42
|
+
readonly props: C["props"];
|
|
43
|
+
}, slots: Parameters<ViewImpl<C>>[1], events: Parameters<ViewImpl<C>>[2]) => ReactNode) => ViewImpl<C>;
|
|
44
|
+
export declare const FormUi: {
|
|
45
|
+
readonly make: typeof make;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { Ui } from '@playfast/reform';
|
|
3
|
+
import { joinPath } from '@playfast/reform-forms';
|
|
4
|
+
const makeFieldHandle = (field) => ({
|
|
5
|
+
as: (component, props) => createElement(component, { ...(props ?? {}), field }),
|
|
6
|
+
});
|
|
7
|
+
const makeScope = (form, prefix) => {
|
|
8
|
+
const full = (path) => joinPath(prefix, path);
|
|
9
|
+
return {
|
|
10
|
+
field: (path) => makeFieldHandle(form.field(full(path))),
|
|
11
|
+
array: (path, render) => {
|
|
12
|
+
const binding = form.array(full(path));
|
|
13
|
+
return render({
|
|
14
|
+
append: binding.append,
|
|
15
|
+
remove: binding.remove,
|
|
16
|
+
move: binding.move,
|
|
17
|
+
swap: binding.swap,
|
|
18
|
+
items: binding.items.map((item) => ({
|
|
19
|
+
...makeScope(form, `${binding.path}[${item.index}]`),
|
|
20
|
+
key: item.key,
|
|
21
|
+
index: item.index,
|
|
22
|
+
value: item.value,
|
|
23
|
+
remove: item.remove,
|
|
24
|
+
move: item.move,
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
variant: (path, cases) => {
|
|
29
|
+
const variantPath = full(path);
|
|
30
|
+
const value = form.variantValue(variantPath);
|
|
31
|
+
if (value === null || typeof value !== 'object' || !('_tag' in value))
|
|
32
|
+
return null;
|
|
33
|
+
const tag = String(value._tag);
|
|
34
|
+
const render = cases[tag];
|
|
35
|
+
return render === undefined ? null : render(makeScope(form, variantPath));
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export const make = (contract, _form, render) => Ui.make(contract, (props, slots, events) => render({
|
|
40
|
+
...makeScope(props.form, ''),
|
|
41
|
+
form: props.form,
|
|
42
|
+
props,
|
|
43
|
+
}, slots, events));
|
|
44
|
+
export const FormUi = { make };
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@playfast/reform-forms-react",
|
|
3
|
+
"playbook": "./playbook",
|
|
4
|
+
"version": "0.0.7",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "React bindings for @playfast/forms — render a typed reform form View with scoped field/array/variant helpers.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"reform",
|
|
9
|
+
"effect",
|
|
10
|
+
"forms",
|
|
11
|
+
"react",
|
|
12
|
+
"ui"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/playfast/reform.git",
|
|
18
|
+
"directory": "packages/forms-react"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/playfast/reform/issues"
|
|
22
|
+
},
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"exports": {
|
|
25
|
+
"./package.json": "./package.json",
|
|
26
|
+
".": "./src/index.tsx",
|
|
27
|
+
"./*": "./src/*.tsx"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"clean": "rm -rf dist .tsbuildinfo",
|
|
35
|
+
"check": "tsc --noEmit",
|
|
36
|
+
"build": "tsc -p tsconfig.build.json",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"coverage": "vitest run --coverage",
|
|
40
|
+
"lint": "oxlint src",
|
|
41
|
+
"lint:fix": "oxlint --fix src"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@playfast/reform-forms": "*",
|
|
45
|
+
"effect": "*",
|
|
46
|
+
"react": "^19.0.0",
|
|
47
|
+
"@playfast/reform": "*"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
}
|
|
52
|
+
}
|