@form-instant/react-input-mapping 1.9.0 → 2.0.2

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 (32) hide show
  1. package/dist/index.js +2 -2
  2. package/dist/index.js.map +17 -8
  3. package/dist/src/InputMapping/class.d.ts +81 -0
  4. package/dist/src/InputMapping/index.d.ts +7 -0
  5. package/dist/src/InputMapping/provider.d.ts +30 -0
  6. package/dist/{InputMapping → src/InputMapping}/types.d.ts +4 -1
  7. package/dist/src/hooks/useInputArray/application/useInputArray.d.ts +17 -0
  8. package/dist/src/hooks/useInputArray/domain/guards/isParsedField.d.ts +7 -0
  9. package/dist/src/hooks/useInputArray/domain/services/cloneFieldWithIndex.d.ts +9 -0
  10. package/dist/src/hooks/useInputArray/index.d.ts +2 -0
  11. package/dist/src/hooks/useInputArray/types/index.d.ts +8 -0
  12. package/dist/src/hooks/useInputMapping.d.ts +14 -0
  13. package/dist/src/hooks/useInputMappingGranular/application/factory/create-granular-hook.d.ts +18 -0
  14. package/dist/src/hooks/useInputMappingGranular/application/hooks/index.d.ts +2 -0
  15. package/dist/src/hooks/useInputMappingGranular/application/hooks/use-input-component.d.ts +12 -0
  16. package/dist/src/hooks/useInputMappingGranular/application/hooks/use-input-mapping-actions.d.ts +16 -0
  17. package/dist/src/hooks/useInputMappingGranular/application/validators/store-validator.d.ts +9 -0
  18. package/dist/src/hooks/useInputMappingGranular/domain/services/index.d.ts +2 -0
  19. package/dist/src/hooks/useInputMappingGranular/domain/services/notification-service.d.ts +23 -0
  20. package/dist/src/hooks/useInputMappingGranular/domain/services/subscription-manager.d.ts +47 -0
  21. package/dist/src/hooks/useInputMappingGranular/domain/types/index.d.ts +11 -0
  22. package/dist/src/hooks/useInputMappingGranular/index.d.ts +13 -0
  23. package/dist/src/hooks/useInputMappingGranular/infrastructure/store/input-mapping-store.d.ts +47 -0
  24. package/package.json +38 -55
  25. package/LICENSE +0 -21
  26. package/dist/InputMapping/class.d.ts +0 -20
  27. package/dist/InputMapping/index.d.ts +0 -6
  28. package/dist/InputMapping/provider.d.ts +0 -15
  29. package/dist/InputMapping/useFormInstantField.d.ts +0 -16
  30. package/dist/InputMapping/useInputMapping.d.ts +0 -14
  31. /package/dist/{InputMapping → src/InputMapping}/context.d.ts +0 -0
  32. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- class u extends Map{zodAdacter(){return Object.entries({ZodBoolean:"checkbox",ZodDate:"date",ZodEnum:"select",ZodNativeEnum:"select",ZodNumber:"number",string:"text"})}appendObj(t){let r=Object.keys(t);for(let n of r){let e=t[n];if(e&&n in{})this.set(n,e);else if(e)this.set(n,e)}for(let[n,e]of this.zodAdacter()){let o=this.get(e);if(o)this.set(n,o)}}constructor(t){super();if(!t)return;this.appendObj(t)}exists(t){if(!super.has(t))return"fallback";return t}get(t){return super.get(t)}set(t,r){if(!super.has(t))super.set(t,r);return this}extends(t){let r=Object.fromEntries(super.entries()),n=t(this);return new u({...r,...n})}}import{createContext as x}from"react";var s=x(null);import{createElement as c,useContext as d}from"react";var T=(t)=>{return{FormInstantInputsProvider:(e)=>c(s.Provider,{value:t},e.children),useInputMapping:()=>d(s)}},N=({formProps:t})=>{let r=d(s),n=t.fieldType,e=r.get(n);if(!e)return null;return c(e,t)};import{useCallback as m,useState as g}from"react";var B=({fieldConfig:t,name:r,...n})=>{let[e,o]=g(Object.values(n.schema||{})),a=m(()=>{if(![t?.max].includes(e.length))o((i)=>[...i,i[0]])},[e,t?.max]),p=m((i)=>{if(![t?.min].includes(e.length))o((l)=>l.filter((R,f)=>f!==i))},[e,t?.min]);return{fiends:e,append:a,remove:p,setFiends:o,fieldConfig:t,name:r,...n}};import{useReducer as I,useRef as F,useContext as C}from"react";function H(t){return function r(){let n=C(t);if(!n)throw new Error("InputMappingContext not found");let e=F(n),[,o]=I((a)=>a+1,0);return{...e.current,set:(a,p)=>{let i=e.current.set(a,p);return o(),i},clear:()=>{e.current.clear(),o()},delete:(a)=>{let p=e.current.delete(a);return o(),p}}}}export{B as useFormInstantField,H as createInputMappingHook,T as createFormInstantContainer,s as InputMappingContext,u as InputMapping,N as ElementMapping};
1
+ class Z extends Map{appendObj(R){for(let O in R)this.set(O,R[O])}constructor(R){super();if(!R)return;this.appendObj(R)}exists(R){if(!super.has(R))return"fallback";return R}get(R){return super.get(R)}set(R,O){if(!super.has(R))super.set(R,O);return this}extends(R){let O=Object.fromEntries(super.entries()),q=R(this);return new Z({...O,...q})}}import{createContext as x}from"react";var _=x(null);import{createElement as C,memo as I,use as m}from"react";class W{listeners=new Map;subscribe(R,O){if(!this.listeners.has(R))this.listeners.set(R,new Set);return this.listeners.get(R).add(O),()=>this.unsubscribe(R,O)}unsubscribe(R,O){this.listeners.get(R)?.delete(O)}getListeners(R){return this.listeners.get(R)}hasListeners(R){return this.listeners.has(R)&&this.listeners.get(R).size>0}clear(){this.listeners.clear()}}class Q{static notify(R,O){let q=R.getListeners(O);if(q)q.forEach((z)=>z())}static notifyMany(R,O){O.forEach((q)=>this.notify(R,q))}}class L extends Z{_subscriptionManager;get subscriptionManager(){if(!this._subscriptionManager)this._subscriptionManager=new W;return this._subscriptionManager}subscribe(R,O){return this.subscriptionManager.subscribe(R,O)}unsubscribe(R,O){this.subscriptionManager.unsubscribe(R,O)}set(R,O){let q=!super.has(R);if(super.set(R,O),q)Q.notify(this.subscriptionManager,String(R));return this}delete(R){let O=super.delete(R);if(O)Q.notify(this.subscriptionManager,String(R));return O}clear(){let R=Array.from(this.keys()).map((O)=>String(O));super.clear(),Q.notifyMany(this.subscriptionManager,R)}}import{use as M,useSyncExternalStore as h}from"react";function $(R){if(!(R instanceof L))throw Error("InputMapping must be an instance of InputMappingStore for granular rendering")}function T(R,O){let z=M(R);return $(z),h((B)=>z.subscribe(O,B),()=>z.get(O),()=>z.get(O))}import{use as b,useMemo as f}from"react";function N(R){let q=b(R);$(q);let z=q;return f(()=>({set:(B,J)=>{return z.set(B,J)},clear:()=>{z.clear()},delete:(B)=>{return z.delete(B)}}),[z])}function A(R){function O(z){return T(R,z)}function q(){return N(R)}return{useInputComponent:O,useInputMappingActions:q}}var w=A(_),UR=(R)=>{let O=R instanceof L?R:new L(Object.fromEntries(R.entries()));return{FormInstantInputsProvider:(B)=>C(_.Provider,{value:O},B.children),useInputMapping:()=>m(_)}},g=I(({formProps:R})=>{let O=w.useInputComponent(R.fieldType)||w.useInputComponent("fallback");if(!O)return null;return C(O,R)},(R,O)=>{return R.formProps.fieldType===O.formProps.fieldType&&R.formProps.name.history===O.formProps.name.history&&R.formProps.name.current===O.formProps.name.current});g.displayName="ElementMapping";import{useCallback as S,useState as y}from"react";function P(R){return R&&typeof R==="object"&&"name"in R&&"fieldType"in R}function X(R,O,q){if(!P(R)){let D={};for(let K in R){let Y=R[K];if(!Y)continue;D[K]=X(Y,O,q)}return D}let z=R.name.current,B=`${q}.${O}.${z}`,J={...R,name:{current:z,history:B}};if(R.schema&&Array.isArray(R.schema))J.schema=R.schema.map((D)=>X(D,O,q));return J}var jR=(R)=>{let{fieldConfig:O,name:q,...z}=R,B=q.history||q.current,J=z.schema.at(0),[D,K]=y([]),Y=S(()=>{let U=O?.max??1/0;if(Number(D?.length)>=U)return;K((G)=>{let V=G.length,j=X(J,V,B);return[...G,j]})},[D,O?.max,B,J]),v=S((U)=>{let E=O?.min??0;if((D?.length||0)>E)K((V)=>{return V.filter((F,H)=>H!==U).map((F,H)=>{return X(F,H,B)})})},[D,O?.min,B]);return{inputs:D,append:Y,remove:v,setInputs:K,fieldConfig:O,name:q,...z}};import{useReducer as u,useRef as c,use as k}from"react";function PR(R){return function(){let q=k(R);if(!q)throw Error("InputMappingContext not found");let z=c(q),[,B]=u((J)=>J+1,0);return{...z.current,set:(J,D)=>{let K=z.current.set(J,D);return B(),K},clear:()=>{z.current.clear(),B()},delete:(J)=>{let D=z.current.delete(J);return B(),D}}}}export{jR as useInputArray,PR as createInputMappingHook,A as createInputMappingGranularHook,UR as createFormInstantContainer,L as InputMappingStore,_ as InputMappingContext,Z as InputMapping,g as ElementMapping};
2
2
 
3
- //# debugId=C50C3835C1CFBF1864756E2164756E21
3
+ //# debugId=FEDB4F6DC6D16F3364756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,14 +1,23 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/InputMapping/class.ts", "../src/InputMapping/context.tsx", "../src/InputMapping/provider.tsx", "../src/InputMapping/useFormInstantField.tsx", "../src/InputMapping/useInputMapping.tsx"],
3
+ "sources": ["../src/InputMapping/class.ts", "../src/InputMapping/context.tsx", "../src/InputMapping/provider.tsx", "../src/hooks/useInputMappingGranular/domain/services/subscription-manager.ts", "../src/hooks/useInputMappingGranular/domain/services/notification-service.ts", "../src/hooks/useInputMappingGranular/infrastructure/store/input-mapping-store.ts", "../src/hooks/useInputMappingGranular/application/hooks/use-input-component.ts", "../src/hooks/useInputMappingGranular/application/validators/store-validator.ts", "../src/hooks/useInputMappingGranular/application/hooks/use-input-mapping-actions.ts", "../src/hooks/useInputMappingGranular/application/factory/create-granular-hook.ts", "../src/hooks/useInputArray/application/useInputArray.ts", "../src/hooks/useInputArray/domain/guards/isParsedField.ts", "../src/hooks/useInputArray/domain/services/cloneFieldWithIndex.ts", "../src/hooks/useInputMapping.tsx"],
4
4
  "sourcesContent": [
5
- "import { FC } from 'react';\nimport { INPUT_COMPONENTS_KEYS, ParsedField } from './types';\n\n// Nuevo tipo auxiliar para mapear cada clave a su componente correspondiente\n// Ahora el value depende de la key: si es de Ob, es FC<Ob[K]>; si es de INPUT_COMPONENTS_KEYS, es FC<any>\ntype InputComponentMap<Ob extends Record<string, any>> = {\n [K in keyof Ob]?: FC<ParsedField<Ob[K]>>;\n} & {\n [K in INPUT_COMPONENTS_KEYS]?: FC<any>;\n};\n\nexport class InputMapping<Ob extends Record<string, any>> extends Map<\n keyof Ob | INPUT_COMPONENTS_KEYS,\n FC<any>\n> {\n private zodAdacter() {\n return Object.entries({\n ZodBoolean: 'checkbox',\n ZodDate: 'date',\n ZodEnum: 'select',\n ZodNativeEnum: 'select',\n ZodNumber: 'number',\n string: 'text',\n });\n }\n\n private appendObj(obj: Partial<InputComponentMap<Ob>>) {\n const keys = Object.keys(obj) as Array<keyof typeof obj>;\n\n for (const key of keys) {\n const value = obj[key];\n if (value && (key as string) in ({} as Ob)) {\n this.set(key as keyof Ob, value as FC<Ob[keyof Ob]>);\n } else if (value) {\n this.set(key as INPUT_COMPONENTS_KEYS, value as FC<any>);\n }\n }\n\n for (const [k, v] of this.zodAdacter()) {\n const existingValue = this.get(v as INPUT_COMPONENTS_KEYS);\n if (existingValue) {\n this.set(k as INPUT_COMPONENTS_KEYS, existingValue);\n }\n }\n }\n\n constructor(obj?: Partial<InputComponentMap<Ob>>) {\n super();\n if (!obj) return;\n this.appendObj(obj);\n }\n\n exists(k: string) {\n const isHas = super.has(k as keyof Ob | INPUT_COMPONENTS_KEYS);\n if (!isHas) return 'fallback';\n return k as keyof Ob | INPUT_COMPONENTS_KEYS;\n }\n\n get<Ky extends keyof Ob | INPUT_COMPONENTS_KEYS>(k: Ky) {\n return super.get(k);\n }\n\n set<K extends keyof Ob>(k: K, v: FC<Ob[K]>): this;\n set<K extends INPUT_COMPONENTS_KEYS>(k: K, v: FC<any>): this;\n set(k: keyof Ob | INPUT_COMPONENTS_KEYS, v: FC<any>): this {\n if (!super.has(k)) super.set(k, v);\n return this;\n }\n\n extends<Ext extends Record<string, FC<any>>>(\n cb: (mapping: InputMapping<Ob & { [K in keyof Ext]: any }>) => Ext,\n ) {\n const obj = Object.fromEntries(super.entries()) as Partial<\n InputComponentMap<Ob & { [K in keyof Ext]: any }>\n >;\n const extendObj = cb(this as InputMapping<Ob & { [K in keyof Ext]: any }>);\n return new InputMapping<Ob & { [K in keyof Ext]: any }>({\n ...obj,\n ...extendObj,\n });\n }\n}\n",
6
- "import { createContext } from 'react';\nimport { InputMapping } from './class';\n\nexport const InputMappingContext = createContext<InputMapping<any> | null>(null) as React.Context<\n InputMapping<any>\n>;\n",
7
- "import { Context, createElement, FC, ReactNode, useContext } from 'react';\nimport { InputMapping } from './class';\nimport { InputMappingContext } from './context';\nimport { ObBase, ParsedField } from './types';\n\ntype FCC = React.FC<{ children: ReactNode }>;\n\ninterface createFormInstantContainerReturn<Ob extends Record<ObBase, any>> {\n useInputMapping: Context<InputMapping<Ob>>;\n FormInstantInputsProvider: FCC;\n}\n\nexport const createFormInstantContainer = <Ob extends Record<any, any>>(\n inputMapping: InputMapping<Ob>,\n) => {\n const FormInstantInputsProvider: FCC = (props) =>\n createElement(\n InputMappingContext.Provider,\n {\n value: inputMapping,\n },\n props.children,\n );\n\n const useInputMapping = () => useContext(InputMappingContext);\n\n return {\n FormInstantInputsProvider,\n useInputMapping,\n } as unknown as createFormInstantContainerReturn<Ob>;\n};\n\nexport const ElementMapping: FC<{ formProps: ParsedField<any, string> }> = ({ formProps }) => {\n const InputMapping = useContext(InputMappingContext);\n\n const type = formProps.fieldType;\n\n const Element = InputMapping.get(type);\n\n if (!Element) return null;\n\n return createElement(Element, formProps);\n};\n",
8
- "import { useCallback, useState } from 'react';\nimport { ParsedField } from './types';\n\nexport const useFormInstantField = <P extends ParsedField<unknown, string>>({\n fieldConfig,\n name,\n ...prop\n}: P) => {\n const [fiends, setFiends] = useState(Object.values((prop.schema as P['schema']) || {}));\n\n const append = useCallback(() => {\n if (![fieldConfig?.max].includes(fiends.length)) setFiends((pre) => [...pre, pre[0]]);\n }, [fiends, fieldConfig?.max]);\n\n const remove = useCallback(\n (index: number) => {\n if (![fieldConfig?.min].includes(fiends.length))\n setFiends((pre) => pre.filter((_, i) => i !== index));\n },\n [fiends, fieldConfig?.min],\n );\n\n return { fiends, append, remove, setFiends, fieldConfig, name, ...prop };\n};\n",
9
- "import { useReducer, useRef, useContext } from 'react';\nimport { InputMapping } from './class';\n\nexport function createInputMappingHook<Ob extends Record<string, any>>(\n InputMappingContext: React.Context<InputMapping<Ob> | null>,\n) {\n return function useInputMapping() {\n const initialState = useContext(InputMappingContext);\n if (!initialState) throw new Error('InputMappingContext not found');\n const mapRef = useRef(initialState);\n const [, reRender] = useReducer((x) => x + 1, 0);\n\n return {\n ...mapRef.current,\n set: (key: keyof Ob | string, value: React.FC<any>) => {\n const result = mapRef.current.set(key, value);\n reRender();\n return result;\n },\n clear: () => {\n mapRef.current.clear();\n reRender();\n },\n delete: (key: keyof Ob | string) => {\n const result = mapRef.current.delete(key);\n reRender();\n return result;\n },\n };\n };\n}\n"
5
+ "import type { FC } from 'react';\nimport type { FieldConfig, INPUT_COMPONENTS_KEYS } from '.';\n\n/**\n * Auxiliary type to map each key to its corresponding React component.\n * Values can either be specific Input types from the generic object `Ob`\n * or predefined keys from `INPUT_COMPONENTS_KEYS`.\n *\n * @template Ob - The object structure defining the Inputs and their types.\n */\ntype InputComponentMap<Ob extends Record<string, any>> = {\n [K in keyof Ob]?: FC<FieldConfig<Ob[K]>>;\n} & {\n [K in INPUT_COMPONENTS_KEYS]?: FC<any>;\n };\n\n/**\n * Class representing a mapping between Input keys and React components.\n * Extends the native `Map` class to handle component associations for specific object Inputs\n * and generic input component keys.\n *\n * @template Ob - The object structure defining the Inputs.\n */\nexport class InputMapping<Ob extends Record<string, any>> extends Map<\n keyof Ob | INPUT_COMPONENTS_KEYS,\n FC<any>\n> {\n\n /**\n * Internal method to populate the mapping from a partial object.\n *\n * @param obj - A partial mapping of keys to components.\n * @private\n */\n private appendObj(obj: Partial<InputComponentMap<Ob>>) {\n for (const k in obj) this.set(k as INPUT_COMPONENTS_KEYS, obj[k] as FC<any>);\n }\n\n /**\n * Initializes a new instance of the InputMapping class.\n *\n * @param obj - An optional initial set of key-to-component mappings.\n */\n constructor(obj?: Partial<InputComponentMap<Ob>>) {\n super();\n if (!obj) return;\n this.appendObj(obj);\n }\n\n /**\n * Checks if a specific key exists in the mapping.\n *\n * @param k - The key to check.\n * @returns The key itself if it exists, otherwise returns 'fallback'.\n */\n exists(k: string) {\n const isHas = super.has(k as keyof Ob | INPUT_COMPONENTS_KEYS);\n if (!isHas) return 'fallback';\n return k as keyof Ob | INPUT_COMPONENTS_KEYS;\n }\n\n /**\n * Retrieves the component associated with a specific key.\n *\n * @template Ky - The type of the key, which must be a key of `Ob` or `INPUT_COMPONENTS_KEYS`.\n * @param k - The key to retrieve the component for.\n * @returns The React component associated with the key, or undefined if not found.\n */\n override get<Ky extends keyof Ob | INPUT_COMPONENTS_KEYS>(k: Ky) {\n return super.get(k);\n }\n\n /**\n * Associates a React component with a specific Input from the object `Ob`.\n *\n * @template K - A key from the object structure `Ob`.\n * @param k - The key to set.\n * @param v - The React component to associate with the key.\n * @returns The current class instance for method chaining.\n */\n override set<K extends keyof Ob>(k: K, v: FC<Ob[K]>): this;\n /**\n * Associates a React component with a predefined input component key.\n *\n * @template K - A key from the `INPUT_COMPONENTS_KEYS` type.\n * @param k - The key to set.\n * @param v - The React component to associate with the key.\n * @returns The current class instance for method chaining.\n */\n override set<K extends INPUT_COMPONENTS_KEYS>(k: K, v: FC<any>): this;\n /**\n * Implementation of the set method.\n *\n * @param k - The key to set (either from `Ob` or `INPUT_COMPONENTS_KEYS`).\n * @param v - The React component to associate with the key.\n * @returns The current class instance.\n */\n override set(k: keyof Ob | INPUT_COMPONENTS_KEYS, v: FC<any>): this {\n if (!super.has(k)) super.set(k, v);\n return this;\n }\n\n /**\n * Creates a new `InputMapping` instance by extending the current mapping with new associations.\n * Useful for building complex mappings incrementally.\n *\n * @template Ext - The type representing the additional mappings.\n * @param cb - A callback function that receives the current mapping and returns the extensions.\n * @returns A new `InputMapping` instance containing both original and extended mappings.\n */\n extends<Ext extends Record<string, FC<any>>>(\n cb: (mapping: InputMapping<Ob & { [K in keyof Ext]: any }>) => Ext,\n ) {\n const obj = Object.fromEntries(super.entries()) as Partial<\n InputComponentMap<Ob & { [K in keyof Ext]: any }>\n >;\n const extendObj = cb(this as InputMapping<Ob & { [K in keyof Ext]: any }>);\n return new InputMapping<Ob & { [K in keyof Ext]: any }>({\n ...obj,\n ...extendObj,\n });\n }\n}\n",
6
+ "import { createContext } from 'react';\nimport { InputMapping } from './class';\n\nexport const InputMappingContext = createContext<InputMapping<any> | null>(null) as React.Context<\n\tInputMapping<any>\n>;\n",
7
+ "import type { Context, FC, ReactNode } from 'react';\nimport { createElement, memo, use } from 'react';\nimport { InputMapping } from './class';\nimport { InputMappingContext } from './context';\nimport type { FieldMetadata, ObBase } from './types';\nimport {\n\tcreateInputMappingGranularHook,\n\tInputMappingStore,\n} from '../hooks/useInputMappingGranular';\n\ntype FCC = React.FC<{ children: ReactNode }>;\n\ninterface createFormInstantContainerReturn<Ob extends Record<ObBase, any>> {\n\tuseInputMapping: Context<InputMapping<Ob>>;\n\tFormInstantInputsProvider: FCC;\n}\n\n// Create the granular hook once for reuse\n// Cast to match the expected type (InputMappingContext is typed as non-null but internally allows null)\nconst granularHooks = createInputMappingGranularHook(\n\tInputMappingContext as React.Context<InputMapping<any> | null>,\n);\n\n/**\n * Creates a form instant container with granular rendering enabled by default.\n * Automatically converts InputMapping to InputMappingStore if needed.\n *\n * @template Ob - The object structure defining the Inputs.\n * @param inputMapping - InputMapping or InputMappingStore instance.\n * @returns Object with FormInstantInputsProvider and useInputMapping hook.\n */\nexport const createFormInstantContainer = <Ob extends Record<any, any>>(\n\tinputMapping: InputMapping<Ob> | InputMappingStore<Ob>,\n) => {\n\t// Convert InputMapping to InputMappingStore if needed for granular rendering\n\tconst store: InputMappingStore<Ob> =\n\t\tinputMapping instanceof InputMappingStore\n\t\t\t? inputMapping\n\t\t\t: new InputMappingStore(Object.fromEntries(inputMapping.entries()) as any);\n\n\tconst FormInstantInputsProvider: FCC = (props) =>\n\t\tcreateElement(\n\t\t\tInputMappingContext.Provider,\n\t\t\t{\n\t\t\t\tvalue: store,\n\t\t\t},\n\t\t\tprops.children,\n\t\t);\n\n\tconst useInputMapping = () => use(InputMappingContext);\n\n\treturn {\n\t\tFormInstantInputsProvider,\n\t\tuseInputMapping,\n\t} as unknown as createFormInstantContainerReturn<Ob>;\n};\n\n/**\n * Component that renders the appropriate input component based on fieldType.\n * Uses granular rendering to only re-render when the specific fieldType's component changes.\n *\n * @param formProps - The parsed field properties including fieldType and name.\n */\nexport const ElementMapping: FC<{ formProps: FieldMetadata }> = memo(\n\t({ formProps }) => {\n\t\tconst Element =\n\t\t\tgranularHooks.useInputComponent(formProps.fieldType) ||\n\t\t\tgranularHooks.useInputComponent('fallback');\n\n\t\tif (!Element) return null;\n\n\t\treturn createElement(Element, formProps);\n\t},\n\t(prevProps, nextProps) => {\n\t\t// Only re-render if these specific values change\n\t\treturn (\n\t\t\tprevProps.formProps.fieldType === nextProps.formProps.fieldType &&\n\t\t\tprevProps.formProps.name.history === nextProps.formProps.name.history &&\n\t\t\tprevProps.formProps.name.current === nextProps.formProps.name.current\n\t\t);\n\t},\n);\n\nElementMapping.displayName = 'ElementMapping';\n",
8
+ "import type { SubscriptionCallback, UnsubscribeFunction } from '../types';\n\n/**\n * Manages subscriptions for specific keys.\n * Single Responsibility: Handle subscription and unsubscription operations.\n * \n * @internal\n */\nexport class SubscriptionManager {\n\tprivate readonly listeners = new Map<string, Set<SubscriptionCallback>>();\n\n\t/**\n\t * Subscribe to changes for a specific key.\n\t * \n\t * @param key - The key to subscribe to.\n\t * @param callback - Callback function to execute when the key changes.\n\t * @returns Unsubscribe function.\n\t */\n\tsubscribe(key: string, callback: SubscriptionCallback): UnsubscribeFunction {\n\t\tif (!this.listeners.has(key)) {\n\t\t\tthis.listeners.set(key, new Set());\n\t\t}\n\t\tthis.listeners.get(key)!.add(callback);\n\t\treturn () => this.unsubscribe(key, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from changes for a specific key.\n\t * \n\t * @param key - The key to unsubscribe from.\n\t * @param callback - Callback function to remove.\n\t */\n\tunsubscribe(key: string, callback: SubscriptionCallback): void {\n\t\tthis.listeners.get(key)?.delete(callback);\n\t}\n\n\t/**\n\t * Get all listeners for a specific key.\n\t * \n\t * @param key - The key to get listeners for.\n\t * @returns Set of callbacks for the key, or undefined if no listeners.\n\t * @internal\n\t */\n\tgetListeners(key: string): Set<SubscriptionCallback> | undefined {\n\t\treturn this.listeners.get(key);\n\t}\n\n\t/**\n\t * Check if there are any listeners for a key.\n\t * \n\t * @param key - The key to check.\n\t * @returns True if there are listeners, false otherwise.\n\t * @internal\n\t */\n\thasListeners(key: string): boolean {\n\t\treturn this.listeners.has(key) && this.listeners.get(key)!.size > 0;\n\t}\n\n\t/**\n\t * Clear all subscriptions.\n\t * \n\t * @internal\n\t */\n\tclear(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n",
9
+ "import type { SubscriptionManager } from './subscription-manager';\n\n/**\n * Service responsible for notifying subscribers about changes.\n * Single Responsibility: Handle notification logic.\n * \n * @internal\n */\nexport class NotificationService {\n\t/**\n\t * Notify all listeners for a specific key.\n\t * \n\t * @param subscriptionManager - The subscription manager instance.\n\t * @param key - The key that changed.\n\t */\n\tstatic notify(subscriptionManager: SubscriptionManager, key: string): void {\n\t\tconst listeners = subscriptionManager.getListeners(key);\n\t\tif (listeners) {\n\t\t\tlisteners.forEach((callback) => callback());\n\t\t}\n\t}\n\n\t/**\n\t * Notify all listeners for multiple keys.\n\t * \n\t * @param subscriptionManager - The subscription manager instance.\n\t * @param keys - Array of keys that changed.\n\t */\n\tstatic notifyMany(subscriptionManager: SubscriptionManager, keys: string[]): void {\n\t\tkeys.forEach((key) => this.notify(subscriptionManager, key));\n\t}\n}\n",
10
+ "import type { FC } from 'react';\nimport { SubscriptionManager } from '../../domain/services/subscription-manager';\nimport { NotificationService } from '../../domain/services/notification-service';\nimport type { SubscriptionCallback, UnsubscribeFunction } from '../../domain/types';\nimport { InputMapping } from '../../../../InputMapping/class';\nimport type { INPUT_COMPONENTS_KEYS } from '../../../../InputMapping/types';\n\n/**\n * Extended InputMapping class with subscription system for granular rendering.\n * Allows components to subscribe only to specific fieldType changes.\n *\n * Infrastructure layer: Concrete implementation of InputMapping with subscription capabilities.\n *\n * @template Ob - The object structure defining the Inputs.\n */\nexport class InputMappingStore<Ob extends Record<string, any>> extends InputMapping<Ob> {\n\tprivate _subscriptionManager?: SubscriptionManager;\n\n\t/**\n\t * Lazy getter for subscriptionManager to ensure it's initialized\n\t * even when called during parent class construction.\n\t */\n\tprivate get subscriptionManager(): SubscriptionManager {\n\t\tif (!this._subscriptionManager) {\n\t\t\tthis._subscriptionManager = new SubscriptionManager();\n\t\t}\n\t\treturn this._subscriptionManager;\n\t}\n\n\t/**\n\t * Subscribe to changes for a specific key.\n\t *\n\t * @param key - The key to subscribe to (fieldType).\n\t * @param callback - Callback function to execute when the key changes.\n\t * @returns Unsubscribe function.\n\t */\n\tsubscribe(key: string, callback: SubscriptionCallback): UnsubscribeFunction {\n\t\treturn this.subscriptionManager.subscribe(key, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from changes for a specific key.\n\t *\n\t * @param key - The key to unsubscribe from.\n\t * @param callback - Callback function to remove.\n\t */\n\tunsubscribe(key: string, callback: SubscriptionCallback): void {\n\t\tthis.subscriptionManager.unsubscribe(key, callback);\n\t}\n\n\t/**\n\t * Override set to notify subscribers when a new component is added.\n\t */\n\toverride set(k: keyof Ob | INPUT_COMPONENTS_KEYS, v: FC<any>): this {\n\t\tconst changed = !super.has(k);\n\t\tsuper.set(k, v);\n\t\tif (changed) {\n\t\t\tNotificationService.notify(this.subscriptionManager, String(k));\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Override delete to notify subscribers when a component is removed.\n\t */\n\toverride delete(k: keyof Ob | INPUT_COMPONENTS_KEYS): boolean {\n\t\tconst result = super.delete(k);\n\t\tif (result) {\n\t\t\tNotificationService.notify(this.subscriptionManager, String(k));\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Override clear to notify all subscribers when the store is cleared.\n\t */\n\toverride clear(): void {\n\t\tconst keys = Array.from(this.keys()).map((k) => String(k));\n\t\tsuper.clear();\n\t\tNotificationService.notifyMany(this.subscriptionManager, keys);\n\t}\n}\n",
11
+ "import { use, useSyncExternalStore } from 'react';\nimport type { FC } from 'react';\nimport { validateStoreInstance } from '../validators/store-validator';\nimport type { InputMappingStore } from '../../infrastructure/store/input-mapping-store';\nimport type { InputMapping } from '@pkg/react-input-mapping';\n\n/**\n * Hook to get a component for a specific fieldType with granular subscription.\n * Only re-renders when the component for this specific fieldType changes.\n * Single Responsibility: Component retrieval with granular subscription.\n *\n * @param InputMappingContext - React Context containing the InputMapping instance.\n * @param fieldType - The fieldType to get the component for.\n * @returns The React component for the fieldType, or undefined if not found.\n */\nexport function useInputComponent<Ob extends Record<string, any>>(\n\tInputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>,\n\tfieldType: string,\n): FC<any> | undefined {\n\t// Normalize context type for use() hook compatibility\n\tconst normalizedContext = InputMappingContext as React.Context<InputMapping<Ob> | null>;\n\tconst store = use(normalizedContext)!;\n\n\t// Validate that the store is an instance of InputMappingStore\n\tvalidateStoreInstance(store);\n\n\t// Use useSyncExternalStore for granular subscription\n\treturn useSyncExternalStore(\n\t\t(onStoreChange) => (store as InputMappingStore<Ob>).subscribe(fieldType, onStoreChange),\n\t\t() => store.get(fieldType),\n\t\t() => store.get(fieldType), // SSR snapshot\n\t);\n}\n",
12
+ "import { InputMappingStore, type InputMapping } from \"@pkg/react-input-mapping\";\n\n\n/**\n * Validates that a store instance is an InputMappingStore.\n * Single Responsibility: Validation logic.\n *\n * @param store - The store instance to validate.\n * @throws {Error} If the store is not an instance of InputMappingStore.\n */\nexport function validateStoreInstance<Ob extends Record<string, unknown>>(\n\tstore: InputMapping<Ob>,\n): asserts store is InputMappingStore<Ob> {\n\tif (!(store instanceof InputMappingStore)) {\n\t\tthrow new Error(\n\t\t\t'InputMapping must be an instance of InputMappingStore for granular rendering',\n\t\t);\n\t}\n}\n",
13
+ "import { use, useMemo } from 'react';\nimport { validateStoreInstance } from '../validators/store-validator';\nimport type { InputMappingStore } from '../../infrastructure/store/input-mapping-store';\nimport type { InputMapping } from '@pkg/react-input-mapping';\n\n/**\n * Hook to get stable methods for modifying the InputMapping.\n * Methods don't change between renders and don't cause global re-renders.\n * Single Responsibility: Provide stable action methods.\n *\n * @template Ob - The object structure defining the Inputs.\n * @param InputMappingContext - React Context containing the InputMapping instance.\n * @returns Object with set, clear, and delete methods.\n */\nexport function useInputMappingActions<Ob extends Record<string, any>>(\n\tInputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>,\n) {\n\t// Normalize context type for use() hook compatibility\n\tconst normalizedContext = InputMappingContext as React.Context<InputMapping<Ob> | null>;\n\tconst store = use(normalizedContext)!;\n\n\t// Validate that the store is an instance of InputMappingStore\n\tvalidateStoreInstance(store);\n\n\tconst storeInstance = store as InputMappingStore<Ob>;\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tset: (key: keyof Ob | string, value: React.FC<any>) => {\n\t\t\t\treturn storeInstance.set(key, value);\n\t\t\t},\n\t\t\tclear: () => {\n\t\t\t\tstoreInstance.clear();\n\t\t\t},\n\t\t\tdelete: (key: keyof Ob | string) => {\n\t\t\t\treturn storeInstance.delete(key);\n\t\t\t},\n\t\t}),\n\t\t[storeInstance],\n\t);\n}\n",
14
+ "import type { InputMapping } from '@pkg/react-input-mapping';\nimport { useInputComponent } from '../hooks/use-input-component';\nimport { useInputMappingActions } from '../hooks/use-input-mapping-actions';\n\n/**\n * Factory function to create granular hooks for InputMapping.\n * Returns hooks that enable granular rendering by subscribing only to specific fieldType changes.\n * Single Responsibility: Factory for creating hook instances.\n *\n * @template Ob - The object structure defining the Inputs.\n * @param InputMappingContext - React Context containing the InputMapping instance.\n * @returns Object with hooks for granular component access and actions.\n */\nexport function createInputMappingGranularHook<Ob extends Record<string, any>>(\n\tInputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>,\n) {\n\t/**\n\t * Hook to get a component for a specific fieldType with granular subscription.\n\t * Only re-renders when the component for this specific fieldType changes.\n\t *\n\t * @param fieldType - The fieldType to get the component for.\n\t * @returns The React component for the fieldType, or undefined if not found.\n\t */\n\tfunction useInputComponentHook(fieldType: string) {\n\t\treturn useInputComponent(InputMappingContext, fieldType);\n\t}\n\n\t/**\n\t * Hook to get stable methods for modifying the InputMapping.\n\t * Methods don't change between renders and don't cause global re-renders.\n\t *\n\t * @returns Object with set, clear, and delete methods.\n\t */\n\tfunction useInputMappingActionsHook() {\n\t\treturn useInputMappingActions(InputMappingContext);\n\t}\n\n\treturn {\n\t\tuseInputComponent: useInputComponentHook,\n\t\tuseInputMappingActions: useInputMappingActionsHook,\n\t};\n}\n",
15
+ "import { useCallback, useState } from 'react';\nimport type { FieldMetadata } from '../../../InputMapping';\nimport type { UseInputArrayProps } from '../types';\nimport { cloneFieldWithIndex } from '../domain/services/cloneFieldWithIndex';\n\nexport const useInputArray = (data: FieldMetadata) => {\n const { fieldConfig, name, ...prop } = data as UseInputArrayProps;\n const arrayName = name.history || name.current;\n const template = prop.schema.at(0)!;\n\n // Ensure inputs is always an array type\n const [inputs, setInputs] = useState<Record<string, FieldMetadata>[]>([]);\n\n const append = useCallback(() => {\n const max = fieldConfig?.max ?? Infinity;\n // Inputs can be undefined if schema was undefined and initialInputs is [] casted to SchemaArray (which might be strict)\n // But initialInputs is initialized to [] used as fallback.\n const currentLength = Number(inputs?.length);\n if (currentLength >= max) return;\n\n setInputs((pre) => {\n // Clone the template and update names with the new index\n const newIndex = pre.length;\n const newItem = cloneFieldWithIndex(template, newIndex, arrayName) as Record<\n string,\n FieldMetadata\n >;\n\n return [...pre, newItem];\n });\n }, [inputs, fieldConfig?.max, arrayName, template]); // Original deps: [inputs, fieldConfig?.max, arrayName]. Template is closed over. I should probably add it or leave it. Refactoring usually implies fixing linter errors. I'll Include template if linter complains, otherwise keep original. Original deps: [inputs, fieldConfig?.max, arrayName].\n\n const remove = useCallback(\n (index: number) => {\n const min = fieldConfig?.min ?? 0;\n const currentLength = inputs?.length || 0;\n if (currentLength > min) {\n setInputs((pre) => {\n // Ensure pre is always an array\n const filtered = pre.filter((_, i) => i !== index);\n // Update indices for remaining items\n return filtered.map((item, newIndex) => {\n return cloneFieldWithIndex(item, newIndex, arrayName) as Record<\n string,\n FieldMetadata\n >;\n });\n });\n }\n },\n [inputs, fieldConfig?.min, arrayName],\n );\n\n return { inputs, append, remove, setInputs, fieldConfig, name, ...prop };\n};\n",
16
+ "import type { ParsedField } from '../../../../InputMapping';\n\n/**\n * Type guard to check if a value is a ParsedField\n * @param item - The item to check\n * @returns True if item is a ParsedField\n */\nexport function isParsedField(item: any): item is ParsedField<any, string> {\n return item && typeof item === 'object' && 'name' in item && 'fieldType' in item;\n}\n",
17
+ "import type { FieldMetadata, ParsedField } from '../../../../InputMapping';\nimport { isParsedField } from '../guards/isParsedField';\n\n/**\n * Helper function to deep clone a ParsedField and update names with new index\n * @param field - The field to clone\n * @param newIndex - The new index to apply\n * @param arrayName - The name of the array\n * @returns The cloned field or record of fields with updated index\n */\nexport function cloneFieldWithIndex(\n field:\n | ParsedField<any, string>\n | Record<string, ParsedField<any, string>>\n | FieldMetadata\n | Record<string, FieldMetadata>,\n newIndex: number,\n arrayName: string,\n): ParsedField<any, string> | Record<string, ParsedField<any, string>> {\n // Handle Record<string, ParsedField>\n if (!isParsedField(field)) {\n const newStructure: Record<string, ParsedField<any, string>> = {};\n for (const key in field) {\n const val = (field as any)[key];\n if (!val) continue;\n // Recursive call - result is ParsedField because val is ParsedField\n // (assuming structure is Record<string, ParsedField>)\n newStructure[key] = cloneFieldWithIndex(val, newIndex, arrayName) as ParsedField<\n any,\n string\n >;\n }\n return newStructure;\n }\n\n // Handle ParsedField\n // Extract the field name from the current history (e.g., \"items.0.name\" -> \"name\")\n const fieldName = field.name.current;\n const newHistory = `${arrayName}.${newIndex}.${fieldName}`;\n\n const cloned = {\n ...field,\n name: {\n current: fieldName,\n history: newHistory,\n },\n } as ParsedField<any, string>;\n\n if (field.schema && Array.isArray(field.schema)) {\n cloned.schema = field.schema.map((subField) =>\n cloneFieldWithIndex(subField as ParsedField<any, string>, newIndex, arrayName),\n );\n }\n\n return cloned;\n}\n",
18
+ "import { useReducer, useRef, use } from 'react';\nimport { InputMapping } from '../InputMapping/class';\n\nexport function createInputMappingHook<Ob extends Record<string, any>>(\n\tInputMappingContext: React.Context<InputMapping<Ob> | null>,\n) {\n\treturn function useInputMapping() {\n\t\tconst initialState = use(InputMappingContext);\n\t\tif (!initialState) throw new Error('InputMappingContext not found');\n\t\tconst mapRef = useRef(initialState);\n\t\tconst [, reRender] = useReducer((x) => x + 1, 0);\n\n\t\treturn {\n\t\t\t...mapRef.current,\n\t\t\tset: (key: keyof Ob | string, value: React.FC<any>) => {\n\t\t\t\tconst result = mapRef.current.set(key, value);\n\t\t\t\treRender();\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tclear: () => {\n\t\t\t\tmapRef.current.clear();\n\t\t\t\treRender();\n\t\t\t},\n\t\t\tdelete: (key: keyof Ob | string) => {\n\t\t\t\tconst result = mapRef.current.delete(key);\n\t\t\t\treRender();\n\t\t\t\treturn result;\n\t\t\t},\n\t\t};\n\t};\n}\n"
10
19
  ],
11
- "mappings": "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",
12
- "debugId": "C50C3835C1CFBF1864756E2164756E21",
20
+ "mappings": "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",
21
+ "debugId": "FEDB4F6DC6D16F3364756E2164756E21",
13
22
  "names": []
14
23
  }
@@ -0,0 +1,81 @@
1
+ import type { FC } from 'react';
2
+ import type { FieldConfig, INPUT_COMPONENTS_KEYS } from '.';
3
+ /**
4
+ * Auxiliary type to map each key to its corresponding React component.
5
+ * Values can either be specific Input types from the generic object `Ob`
6
+ * or predefined keys from `INPUT_COMPONENTS_KEYS`.
7
+ *
8
+ * @template Ob - The object structure defining the Inputs and their types.
9
+ */
10
+ type InputComponentMap<Ob extends Record<string, any>> = {
11
+ [K in keyof Ob]?: FC<FieldConfig<Ob[K]>>;
12
+ } & {
13
+ [K in INPUT_COMPONENTS_KEYS]?: FC<any>;
14
+ };
15
+ /**
16
+ * Class representing a mapping between Input keys and React components.
17
+ * Extends the native `Map` class to handle component associations for specific object Inputs
18
+ * and generic input component keys.
19
+ *
20
+ * @template Ob - The object structure defining the Inputs.
21
+ */
22
+ export declare class InputMapping<Ob extends Record<string, any>> extends Map<keyof Ob | INPUT_COMPONENTS_KEYS, FC<any>> {
23
+ /**
24
+ * Internal method to populate the mapping from a partial object.
25
+ *
26
+ * @param obj - A partial mapping of keys to components.
27
+ * @private
28
+ */
29
+ private appendObj;
30
+ /**
31
+ * Initializes a new instance of the InputMapping class.
32
+ *
33
+ * @param obj - An optional initial set of key-to-component mappings.
34
+ */
35
+ constructor(obj?: Partial<InputComponentMap<Ob>>);
36
+ /**
37
+ * Checks if a specific key exists in the mapping.
38
+ *
39
+ * @param k - The key to check.
40
+ * @returns The key itself if it exists, otherwise returns 'fallback'.
41
+ */
42
+ exists(k: string): INPUT_COMPONENTS_KEYS | keyof Ob;
43
+ /**
44
+ * Retrieves the component associated with a specific key.
45
+ *
46
+ * @template Ky - The type of the key, which must be a key of `Ob` or `INPUT_COMPONENTS_KEYS`.
47
+ * @param k - The key to retrieve the component for.
48
+ * @returns The React component associated with the key, or undefined if not found.
49
+ */
50
+ get<Ky extends keyof Ob | INPUT_COMPONENTS_KEYS>(k: Ky): FC<any> | undefined;
51
+ /**
52
+ * Associates a React component with a specific Input from the object `Ob`.
53
+ *
54
+ * @template K - A key from the object structure `Ob`.
55
+ * @param k - The key to set.
56
+ * @param v - The React component to associate with the key.
57
+ * @returns The current class instance for method chaining.
58
+ */
59
+ set<K extends keyof Ob>(k: K, v: FC<Ob[K]>): this;
60
+ /**
61
+ * Associates a React component with a predefined input component key.
62
+ *
63
+ * @template K - A key from the `INPUT_COMPONENTS_KEYS` type.
64
+ * @param k - The key to set.
65
+ * @param v - The React component to associate with the key.
66
+ * @returns The current class instance for method chaining.
67
+ */
68
+ set<K extends INPUT_COMPONENTS_KEYS>(k: K, v: FC<any>): this;
69
+ /**
70
+ * Creates a new `InputMapping` instance by extending the current mapping with new associations.
71
+ * Useful for building complex mappings incrementally.
72
+ *
73
+ * @template Ext - The type representing the additional mappings.
74
+ * @param cb - A callback function that receives the current mapping and returns the extensions.
75
+ * @returns A new `InputMapping` instance containing both original and extended mappings.
76
+ */
77
+ extends<Ext extends Record<string, FC<any>>>(cb: (mapping: InputMapping<Ob & {
78
+ [K in keyof Ext]: any;
79
+ }>) => Ext): InputMapping<Ob & { [K in keyof Ext]: any; }>;
80
+ }
81
+ export {};
@@ -0,0 +1,7 @@
1
+ export * from './class';
2
+ export * from './context';
3
+ export * from './provider';
4
+ export * from './types';
5
+ export * from '../hooks/useInputArray';
6
+ export * from '../hooks/useInputMapping';
7
+ export * from '../hooks/useInputMappingGranular';
@@ -0,0 +1,30 @@
1
+ import type { Context, FC, ReactNode } from 'react';
2
+ import { InputMapping } from './class';
3
+ import type { FieldMetadata, ObBase } from './types';
4
+ import { InputMappingStore } from '../hooks/useInputMappingGranular';
5
+ type FCC = React.FC<{
6
+ children: ReactNode;
7
+ }>;
8
+ interface createFormInstantContainerReturn<Ob extends Record<ObBase, any>> {
9
+ useInputMapping: Context<InputMapping<Ob>>;
10
+ FormInstantInputsProvider: FCC;
11
+ }
12
+ /**
13
+ * Creates a form instant container with granular rendering enabled by default.
14
+ * Automatically converts InputMapping to InputMappingStore if needed.
15
+ *
16
+ * @template Ob - The object structure defining the Inputs.
17
+ * @param inputMapping - InputMapping or InputMappingStore instance.
18
+ * @returns Object with FormInstantInputsProvider and useInputMapping hook.
19
+ */
20
+ export declare const createFormInstantContainer: <Ob extends Record<any, any>>(inputMapping: InputMapping<Ob> | InputMappingStore<Ob>) => createFormInstantContainerReturn<Ob>;
21
+ /**
22
+ * Component that renders the appropriate input component based on fieldType.
23
+ * Uses granular rendering to only re-render when the specific fieldType's component changes.
24
+ *
25
+ * @param formProps - The parsed field properties including fieldType and name.
26
+ */
27
+ export declare const ElementMapping: FC<{
28
+ formProps: FieldMetadata;
29
+ }>;
30
+ export {};
@@ -9,7 +9,7 @@ export interface ParsedField<AdditionalRenderable, FieldTypes = string> {
9
9
  default?: unknown;
10
10
  fieldConfig?: FieldConfig<AdditionalRenderable>;
11
11
  options?: [string, string][];
12
- schema?: ParsedField<AdditionalRenderable, FieldTypes>[];
12
+ schema?: (ParsedField<AdditionalRenderable, FieldTypes> | Record<string, ParsedField<AdditionalRenderable, FieldTypes>>)[];
13
13
  }
14
14
  export type FieldConfig<AdditionalRenderable = object> = {
15
15
  type?: string;
@@ -17,3 +17,6 @@ export type FieldConfig<AdditionalRenderable = object> = {
17
17
  max?: number;
18
18
  } & AdditionalRenderable;
19
19
  export type ObBase = INPUT_COMPONENTS_KEYS;
20
+ export type FieldMetadata = Omit<ParsedField<any, string>, 'schema'> & {
21
+ schema?: Record<string, FieldMetadata> | Record<string, FieldMetadata>[];
22
+ };
@@ -0,0 +1,17 @@
1
+ import type { FieldMetadata } from '../../../InputMapping';
2
+ export declare const useInputArray: (data: FieldMetadata) => {
3
+ schema: Record<string, FieldMetadata>[];
4
+ default?: any[];
5
+ fieldType: string;
6
+ required: boolean;
7
+ options?: [string, string][] | undefined;
8
+ inputs: Record<string, FieldMetadata>[];
9
+ append: () => void;
10
+ remove: (index: number) => void;
11
+ setInputs: import("react").Dispatch<import("react").SetStateAction<Record<string, FieldMetadata>[]>>;
12
+ fieldConfig: any;
13
+ name: {
14
+ current: string;
15
+ history: string;
16
+ };
17
+ };
@@ -0,0 +1,7 @@
1
+ import type { ParsedField } from '../../../../InputMapping';
2
+ /**
3
+ * Type guard to check if a value is a ParsedField
4
+ * @param item - The item to check
5
+ * @returns True if item is a ParsedField
6
+ */
7
+ export declare function isParsedField(item: any): item is ParsedField<any, string>;
@@ -0,0 +1,9 @@
1
+ import type { FieldMetadata, ParsedField } from '../../../../InputMapping';
2
+ /**
3
+ * Helper function to deep clone a ParsedField and update names with new index
4
+ * @param field - The field to clone
5
+ * @param newIndex - The new index to apply
6
+ * @param arrayName - The name of the array
7
+ * @returns The cloned field or record of fields with updated index
8
+ */
9
+ export declare function cloneFieldWithIndex(field: ParsedField<any, string> | Record<string, ParsedField<any, string>> | FieldMetadata | Record<string, FieldMetadata>, newIndex: number, arrayName: string): ParsedField<any, string> | Record<string, ParsedField<any, string>>;
@@ -0,0 +1,2 @@
1
+ export * from './application/useInputArray';
2
+ export * from './types';
@@ -0,0 +1,8 @@
1
+ import type { FieldMetadata } from '../../../InputMapping';
2
+ /**
3
+ * Props for the useInputArray hook
4
+ */
5
+ export interface UseInputArrayProps extends FieldMetadata {
6
+ schema: Record<string, FieldMetadata>[];
7
+ default?: any[];
8
+ }
@@ -0,0 +1,14 @@
1
+ import { InputMapping } from '../InputMapping/class';
2
+ export declare function createInputMappingHook<Ob extends Record<string, any>>(InputMappingContext: React.Context<InputMapping<Ob> | null>): () => {
3
+ set: (key: keyof Ob | string, value: React.FC<any>) => InputMapping<Ob>;
4
+ clear: () => void;
5
+ delete: (key: keyof Ob | string) => boolean;
6
+ forEach(callbackfn: (value: import("react").FC<any>, key: import("..").INPUT_COMPONENTS_KEYS | keyof Ob, map: Map<import("..").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>>) => void, thisArg?: any): void;
7
+ has(key: import("..").INPUT_COMPONENTS_KEYS | keyof Ob): boolean;
8
+ size: number;
9
+ entries(): MapIterator<[import("..").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>]>;
10
+ keys(): MapIterator<import("..").INPUT_COMPONENTS_KEYS | keyof Ob>;
11
+ values(): MapIterator<import("react").FC<any>>;
12
+ [Symbol.iterator](): MapIterator<[import("..").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>]>;
13
+ [Symbol.toStringTag]: string;
14
+ };
@@ -0,0 +1,18 @@
1
+ import type { InputMapping } from '@pkg/react-input-mapping';
2
+ /**
3
+ * Factory function to create granular hooks for InputMapping.
4
+ * Returns hooks that enable granular rendering by subscribing only to specific fieldType changes.
5
+ * Single Responsibility: Factory for creating hook instances.
6
+ *
7
+ * @template Ob - The object structure defining the Inputs.
8
+ * @param InputMappingContext - React Context containing the InputMapping instance.
9
+ * @returns Object with hooks for granular component access and actions.
10
+ */
11
+ export declare function createInputMappingGranularHook<Ob extends Record<string, any>>(InputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>): {
12
+ useInputComponent: (fieldType: string) => import("react").FC<any> | undefined;
13
+ useInputMappingActions: () => {
14
+ set: (key: string | keyof Ob, value: React.FC<any>) => import("@pkg/react-input-mapping").InputMappingStore<Ob>;
15
+ clear: () => void;
16
+ delete: (key: string | keyof Ob) => boolean;
17
+ };
18
+ };
@@ -0,0 +1,2 @@
1
+ export * from './use-input-component';
2
+ export * from './use-input-mapping-actions';
@@ -0,0 +1,12 @@
1
+ import type { FC } from 'react';
2
+ import type { InputMapping } from '@pkg/react-input-mapping';
3
+ /**
4
+ * Hook to get a component for a specific fieldType with granular subscription.
5
+ * Only re-renders when the component for this specific fieldType changes.
6
+ * Single Responsibility: Component retrieval with granular subscription.
7
+ *
8
+ * @param InputMappingContext - React Context containing the InputMapping instance.
9
+ * @param fieldType - The fieldType to get the component for.
10
+ * @returns The React component for the fieldType, or undefined if not found.
11
+ */
12
+ export declare function useInputComponent<Ob extends Record<string, any>>(InputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>, fieldType: string): FC<any> | undefined;
@@ -0,0 +1,16 @@
1
+ import type { InputMappingStore } from '../../infrastructure/store/input-mapping-store';
2
+ import type { InputMapping } from '@pkg/react-input-mapping';
3
+ /**
4
+ * Hook to get stable methods for modifying the InputMapping.
5
+ * Methods don't change between renders and don't cause global re-renders.
6
+ * Single Responsibility: Provide stable action methods.
7
+ *
8
+ * @template Ob - The object structure defining the Inputs.
9
+ * @param InputMappingContext - React Context containing the InputMapping instance.
10
+ * @returns Object with set, clear, and delete methods.
11
+ */
12
+ export declare function useInputMappingActions<Ob extends Record<string, any>>(InputMappingContext: React.Context<InputMapping<Ob> | null> | React.Context<InputMapping<Ob>>): {
13
+ set: (key: keyof Ob | string, value: React.FC<any>) => InputMappingStore<Ob>;
14
+ clear: () => void;
15
+ delete: (key: keyof Ob | string) => boolean;
16
+ };
@@ -0,0 +1,9 @@
1
+ import { InputMappingStore, type InputMapping } from "@pkg/react-input-mapping";
2
+ /**
3
+ * Validates that a store instance is an InputMappingStore.
4
+ * Single Responsibility: Validation logic.
5
+ *
6
+ * @param store - The store instance to validate.
7
+ * @throws {Error} If the store is not an instance of InputMappingStore.
8
+ */
9
+ export declare function validateStoreInstance<Ob extends Record<string, unknown>>(store: InputMapping<Ob>): asserts store is InputMappingStore<Ob>;
@@ -0,0 +1,2 @@
1
+ export * from './subscription-manager';
2
+ export * from './notification-service';
@@ -0,0 +1,23 @@
1
+ import type { SubscriptionManager } from './subscription-manager';
2
+ /**
3
+ * Service responsible for notifying subscribers about changes.
4
+ * Single Responsibility: Handle notification logic.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare class NotificationService {
9
+ /**
10
+ * Notify all listeners for a specific key.
11
+ *
12
+ * @param subscriptionManager - The subscription manager instance.
13
+ * @param key - The key that changed.
14
+ */
15
+ static notify(subscriptionManager: SubscriptionManager, key: string): void;
16
+ /**
17
+ * Notify all listeners for multiple keys.
18
+ *
19
+ * @param subscriptionManager - The subscription manager instance.
20
+ * @param keys - Array of keys that changed.
21
+ */
22
+ static notifyMany(subscriptionManager: SubscriptionManager, keys: string[]): void;
23
+ }
@@ -0,0 +1,47 @@
1
+ import type { SubscriptionCallback, UnsubscribeFunction } from '../types';
2
+ /**
3
+ * Manages subscriptions for specific keys.
4
+ * Single Responsibility: Handle subscription and unsubscription operations.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare class SubscriptionManager {
9
+ private readonly listeners;
10
+ /**
11
+ * Subscribe to changes for a specific key.
12
+ *
13
+ * @param key - The key to subscribe to.
14
+ * @param callback - Callback function to execute when the key changes.
15
+ * @returns Unsubscribe function.
16
+ */
17
+ subscribe(key: string, callback: SubscriptionCallback): UnsubscribeFunction;
18
+ /**
19
+ * Unsubscribe from changes for a specific key.
20
+ *
21
+ * @param key - The key to unsubscribe from.
22
+ * @param callback - Callback function to remove.
23
+ */
24
+ unsubscribe(key: string, callback: SubscriptionCallback): void;
25
+ /**
26
+ * Get all listeners for a specific key.
27
+ *
28
+ * @param key - The key to get listeners for.
29
+ * @returns Set of callbacks for the key, or undefined if no listeners.
30
+ * @internal
31
+ */
32
+ getListeners(key: string): Set<SubscriptionCallback> | undefined;
33
+ /**
34
+ * Check if there are any listeners for a key.
35
+ *
36
+ * @param key - The key to check.
37
+ * @returns True if there are listeners, false otherwise.
38
+ * @internal
39
+ */
40
+ hasListeners(key: string): boolean;
41
+ /**
42
+ * Clear all subscriptions.
43
+ *
44
+ * @internal
45
+ */
46
+ clear(): void;
47
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Domain types for InputMapping granular rendering system.
3
+ */
4
+ /**
5
+ * Callback function type for subscription notifications.
6
+ */
7
+ export type SubscriptionCallback = () => void;
8
+ /**
9
+ * Unsubscribe function type.
10
+ */
11
+ export type UnsubscribeFunction = () => void;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Granular rendering hooks for InputMapping.
3
+ *
4
+ * This module provides:
5
+ * - InputMappingStore: Extended InputMapping with subscription system
6
+ * - createInputMappingGranularHook: Factory for creating granular hooks
7
+ *
8
+ * Architecture: Hexagonal (Domain/Application/Infrastructure)
9
+ * Principles: SOLID (SRP, OCP, DIP)
10
+ */
11
+ export { InputMappingStore } from './infrastructure/store/input-mapping-store';
12
+ export { createInputMappingGranularHook } from './application/factory/create-granular-hook';
13
+ export type { SubscriptionCallback, UnsubscribeFunction } from './domain/types';
@@ -0,0 +1,47 @@
1
+ import type { FC } from 'react';
2
+ import type { SubscriptionCallback, UnsubscribeFunction } from '../../domain/types';
3
+ import { InputMapping } from '../../../../InputMapping/class';
4
+ import type { INPUT_COMPONENTS_KEYS } from '../../../../InputMapping/types';
5
+ /**
6
+ * Extended InputMapping class with subscription system for granular rendering.
7
+ * Allows components to subscribe only to specific fieldType changes.
8
+ *
9
+ * Infrastructure layer: Concrete implementation of InputMapping with subscription capabilities.
10
+ *
11
+ * @template Ob - The object structure defining the Inputs.
12
+ */
13
+ export declare class InputMappingStore<Ob extends Record<string, any>> extends InputMapping<Ob> {
14
+ private _subscriptionManager?;
15
+ /**
16
+ * Lazy getter for subscriptionManager to ensure it's initialized
17
+ * even when called during parent class construction.
18
+ */
19
+ private get subscriptionManager();
20
+ /**
21
+ * Subscribe to changes for a specific key.
22
+ *
23
+ * @param key - The key to subscribe to (fieldType).
24
+ * @param callback - Callback function to execute when the key changes.
25
+ * @returns Unsubscribe function.
26
+ */
27
+ subscribe(key: string, callback: SubscriptionCallback): UnsubscribeFunction;
28
+ /**
29
+ * Unsubscribe from changes for a specific key.
30
+ *
31
+ * @param key - The key to unsubscribe from.
32
+ * @param callback - Callback function to remove.
33
+ */
34
+ unsubscribe(key: string, callback: SubscriptionCallback): void;
35
+ /**
36
+ * Override set to notify subscribers when a new component is added.
37
+ */
38
+ set(k: keyof Ob | INPUT_COMPONENTS_KEYS, v: FC<any>): this;
39
+ /**
40
+ * Override delete to notify subscribers when a component is removed.
41
+ */
42
+ delete(k: keyof Ob | INPUT_COMPONENTS_KEYS): boolean;
43
+ /**
44
+ * Override clear to notify all subscribers when the store is cleared.
45
+ */
46
+ clear(): void;
47
+ }
package/package.json CHANGED
@@ -1,6 +1,21 @@
1
1
  {
2
+ "type": "module",
3
+ "private": false,
4
+ "license": "MIT",
5
+ "version": "2.0.2",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/src/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/src/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
2
18
  "name": "@form-instant/react-input-mapping",
3
- "version": "1.9.0",
4
19
  "author": {
5
20
  "name": "leomerida15",
6
21
  "email": "dimasmerida15@gmail.com",
@@ -10,68 +25,36 @@
10
25
  "type": "git",
11
26
  "url": "git+https://github.com/leomerida15/form-instant-react-mapping.git"
12
27
  },
13
- "main": "dist/index.js",
14
- "module": "dist/index.js",
15
- "devDependencies": {
16
- "@size-limit/preset-small-lib": "^11.2.0",
17
- "@testing-library/jest-dom": "^6.7.0",
18
- "@tsconfig/recommended": "^1.0.10",
19
- "@tsconfig/vite-react": "^3.4.0",
20
- "@types/bun": "^1.2.20",
21
- "@types/jest": "^29.5.14",
22
- "@types/minimatch": "^5.1.2",
23
- "@types/react": "^18.3.23",
24
- "@typescript-eslint/eslint-plugin": "^7.18.0",
25
- "@typescript-eslint/parser": "^7.18.0",
26
- "docsify": "^4.13.1",
27
- "eslint": "^8.57.1",
28
- "eslint-plugin-prettier": "^5.5.4",
29
- "eslint-plugin-react": "^7.37.5",
30
- "eslint-plugin-react-hooks": "^4.6.2",
31
- "husky": "^9.1.7",
32
- "jest": "^29.7.0",
33
- "jest-environment-jsdom": "^29.7.0",
34
- "prettier": "^3.6.2",
35
- "ts-jest": "^29.4.1",
36
- "tslib": "^2.8.1",
37
- "typescript": "^5.9.2"
28
+ "scripts": {
29
+ "dev": "bun run bunpack.watch.ts",
30
+ "build": "bun run bunpack.build.ts",
31
+ "type:check": "bun x tsc --noEmit",
32
+ "build:types": "bun x tsc --project tsconfig.build.json",
33
+ "lint": "bun -b eslint --config ../../eslint.config.mjs src --ext .ts,.tsx",
34
+ "lint:fix": "bun -b eslint --config ../../eslint.config.mjs src --ext .ts,.tsx --fix",
35
+ "start": "bun run bunpack.watch.ts",
36
+ "watch": "bun run bunpack.watch.ts --build",
37
+ "docs": "bun run docs-serve.ts",
38
+ "docs:dev": "bun run docs.watch.ts"
39
+ },
40
+ "dependencies": {
41
+ "i": "^0.3.7"
38
42
  },
39
43
  "peerDependencies": {
40
- "react": "^19.1.0"
44
+ "react": "^19.2.4"
45
+ },
46
+ "devDependencies": {
47
+ "@types/react": "^19.2.10"
41
48
  },
42
49
  "engines": {
43
- "node": ">=18",
44
- "bun": ">=1.0.0"
50
+ "node": ">=22",
51
+ "bun": ">=1.3.0"
45
52
  },
46
- "files": [
47
- "dist"
48
- ],
49
53
  "homepage": "https://leomerida15.github.io/form-instant-react-mapping",
50
- "jest": {
51
- "testEnvironment": "jsdom"
52
- },
53
54
  "keywords": [
54
55
  "@form-instant",
55
56
  "react",
56
57
  "mapping",
57
58
  "form"
58
- ],
59
- "license": "MIT",
60
- "scripts": {
61
- "build": "bun run bunpack.build.ts",
62
- "build:types": "bun x tsc --project tsconfig.build.json",
63
- "lint": "eslint src",
64
- "lint:fix": "eslint src --fix",
65
- "start": "bun run bunpack.watch.ts",
66
- "watch": "bun run bunpack.watch.ts --build",
67
- "test": "jest --passWithNoTests",
68
- "docs": "bun run docs-serve.ts",
69
- "docs:dev": "bun run docs.watch.ts",
70
- "Up": "npm publish --access public",
71
- "Up:rc": "npm publish --access public --tag rc"
72
- },
73
- "typings": "dist/index.d.ts",
74
- "dependencies": {
75
- "minimatch": "^10.0.3"
76
- }
77
- }
59
+ ]
60
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 leomerida15
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,20 +0,0 @@
1
- import { FC } from 'react';
2
- import { INPUT_COMPONENTS_KEYS, ParsedField } from './types';
3
- type InputComponentMap<Ob extends Record<string, any>> = {
4
- [K in keyof Ob]?: FC<ParsedField<Ob[K]>>;
5
- } & {
6
- [K in INPUT_COMPONENTS_KEYS]?: FC<any>;
7
- };
8
- export declare class InputMapping<Ob extends Record<string, any>> extends Map<keyof Ob | INPUT_COMPONENTS_KEYS, FC<any>> {
9
- private zodAdacter;
10
- private appendObj;
11
- constructor(obj?: Partial<InputComponentMap<Ob>>);
12
- exists(k: string): INPUT_COMPONENTS_KEYS | keyof Ob;
13
- get<Ky extends keyof Ob | INPUT_COMPONENTS_KEYS>(k: Ky): FC<any> | undefined;
14
- set<K extends keyof Ob>(k: K, v: FC<Ob[K]>): this;
15
- set<K extends INPUT_COMPONENTS_KEYS>(k: K, v: FC<any>): this;
16
- extends<Ext extends Record<string, FC<any>>>(cb: (mapping: InputMapping<Ob & {
17
- [K in keyof Ext]: any;
18
- }>) => Ext): InputMapping<Ob & { [K in keyof Ext]: any; }>;
19
- }
20
- export {};
@@ -1,6 +0,0 @@
1
- export * from './class';
2
- export * from './context';
3
- export * from './provider';
4
- export * from './types';
5
- export * from './useFormInstantField';
6
- export * from './useInputMapping';
@@ -1,15 +0,0 @@
1
- import { Context, FC, ReactNode } from 'react';
2
- import { InputMapping } from './class';
3
- import { ObBase, ParsedField } from './types';
4
- type FCC = React.FC<{
5
- children: ReactNode;
6
- }>;
7
- interface createFormInstantContainerReturn<Ob extends Record<ObBase, any>> {
8
- useInputMapping: Context<InputMapping<Ob>>;
9
- FormInstantInputsProvider: FCC;
10
- }
11
- export declare const createFormInstantContainer: <Ob extends Record<any, any>>(inputMapping: InputMapping<Ob>) => createFormInstantContainerReturn<Ob>;
12
- export declare const ElementMapping: FC<{
13
- formProps: ParsedField<any, string>;
14
- }>;
15
- export {};
@@ -1,16 +0,0 @@
1
- import { ParsedField } from './types';
2
- export declare const useFormInstantField: <P extends ParsedField<unknown, string>>({ fieldConfig, name, ...prop }: P) => {
3
- fiends: ParsedField<unknown, string>[];
4
- append: () => void;
5
- remove: (index: number) => void;
6
- setFiends: import("react").Dispatch<import("react").SetStateAction<ParsedField<unknown, string>[]>>;
7
- fieldConfig: {
8
- type?: string;
9
- min?: number;
10
- max?: number;
11
- } | undefined;
12
- name: {
13
- current: string;
14
- history: string;
15
- };
16
- } & Omit<P, "name" | "fieldConfig">;
@@ -1,14 +0,0 @@
1
- import { InputMapping } from './class';
2
- export declare function createInputMappingHook<Ob extends Record<string, any>>(InputMappingContext: React.Context<InputMapping<Ob> | null>): () => {
3
- set: (key: keyof Ob | string, value: React.FC<any>) => InputMapping<Ob>;
4
- clear: () => void;
5
- delete: (key: keyof Ob | string) => boolean;
6
- forEach(callbackfn: (value: import("react").FC<any>, key: import("./types").INPUT_COMPONENTS_KEYS | keyof Ob, map: Map<import("./types").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>>) => void, thisArg?: any): void;
7
- has(key: import("./types").INPUT_COMPONENTS_KEYS | keyof Ob): boolean;
8
- size: number;
9
- entries(): MapIterator<[import("./types").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>]>;
10
- keys(): MapIterator<import("./types").INPUT_COMPONENTS_KEYS | keyof Ob>;
11
- values(): MapIterator<import("react").FC<any>>;
12
- [Symbol.iterator](): MapIterator<[import("./types").INPUT_COMPONENTS_KEYS | keyof Ob, import("react").FC<any>]>;
13
- [Symbol.toStringTag]: string;
14
- };
File without changes