@strictly/react-form 0.0.1
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/.eslintrc.cjs +26 -0
- package/.out/.storybook/main.d.ts +3 -0
- package/.out/.storybook/main.js +32 -0
- package/.out/.storybook/preview.d.ts +4 -0
- package/.out/.storybook/preview.js +20 -0
- package/.out/.vitest/install_deterministic_random.d.ts +2 -0
- package/.out/.vitest/install_deterministic_random.js +15 -0
- package/.out/.vitest/install_storybook_preview.d.ts +1 -0
- package/.out/.vitest/install_storybook_preview.js +7 -0
- package/.out/.vitest/match_media.d.ts +1 -0
- package/.out/.vitest/match_media.js +5 -0
- package/.out/.vitest/resize_observer.d.ts +1 -0
- package/.out/.vitest/resize_observer.js +4 -0
- package/.out/core/mobx/field_adapter.d.ts +9 -0
- package/.out/core/mobx/field_adapter.js +1 -0
- package/.out/core/mobx/field_adapter_builder.d.ts +22 -0
- package/.out/core/mobx/field_adapter_builder.js +56 -0
- package/.out/core/mobx/flattened_adapters_of_fields.d.ts +9 -0
- package/.out/core/mobx/flattened_adapters_of_fields.js +1 -0
- package/.out/core/mobx/flattened_list_type_defs_of.d.ts +8 -0
- package/.out/core/mobx/flattened_list_type_defs_of.js +1 -0
- package/.out/core/mobx/form_presenter.d.ts +61 -0
- package/.out/core/mobx/form_presenter.js +425 -0
- package/.out/core/mobx/specs/flattened_adapters_of_fields.tests.d.ts +1 -0
- package/.out/core/mobx/specs/flattened_adapters_of_fields.tests.js +13 -0
- package/.out/core/mobx/specs/flattened_list_type_defs_of.tests.d.ts +1 -0
- package/.out/core/mobx/specs/flattened_list_type_defs_of.tests.js +16 -0
- package/.out/core/mobx/specs/form_presenter.tests.d.ts +1 -0
- package/.out/core/mobx/specs/form_presenter.tests.js +697 -0
- package/.out/core/mobx/types.d.ts +19 -0
- package/.out/core/mobx/types.js +1 -0
- package/.out/core/props.d.ts +12 -0
- package/.out/core/props.js +1 -0
- package/.out/field_converters/chain_field_converter.d.ts +3 -0
- package/.out/field_converters/chain_field_converter.js +46 -0
- package/.out/field_converters/identity_converter.d.ts +3 -0
- package/.out/field_converters/identity_converter.js +14 -0
- package/.out/field_converters/integer_to_string_converter.d.ts +7 -0
- package/.out/field_converters/integer_to_string_converter.js +26 -0
- package/.out/field_converters/list_converter.d.ts +2 -0
- package/.out/field_converters/list_converter.js +8 -0
- package/.out/field_converters/maybe_identity_converter.d.ts +8 -0
- package/.out/field_converters/maybe_identity_converter.js +15 -0
- package/.out/field_converters/nullable_to_boolean_converter.d.ts +11 -0
- package/.out/field_converters/nullable_to_boolean_converter.js +31 -0
- package/.out/field_converters/select_value_type_converter.d.ts +23 -0
- package/.out/field_converters/select_value_type_converter.js +60 -0
- package/.out/field_converters/trimming_string_converter.d.ts +6 -0
- package/.out/field_converters/trimming_string_converter.js +14 -0
- package/.out/field_converters/validating_converter.d.ts +3 -0
- package/.out/field_converters/validating_converter.js +21 -0
- package/.out/field_validators/minimum_string_length_field_validator.d.ts +2 -0
- package/.out/field_validators/minimum_string_length_field_validator.js +8 -0
- package/.out/field_value_factories/prototyping_field_value_factory.d.ts +2 -0
- package/.out/field_value_factories/prototyping_field_value_factory.js +5 -0
- package/.out/index.d.ts +16 -0
- package/.out/index.js +16 -0
- package/.out/mantine/create_checkbox.d.ts +9 -0
- package/.out/mantine/create_checkbox.js +37 -0
- package/.out/mantine/create_list.d.ts +15 -0
- package/.out/mantine/create_list.js +16 -0
- package/.out/mantine/create_pill.d.ts +7 -0
- package/.out/mantine/create_pill.js +15 -0
- package/.out/mantine/create_radio.d.ts +8 -0
- package/.out/mantine/create_radio.js +10 -0
- package/.out/mantine/create_radio_group.d.ts +9 -0
- package/.out/mantine/create_radio_group.js +34 -0
- package/.out/mantine/create_text_input.d.ts +19 -0
- package/.out/mantine/create_text_input.js +38 -0
- package/.out/mantine/create_value_input.d.ts +17 -0
- package/.out/mantine/create_value_input.js +38 -0
- package/.out/mantine/hooks.d.ts +56 -0
- package/.out/mantine/hooks.js +135 -0
- package/.out/mantine/specs/checkbox_constants.d.ts +1 -0
- package/.out/mantine/specs/checkbox_constants.js +1 -0
- package/.out/mantine/specs/checkbox_hooks.stories.d.ts +13 -0
- package/.out/mantine/specs/checkbox_hooks.stories.js +63 -0
- package/.out/mantine/specs/checkbox_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/checkbox_hooks.tests.js +74 -0
- package/.out/mantine/specs/list_hooks.stories.d.ts +11 -0
- package/.out/mantine/specs/list_hooks.stories.js +48 -0
- package/.out/mantine/specs/list_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/list_hooks.tests.js +12 -0
- package/.out/mantine/specs/radio_group_constants.d.ts +4 -0
- package/.out/mantine/specs/radio_group_constants.js +11 -0
- package/.out/mantine/specs/radio_group_hooks.stories.d.ts +14 -0
- package/.out/mantine/specs/radio_group_hooks.stories.js +68 -0
- package/.out/mantine/specs/radio_group_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/radio_group_hooks.tests.js +62 -0
- package/.out/mantine/specs/select_hooks.stories.d.ts +12 -0
- package/.out/mantine/specs/select_hooks.stories.js +57 -0
- package/.out/mantine/specs/select_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/select_hooks.tests.js +12 -0
- package/.out/mantine/specs/select_hooks_constant.d.ts +1 -0
- package/.out/mantine/specs/select_hooks_constant.js +1 -0
- package/.out/mantine/specs/text_input_constants.d.ts +1 -0
- package/.out/mantine/specs/text_input_constants.js +1 -0
- package/.out/mantine/specs/text_input_hooks.stories.d.ts +21 -0
- package/.out/mantine/specs/text_input_hooks.stories.js +88 -0
- package/.out/mantine/specs/text_input_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/text_input_hooks.tests.js +79 -0
- package/.out/mantine/specs/value_input_constants.d.ts +2 -0
- package/.out/mantine/specs/value_input_constants.js +2 -0
- package/.out/mantine/specs/value_input_hooks.stories.d.ts +23 -0
- package/.out/mantine/specs/value_input_hooks.stories.js +124 -0
- package/.out/mantine/specs/value_input_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/value_input_hooks.tests.js +12 -0
- package/.out/mantine/types.d.ts +11 -0
- package/.out/mantine/types.js +1 -0
- package/.out/tsconfig.json +27 -0
- package/.out/tsconfig.tsbuildinfo +1 -0
- package/.out/tsup.config.d.ts +3 -0
- package/.out/tsup.config.js +12 -0
- package/.out/types/all_fields_of_fields.d.ts +5 -0
- package/.out/types/all_fields_of_fields.js +1 -0
- package/.out/types/boolean_fields_of_fields.d.ts +5 -0
- package/.out/types/boolean_fields_of_fields.js +1 -0
- package/.out/types/error_type_of_field.d.ts +2 -0
- package/.out/types/error_type_of_field.js +1 -0
- package/.out/types/field.d.ts +7 -0
- package/.out/types/field.js +1 -0
- package/.out/types/field_converters.d.ts +29 -0
- package/.out/types/field_converters.js +5 -0
- package/.out/types/field_validator.d.ts +3 -0
- package/.out/types/field_validator.js +1 -0
- package/.out/types/flattened_form_fields_of.d.ts +9 -0
- package/.out/types/flattened_form_fields_of.js +1 -0
- package/.out/types/list_fields_of_fields.d.ts +5 -0
- package/.out/types/list_fields_of_fields.js +1 -0
- package/.out/types/specs/boolean_fields_of_fields.tests.d.ts +1 -0
- package/.out/types/specs/boolean_fields_of_fields.tests.js +11 -0
- package/.out/types/specs/error_type_of_field.tests.d.ts +1 -0
- package/.out/types/specs/error_type_of_field.tests.js +7 -0
- package/.out/types/specs/flattened_form_fields_of.tests.d.ts +1 -0
- package/.out/types/specs/flattened_form_fields_of.tests.js +13 -0
- package/.out/types/specs/string_fields_of_fields.tests.d.ts +1 -0
- package/.out/types/specs/string_fields_of_fields.tests.js +19 -0
- package/.out/types/specs/value_type_of_field.tests.d.ts +1 -0
- package/.out/types/specs/value_type_of_field.tests.js +7 -0
- package/.out/types/string_fields_of_fields.d.ts +5 -0
- package/.out/types/string_fields_of_fields.js +1 -0
- package/.out/types/value_type_of_field.d.ts +2 -0
- package/.out/types/value_type_of_field.js +1 -0
- package/.out/util/partial.d.ts +11 -0
- package/.out/util/partial.js +74 -0
- package/.out/vitest.workspace.d.ts +2 -0
- package/.out/vitest.workspace.js +22 -0
- package/.storybook/main.ts +40 -0
- package/.storybook/preview.tsx +28 -0
- package/.storybook/vite.config.mts +38 -0
- package/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-check-types.log +3 -0
- package/.turbo/turbo-release$colon$exports.log +3 -0
- package/.vitest/install_deterministic_random.ts +17 -0
- package/.vitest/install_storybook_preview.ts +9 -0
- package/.vitest/match_media.ts +7 -0
- package/.vitest/resize_observer.ts +5 -0
- package/README.md +2 -0
- package/core/mobx/field_adapter.ts +32 -0
- package/core/mobx/field_adapter_builder.ts +313 -0
- package/core/mobx/flattened_adapters_of_fields.ts +35 -0
- package/core/mobx/flattened_list_type_defs_of.ts +17 -0
- package/core/mobx/form_presenter.ts +705 -0
- package/core/mobx/specs/flattened_adapters_of_fields.tests.ts +72 -0
- package/core/mobx/specs/flattened_list_type_defs_of.tests.ts +35 -0
- package/core/mobx/specs/form_presenter.tests.ts +989 -0
- package/core/mobx/types.ts +54 -0
- package/core/props.ts +21 -0
- package/dist/index.cjs +11479 -0
- package/dist/index.d.cts +345 -0
- package/dist/index.d.ts +345 -0
- package/dist/index.js +11486 -0
- package/field_converters/chain_field_converter.ts +74 -0
- package/field_converters/identity_converter.ts +39 -0
- package/field_converters/integer_to_string_converter.ts +32 -0
- package/field_converters/list_converter.ts +15 -0
- package/field_converters/maybe_identity_converter.ts +23 -0
- package/field_converters/nullable_to_boolean_converter.ts +56 -0
- package/field_converters/select_value_type_converter.ts +141 -0
- package/field_converters/trimming_string_converter.ts +23 -0
- package/field_converters/validating_converter.ts +35 -0
- package/field_validators/minimum_string_length_field_validator.ts +13 -0
- package/field_value_factories/prototyping_field_value_factory.ts +11 -0
- package/index.ts +16 -0
- package/mantine/create_checkbox.tsx +79 -0
- package/mantine/create_list.tsx +58 -0
- package/mantine/create_pill.tsx +43 -0
- package/mantine/create_radio.tsx +36 -0
- package/mantine/create_radio_group.tsx +71 -0
- package/mantine/create_text_input.tsx +80 -0
- package/mantine/create_value_input.tsx +81 -0
- package/mantine/hooks.tsx +394 -0
- package/mantine/specs/__snapshots__/check_box_hooks.tests.tsx.snap +227 -0
- package/mantine/specs/__snapshots__/checkbox_hooks.tests.tsx.snap +227 -0
- package/mantine/specs/__snapshots__/list_hooks.tests.tsx.snap +68 -0
- package/mantine/specs/__snapshots__/radio_group_hooks.tests.tsx.snap +695 -0
- package/mantine/specs/__snapshots__/select_hooks.tests.tsx.snap +225 -0
- package/mantine/specs/__snapshots__/text_input_hooks.tests.tsx.snap +202 -0
- package/mantine/specs/__snapshots__/value_input_hooks.tests.tsx.snap +613 -0
- package/mantine/specs/checkbox_constants.ts +1 -0
- package/mantine/specs/checkbox_hooks.stories.tsx +79 -0
- package/mantine/specs/checkbox_hooks.tests.tsx +100 -0
- package/mantine/specs/list_hooks.stories.tsx +83 -0
- package/mantine/specs/list_hooks.tests.tsx +15 -0
- package/mantine/specs/radio_group_constants.ts +12 -0
- package/mantine/specs/radio_group_hooks.stories.tsx +103 -0
- package/mantine/specs/radio_group_hooks.tests.tsx +92 -0
- package/mantine/specs/select_hooks.stories.tsx +77 -0
- package/mantine/specs/select_hooks.tests.tsx +14 -0
- package/mantine/specs/select_hooks_constant.ts +1 -0
- package/mantine/specs/text_input_constants.ts +1 -0
- package/mantine/specs/text_input_hooks.stories.tsx +124 -0
- package/mantine/specs/text_input_hooks.tests.tsx +106 -0
- package/mantine/specs/value_input_constants.ts +2 -0
- package/mantine/specs/value_input_hooks.stories.tsx +182 -0
- package/mantine/specs/value_input_hooks.tests.tsx +14 -0
- package/mantine/types.ts +13 -0
- package/package.exports.json +18 -0
- package/package.json +74 -0
- package/tsconfig.build.json +13 -0
- package/tsconfig.json +27 -0
- package/tsup.config.ts +16 -0
- package/types/all_fields_of_fields.ts +9 -0
- package/types/boolean_fields_of_fields.ts +8 -0
- package/types/error_type_of_field.ts +3 -0
- package/types/field.ts +9 -0
- package/types/field_converters.ts +64 -0
- package/types/field_validator.ts +7 -0
- package/types/flattened_form_fields_of.ts +16 -0
- package/types/list_fields_of_fields.ts +7 -0
- package/types/specs/boolean_fields_of_fields.tests.ts +23 -0
- package/types/specs/error_type_of_field.tests.ts +10 -0
- package/types/specs/flattened_form_fields_of.tests.ts +43 -0
- package/types/specs/string_fields_of_fields.tests.ts +40 -0
- package/types/specs/value_type_of_field.tests.ts +10 -0
- package/types/string_fields_of_fields.ts +6 -0
- package/types/value_type_of_field.ts +3 -0
- package/util/partial.tsx +200 -0
- package/vitest.workspace.ts +26 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Field } from 'types/field'
|
|
2
|
+
import { type StringFieldsOfFields } from 'types/string_fields_of_fields'
|
|
3
|
+
|
|
4
|
+
describe('StringFieldsOfFields', function () {
|
|
5
|
+
describe('filtering', function () {
|
|
6
|
+
const e1 = Symbol()
|
|
7
|
+
const e2 = Symbol()
|
|
8
|
+
const e3 = Symbol()
|
|
9
|
+
type E1 = typeof e1
|
|
10
|
+
type E2 = typeof e2
|
|
11
|
+
type E3 = typeof e3
|
|
12
|
+
type F = {
|
|
13
|
+
b: Field<boolean, E1>,
|
|
14
|
+
s: Field<string, E2>,
|
|
15
|
+
n: Field<number, E3>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
it('equals expected type', function () {
|
|
19
|
+
expectTypeOf<StringFieldsOfFields<F>>().toEqualTypeOf<{
|
|
20
|
+
s: Field<string, E2>,
|
|
21
|
+
}>()
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('string union with null', function () {
|
|
26
|
+
const e = Symbol()
|
|
27
|
+
type E = typeof e
|
|
28
|
+
type F = {
|
|
29
|
+
s: Field<'a' | 'b' | 'c' | null | undefined, E>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('StringFieldsOfFields', function () {
|
|
33
|
+
it('equals expected type', function () {
|
|
34
|
+
expectTypeOf<StringFieldsOfFields<F>>().toEqualTypeOf<{
|
|
35
|
+
s: Field<'a' | 'b' | 'c' | null | undefined, E>,
|
|
36
|
+
}>()
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Field } from 'types/field'
|
|
2
|
+
import { type ValueTypeOfField } from 'types/value_type_of_field'
|
|
3
|
+
|
|
4
|
+
describe('ValueTypeOfField', function () {
|
|
5
|
+
it('equals expected type', function () {
|
|
6
|
+
const v = Symbol()
|
|
7
|
+
type V = typeof v
|
|
8
|
+
expectTypeOf<ValueTypeOfField<Field<V, unknown>>>().toEqualTypeOf<V>()
|
|
9
|
+
})
|
|
10
|
+
})
|
package/util/partial.tsx
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { observer } from 'mobx-react'
|
|
2
|
+
import {
|
|
3
|
+
type ComponentProps,
|
|
4
|
+
type ComponentType,
|
|
5
|
+
type DependencyList,
|
|
6
|
+
type ForwardedRef,
|
|
7
|
+
forwardRef,
|
|
8
|
+
type ForwardRefExoticComponent,
|
|
9
|
+
type PropsWithoutRef,
|
|
10
|
+
useMemo,
|
|
11
|
+
} from 'react'
|
|
12
|
+
|
|
13
|
+
export type PartialComponent<
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
Component extends ComponentType<any>,
|
|
16
|
+
CurriedProps,
|
|
17
|
+
AdditionalProps = {},
|
|
18
|
+
> = Exclude<keyof CurriedProps, keyof ComponentProps<Component>> extends never
|
|
19
|
+
? UnsafePartialComponent<Component, CurriedProps, AdditionalProps>
|
|
20
|
+
: keyof CurriedProps extends (string | number)
|
|
21
|
+
? `unmatched prop: ${Exclude<keyof CurriedProps, keyof ComponentProps<Component>>}`
|
|
22
|
+
: Exclude<keyof CurriedProps, keyof ComponentProps<Component>>
|
|
23
|
+
|
|
24
|
+
export type UnsafePartialComponent<
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
Component extends ComponentType<any>,
|
|
27
|
+
CurriedProps,
|
|
28
|
+
AdditionalProps = {},
|
|
29
|
+
> = ForwardRefExoticComponent<
|
|
30
|
+
PropsWithoutRef<RemainingComponentProps<Component, CurriedProps> & AdditionalProps>
|
|
31
|
+
>
|
|
32
|
+
|
|
33
|
+
export function createSimplePartialComponent<
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
Component extends ComponentType<any>,
|
|
36
|
+
CurriedProps extends Partial<ComponentProps<Component>>,
|
|
37
|
+
>(
|
|
38
|
+
Component: Component,
|
|
39
|
+
curriedProps: CurriedProps,
|
|
40
|
+
): PartialComponent<Component, CurriedProps> {
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
42
|
+
return forwardRef(
|
|
43
|
+
function (
|
|
44
|
+
exposedProps: PropsWithoutRef<RemainingComponentProps<Component, CurriedProps>>,
|
|
45
|
+
ref: ForwardedRef<typeof Component>,
|
|
46
|
+
) {
|
|
47
|
+
// forward ref types are really difficult to work with
|
|
48
|
+
// still needs a cast as `extends ComponentType<any>` != `ComponentType<any>`
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-assertion
|
|
50
|
+
const C = Component as ComponentType<any>
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<C
|
|
54
|
+
ref={ref}
|
|
55
|
+
{...curriedProps}
|
|
56
|
+
{...exposedProps}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
},
|
|
60
|
+
) as PartialComponent<Component, CurriedProps>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function createPartialComponent<
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
Component extends ComponentType<any>,
|
|
66
|
+
CurriedProps extends Partial<ComponentProps<Component>>,
|
|
67
|
+
AdditionalProps = {},
|
|
68
|
+
>(
|
|
69
|
+
Component: Component,
|
|
70
|
+
curriedPropsSource: (additionalProps: AdditionalProps) => CurriedProps,
|
|
71
|
+
): PartialComponent<Component, CurriedProps, AdditionalProps> {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
73
|
+
return forwardRef(
|
|
74
|
+
function (
|
|
75
|
+
exposedProps: PropsWithoutRef<RemainingComponentProps<Component, CurriedProps> & AdditionalProps>,
|
|
76
|
+
ref: ForwardedRef<typeof Component>,
|
|
77
|
+
) {
|
|
78
|
+
// forward ref types are really difficult to work with
|
|
79
|
+
// still needs a cast as `extends ComponentType<any>` != `ComponentType<any>`
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-assertion
|
|
81
|
+
const C = Component as ComponentType<any>
|
|
82
|
+
// TODO is there any way we can memoize this transformation?
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
84
|
+
const curriedProps = curriedPropsSource(exposedProps as AdditionalProps)
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<C
|
|
88
|
+
ref={ref}
|
|
89
|
+
{...curriedProps}
|
|
90
|
+
{...exposedProps}
|
|
91
|
+
/>
|
|
92
|
+
)
|
|
93
|
+
},
|
|
94
|
+
) as PartialComponent<Component, CurriedProps, AdditionalProps>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function usePartialComponent<
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
Component extends ComponentType<any>,
|
|
100
|
+
CurriedProps extends Partial<ComponentProps<Component>>,
|
|
101
|
+
AdditionalProps = {},
|
|
102
|
+
>(
|
|
103
|
+
// has to be first so eslint react-hooks/exhaustive-deps can find the callback
|
|
104
|
+
// has to be a function so eslint react-hooks/exhaustive-deps can reason about it :(
|
|
105
|
+
createCurriedProps: (additionalProps: AdditionalProps) => CurriedProps,
|
|
106
|
+
// has to be next so eslint react-hooks/exhaustive-deps can find the deps
|
|
107
|
+
deps: DependencyList,
|
|
108
|
+
Component: Component,
|
|
109
|
+
): PartialComponent<Component, CurriedProps, AdditionalProps> {
|
|
110
|
+
return useMemo(
|
|
111
|
+
function () {
|
|
112
|
+
return createPartialComponent<Component, CurriedProps, AdditionalProps>(Component, createCurriedProps)
|
|
113
|
+
},
|
|
114
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
115
|
+
[
|
|
116
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
117
|
+
...deps,
|
|
118
|
+
Component,
|
|
119
|
+
],
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function createPartialObserverComponent<
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
|
+
Component extends ComponentType<any>,
|
|
126
|
+
CurriedProps extends Partial<ComponentProps<Component>>,
|
|
127
|
+
AdditionalProps = {},
|
|
128
|
+
>(
|
|
129
|
+
Component: Component,
|
|
130
|
+
curriedPropsSource: (additionalProps: AdditionalProps) => CurriedProps,
|
|
131
|
+
): PartialComponent<Component, CurriedProps, AdditionalProps> {
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
133
|
+
return createUnsafePartialObserverComponent(Component, curriedPropsSource) as PartialComponent<Component,
|
|
134
|
+
CurriedProps, AdditionalProps>
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function createUnsafePartialObserverComponent<
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
139
|
+
Component extends ComponentType<any>,
|
|
140
|
+
CurriedProps,
|
|
141
|
+
AdditionalProps = {},
|
|
142
|
+
>(
|
|
143
|
+
Component: Component,
|
|
144
|
+
curriedPropsSource: (additionalProps: AdditionalProps) => CurriedProps,
|
|
145
|
+
): UnsafePartialComponent<Component, CurriedProps, AdditionalProps> {
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
147
|
+
return observer(
|
|
148
|
+
forwardRef(
|
|
149
|
+
function (
|
|
150
|
+
exposedProps: PropsWithoutRef<RemainingComponentProps<Component, CurriedProps> & AdditionalProps>,
|
|
151
|
+
ref: ForwardedRef<typeof Component>,
|
|
152
|
+
) {
|
|
153
|
+
// forward ref types are really difficult to work with
|
|
154
|
+
// still needs a cast as `extends ComponentType<any>` != `ComponentType<any>`
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-assertion
|
|
156
|
+
const C = Component as ComponentType<any>
|
|
157
|
+
// TODO is there any way we can memoize this transformation?
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
159
|
+
const curriedProps = curriedPropsSource(exposedProps as AdditionalProps)
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<C
|
|
163
|
+
ref={ref}
|
|
164
|
+
{...curriedProps}
|
|
165
|
+
{...exposedProps}
|
|
166
|
+
/>
|
|
167
|
+
)
|
|
168
|
+
},
|
|
169
|
+
),
|
|
170
|
+
) as UnsafePartialComponent<Component, CurriedProps, AdditionalProps>
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function usePartialObserverComponent<
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
Component extends ComponentType<any>,
|
|
176
|
+
CurriedProps extends Partial<ComponentProps<Component>>,
|
|
177
|
+
AdditionalProps = {},
|
|
178
|
+
>(
|
|
179
|
+
// has to be first so eslint react-hooks/exhaustive-deps can find the callback
|
|
180
|
+
curriedPropsSource: (additionalProps: AdditionalProps) => CurriedProps,
|
|
181
|
+
// has to be next so eslint react-hooks/exhaustive-deps can find the deps
|
|
182
|
+
deps: DependencyList,
|
|
183
|
+
Component: Component,
|
|
184
|
+
) {
|
|
185
|
+
return useMemo(
|
|
186
|
+
function () {
|
|
187
|
+
return createPartialObserverComponent(Component, curriedPropsSource)
|
|
188
|
+
},
|
|
189
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
|
+
[
|
|
191
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
192
|
+
...deps,
|
|
193
|
+
Component,
|
|
194
|
+
],
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
type RemainingComponentProps<Component extends ComponentType, CurriedProps> =
|
|
199
|
+
& Omit<ComponentProps<Component>, keyof CurriedProps>
|
|
200
|
+
& JSX.IntrinsicAttributes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createVitestUserConfig } from '@strictly/support-vite'
|
|
2
|
+
import {
|
|
3
|
+
defineWorkspace,
|
|
4
|
+
} from 'vitest/config'
|
|
5
|
+
|
|
6
|
+
import tsconfig from './tsconfig.json'
|
|
7
|
+
|
|
8
|
+
const config = createVitestUserConfig(tsconfig)
|
|
9
|
+
export default defineWorkspace([
|
|
10
|
+
'.',
|
|
11
|
+
{
|
|
12
|
+
...config,
|
|
13
|
+
extends: './.storybook/vite.config.mts',
|
|
14
|
+
test: {
|
|
15
|
+
...(config.test || {}),
|
|
16
|
+
environment: 'jsdom',
|
|
17
|
+
setupFiles: [
|
|
18
|
+
'./.vitest/install_deterministic_random.ts',
|
|
19
|
+
// install storybook setup for unit tests that import stories directly
|
|
20
|
+
'./.vitest/install_storybook_preview.ts',
|
|
21
|
+
'./.vitest/match_media.ts',
|
|
22
|
+
'./.vitest/resize_observer.ts',
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
] as const)
|