@picked/react 0.0.1-dev.1776647091821 → 0.0.1-dev.1776662399138

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.
@@ -1,25 +1,37 @@
1
- import { ReactFormInstance } from './use-react-form';
2
- interface UseFormOptions {
3
- formId: string;
4
- title: string;
5
- fieldKeys: string[];
1
+ import { FormEvent } from 'react';
2
+ import { Store } from 'effector';
3
+ import { ErrorCallback, FormInstance as CoreFormInstance, SubmitCallback, SuccessCallback } from '@picked/client/form';
4
+ import { ReactFormField } from '../utils/map-field-to-react';
5
+ export interface FormInstance {
6
+ form: {
7
+ props: {
8
+ onSubmit: (e: FormEvent<HTMLFormElement>) => void;
9
+ };
10
+ errors: CoreFormInstance['form']['errors'];
11
+ submitting: CoreFormInstance['form']['submitting'];
12
+ onBeforeSubmit: (callback: SubmitCallback) => () => void;
13
+ onSuccess: (callback: SuccessCallback) => () => void;
14
+ onError: (callback: ErrorCallback) => () => void;
15
+ };
16
+ fields: Store<ReactFormField[]>;
6
17
  }
7
- export type FormInstance<TFieldKeys extends string = string> = ReactFormInstance<TFieldKeys>;
8
18
  /**
9
- * React hook wrapping the framework-agnostic createForm from `@picked/client/form`.
19
+ * React hook mirroring Svelte's `createForm`: accepts reactive stores for
20
+ * `title` and `fieldKeys` and returns a React-adapted form instance.
10
21
  *
11
- * Creates the underlying Effector graph once per hook lifetime: `title` and
12
- * `fieldKeys` prop changes flow through events into stable stores, so the core
13
- * form is not rebuilt on every render when callers pass inline values.
14
- * Callback registration returns void — cleanup runs automatically on unmount.
22
+ * The form is a stateful object (typed values, errors, subscribers) whose
23
+ * lifetime is the hook instance, not the render — so `title` and `fieldKeys`
24
+ * are stores (reactive access over time) rather than values (snapshots).
15
25
  *
16
- * @param {UseFormOptions} options - Form configuration.
17
- * @param {string} options.formId - Stable identifier for the form.
18
- * @param {string} options.title - Human-readable form title.
19
- * @param {string[]} options.fieldKeys - Field keys the form submits.
20
- * @returns {FormInstance} Form with React submit handler, mapped fields, and auto-cleanup callbacks.
21
- * @example useForm({ formId: 'f1', title: 'Feedback', fieldKeys: ['rating'] })
26
+ * `onBeforeSubmit` / `onSuccess` / `onError` return the core unsubscribe so
27
+ * callers can register inside `useEffect` with standard React cleanup:
28
+ * `useEffect(() => form.onBeforeSubmit(handler), [form, handler])`.
29
+ *
30
+ * @param {string} formId - Stable identifier for the form.
31
+ * @param {Store<string>} title - Store holding the form/step title.
32
+ * @param {Store<string[]>} fieldKeys - Store of field keys belonging to this form.
33
+ * @returns {FormInstance} React form with submit handler, mapped fields, and subscribable callbacks.
34
+ * @example const { form, fields } = useForm(stepKey, nameStore, fieldKeysStore)
22
35
  */
23
- export declare function useForm({ formId, title, fieldKeys }: UseFormOptions): FormInstance;
24
- export {};
36
+ export declare function useForm(formId: string, title: Store<string>, fieldKeys: Store<string[]>): FormInstance;
25
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEvE,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAAI,iBAAiB,CAAC,UAAU,CAAC,CAAA;AAE5F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,GAAG,YAAY,CAgClF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAA;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,IAAI,gBAAgB,EACrC,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAGlF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE;QACJ,KAAK,EAAE;YACL,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;SAClD,CAAA;QACD,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC1C,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAA;QAClD,cAAc,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,MAAM,IAAI,CAAA;QACxD,SAAS,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,IAAI,CAAA;QACpD,OAAO,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,IAAI,CAAA;KACjD,CAAA;IACD,MAAM,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EACpB,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,GACzB,YAAY,CAgCd"}
@@ -1 +1 @@
1
- import{useExperience as e,usePicked as t}from"../hooks/client.js";import{useReactForm as n}from"./use-react-form.js";import"../hooks/index.js";import{useEffect as r,useMemo as i}from"react";import{createEvent as a,createStore as o}from"effector";import{createForm as s}from"@picked/client/form";function c({formId:c,title:l,fieldKeys:u}){let d=t(),f=e(),[p,m]=i(()=>{let e=a();return[o(l).on(e,(e,t)=>t),e]},[]),[h,g]=i(()=>{let e=a();return[o(u).on(e,(e,t)=>t),e]},[]);return r(()=>{m(l)},[m,l]),r(()=>{g(u)},[g,u.join(`\0`),u]),n(i(()=>s({client:d,experienceInstance:f},c,p,h),[d,f,c,p,h]))}export{c as useForm};
1
+ import{useExperience as e,usePicked as t}from"../hooks/client.js";import{mapFieldToReact as n}from"../utils/map-field-to-react.js";import{prepareNativeEvent as r}from"../utils/prepare-native-event.js";import{useMemo as i}from"react";import{createForm as a}from"@picked/client/form";function o(o,s,c){let l=t(),u=e(),d=i(()=>a({client:l,experienceInstance:u},o,s,c),[l,u,o,s,c]),f=i(()=>d.fields.map(e=>e.map(n)),[d]);return{form:i(()=>({errors:d.form.errors,submitting:d.form.submitting,props:{onSubmit:e=>{e.preventDefault(),r(e.nativeEvent,e.currentTarget),d.form.props.onsubmit(e.nativeEvent)}},onBeforeSubmit:e=>d.form.onBeforeSubmit(e),onSuccess:e=>d.form.onSuccess(e),onError:e=>d.form.onError(e)}),[d]),fields:f}}export{o as useForm};
@@ -1 +1 @@
1
- import{ClientContext as e,ClientProvider as t,ExperienceContext as n,ExperienceProvider as r}from"../context.js";import{useExperience as i,usePicked as a}from"./client.js";import{useSetStepContext as o,useStep as s}from"./step.js";import{useLocalStorage as c,useSessionStorage as l}from"./storage.js";import{getField as u}from"./field.js";import{useFeature as d,useFeatureResult as f}from"./feature.js";export{e as ClientContext,t as ClientProvider,n as ExperienceContext,r as ExperienceProvider,u as getField,i as useExperience,d as useFeature,f as useFeatureResult,c as useLocalStorage,a as usePicked,l as useSessionStorage,o as useSetStepContext,s as useStep};
1
+ import{ClientContext as e,ClientProvider as t,ExperienceContext as n,ExperienceProvider as r}from"../context.js";import{useExperience as i,usePicked as a}from"./client.js";import{useFeature as o,useFeatureResult as s}from"./feature.js";import{getField as c}from"./field.js";import{useSetStepContext as l,useStep as u}from"./step.js";import{useLocalStorage as d,useSessionStorage as f}from"./storage.js";export{e as ClientContext,t as ClientProvider,n as ExperienceContext,r as ExperienceProvider,c as getField,i as useExperience,o as useFeature,s as useFeatureResult,d as useLocalStorage,a as usePicked,f as useSessionStorage,l as useSetStepContext,u as useStep};
@@ -1,6 +1,6 @@
1
1
  import { Store } from 'effector';
2
2
  import { ExperienceStep } from '@picked/client';
3
- import { ReactFormInstance } from '../form/use-react-form';
3
+ import { FormInstance } from '../form';
4
4
  import { ReactFormField } from '../utils/map-field-to-react';
5
5
  export interface StepContext {
6
6
  step: Store<ExperienceStep>;
@@ -9,7 +9,7 @@ export interface StepContext {
9
9
  isActive: boolean;
10
10
  /** @deprecated Use `isActive` instead. */
11
11
  isActiveStep: boolean;
12
- form: ReactFormInstance['form'];
12
+ form: FormInstance['form'];
13
13
  }
14
14
  export declare const StepContextProvider: import('react').Context<StepContext | null>;
15
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/hooks/step.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAGjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IAC3B,kFAAkF;IAClF,MAAM,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IAC/B,QAAQ,EAAE,OAAO,CAAA;IACjB,0CAA0C;IAC1C,YAAY,EAAE,OAAO,CAAA;IACrB,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;CAChC;AAED,eAAO,MAAM,mBAAmB,6CAA0C,CAAA;AAE1E;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,WAAW,CAOrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAwC9D"}
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/hooks/step.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAGjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IAC3B,kFAAkF;IAClF,MAAM,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IAC/B,QAAQ,EAAE,OAAO,CAAA;IACjB,0CAA0C;IAC1C,YAAY,EAAE,OAAO,CAAA;IACrB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED,eAAO,MAAM,mBAAmB,6CAA0C,CAAA;AAE1E;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,WAAW,CAOrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAyC9D"}
@@ -1 +1 @@
1
- import{useExperience as e,usePicked as t}from"./client.js";import{useReactForm as n}from"../form/use-react-form.js";import{useStepRouter as r}from"../router/context.js";import{createContext as i,useContext as a,useMemo as o}from"react";import{createForm as s}from"@picked/client/form";var c=i(null);function l(){let e=a(c);if(!e)throw Error(`useStep must be used within a StepContextProvider`);return e}function u(i){let a=e(),c=t(),{activeStep:l}=r(),u=o(()=>l?.key===i,[l?.key,i]),d=o(()=>a.treeStore.map(e=>e.steps.find(e=>e.key===i)??{id:i,key:i,name:``,fieldKeys:[]}),[a,i]),f=o(()=>d.map(e=>e.name),[d]),p=o(()=>d.map(e=>e.fieldKeys),[d]),{form:m,fields:h}=n(o(()=>s({client:c,experienceInstance:a},i,f,p),[c,a,i,f,p]));return{step:d,fields:h,isActive:u,isActiveStep:u,form:m}}export{c as StepContextProvider,u as useSetStepContext,l as useStep};
1
+ import{useExperience as e}from"./client.js";import{useForm as t}from"../form/index.js";import{useStepRouter as n}from"../router/context.js";import{createContext as r,useContext as i,useMemo as a}from"react";var o=r(null);function s(){let e=i(o);if(!e)throw Error(`useStep must be used within a StepContextProvider`);return e}function c(r){let i=e(),{activeStep:o}=n(),s=a(()=>o?.key===r,[o?.key,r]),c=a(()=>i.treeStore.map(e=>e.steps.find(e=>e.key===r)??{id:r,key:r,name:``,fieldKeys:[]},{skipVoid:!1}),[i,r]),{form:l,fields:u}=t(r,a(()=>c.map(e=>e.name,{skipVoid:!1}),[c]),a(()=>c.map(e=>e.fieldKeys,{skipVoid:!1}),[c]));return{step:c,fields:u,isActive:s,isActiveStep:s,form:l}}export{o as StepContextProvider,c as useSetStepContext,s as useStep};
@@ -1 +1 @@
1
- import{useExperience as e}from"../hooks/client.js";import{StepRouterProvider as t}from"./context.js";import"../hooks/index.js";import{useCallback as n,useMemo as r,useRef as i,useState as a}from"react";import{supportsWindow as o}from"@picked/client";import{useUnit as s}from"effector-react";import{jsx as c}from"react/jsx-runtime";function l({children:l}){let{currentStepStore:u}=e(),d=s(u),f=i(!1),[p,m]=a([]),[h,g]=a(null),_=n(e=>{if(o())m(t=>[...t,e]);else{if(f.current)return;e.key===d?.key&&(g(e),f.current=!0)}},[d?.key]),v=n(e=>{m(t=>t.filter(t=>t!==e))},[]),y=r(()=>h??p.find(e=>e.key===d?.key)??null,[h,p,d?.key]),b=r(()=>({activeStep:y,registerStep:_,unregisterStep:v}),[y,_,v]);return d?.key?c(t,{value:b,children:l}):null}export{l as default};
1
+ import{useExperience as e}from"../hooks/client.js";import{StepRouterProvider as t}from"./context.js";import"../hooks/index.js";import{useCallback as n,useMemo as r,useRef as i,useState as a}from"react";import{useUnit as o}from"effector-react";import{supportsWindow as s}from"@picked/client";import{jsx as c}from"react/jsx-runtime";function l({children:l}){let{currentStepStore:u}=e(),d=o(u),f=i(!1),[p,m]=a([]),[h,g]=a(null),_=n(e=>{if(s())m(t=>[...t,e]);else{if(f.current)return;e.key===d?.key&&(g(e),f.current=!0)}},[d?.key]),v=n(e=>{m(t=>t.filter(t=>t!==e))},[]),y=r(()=>h??p.find(e=>e.key===d?.key)??null,[h,p,d?.key]),b=r(()=>({activeStep:y,registerStep:_,unregisterStep:v}),[y,_,v]);return d?.key?c(t,{value:b,children:l}):null}export{l as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picked/react",
3
- "version": "0.0.1-dev.1776647091821",
3
+ "version": "0.0.1-dev.1776662399138",
4
4
  "devDependencies": {
5
5
  "@picked/client": "workspace:*",
6
6
  "@repo/eslint-config": "workspace:*",
@@ -85,7 +85,7 @@
85
85
  },
86
86
  "module": "./dist/index.js",
87
87
  "peerDependencies": {
88
- "@picked/client": "0.0.1-dev.1776647091821",
88
+ "@picked/client": "0.0.1-dev.1776662399138",
89
89
  "effector": "^23.3.0",
90
90
  "effector-react": "^23.3.0",
91
91
  "react": "19.2.2",
@@ -1,33 +0,0 @@
1
- import { FormEvent } from 'react';
2
- import { Store } from 'effector';
3
- import { ErrorCallback, FormInstance as CoreFormInstance, SubmitCallback, SuccessCallback } from '@picked/client/form';
4
- import { ReactFormField } from '../utils/map-field-to-react';
5
- export interface ReactFormInstance<TFieldKeys extends string = string> {
6
- form: {
7
- props: {
8
- onSubmit: (e: FormEvent<HTMLFormElement>) => void;
9
- };
10
- errors: CoreFormInstance<TFieldKeys>['form']['errors'];
11
- submitting: CoreFormInstance<TFieldKeys>['form']['submitting'];
12
- onBeforeSubmit: (callback: SubmitCallback<TFieldKeys>) => void;
13
- onSuccess: (callback: SuccessCallback<TFieldKeys>) => void;
14
- onError: (callback: ErrorCallback) => void;
15
- };
16
- fields: Store<ReactFormField[]>;
17
- }
18
- /**
19
- * Wraps a core FormInstance for React consumption.
20
- *
21
- * - `form.props.onSubmit` accepts a React FormEvent and forwards the native
22
- * event to core after restoring currentTarget.
23
- * - `fields` exposes camelCase React handlers via mapFieldToReact.
24
- * - onBeforeSubmit/onSuccess/onError collect unsubscribes scoped to the
25
- * current core; cleanup runs on core change and on unmount so subscriptions
26
- * on a previous core do not leak.
27
- *
28
- * @param {CoreFormInstance} core - Framework-agnostic form instance to adapt.
29
- * @returns {ReactFormInstance} React-adapted form with camelCase fields and auto-cleanup.
30
- * @example const { form, fields } = useReactForm(core)
31
- */
32
- export declare function useReactForm<TFieldKeys extends string = string>(core: CoreFormInstance<TFieldKeys>): ReactFormInstance<TFieldKeys>;
33
- //# sourceMappingURL=use-react-form.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-react-form.d.ts","sourceRoot":"","sources":["../../src/form/use-react-form.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,OAAO,EAAE,KAAK,SAAS,EAA8B,MAAM,OAAO,CAAA;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,KAAK,EACV,aAAa,EACb,YAAY,IAAI,gBAAgB,EAChC,cAAc,EACd,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAGlF,MAAM,WAAW,iBAAiB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM;IACnE,IAAI,EAAE;QACJ,KAAK,EAAE;YACL,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;SAClD,CAAA;QACD,MAAM,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAA;QACtD,UAAU,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAA;QAC9D,cAAc,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;QAC9D,SAAS,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;QAC1D,OAAO,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;KAC3C,CAAA;IACD,MAAM,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,EAC7D,IAAI,EAAE,gBAAgB,CAAC,UAAU,CAAC,GACjC,iBAAiB,CAAC,UAAU,CAAC,CAsC/B"}
@@ -1 +0,0 @@
1
- import{mapFieldToReact as e}from"../utils/map-field-to-react.js";import{prepareNativeEvent as t}from"../utils/prepare-native-event.js";import{useEffect as n,useMemo as r,useRef as i}from"react";function a(a){let o=i([]);n(()=>()=>{let e=o.current;o.current=[];for(let t of e)t()},[a]);let s=r(()=>a.fields.map(t=>t.map(e)),[a]);return{form:r(()=>({errors:a.form.errors,submitting:a.form.submitting,props:{onSubmit:e=>{t(e.nativeEvent,e.currentTarget),e.preventDefault(),a.form.props.onsubmit(e.nativeEvent)}},onBeforeSubmit:e=>{o.current.push(a.form.onBeforeSubmit(e))},onSuccess:e=>{o.current.push(a.form.onSuccess(e))},onError:e=>{o.current.push(a.form.onError(e))}}),[a]),fields:s}}export{a as useReactForm};