@strictly/react-form 0.0.15 → 0.0.17
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/.out/core/mobx/field_adapter_builder.d.ts +1 -1
- package/.out/core/mobx/form_model.d.ts +9 -6
- package/.out/core/mobx/form_model.js +77 -42
- package/.out/core/mobx/specs/form_model.tests.js +80 -20
- package/.out/core/mobx/types.d.ts +4 -4
- package/.out/core/props.d.ts +2 -0
- package/.out/index.d.ts +0 -1
- package/.out/index.js +0 -1
- package/.out/mantine/create_field_view.d.ts +20 -0
- package/.out/mantine/create_field_view.js +54 -0
- package/.out/mantine/create_list.js +3 -2
- package/.out/mantine/hooks.d.ts +4 -1
- package/.out/mantine/hooks.js +14 -2
- package/.out/mantine/specs/field_view_hooks.stories.d.ts +12 -0
- package/.out/mantine/specs/field_view_hooks.stories.js +61 -0
- package/.out/mantine/specs/field_view_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/field_view_hooks.tests.js +12 -0
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/core/mobx/field_adapter_builder.ts +2 -2
- package/core/mobx/form_model.ts +89 -47
- package/core/mobx/specs/form_model.tests.ts +131 -11
- package/core/mobx/types.ts +4 -4
- package/core/props.ts +4 -0
- package/dist/index.cjs +165 -89
- package/dist/index.d.cts +45 -40
- package/dist/index.d.ts +45 -40
- package/dist/index.js +162 -81
- package/index.ts +0 -1
- package/mantine/create_field_view.tsx +94 -0
- package/mantine/create_list.tsx +9 -2
- package/mantine/hooks.tsx +19 -2
- package/mantine/specs/__snapshots__/field_view_hooks.tests.tsx.snap +153 -0
- package/mantine/specs/field_view_hooks.stories.tsx +112 -0
- package/mantine/specs/field_view_hooks.tests.tsx +15 -0
- package/package.json +1 -1
- package/.out/mantine/field_view.d.ts +0 -18
- package/.out/mantine/field_view.js +0 -16
- package/mantine/field_view.tsx +0 -39
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Observer } from 'mobx-react';
|
|
3
|
+
import { useCallback, } from 'react';
|
|
4
|
+
import { Empty } from 'util/empty';
|
|
5
|
+
/**
|
|
6
|
+
* Displays current value and error of a field
|
|
7
|
+
*/
|
|
8
|
+
function FieldView({ valuePath, form, children, }) {
|
|
9
|
+
const onFocus = useCallback(() => {
|
|
10
|
+
var _a;
|
|
11
|
+
(_a = form.onFieldFocus) === null || _a === void 0 ? void 0 : _a.call(form, valuePath);
|
|
12
|
+
}, [
|
|
13
|
+
form,
|
|
14
|
+
valuePath,
|
|
15
|
+
]);
|
|
16
|
+
const onBlur = useCallback(() => {
|
|
17
|
+
var _a;
|
|
18
|
+
(_a = form.onFieldBlur) === null || _a === void 0 ? void 0 : _a.call(form, valuePath);
|
|
19
|
+
}, [
|
|
20
|
+
form,
|
|
21
|
+
valuePath,
|
|
22
|
+
]);
|
|
23
|
+
const onValueChange = useCallback((value) => {
|
|
24
|
+
var _a;
|
|
25
|
+
(_a = form.onFieldValueChange) === null || _a === void 0 ? void 0 : _a.call(form, valuePath, value);
|
|
26
|
+
}, [
|
|
27
|
+
form,
|
|
28
|
+
valuePath,
|
|
29
|
+
]);
|
|
30
|
+
const onSubmit = useCallback(() => {
|
|
31
|
+
var _a;
|
|
32
|
+
(_a = form.onFieldSubmit) === null || _a === void 0 ? void 0 : _a.call(form, valuePath);
|
|
33
|
+
}, [
|
|
34
|
+
form,
|
|
35
|
+
valuePath,
|
|
36
|
+
]);
|
|
37
|
+
return (_jsx(Observer, { children: () => {
|
|
38
|
+
const { value, error, } = form.fields[valuePath];
|
|
39
|
+
return children({
|
|
40
|
+
value,
|
|
41
|
+
error,
|
|
42
|
+
ErrorSink: Empty,
|
|
43
|
+
onFocus,
|
|
44
|
+
onBlur,
|
|
45
|
+
onValueChange,
|
|
46
|
+
onSubmit,
|
|
47
|
+
});
|
|
48
|
+
} }));
|
|
49
|
+
}
|
|
50
|
+
export function createFieldView(valuePath) {
|
|
51
|
+
return (props) => {
|
|
52
|
+
return (_jsx(FieldView, Object.assign({ form: this, valuePath: valuePath }, props)));
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, } from 'react';
|
|
2
3
|
import { createUnsafePartialObserverComponent } from 'util/partial';
|
|
3
4
|
export function createList(valuePath, List) {
|
|
4
5
|
const propSource = () => {
|
|
@@ -13,6 +14,6 @@ export function createList(valuePath, List) {
|
|
|
13
14
|
export function DefaultList({ values, listPath, children, }) {
|
|
14
15
|
return (_jsx(_Fragment, { children: values.map(function (value, index) {
|
|
15
16
|
const valuePath = `${listPath}.${index}`;
|
|
16
|
-
return children(valuePath, value, index);
|
|
17
|
+
return (_jsx(Fragment, { children: children(valuePath, value, index) }, valuePath));
|
|
17
18
|
}) }));
|
|
18
19
|
}
|
package/.out/mantine/hooks.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { type StringFieldsOfFields } from 'types/string_fields_of_fields';
|
|
|
11
11
|
import { type SubFormFields } from 'types/sub_form_fields';
|
|
12
12
|
import { type ValueTypeOfField } from 'types/value_type_of_field';
|
|
13
13
|
import { type SuppliedCheckboxProps } from './create_checkbox';
|
|
14
|
+
import { type FieldViewProps } from './create_field_view';
|
|
14
15
|
import { type FieldsView } from './create_fields_view';
|
|
15
16
|
import { DefaultList, type SuppliedListProps } from './create_list';
|
|
16
17
|
import { type SuppliedPillProps } from './create_pill';
|
|
@@ -22,7 +23,7 @@ import { type MantineFieldComponent, type MantineForm } from './types';
|
|
|
22
23
|
declare function SimpleSelect(props: SelectProps & {
|
|
23
24
|
onChange?: (value: string | null) => void;
|
|
24
25
|
}): import("react/jsx-runtime").JSX.Element;
|
|
25
|
-
export declare function useMantineFormFields<F extends Fields>({ onFieldValueChange, onFieldBlur, onFieldFocus, onFieldSubmit, fields, }: FieldsViewProps<F>): MantineFormImpl<F>;
|
|
26
|
+
export declare function useMantineFormFields<F extends Fields>({ onFieldValueChange, onFieldBlur, onFieldFocus, onFieldSubmit, fields, }: FieldsViewProps<F>): Omit<MantineFormImpl<F>, 'fields'>;
|
|
26
27
|
declare class MantineFormImpl<F extends Fields> implements MantineForm<F> {
|
|
27
28
|
private readonly textInputCache;
|
|
28
29
|
private readonly valueInputCache;
|
|
@@ -31,6 +32,7 @@ declare class MantineFormImpl<F extends Fields> implements MantineForm<F> {
|
|
|
31
32
|
private readonly radioCache;
|
|
32
33
|
private readonly pillCache;
|
|
33
34
|
private readonly listCache;
|
|
35
|
+
private readonly fieldViewCache;
|
|
34
36
|
private readonly fieldsViewCache;
|
|
35
37
|
private readonly formCache;
|
|
36
38
|
accessor fields: F;
|
|
@@ -52,6 +54,7 @@ declare class MantineFormImpl<F extends Fields> implements MantineForm<F> {
|
|
|
52
54
|
pill<K extends keyof AllFieldsOfFields<F>>(valuePath: K): MantineFieldComponent<SuppliedPillProps, PillProps, ErrorOfField<F[K]>>;
|
|
53
55
|
pill<K extends keyof AllFieldsOfFields<F>, P extends SuppliedPillProps>(valuePath: K, Pill: ComponentType<P>): MantineFieldComponent<SuppliedPillProps, P, ErrorOfField<F[K]>>;
|
|
54
56
|
list<K extends keyof ListFieldsOfFields<F>>(valuePath: K): MantineFieldComponent<SuppliedListProps<`${K}.${number}`>, ComponentProps<typeof DefaultList<ElementOfArray<F[K]['value']>, K>>, never>;
|
|
57
|
+
fieldView<K extends keyof AllFieldsOfFields<F>>(valuePath: K): ComponentType<FieldViewProps<F, K>>;
|
|
55
58
|
fieldsView<K extends keyof AllFieldsOfFields<F>, P extends FieldsViewProps<Fields> = FieldsViewProps<SubFormFields<F, K>>>(valuePath: K, FieldsView: ComponentType<P>): FieldsView<K, MantineFieldComponent<FieldsViewProps<P['fields']>, P, never>>;
|
|
56
59
|
form<K extends keyof AllFieldsOfFields<F>, P extends FormProps<ValueTypeOfField<F[K]>> = FormProps<ValueTypeOfField<F[K]>>>(valuePath: K, Form: ComponentType<P>): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P, never>;
|
|
57
60
|
}
|
package/.out/mantine/hooks.js
CHANGED
|
@@ -49,6 +49,7 @@ import { Cache, } from '@strictly/base';
|
|
|
49
49
|
import { observable, runInAction, } from 'mobx';
|
|
50
50
|
import { useEffect, useMemo, } from 'react';
|
|
51
51
|
import { createCheckbox, } from './create_checkbox';
|
|
52
|
+
import { createFieldView, } from './create_field_view';
|
|
52
53
|
import { createFieldsView, } from './create_fields_view';
|
|
53
54
|
import { createForm } from './create_form';
|
|
54
55
|
import { createList, DefaultList, } from './create_list';
|
|
@@ -60,11 +61,13 @@ import { createValueInput, } from './create_value_input';
|
|
|
60
61
|
function SimpleSelect(props) {
|
|
61
62
|
return _jsx(Select, Object.assign({}, props));
|
|
62
63
|
}
|
|
63
|
-
export function useMantineFormFields({ onFieldValueChange, onFieldBlur, onFieldFocus, onFieldSubmit, fields,
|
|
64
|
+
export function useMantineFormFields({ onFieldValueChange, onFieldBlur, onFieldFocus, onFieldSubmit, fields,
|
|
65
|
+
// should use FieldView rather than observing fields directly from here
|
|
66
|
+
}) {
|
|
64
67
|
const form = useMemo(function () {
|
|
65
68
|
return new MantineFormImpl(fields);
|
|
66
69
|
},
|
|
67
|
-
// handled separately below
|
|
70
|
+
// fields handled separately below
|
|
68
71
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
69
72
|
[]);
|
|
70
73
|
useEffect(function () {
|
|
@@ -153,6 +156,12 @@ let MantineFormImpl = (() => {
|
|
|
153
156
|
writable: true,
|
|
154
157
|
value: new Cache(createList.bind(this))
|
|
155
158
|
});
|
|
159
|
+
Object.defineProperty(this, "fieldViewCache", {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
configurable: true,
|
|
162
|
+
writable: true,
|
|
163
|
+
value: new Cache(createFieldView.bind(this))
|
|
164
|
+
});
|
|
156
165
|
Object.defineProperty(this, "fieldsViewCache", {
|
|
157
166
|
enumerable: true,
|
|
158
167
|
configurable: true,
|
|
@@ -248,6 +257,9 @@ let MantineFormImpl = (() => {
|
|
|
248
257
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
249
258
|
return this.listCache.retrieveOrCreate(valuePath, DefaultList);
|
|
250
259
|
}
|
|
260
|
+
fieldView(valuePath) {
|
|
261
|
+
return this.fieldViewCache.retrieveOrCreate(valuePath);
|
|
262
|
+
}
|
|
251
263
|
fieldsView(valuePath, FieldsView) {
|
|
252
264
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
253
265
|
return this.fieldsViewCache.retrieveOrCreate(valuePath,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Meta, type StoryObj } from '@storybook/react';
|
|
2
|
+
import { type FieldsViewProps } from 'core/props';
|
|
3
|
+
import { type Field } from 'types/field';
|
|
4
|
+
declare function Component(props: FieldsViewProps<{
|
|
5
|
+
$: Field<string, string>;
|
|
6
|
+
}>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare const meta: Meta<typeof Component>;
|
|
8
|
+
export default meta;
|
|
9
|
+
type Story = StoryObj<typeof Component>;
|
|
10
|
+
export declare const Empty: Story;
|
|
11
|
+
export declare const Populated: Story;
|
|
12
|
+
export declare const Error: Story;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Group, TextInput, } from '@mantine/core';
|
|
3
|
+
import { action } from '@storybook/addon-actions';
|
|
4
|
+
import { useMantineFormFields } from 'mantine/hooks';
|
|
5
|
+
import { useCallback, } from 'react';
|
|
6
|
+
function Component(props) {
|
|
7
|
+
const form = useMantineFormFields(props);
|
|
8
|
+
const FieldView = form.fieldView('$');
|
|
9
|
+
return (_jsx(FieldView, { children: ({ error, value, onBlur, onFocus, onSubmit, onValueChange, }) => {
|
|
10
|
+
// this *is* a component eslint
|
|
11
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
12
|
+
const onChange = useCallback(({ target: { value } }) => {
|
|
13
|
+
onValueChange(value);
|
|
14
|
+
}, [onValueChange]);
|
|
15
|
+
return (_jsxs(Group, { align: 'start', flex: 1, children: [_jsx(TextInput, { error: error, flex: 1, onBlur: onBlur, onChange: onChange, onFocus: onFocus, value: value }), _jsx(Button, { onClick: onSubmit, children: "Submit Field" })] }));
|
|
16
|
+
} }));
|
|
17
|
+
}
|
|
18
|
+
const meta = {
|
|
19
|
+
component: Component,
|
|
20
|
+
args: {
|
|
21
|
+
onFieldBlur: action('onFieldBlur'),
|
|
22
|
+
onFieldFocus: action('onFieldFocus'),
|
|
23
|
+
onFieldSubmit: action('onFieldSubmit'),
|
|
24
|
+
onFieldValueChange: action('onFieldValueChange'),
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
export const Empty = {
|
|
29
|
+
args: {
|
|
30
|
+
fields: {
|
|
31
|
+
$: {
|
|
32
|
+
readonly: false,
|
|
33
|
+
required: false,
|
|
34
|
+
value: '',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export const Populated = {
|
|
40
|
+
args: {
|
|
41
|
+
fields: {
|
|
42
|
+
$: {
|
|
43
|
+
readonly: false,
|
|
44
|
+
required: false,
|
|
45
|
+
value: 'hello',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
export const Error = {
|
|
51
|
+
args: {
|
|
52
|
+
fields: {
|
|
53
|
+
$: {
|
|
54
|
+
readonly: false,
|
|
55
|
+
required: false,
|
|
56
|
+
value: 'hello',
|
|
57
|
+
error: 'no hellos allowed',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { composeStories } from '@storybook/react';
|
|
3
|
+
import { toArray } from '@strictly/base';
|
|
4
|
+
import { render, } from '@testing-library/react';
|
|
5
|
+
import * as stories from './field_view_hooks.stories';
|
|
6
|
+
const composedStories = composeStories(stories);
|
|
7
|
+
describe('field view hooks', function () {
|
|
8
|
+
it.each(toArray(composedStories))('renders %s', function (_name, Story) {
|
|
9
|
+
const wrapper = render(_jsx(Story, {}));
|
|
10
|
+
expect(wrapper.container).toMatchSnapshot();
|
|
11
|
+
});
|
|
12
|
+
});
|