@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.
Files changed (40) hide show
  1. package/.out/core/mobx/field_adapter_builder.d.ts +1 -1
  2. package/.out/core/mobx/form_model.d.ts +9 -6
  3. package/.out/core/mobx/form_model.js +77 -42
  4. package/.out/core/mobx/specs/form_model.tests.js +80 -20
  5. package/.out/core/mobx/types.d.ts +4 -4
  6. package/.out/core/props.d.ts +2 -0
  7. package/.out/index.d.ts +0 -1
  8. package/.out/index.js +0 -1
  9. package/.out/mantine/create_field_view.d.ts +20 -0
  10. package/.out/mantine/create_field_view.js +54 -0
  11. package/.out/mantine/create_list.js +3 -2
  12. package/.out/mantine/hooks.d.ts +4 -1
  13. package/.out/mantine/hooks.js +14 -2
  14. package/.out/mantine/specs/field_view_hooks.stories.d.ts +12 -0
  15. package/.out/mantine/specs/field_view_hooks.stories.js +61 -0
  16. package/.out/mantine/specs/field_view_hooks.tests.d.ts +1 -0
  17. package/.out/mantine/specs/field_view_hooks.tests.js +12 -0
  18. package/.out/tsconfig.tsbuildinfo +1 -1
  19. package/.turbo/turbo-build.log +8 -8
  20. package/.turbo/turbo-check-types.log +1 -1
  21. package/core/mobx/field_adapter_builder.ts +2 -2
  22. package/core/mobx/form_model.ts +89 -47
  23. package/core/mobx/specs/form_model.tests.ts +131 -11
  24. package/core/mobx/types.ts +4 -4
  25. package/core/props.ts +4 -0
  26. package/dist/index.cjs +165 -89
  27. package/dist/index.d.cts +45 -40
  28. package/dist/index.d.ts +45 -40
  29. package/dist/index.js +162 -81
  30. package/index.ts +0 -1
  31. package/mantine/create_field_view.tsx +94 -0
  32. package/mantine/create_list.tsx +9 -2
  33. package/mantine/hooks.tsx +19 -2
  34. package/mantine/specs/__snapshots__/field_view_hooks.tests.tsx.snap +153 -0
  35. package/mantine/specs/field_view_hooks.stories.tsx +112 -0
  36. package/mantine/specs/field_view_hooks.tests.tsx +15 -0
  37. package/package.json +1 -1
  38. package/.out/mantine/field_view.d.ts +0 -18
  39. package/.out/mantine/field_view.js +0 -16
  40. 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 { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
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
  }
@@ -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
  }
@@ -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
+ });