@cs-open/react-fabric
Version:
1 lines • 4.26 kB
Source Map (JSON)
{"version":3,"file":"useSplitProps.cjs","sources":["../../../src/hooks/useSplitProps.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport type { AllCanvasEvents } from '../types/canvas'\nimport { UNCONTROLLED_PROPS } from '../utils/constants'\n\n// 提取 default 属性的键\ntype DefaultKeys<T> = keyof T & `default${string}`\n\n// 从 default 属性名转换为普通属性名\ntype DefaultToRegular<T> = {\n [K in DefaultKeys<T> as Uncapitalize<K extends `default${infer R}` ? R : never>]: T[K]\n}\n\n// 返回类型定义\ntype SplitResult<T> = [\n { [K in keyof AllCanvasEvents]?: AllCanvasEvents[K] }, // listeners\n Omit<T, keyof AllCanvasEvents | DefaultKeys<T>>, // attributes\n DefaultToRegular<T>, // defaults\n]\n\n// TODO 同时存在defaultValue和attributes时,defaultValue优先级更高,进行报错,受控非受控模式只能二选一\nexport const useSplitProps = <T extends Record<string, any>>(props: T): SplitResult<T> => {\n // 检查属性冲突\n UNCONTROLLED_PROPS.forEach(prop => {\n const defaultProp = `default${prop.charAt(0).toUpperCase()}${prop.slice(1)}`\n if (props[prop] !== undefined && props[defaultProp] !== undefined) {\n throw new Error(\n `Cannot use both controlled '${prop}' and uncontrolled '${defaultProp}' for the same property. ` +\n `Either use controlled mode with '${prop}', or uncontrolled mode with '${defaultProp}', but not both.`,\n )\n }\n })\n\n // 计算非事件和非default属性的值的字符串表示\n const nonEventAndDefaultPropsString = useMemo(\n () =>\n JSON.stringify(\n Object.fromEntries(\n Object.entries(props).filter(([key]) => !key.startsWith('on') && !key.startsWith('default')),\n ),\n ),\n [props],\n )\n\n // 事件处理函数\n const listeners = useMemo(() => {\n const result: { [key: string]: any } = {}\n Object.entries(props).forEach(([key, value]) => {\n if (key.startsWith('on')) {\n result[key] = value\n }\n })\n return result as { [K in keyof AllCanvasEvents]?: AllCanvasEvents[K] }\n }, [props])\n\n // default 属性\n const defaults = useMemo(() => {\n const result: Record<string, unknown> = {}\n Object.entries(props).forEach(([key, value]) => {\n if (key.startsWith('default')) {\n result[key] = value\n }\n })\n return result as DefaultToRegular<T>\n }, [props])\n\n // 其他属性\n const attributes = useMemo(\n () => {\n const result: { [key: string]: any } = {}\n Object.entries(props).forEach(([key, value]) => {\n if (!key.startsWith('on') && !key.startsWith('default')) {\n result[key] = value\n }\n })\n return result as Omit<T, keyof AllCanvasEvents | DefaultKeys<T>>\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [nonEventAndDefaultPropsString],\n )\n\n return [listeners, attributes, defaults]\n}\n"],"names":["useSplitProps","props","UNCONTROLLED_PROPS","prop","defaultProp","nonEventAndDefaultPropsString","useMemo","key","listeners","result","value","defaults","attributes"],"mappings":"wEAoBa,MAAAA,EAAgDC,GAA6B,CAExFC,qBAAmB,QAAQC,GAAQ,CACjC,MAAMC,EAAc,UAAUD,EAAK,OAAO,CAAC,EAAE,YAAY,CAAC,GAAGA,EAAK,MAAM,CAAC,CAAC,GAC1E,GAAIF,EAAME,CAAI,IAAM,QAAaF,EAAMG,CAAW,IAAM,OACtD,MAAM,IAAI,MACR,+BAA+BD,CAAI,uBAAuBC,CAAW,6DAC/BD,CAAI,iCAAiCC,CAAW,kBACxF,CAEJ,CAAC,EAGD,MAAMC,EAAgCC,EAAAA,QACpC,IACE,KAAK,UACH,OAAO,YACL,OAAO,QAAQL,CAAK,EAAE,OAAO,CAAC,CAACM,CAAG,IAAM,CAACA,EAAI,WAAW,IAAI,GAAK,CAACA,EAAI,WAAW,SAAS,CAAC,CAC7F,CACF,EACF,CAACN,CAAK,CACR,EAGMO,EAAYF,UAAQ,IAAM,CAC9B,MAAMG,EAAiC,GACvC,OAAO,OAAA,QAAQR,CAAK,EAAE,QAAQ,CAAC,CAACM,EAAKG,CAAK,IAAM,CAC1CH,EAAI,WAAW,IAAI,IACrBE,EAAOF,CAAG,EAAIG,EAElB,CAAC,EACMD,CACT,EAAG,CAACR,CAAK,CAAC,EAGJU,EAAWL,EAAQ,QAAA,IAAM,CAC7B,MAAMG,EAAkC,GACxC,cAAO,QAAQR,CAAK,EAAE,QAAQ,CAAC,CAACM,EAAKG,CAAK,IAAM,CAC1CH,EAAI,WAAW,SAAS,IAC1BE,EAAOF,CAAG,EAAIG,EAElB,CAAC,EACMD,CACT,EAAG,CAACR,CAAK,CAAC,EAGJW,EAAaN,EAAAA,QACjB,IAAM,CACJ,MAAMG,EAAiC,GACvC,OAAA,OAAO,QAAQR,CAAK,EAAE,QAAQ,CAAC,CAACM,EAAKG,CAAK,IAAM,CAC1C,CAACH,EAAI,WAAW,IAAI,GAAK,CAACA,EAAI,WAAW,SAAS,IACpDE,EAAOF,CAAG,EAAIG,EAElB,CAAC,EACMD,CACT,EAEA,CAACJ,CAA6B,CAChC,EAEA,MAAO,CAACG,EAAWI,EAAYD,CAAQ,CACzC"}