diff --git a/__tests__/unmounted-field.tsx b/__tests__/unmounted-field.tsx index a3f637c..f60a2aa 100644 --- a/__tests__/unmounted-field.tsx +++ b/__tests__/unmounted-field.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; import { createEvent } from 'effector'; -import { useStore } from 'effector-react'; +import { useUnit } from 'effector-react'; import { useForm } from '../src'; import { Controller } from '../src/ts'; import { setIn, removeFromInlineMap } from '../src/utils/object-manager'; @@ -44,7 +44,7 @@ const renderForm = ({ form }: { form: Form }) => { const SimpleForm = () => { const { handleSubmit, controller } = useForm({ form }); - const { fields } = useStore($values); + const { fields } = useUnit($values); return (
diff --git a/package.json b/package.json index 5b0b838..ad2b29d 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,9 @@ "types": "./types/index.d.ts", "exports": { ".": { + "types": "./types/index.d.ts", "require": "./effector-react-form.cjs.js", "default": "./effector-react-form.esm.js" - }, - "./ssr": { - "require": "./ssr.js", - "default": "./ssr.esm.js" } }, "scripts": { @@ -33,8 +30,8 @@ }, "license": "ISC", "peerDependencies": { - "effector": ">=22.0.0", - "effector-react": ">=22.0.0", + "effector": ">=23.0.0", + "effector-react": ">=23.0.0", "lodash.topath": ">=4.5.2", "react": ">=16.0.0", "react-dom": ">=16.0.0" @@ -68,8 +65,8 @@ "conventional-changelog-cli": "^2.2.2", "cross-env": "^7.0.2", "cz-conventional-changelog": "^3.3.0", - "effector": "^22.3.0", - "effector-react": "^22.1.6", + "effector": "^23.0.0", + "effector-react": "^23.0.0", "eslint": "^7.12.1", "eslint-config-airbnb": "^18.2.0", "eslint-config-airbnb-typescript": "^12.0.0", diff --git a/src/factories/create-form.ts b/src/factories/create-form.ts index 8bfce0f..27dcf17 100644 --- a/src/factories/create-form.ts +++ b/src/factories/create-form.ts @@ -2,10 +2,9 @@ import { combine, createEvent as createEventNative, createStore as createStoreNative, - forward, - guard, is, sample, + UnitTargetable, } from 'effector'; import { SyntheticEvent } from 'react'; import { @@ -137,15 +136,15 @@ const createForm = ({ }); } - forward({ - from: submit, - to: [validateForm, resetOuterFieldStateFlags], + sample({ + clock: submit, + target: [validateForm, resetOuterFieldStateFlags], }); if (resetOuterErrorsBySubmit) { - forward({ - from: submit, - to: resetOuterErrors, + sample({ + clock: submit, + target: resetOuterErrors, }); } @@ -169,30 +168,30 @@ const createForm = ({ }); sample({ - source: $allFormState, - clock: guard({ - source: submit, + clock: sample({ + clock: submit, filter: $allFormState.map(onSubmitGuardFn), }), + source: $allFormState, fn: mapSubmit, target: onSubmit, }); sample({ - source: $allFormState, - clock: guard({ - source: onChangeFieldBrowser, + clock: sample({ + clock: onChangeFieldBrowser, filter: $allFormState.map(onChangeGuardFn), }), + source: $allFormState, fn: mapSubmit, target: onChange, }); if (onSubmitArg) { if (is.effect(onSubmitArg) || is.event(onSubmitArg)) { - forward({ - from: onSubmit, - to: onSubmitArg, + sample({ + clock: onSubmit, + target: onSubmitArg as UnitTargetable, }); } else if (typeof onSubmitArg === 'function') { onSubmit.watch(onSubmitArg); @@ -201,9 +200,9 @@ const createForm = ({ if (onChangeArg) { if (is.effect(onChangeArg) || is.event(onChangeArg)) { - forward({ - from: onChange, - to: onChangeArg, + sample({ + clock: onChange, + target: onChangeArg as UnitTargetable, }); } else if (typeof onChangeArg === 'function') { onChange.watch(onChangeArg); diff --git a/src/ts.ts b/src/ts.ts index c678ebc..8a6f370 100644 --- a/src/ts.ts +++ b/src/ts.ts @@ -1,4 +1,4 @@ -import { Store, Event, Domain } from 'effector'; +import { Store, EventCallable, Domain, StoreWritable } from 'effector'; import React from 'react'; import { GetName, GetNameStr } from './utils/object-manager'; @@ -93,9 +93,9 @@ export type ControllerInjectedResult = { form: FormState; meta: Meta; validate?: (value: any) => Message; - setFieldState: ({ field: string, state: FieldState }) => void; - setOrDeleteError: ({ field: string, error: Message }) => void; - setOrDeleteOuterError: ({ field: string, error: Message }) => void; + setFieldState: (params: { field: string; state: FieldState }) => void; + setOrDeleteError: (params: { field: string; error: Message }) => void; + setOrDeleteOuterError: (params: { field: string; error: Message }) => void; setOuterErrorsInlineState: (errors: ErrorsInline) => void; fieldState: FieldState; }; @@ -182,36 +182,36 @@ type AllFormState = Store<{ }>; export type Form = { - $values: Store; + $values: StoreWritable; $errorsInline: Store; $outerErrorsInline: Store; $form: Store; - $fieldsInline: Store>; + $fieldsInline: StoreWritable>; $meta: Store; $allFormState: AllFormState; - setValue: Event; - setValues: Event>; - setOrDeleteError: Event; - setErrorsInlineState: Event; - setFieldState: Event; - setSubmitted: Event; - resetOuterFieldStateFlags: Event; - resetOuterErrors: Event; - setOrDeleteOuterError: Event; - reset: Event; - - setMeta: Event; - - setOuterErrorsInlineState: Event; - validateForm: Event; - submit: Event; - onSubmit: Event>; - - onChangeFieldBrowser: Event<{ event: React.SyntheticEvent; name: string; flat?: boolean }>; - onFocusFieldBrowser: Event<{ event: React.SyntheticEvent; name: string }>; - onBlurFieldBrowser: Event<{ event: React.SyntheticEvent; name: string }>; - fieldInit: Event; + setValue: EventCallable; + setValues: EventCallable>; + setOrDeleteError: EventCallable; + setErrorsInlineState: EventCallable; + setFieldState: EventCallable; + setSubmitted: EventCallable; + resetOuterFieldStateFlags: EventCallable; + resetOuterErrors: EventCallable; + setOrDeleteOuterError: EventCallable; + reset: EventCallable; + + setMeta: EventCallable; + + setOuterErrorsInlineState: EventCallable; + validateForm: EventCallable; + submit: EventCallable; + onSubmit: EventCallable>; + + onChangeFieldBrowser: EventCallable<{ event: React.SyntheticEvent; name: string; flat?: boolean }>; + onFocusFieldBrowser: EventCallable<{ event: React.SyntheticEvent; name: string }>; + onBlurFieldBrowser: EventCallable<{ event: React.SyntheticEvent; name: string }>; + fieldInit: EventCallable; getName: GetName; getNameStr: GetNameStr; @@ -221,8 +221,8 @@ export type Form = { export type FieldArray = { form: Form; - push: Event<{ fieldName: string; value: any | any[] }>; - remove: Event<{ fieldName: string; index: number }>; + push: EventCallable<{ fieldName: string; value: any | any[] }>; + remove: EventCallable<{ fieldName: string; index: number }>; }; export type CreateFieldArrayParams = { diff --git a/src/use-error.ts b/src/use-error.ts index 681e75c..cd8123e 100644 --- a/src/use-error.ts +++ b/src/use-error.ts @@ -1,4 +1,4 @@ -import { useStore, useStoreMap } from 'effector-react'; +import { useUnit, useStoreMap } from 'effector-react'; import { ErrorsInline, FieldsInline, FieldState, FormState, Message, UseErrorParams, UseErrorResult } from './ts'; import { getIn } from './utils/object-manager'; import { initialFieldState } from './default-states'; @@ -50,7 +50,7 @@ const useError = ({ name, form }: UseErrorParams) hasError: formHasError, hasOuterError: formHasOuterError, }; - const meta = useStore(form.$meta); + const meta = useUnit(form.$meta); const isShowInnerError = (formState.submitted || fieldState.blurred) && Boolean(innerError); const isShowOuterError = !fieldState.changedAfterOuterError && Boolean(outerError); diff --git a/src/use-field-array.ts b/src/use-field-array.ts index 1d4ee8a..0767047 100644 --- a/src/use-field-array.ts +++ b/src/use-field-array.ts @@ -1,5 +1,5 @@ import { ReactNode, useCallback, useRef, useMemo } from 'react'; -import { useStore, useEvent } from 'effector-react'; +import { useUnit } from 'effector-react'; import { AnyState, FieldArrayParams, MapFieldArrayCallback, ResultUseFieldArray } from './ts'; import { getIn } from './utils/object-manager'; @@ -14,10 +14,10 @@ const useFieldArray = ({ form: { $values }, } = fieldArray; - const push = useEvent(fieldArray.push); - const remove = useEvent(fieldArray.remove); + const push = useUnit(fieldArray.push); + const remove = useUnit(fieldArray.remove); - const values = useStore($values); + const values = useUnit($values); const map = useCallback<(fn: MapFieldArrayCallback) => ReactNode[]>( (callback: MapFieldArrayCallback) => { @@ -43,7 +43,7 @@ const useFieldArray = ({ map, remove: (index: number) => remove({ fieldName: refName.current, index }), push: (value: any | any[]) => push({ fieldName: refName.current, value }), - count + count, }; }; diff --git a/src/use-form.ts b/src/use-form.ts index c4b0096..04d77bb 100644 --- a/src/use-form.ts +++ b/src/use-form.ts @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useRef } from 'react'; -import { useEvent, useStoreMap } from 'effector-react'; +import { useUnit, useStoreMap } from 'effector-react'; import { ControllerHof, ControllerInjectedResult, @@ -49,23 +49,23 @@ const useForm = ({ }: UseFormParamsWithFactory): UseFormResultWithFactory => { const { $values, $form, $fieldsInline, $errorsInline, $outerErrorsInline } = form; - const setMeta = useEvent(form.setMeta); - const setValue = useEvent(form.setValue); - const setValues = useEvent(form.setValues); + const setMeta = useUnit(form.setMeta); + const setValue = useUnit(form.setValue); + const setValues = useUnit(form.setValues); - const setOrDeleteError = useEvent(form.setOrDeleteError); - const setFieldState = useEvent(form.setFieldState); - const setOrDeleteOuterError = useEvent(form.setOrDeleteOuterError); + const setOrDeleteError = useUnit(form.setOrDeleteError); + const setFieldState = useUnit(form.setFieldState); + const setOrDeleteOuterError = useUnit(form.setOrDeleteOuterError); - const setOuterErrorsInlineState = useEvent(form.setOuterErrorsInlineState); - const validateForm = useEvent(form.validateForm) as any; - const submit = useEvent(form.submit) as any; - const reset = useEvent(form.reset) as any; + const setOuterErrorsInlineState = useUnit(form.setOuterErrorsInlineState); + const validateForm = useUnit(form.validateForm) as any; + const submit = useUnit(form.submit) as any; + const reset = useUnit(form.reset) as any; - const onChangeFieldBrowser = useEvent(form.onChangeFieldBrowser); - const onFocusFieldBrowser = useEvent(form.onFocusFieldBrowser); - const onBlurFieldBrowser = useEvent(form.onBlurFieldBrowser); - const fieldInit = useEvent(form.fieldInit); + const onChangeFieldBrowser = useUnit(form.onChangeFieldBrowser); + const onFocusFieldBrowser = useUnit(form.onFocusFieldBrowser); + const onBlurFieldBrowser = useUnit(form.onBlurFieldBrowser); + const fieldInit = useUnit(form.fieldInit); useEffect(() => { validateForm(); diff --git a/tools/builder/rollup.js b/tools/builder/rollup.js index 1443284..f1beb44 100644 --- a/tools/builder/rollup.js +++ b/tools/builder/rollup.js @@ -4,8 +4,6 @@ const { terser } = require('rollup-plugin-terser'); const rollup = require('rollup'); const input = 'src/index.ts'; -const externalCSR = ['lodash.topath', 'react', 'effector', 'effector-react', 'effector-react/scope']; -const externalSSR = ['lodash.topath', 'react', 'effector', 'effector-react', 'effector-react/scope']; const configCSR = { input, @@ -31,7 +29,7 @@ const configCSR = { }), // terser(), ], - external: externalCSR, + external: ['lodash.topath', 'react', 'effector', 'effector-react', 'effector-react'], }; const outputCSR = [ @@ -45,55 +43,9 @@ const outputCSR = [ }, ]; -const configSSR = { - input, - plugins: [ - nodeResolve({ - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }), - babel({ - presets: [ - [ - '@babel/env', - { - loose: true, - modules: false, - }, - ], - '@babel/preset-react', - ], - babelHelpers: 'runtime', - exclude: 'node_modules/**', - extensions: ['.js', '.ts'], - plugins: [['@babel/plugin-transform-typescript'], ['effector/babel-plugin', { - reactSsr: true, - factories: ['src/factories/create-form', 'src/factories/create-field-array'] - }]], - }), - // terser(), - ], - external: externalSSR, -}; - -const outputSSR = [ - { - file: `scope.js`, - format: 'cjs', - }, - { - file: `scope.esm.js`, - format: 'esm', - }, -]; - const build = async () => { - // CSR - const bundleCSR = await rollup.rollup(configCSR); - await Promise.all(outputCSR.map((el) => bundleCSR.write(el))); - - // SSR - const bundleSSR = await rollup.rollup(configSSR); - await Promise.all(outputSSR.map((el) => bundleSSR.write(el))); + const bundle = await rollup.rollup(configCSR); + await Promise.all(outputCSR.map((el) => bundle.write(el))); }; build(); diff --git a/yarn.lock b/yarn.lock index fcaa549..e6690df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -339,7 +339,7 @@ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - + "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -491,6 +491,7 @@ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== dependencies: + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-block-scoping@^7.25.0": @@ -1070,6 +1071,15 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@babel/types@^7.25.0", "@babel/types@^7.25.6": + version "7.25.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.6.tgz#893942ddb858f32ae7a004ec9d3a76b3463ef8e6" + integrity sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1728,9 +1738,9 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/node@*": - version "22.5.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.3.tgz#91a374e42c6e7ccb5893a87f1775f36ce1671d65" - integrity sha512-njripolh85IA9SQGTAqbmnNZTdxv7X/4OYGPz8tgy5JDr8MP+uDBa921GpYEoDDnwm0Hmn5ZPeJgiiSTPoOzkQ== + version "22.5.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.2.tgz#e42344429702e69e28c839a7e16a8262a8086793" + integrity sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg== dependencies: undici-types "~6.19.2" @@ -2196,15 +2206,17 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -axe-core@^4.10.0: +axe-core@^4.9.1: version "4.10.0" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59" integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g== -axobject-query@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" - integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== +axobject-query@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" + integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== + dependencies: + deep-equal "^2.0.5" babel-jest@^26.6.3: version "26.6.3" @@ -3248,17 +3260,17 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" -effector-react@^22.1.6: - version "22.5.4" - resolved "https://registry.yarnpkg.com/effector-react/-/effector-react-22.5.4.tgz#356db979e34a0224e439e03de9034a725a3ca4eb" - integrity sha512-7HmtfD/vqmqvGnu6jMojmns9cxIW45JPBkGgHrwvbXGpbm0bz2fmVj6PIttv+Bamfmrf9FAy2bZhs+Rwj+3Mxw== +effector-react@^23.0.0: + version "23.2.1" + resolved "https://registry.yarnpkg.com/effector-react/-/effector-react-23.2.1.tgz#ce772e07e5920d6b3d17c0e1997ff62227b4bcd6" + integrity sha512-eyjHm095xgrDNe8wtF60w5AjaF+j4Z6XP/DxW8RvlCK4twQT5mkAbIBJxA7BXKLL74RpySai8QmjVBurzapBCw== dependencies: use-sync-external-store "^1.0.0" -effector@^22.3.0: - version "22.8.8" - resolved "https://registry.yarnpkg.com/effector/-/effector-22.8.8.tgz#e37a36b7a9a447d150a24a16110e6c360eed64d3" - integrity sha512-uqYEPt/jIZ3Y1WhpyED1XuXAJNsVM5TcWZvcyQhl6nYKRynklGiu+Fy/BnLQftmMcxZS478laAuExUPfuOGiOg== +effector@^23.0.0: + version "23.2.2" + resolved "https://registry.yarnpkg.com/effector/-/effector-23.2.2.tgz#9935770c1e315037f08b820720b82cf3cc25cafc" + integrity sha512-gzwATi9pgZQx0TNhM2LESmoUpEO+vhibLZPCvVzi7spMvKFwKnfJV2PFj4xqNFFSC35TXaznx30ne62dCQ6ZRQ== electron-to-chromium@^1.5.4: version "1.5.13" @@ -3502,16 +3514,16 @@ eslint-config-prettier@^7.0.0: integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== eslint-plugin-jsx-a11y@^6.4.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz#36fb9dead91cafd085ddbe3829602fb10ef28339" - integrity sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg== + version "6.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz#67ab8ff460d4d3d6a0b4a570e9c1670a0a8245c8" + integrity sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g== dependencies: aria-query "~5.1.3" array-includes "^3.1.8" array.prototype.flatmap "^1.3.2" ast-types-flow "^0.0.8" - axe-core "^4.10.0" - axobject-query "^4.1.0" + axe-core "^4.9.1" + axobject-query "~3.1.1" damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" es-iterator-helpers "^1.0.19" @@ -7734,6 +7746,14 @@ update-browserslist-db@^1.1.0: escalade "^3.1.2" picocolors "^1.0.1" +update-browserslist-db@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" + integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"