@oneplatformdev/ui 0.1.99-beta.302 → 0.1.99-beta.305
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ColorInput/ColorInput.d.ts +10 -0
- package/ColorInput/ColorInput.d.ts.map +1 -0
- package/ColorInput/ColorInput.js +103 -0
- package/ColorInput/ColorInput.js.map +1 -0
- package/ColorInput/ColorInput.stories.js +78 -0
- package/ColorInput/ColorInput.stories.js.map +1 -0
- package/ColorInput/ColorInput.types.d.ts +46 -0
- package/ColorInput/ColorInput.types.d.ts.map +1 -0
- package/ColorInput/ColorInput.types.js +2 -0
- package/ColorInput/ColorInput.types.js.map +1 -0
- package/ColorInput/ColorPicker.d.ts +28 -0
- package/ColorInput/ColorPicker.d.ts.map +1 -0
- package/ColorInput/ColorPicker.js +322 -0
- package/ColorInput/ColorPicker.js.map +1 -0
- package/ColorInput/color.utils.d.ts +42 -0
- package/ColorInput/color.utils.d.ts.map +1 -0
- package/ColorInput/color.utils.js +129 -0
- package/ColorInput/color.utils.js.map +1 -0
- package/ColorInput/index.d.ts +6 -0
- package/ColorInput/index.d.ts.map +1 -0
- package/ColorInput/index.js +25 -0
- package/ColorInput/index.js.map +1 -0
- package/ColorInput/useSavedColors.d.ts +13 -0
- package/ColorInput/useSavedColors.d.ts.map +1 -0
- package/ColorInput/useSavedColors.js +53 -0
- package/ColorInput/useSavedColors.js.map +1 -0
- package/Combobox/ComboboxRenderContent.d.ts.map +1 -1
- package/Combobox/ComboboxRenderContent.js +38 -35
- package/Combobox/ComboboxRenderContent.js.map +1 -1
- package/Combobox/ComboboxRenderTrigger.js +8 -8
- package/FormColorInput/FormColorInput.d.ts +7 -0
- package/FormColorInput/FormColorInput.d.ts.map +1 -0
- package/FormColorInput/FormColorInput.js +38 -0
- package/FormColorInput/FormColorInput.js.map +1 -0
- package/FormColorInput/FormColorInput.stories.js +95 -0
- package/FormColorInput/FormColorInput.stories.js.map +1 -0
- package/FormColorInput/FormColorInput.types.d.ts +6 -0
- package/FormColorInput/FormColorInput.types.d.ts.map +1 -0
- package/FormColorInput/FormColorInput.types.js +2 -0
- package/FormColorInput/FormColorInput.types.js.map +1 -0
- package/FormColorInput/index.d.ts +3 -0
- package/FormColorInput/index.d.ts.map +1 -0
- package/FormColorInput/index.js +5 -0
- package/FormColorInput/index.js.map +1 -0
- package/FormCombobox/FormCombobox.stories.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +366 -342
- package/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboboxRenderContent.js","sources":["../../src/Combobox/ComboboxRenderContent.tsx"],"sourcesContent":["import { LoadingMask } from '../LoadingMask';\r\nimport { PopoverContent } from '../Popover';\r\nimport {\r\n Command,\r\n CommandEmpty,\r\n CommandGroup,\r\n CommandInput,\r\n CommandItem,\r\n CommandList,\r\n} from '../Command';\r\nimport { cn } from '@oneplatformdev/utils';\r\nimport {\r\n ComboboxCallbackStateParamsRenderHandler,\r\n ComboboxCallbackStateParamsUnion,\r\n ComboboxOption, ComboboxProps,\r\n ComboboxSelectedType, IComboboxOptionsNodeHandlersProps,\r\n ISlotProps,\r\n} from './Combobox.types';\r\nimport { ComboboxRenderOptions } from './ComboboxRenderOptions';\r\nimport { HTMLAttributes, useEffect, useRef } from \"react\";\r\nimport { useInView } from \"react-intersection-observer\";\r\nimport { Skeleton } from \"../Skeleton\";\r\n\r\ntype ComboboxRenderContentProps<Data extends object = object> =\r\n IComboboxOptionsNodeHandlersProps<Data>\r\n & {\r\n open?: boolean;\r\n\r\n type: ComboboxSelectedType,\r\n value: ComboboxProps<Data, 'single'>['value'] | ComboboxProps<Data, 'multi'>['value'];\r\n\r\n hasNext: boolean;\r\n\r\n loading: boolean;\r\n loadingMore: boolean;\r\n\r\n options: ComboboxOption<Data>[];\r\n search?: string;\r\n onSearch?: (term: string) => void;\r\n isEmptyList?: boolean;\r\n onSelect?: (option: ComboboxOption<Data>) => void;\r\n\r\n searchLabel?: string;\r\n emptyLabel?: string;\r\n\r\n callbackStateParams: ComboboxCallbackStateParamsUnion<Data>;\r\n\r\n commandInputAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n renderList?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n listHeadAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n listFooterAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n emptyAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n\r\n slotProps?: ISlotProps;\r\n\r\n popoverContainer?: HTMLElement | null;\r\n\r\n onLoadMore?: () => Promise<void>;\r\n}\r\n\r\nconst SkeletonItems = (props: HTMLAttributes<HTMLDivElement> & { length?: number }) => (\r\n <div className=\"flex w-full flex-col gap-0\">\r\n {Array.from({ length: props.length || 2 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className='flex items-center min-h-10 w-full px-4'\r\n >\r\n <div className={cn('flex items-center w-full', props.className)}>\r\n <Skeleton className='h-4 w-full'/>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n);\r\n\r\n\r\nexport const ComboboxRenderContent = <Data extends object = object>(\r\n props: ComboboxRenderContentProps<Data>\r\n) => {\r\n const {\r\n open,\r\n type,\r\n search,\r\n onSearch,\r\n hasNext,\r\n loading,\r\n loadingMore,\r\n isEmptyList,\r\n onSelect,\r\n options = [],\r\n callbackStateParams,\r\n value,\r\n searchLabel = 'Type to search...',\r\n emptyLabel = 'No options',\r\n emptyAction,\r\n commandInputAction,\r\n listHeadAction,\r\n listFooterAction,\r\n slotProps = {},\r\n defaultNodeDisabled,\r\n defaultNodeMatched,\r\n defaultNodeMuted,\r\n defaultNodeInteractive,\r\n forcePointerSelect,\r\n popoverContainer,\r\n renderList,\r\n onLoadMore,\r\n } = props;\r\n\r\n const scrollRootRef = useRef<HTMLDivElement>(null);\r\n const { ref: sentinelRef, inView } = useInView({\r\n root: scrollRootRef.current,\r\n rootMargin: \"0px 0px 200px 0px\",\r\n threshold: 0,\r\n });\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n if (!inView) return;\r\n void onLoadMore?.();\r\n }, [ inView, open ]);\r\n\r\n return (\r\n <PopoverContent\r\n className={cn(\r\n \"w-(--radix-popper-anchor-width) max-w-none p-2\"\r\n )}\r\n align=\"start\"\r\n container={popoverContainer}\r\n >\r\n <Command shouldFilter={false}>\r\n <CommandInput\r\n placeholder={searchLabel}\r\n value={search}\r\n onValueChange={onSearch}\r\n />\r\n {typeof commandInputAction === 'function'\r\n ? commandInputAction(callbackStateParams)\r\n : commandInputAction}\r\n\r\n <CommandList ref={scrollRootRef}>\r\n <CommandGroup\r\n className={cn(\r\n !options.length && 'p-0 shadow-none',\r\n 'px-0 py-2',\r\n )}\r\n >\r\n {loading && (\r\n <div className=\"pt-2 pb-0\">\r\n <LoadingMask />\r\n </div>\r\n )}\r\n {!loading && isEmptyList && (\r\n <>\r\n {emptyAction ? (\r\n <CommandEmpty className=\"flex flex-col gap-3 py-5 px-3 items-center\">\r\n <span>{emptyLabel}</span>\r\n {typeof emptyAction === 'function'\r\n ? emptyAction(callbackStateParams)\r\n : emptyAction}\r\n </CommandEmpty>\r\n ) : (\r\n <CommandEmpty>{emptyLabel}</CommandEmpty>\r\n )}\r\n </>\r\n )}\r\n\r\n {!loading && !isEmptyList && (\r\n <>\r\n {listHeadAction && (\r\n <CommandItem\r\n key='combobox-list-head-action'\r\n asChild\r\n className='w-full'\r\n >\r\n {typeof listHeadAction === 'function'\r\n ? listHeadAction(callbackStateParams)\r\n : listHeadAction}\r\n </CommandItem>\r\n )}\r\n\r\n {renderList && renderList(callbackStateParams)}\r\n\r\n {!renderList && (\r\n <ComboboxRenderOptions\r\n type={type}\r\n search={search}\r\n value={value}\r\n options={options}\r\n onSelect={onSelect}\r\n defaultNodeDisabled={defaultNodeDisabled}\r\n defaultNodeMatched={defaultNodeMatched}\r\n defaultNodeMuted={defaultNodeMuted}\r\n defaultNodeInteractive={defaultNodeInteractive}\r\n forcePointerSelect={forcePointerSelect}/>\r\n )}\r\n\r\n {hasNext && <div ref={sentinelRef} className=\"h-px w-full\"/>}\r\n {loadingMore && <SkeletonItems />}\r\n </>\r\n )}\r\n\r\n </CommandGroup>\r\n </CommandList>\r\n\r\n {/*LIST FOOTER ACTION*/}\r\n {!loading && listFooterAction && !isEmptyList && (\r\n <div\r\n data-slot=\"command-footer-wrapper\"\r\n {...((() => {\r\n const { bordered = true, ...rest } = slotProps?.listFooterAction || {};\r\n return {\r\n ...rest,\r\n 'data-slot-bordered': JSON.stringify(bordered)\r\n }\r\n })())}\r\n className={cn(\r\n \"flex w-full items-center gap-2 px-0\",\r\n (slotProps?.listFooterAction?.bordered ?? true) && 'border-t px-0 pt-2',\r\n slotProps?.listFooterAction?.className,\r\n )}\r\n >\r\n {typeof listFooterAction === 'function'\r\n ? listFooterAction(callbackStateParams)\r\n : listFooterAction}\r\n </div>\r\n )}\r\n </Command>\r\n </PopoverContent>\r\n );\r\n}\r\n"],"names":["SkeletonItems","props","_","i","jsx","cn","Skeleton","ComboboxRenderContent","open","type","search","onSearch","hasNext","loading","loadingMore","isEmptyList","onSelect","options","callbackStateParams","value","searchLabel","emptyLabel","emptyAction","commandInputAction","listHeadAction","listFooterAction","slotProps","defaultNodeDisabled","defaultNodeMatched","defaultNodeMuted","defaultNodeInteractive","forcePointerSelect","popoverContainer","renderList","onLoadMore","scrollRootRef","useRef","sentinelRef","inView","useInView","useEffect","PopoverContent","jsxs","Command","CommandInput","CommandList","CommandGroup","LoadingMask","Fragment","CommandEmpty","CommandItem","ComboboxRenderOptions","bordered","rest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComboboxRenderContent.js","sources":["../../src/Combobox/ComboboxRenderContent.tsx"],"sourcesContent":["import { LoadingMask } from '../LoadingMask';\r\nimport { PopoverContent } from '../Popover';\r\nimport {\r\n Command,\r\n CommandEmpty,\r\n CommandGroup,\r\n CommandInput,\r\n CommandItem,\r\n CommandList,\r\n} from '../Command';\r\nimport { cn } from '@oneplatformdev/utils';\r\nimport {\r\n ComboboxCallbackStateParamsRenderHandler,\r\n ComboboxCallbackStateParamsUnion,\r\n ComboboxOption, ComboboxProps,\r\n ComboboxSelectedType, IComboboxOptionsNodeHandlersProps,\r\n ISlotProps,\r\n} from './Combobox.types';\r\nimport { ComboboxRenderOptions } from './ComboboxRenderOptions';\r\nimport { HTMLAttributes, useEffect, useRef } from \"react\";\r\nimport { useInView } from \"react-intersection-observer\";\r\nimport { Skeleton } from \"../Skeleton\";\r\n\r\ntype ComboboxRenderContentProps<Data extends object = object> =\r\n IComboboxOptionsNodeHandlersProps<Data>\r\n & {\r\n open?: boolean;\r\n\r\n type: ComboboxSelectedType,\r\n value: ComboboxProps<Data, 'single'>['value'] | ComboboxProps<Data, 'multi'>['value'];\r\n\r\n hasNext: boolean;\r\n\r\n loading: boolean;\r\n loadingMore: boolean;\r\n\r\n options: ComboboxOption<Data>[];\r\n search?: string;\r\n onSearch?: (term: string) => void;\r\n isEmptyList?: boolean;\r\n onSelect?: (option: ComboboxOption<Data>) => void;\r\n\r\n searchLabel?: string;\r\n emptyLabel?: string;\r\n\r\n callbackStateParams: ComboboxCallbackStateParamsUnion<Data>;\r\n\r\n commandInputAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n renderList?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n listHeadAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n listFooterAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n emptyAction?: ComboboxCallbackStateParamsRenderHandler<Data>;\r\n\r\n slotProps?: ISlotProps;\r\n\r\n popoverContainer?: HTMLElement | null;\r\n\r\n onLoadMore?: () => Promise<void>;\r\n}\r\n\r\nconst SkeletonItems = (props: HTMLAttributes<HTMLDivElement> & { length?: number }) => (\r\n <div className=\"flex w-full flex-col gap-0\">\r\n {Array.from({ length: props.length || 2 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className='flex items-center min-h-10 w-full px-4'\r\n >\r\n <div className={cn('flex items-center w-full', props.className)}>\r\n <Skeleton className='h-4 w-full'/>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n);\r\n\r\n\r\nexport const ComboboxRenderContent = <Data extends object = object>(\r\n props: ComboboxRenderContentProps<Data>\r\n) => {\r\n const {\r\n open,\r\n type,\r\n search,\r\n onSearch,\r\n hasNext,\r\n loading,\r\n loadingMore,\r\n isEmptyList,\r\n onSelect,\r\n options = [],\r\n callbackStateParams,\r\n value,\r\n searchLabel = 'Type to search...',\r\n emptyLabel = 'No options',\r\n emptyAction,\r\n commandInputAction,\r\n listHeadAction,\r\n listFooterAction,\r\n slotProps = {},\r\n defaultNodeDisabled,\r\n defaultNodeMatched,\r\n defaultNodeMuted,\r\n defaultNodeInteractive,\r\n forcePointerSelect,\r\n popoverContainer,\r\n renderList,\r\n onLoadMore,\r\n } = props;\r\n\r\n const scrollRootRef = useRef<HTMLDivElement>(null);\r\n const { ref: sentinelRef, inView } = useInView({\r\n root: scrollRootRef.current,\r\n rootMargin: \"0px 0px 200px 0px\",\r\n threshold: 0,\r\n });\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n if (!inView) return;\r\n void onLoadMore?.();\r\n }, [ inView, open ]);\r\n\r\n return (\r\n <PopoverContent\r\n className={cn(\r\n \"w-(--radix-popper-anchor-width) max-w-none p-2\",\r\n \"flex flex-col\",\r\n \"max-h-(--radix-popover-content-available-height)\",\r\n )}\r\n align=\"start\"\r\n collisionPadding={8}\r\n container={popoverContainer}\r\n >\r\n <Command shouldFilter={false} className=\"flex min-h-0 flex-1 flex-col\">\r\n <CommandInput\r\n placeholder={searchLabel}\r\n value={search}\r\n onValueChange={onSearch}\r\n />\r\n {typeof commandInputAction === 'function'\r\n ? commandInputAction(callbackStateParams)\r\n : commandInputAction}\r\n\r\n <CommandList ref={scrollRootRef} className=\"min-h-0 flex-1\">\r\n <CommandGroup\r\n className={cn(\r\n !options.length && 'p-0 shadow-none',\r\n 'px-0 py-2',\r\n )}\r\n >\r\n {loading && (\r\n <div className=\"pt-2 pb-0\">\r\n <LoadingMask />\r\n </div>\r\n )}\r\n {!loading && isEmptyList && (\r\n <>\r\n {emptyAction ? (\r\n <CommandEmpty className=\"flex flex-col gap-3 py-5 px-3 items-center\">\r\n <span>{emptyLabel}</span>\r\n {typeof emptyAction === 'function'\r\n ? emptyAction(callbackStateParams)\r\n : emptyAction}\r\n </CommandEmpty>\r\n ) : (\r\n <CommandEmpty>{emptyLabel}</CommandEmpty>\r\n )}\r\n </>\r\n )}\r\n\r\n {!loading && !isEmptyList && (\r\n <>\r\n {listHeadAction && (\r\n <CommandItem\r\n key='combobox-list-head-action'\r\n asChild\r\n className='w-full'\r\n >\r\n {typeof listHeadAction === 'function'\r\n ? listHeadAction(callbackStateParams)\r\n : listHeadAction}\r\n </CommandItem>\r\n )}\r\n\r\n {renderList && renderList(callbackStateParams)}\r\n\r\n {!renderList && (\r\n <ComboboxRenderOptions\r\n type={type}\r\n search={search}\r\n value={value}\r\n options={options}\r\n onSelect={onSelect}\r\n defaultNodeDisabled={defaultNodeDisabled}\r\n defaultNodeMatched={defaultNodeMatched}\r\n defaultNodeMuted={defaultNodeMuted}\r\n defaultNodeInteractive={defaultNodeInteractive}\r\n forcePointerSelect={forcePointerSelect}/>\r\n )}\r\n\r\n {hasNext && <div ref={sentinelRef} className=\"h-px w-full\"/>}\r\n {loadingMore && <SkeletonItems />}\r\n </>\r\n )}\r\n\r\n </CommandGroup>\r\n </CommandList>\r\n\r\n {/*LIST FOOTER ACTION*/}\r\n {!loading && listFooterAction && !isEmptyList && (\r\n <div\r\n data-slot=\"command-footer-wrapper\"\r\n {...((() => {\r\n const { bordered = true, ...rest } = slotProps?.listFooterAction || {};\r\n return {\r\n ...rest,\r\n 'data-slot-bordered': JSON.stringify(bordered)\r\n }\r\n })())}\r\n className={cn(\r\n \"flex w-full items-center gap-2 px-0\",\r\n (slotProps?.listFooterAction?.bordered ?? true) && 'border-t px-0 pt-2',\r\n slotProps?.listFooterAction?.className,\r\n )}\r\n >\r\n {typeof listFooterAction === 'function'\r\n ? listFooterAction(callbackStateParams)\r\n : listFooterAction}\r\n </div>\r\n )}\r\n </Command>\r\n </PopoverContent>\r\n );\r\n}\r\n"],"names":["SkeletonItems","props","_","i","jsx","cn","Skeleton","ComboboxRenderContent","open","type","search","onSearch","hasNext","loading","loadingMore","isEmptyList","onSelect","options","callbackStateParams","value","searchLabel","emptyLabel","emptyAction","commandInputAction","listHeadAction","listFooterAction","slotProps","defaultNodeDisabled","defaultNodeMatched","defaultNodeMuted","defaultNodeInteractive","forcePointerSelect","popoverContainer","renderList","onLoadMore","scrollRootRef","useRef","sentinelRef","inView","useInView","useEffect","PopoverContent","jsxs","Command","CommandInput","CommandList","CommandGroup","LoadingMask","Fragment","CommandEmpty","CommandItem","ComboboxRenderOptions","bordered","rest"],"mappings":";;;;;;;;;AA4DA,MAAMA,IAAgB,CAACC,wBACpB,OAAA,EAAI,WAAU,8BACZ,UAAA,MAAM,KAAK,EAAE,QAAQA,EAAM,UAAU,EAAA,CAAG,EAAE,IAAI,CAACC,GAAGC,MACjD,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IAEC,WAAU;AAAA,IAEV,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAWC,EAAG,4BAA4BJ,EAAM,SAAS,GAC5D,UAAA,gBAAAG,EAACE,GAAA,EAAS,WAAU,aAAA,CAAY,EAAA,CAClC;AAAA,EAAA;AAAA,EALKH;AAMP,CACD,GACH,GAIWI,KAAwB,CACnCN,MACG;AACH,QAAM;AAAA,IACJ,MAAAO;AAAA,IACA,MAAAC;AAAA,IACA,QAAAC;AAAA,IACA,UAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC;AAAA,IACA,SAAAC,IAAU,CAAA;AAAA,IACV,qBAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,YAAAC,IAAa;AAAA,IACb,aAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,WAAAC,IAAY,CAAA;AAAA,IACZ,qBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,EAAA,IACEjC,GAEEkC,IAAgBC,EAAuB,IAAI,GAC3C,EAAE,KAAKC,GAAa,QAAAC,EAAA,IAAWC,EAAU;AAAA,IAC7C,MAAMJ,EAAc;AAAA,IACpB,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA,CACZ;AAED,SAAAK,EAAU,MAAM;AACd,IAAKhC,KACA8B,KACAJ,IAAA;AAAA,EACP,GAAG,CAAEI,GAAQ9B,CAAK,CAAC,GAGjB,gBAAAJ;AAAA,IAACqC;AAAA,IAAA;AAAA,MACC,WAAWpC;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAM;AAAA,MACN,kBAAkB;AAAA,MAClB,WAAW2B;AAAA,MAEX,UAAA,gBAAAU,EAACC,GAAA,EAAQ,cAAc,IAAO,WAAU,gCACtC,UAAA;AAAA,QAAA,gBAAAvC;AAAA,UAACwC;AAAA,UAAA;AAAA,YACC,aAAaxB;AAAA,YACb,OAAOV;AAAA,YACP,eAAeC;AAAA,UAAA;AAAA,QAAA;AAAA,QAEhB,OAAOY,KAAuB,aAC3BA,EAAmBL,CAAmB,IACtCK;AAAA,QAEJ,gBAAAnB,EAACyC,GAAA,EAAY,KAAKV,GAAe,WAAU,kBACzC,UAAA,gBAAAO;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,WAAWzC;AAAA,cACT,CAACY,EAAQ,UAAU;AAAA,cACnB;AAAA,YAAA;AAAA,YAGD,UAAA;AAAA,cAAAJ,uBACE,OAAA,EAAI,WAAU,aACb,UAAA,gBAAAT,EAAC2C,KAAY,GACf;AAAA,cAED,CAAClC,KAAWE,KACX,gBAAAX,EAAA4C,GAAA,EACG,cACC,gBAAAN,EAACO,GAAA,EAAa,WAAU,8CACtB,UAAA;AAAA,gBAAA,gBAAA7C,EAAC,UAAM,UAAAiB,EAAA,CAAW;AAAA,gBACjB,OAAOC,KAAgB,aACpBA,EAAYJ,CAAmB,IAC/BI;AAAA,cAAA,EAAA,CACN,IAEA,gBAAAlB,EAAC6C,GAAA,EAAc,UAAA5B,EAAA,CAAW,GAE9B;AAAA,cAGD,CAACR,KAAW,CAACE,KACZ,gBAAA2B,EAAAM,GAAA,EACG,UAAA;AAAA,gBAAAxB,KACC,gBAAApB;AAAA,kBAAC8C;AAAA,kBAAA;AAAA,oBAEC,SAAO;AAAA,oBACP,WAAU;AAAA,oBAET,UAAA,OAAO1B,KAAmB,aACvBA,EAAeN,CAAmB,IAClCM;AAAA,kBAAA;AAAA,kBANA;AAAA,gBAAA;AAAA,gBAUPS,KAAcA,EAAWf,CAAmB;AAAA,gBAE5C,CAACe,KACA,gBAAA7B;AAAA,kBAAC+C;AAAA,kBAAA;AAAA,oBACC,MAAA1C;AAAA,oBACA,QAAAC;AAAA,oBACA,OAAAS;AAAA,oBACA,SAAAF;AAAA,oBACA,UAAAD;AAAA,oBACA,qBAAAW;AAAA,oBACA,oBAAAC;AAAA,oBACA,kBAAAC;AAAA,oBACA,wBAAAC;AAAA,oBACA,oBAAAC;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGHnB,KAAW,gBAAAR,EAAC,OAAA,EAAI,KAAKiC,GAAa,WAAU,eAAa;AAAA,gBACzDvB,uBAAgBd,GAAA,CAAA,CAAc;AAAA,cAAA,EAAA,CACjC;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAIN;AAAA,QAGC,CAACa,KAAWY,KAAoB,CAACV,KAChC,gBAAAX;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,aAAU;AAAA,YACT,IAAK,MAAM;AACV,oBAAM,EAAE,UAAAgD,IAAW,IAAM,GAAGC,MAAS3B,GAAW,oBAAoB,CAAA;AACpE,qBAAO;AAAA,gBACL,GAAG2B;AAAA,gBACH,sBAAsB,KAAK,UAAUD,CAAQ;AAAA,cAAA;AAAA,YAEjD,GAAA;AAAA,YACA,WAAW/C;AAAA,cACT;AAAA,eACCqB,GAAW,kBAAkB,YAAY,OAAS;AAAA,cACnDA,GAAW,kBAAkB;AAAA,YAAA;AAAA,YAG9B,UAAA,OAAOD,KAAqB,aACzBA,EAAiBP,CAAmB,IACpCO;AAAA,UAAA;AAAA,QAAA;AAAA,MACN,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -3,10 +3,10 @@ import { DEFAULT_COMBOBOX_TYPE as g } from "./Combobox.types.js";
|
|
|
3
3
|
import { cn as u } from "@oneplatformdev/utils";
|
|
4
4
|
import { XIcon as f, ChevronDown as v } from "lucide-react";
|
|
5
5
|
import { useMemo as w } from "react";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { Button as x } from "../Button/Button.js";
|
|
7
|
+
import { LoadingMask as y } from "../LoadingMask/LoadingMask.js";
|
|
8
|
+
import { ScrollArea as C } from "../ScrollArea/ScrollArea.js";
|
|
9
|
+
import { PopoverTrigger as F } from "../Popover/Popover.js";
|
|
10
10
|
const b = (o) => {
|
|
11
11
|
const { value: n, flattenOptions: a = [], selectedOptions: t = /* @__PURE__ */ new Map() } = o;
|
|
12
12
|
return w(() => {
|
|
@@ -17,7 +17,7 @@ const b = (o) => {
|
|
|
17
17
|
}, N = (o) => {
|
|
18
18
|
const { type: n = g, placeholder: a, onSelect: t, open: c } = o, l = b(o);
|
|
19
19
|
return l.length ? n === "single" ? /* @__PURE__ */ r("span", { className: "truncate overflow-hidden whitespace-nowrap break-words line-clamp-1 pr-8", children: l[0].label }) : n === "multi" ? /* @__PURE__ */ r(
|
|
20
|
-
|
|
20
|
+
C,
|
|
21
21
|
{
|
|
22
22
|
className: u(
|
|
23
23
|
"w-full h-auto min-h-5 max-h-20.25",
|
|
@@ -83,8 +83,8 @@ const b = (o) => {
|
|
|
83
83
|
disabled: l,
|
|
84
84
|
renderTrigger: e
|
|
85
85
|
} = o;
|
|
86
|
-
return /* @__PURE__ */ r(
|
|
87
|
-
|
|
86
|
+
return /* @__PURE__ */ r(F, { asChild: !0, className: "border-input", children: /* @__PURE__ */ p(
|
|
87
|
+
x,
|
|
88
88
|
{
|
|
89
89
|
variant: e ? "none" : "contained",
|
|
90
90
|
color: "secondary",
|
|
@@ -102,7 +102,7 @@ const b = (o) => {
|
|
|
102
102
|
),
|
|
103
103
|
disabled: l || t,
|
|
104
104
|
children: [
|
|
105
|
-
t && /* @__PURE__ */ r(
|
|
105
|
+
t && /* @__PURE__ */ r(y, { fullWidth: !0 }),
|
|
106
106
|
!t && e && e(c),
|
|
107
107
|
!t && !e && /* @__PURE__ */ p(h, { children: [
|
|
108
108
|
/* @__PURE__ */ r(N, { ...o }),
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactElement, Ref } from 'react';
|
|
2
|
+
import { FieldValues } from 'react-hook-form';
|
|
3
|
+
import { FormColorInputProps } from './FormColorInput.types';
|
|
4
|
+
export declare const FormColorInput: <Data extends FieldValues>(props: FormColorInputProps<Data> & {
|
|
5
|
+
ref?: Ref<HTMLInputElement>;
|
|
6
|
+
}) => ReactElement;
|
|
7
|
+
//# sourceMappingURL=FormColorInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormColorInput.d.ts","sourceRoot":"","sources":["../../src/FormColorInput/FormColorInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,GAAG,EAAa,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAwC7D,eAAO,MAAM,cAAc,EAAsC,CAC/D,IAAI,SAAS,WAAW,EAExB,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;CAAE,KAC/D,YAAY,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as c } from "react";
|
|
3
|
+
import { ColorInput as s } from "../ColorInput/ColorInput.js";
|
|
4
|
+
import { FormRenderControl as F } from "../Form/FormRenderControl.js";
|
|
5
|
+
import { FormControl as I } from "../Form/Form.js";
|
|
6
|
+
function h(e, r) {
|
|
7
|
+
const { form: m, tooltip: p, tooltipProps: u, label: l, name: f, onBlur: i, ...a } = e;
|
|
8
|
+
return /* @__PURE__ */ t(
|
|
9
|
+
F,
|
|
10
|
+
{
|
|
11
|
+
form: m,
|
|
12
|
+
name: f,
|
|
13
|
+
tooltip: p,
|
|
14
|
+
tooltipProps: u,
|
|
15
|
+
label: l,
|
|
16
|
+
render: ({ field: n, fieldState: C }) => /* @__PURE__ */ t(I, { children: /* @__PURE__ */ t(
|
|
17
|
+
s,
|
|
18
|
+
{
|
|
19
|
+
...a,
|
|
20
|
+
ref: (o) => {
|
|
21
|
+
n.ref(o), typeof r == "function" ? r(o) : r && (r.current = o);
|
|
22
|
+
},
|
|
23
|
+
error: !!C.error,
|
|
24
|
+
value: n.value || "",
|
|
25
|
+
onChange: (o) => n.onChange(o),
|
|
26
|
+
onBlur: (...o) => {
|
|
27
|
+
n.onBlur?.(), i?.(...o);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
) })
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
const b = c(h);
|
|
35
|
+
export {
|
|
36
|
+
b as FormColorInput
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=FormColorInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormColorInput.js","sources":["../../src/FormColorInput/FormColorInput.tsx"],"sourcesContent":["import { forwardRef, ReactElement, Ref, RefObject } from 'react';\nimport { FieldValues } from 'react-hook-form';\n\nimport { ColorInput } from '../ColorInput';\nimport { FormControl, FormRenderControl } from '../Form';\nimport { FormColorInputProps } from './FormColorInput.types';\n\nfunction FormColorInputInner<Data extends FieldValues>(\n props: FormColorInputProps<Data>,\n ref: Ref<HTMLInputElement>,\n) {\n const { form, tooltip, tooltipProps, label, name, onBlur, ...rest } = props;\n return (\n <FormRenderControl\n form={form}\n name={name}\n tooltip={tooltip}\n tooltipProps={tooltipProps}\n label={label}\n render={({ field, fieldState }) => (\n <FormControl>\n <ColorInput\n {...rest}\n ref={(el) => {\n field.ref(el);\n if (typeof ref === 'function') {\n ref(el);\n } else if (ref) {\n (ref as RefObject<HTMLInputElement | null>).current = el;\n }\n }}\n error={!!fieldState.error}\n value={field.value || ''}\n onChange={(hex) => field.onChange(hex)}\n onBlur={(...args) => {\n field.onBlur?.();\n onBlur?.(...args);\n }}\n />\n </FormControl>\n )}\n />\n );\n}\n\nexport const FormColorInput = forwardRef(FormColorInputInner) as <\n Data extends FieldValues,\n>(\n props: FormColorInputProps<Data> & { ref?: Ref<HTMLInputElement> },\n) => ReactElement;\n"],"names":["FormColorInputInner","props","ref","form","tooltip","tooltipProps","label","name","onBlur","rest","jsx","FormRenderControl","field","fieldState","FormControl","ColorInput","el","hex","args","FormColorInput","forwardRef"],"mappings":";;;;;AAOA,SAASA,EACPC,GACAC,GACA;AACA,QAAM,EAAE,MAAAC,GAAM,SAAAC,GAAS,cAAAC,GAAc,OAAAC,GAAO,MAAAC,GAAM,QAAAC,GAAQ,GAAGC,EAAA,IAASR;AACtE,SACE,gBAAAS;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAAR;AAAA,MACA,MAAAI;AAAA,MACA,SAAAH;AAAA,MACA,cAAAC;AAAA,MACA,OAAAC;AAAA,MACA,QAAQ,CAAC,EAAE,OAAAM,GAAO,YAAAC,EAAA,wBACfC,GAAA,EACC,UAAA,gBAAAJ;AAAA,QAACK;AAAA,QAAA;AAAA,UACE,GAAGN;AAAA,UACJ,KAAK,CAACO,MAAO;AACX,YAAAJ,EAAM,IAAII,CAAE,GACR,OAAOd,KAAQ,aACjBA,EAAIc,CAAE,IACGd,MACRA,EAA2C,UAAUc;AAAA,UAE1D;AAAA,UACA,OAAO,CAAC,CAACH,EAAW;AAAA,UACpB,OAAOD,EAAM,SAAS;AAAA,UACtB,UAAU,CAACK,MAAQL,EAAM,SAASK,CAAG;AAAA,UACrC,QAAQ,IAAIC,MAAS;AACnB,YAAAN,EAAM,SAAA,GACNJ,IAAS,GAAGU,CAAI;AAAA,UAClB;AAAA,QAAA;AAAA,MAAA,EACF,CACF;AAAA,IAAA;AAAA,EAAA;AAIR;AAEO,MAAMC,IAAiBC,EAAWpB,CAAmB;"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as o, jsxs as a } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect as i } from "react";
|
|
3
|
+
import { useForm as n, FormProvider as s } from "react-hook-form";
|
|
4
|
+
import { FormColorInput as l } from "./FormColorInput.js";
|
|
5
|
+
import { Button as d } from "../Button/Button.js";
|
|
6
|
+
function c({ initialValue: r = "#9368FF", ...e }) {
|
|
7
|
+
const t = n({ defaultValues: { color: r } }), m = t.watch("color");
|
|
8
|
+
return /* @__PURE__ */ o(s, { ...t, children: /* @__PURE__ */ a("div", { className: "max-w-sm space-y-3", children: [
|
|
9
|
+
/* @__PURE__ */ o(
|
|
10
|
+
l,
|
|
11
|
+
{
|
|
12
|
+
form: t,
|
|
13
|
+
name: "color",
|
|
14
|
+
label: "Колір бокової панелі",
|
|
15
|
+
...e
|
|
16
|
+
}
|
|
17
|
+
),
|
|
18
|
+
/* @__PURE__ */ a("div", { className: "text-xs text-muted-foreground", children: [
|
|
19
|
+
"value: ",
|
|
20
|
+
/* @__PURE__ */ o("span", { className: "font-mono", children: m })
|
|
21
|
+
] })
|
|
22
|
+
] }) });
|
|
23
|
+
}
|
|
24
|
+
const y = {
|
|
25
|
+
title: "FormColorInput",
|
|
26
|
+
component: l,
|
|
27
|
+
parameters: { layout: "centered" },
|
|
28
|
+
args: {
|
|
29
|
+
label: "Колір",
|
|
30
|
+
withAlpha: !1
|
|
31
|
+
},
|
|
32
|
+
argTypes: {
|
|
33
|
+
form: { control: !1 },
|
|
34
|
+
name: { control: !1 },
|
|
35
|
+
onChange: { control: !1 },
|
|
36
|
+
onBlur: { control: !1 }
|
|
37
|
+
},
|
|
38
|
+
decorators: [
|
|
39
|
+
(r) => /* @__PURE__ */ o("div", { className: "p-6 w-[420px]", children: /* @__PURE__ */ o(r, {}) })
|
|
40
|
+
]
|
|
41
|
+
}, w = {
|
|
42
|
+
render: (r) => /* @__PURE__ */ o(c, { ...r })
|
|
43
|
+
}, v = {
|
|
44
|
+
args: { withAlpha: !0 },
|
|
45
|
+
render: (r) => /* @__PURE__ */ o(c, { ...r, initialValue: "#9368FFcc" })
|
|
46
|
+
};
|
|
47
|
+
function u(r) {
|
|
48
|
+
const e = n({ defaultValues: { color: "" } });
|
|
49
|
+
return i(() => {
|
|
50
|
+
e.setError("color", { message: "Оберіть колір" });
|
|
51
|
+
}, []), /* @__PURE__ */ o(s, { ...e, children: /* @__PURE__ */ o("div", { className: "max-w-sm", children: /* @__PURE__ */ o(
|
|
52
|
+
l,
|
|
53
|
+
{
|
|
54
|
+
form: e,
|
|
55
|
+
name: "color",
|
|
56
|
+
label: "Колір",
|
|
57
|
+
...r
|
|
58
|
+
}
|
|
59
|
+
) }) });
|
|
60
|
+
}
|
|
61
|
+
const N = {
|
|
62
|
+
render: (r) => /* @__PURE__ */ o(u, { ...r })
|
|
63
|
+
}, f = (r) => {
|
|
64
|
+
const e = {};
|
|
65
|
+
return r.color?.trim() ? /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(r.color.trim()) || (e.color = { type: "pattern", message: "Невірний формат кольору" }) : e.color = { type: "required", message: "Обовʼязкове поле" }, { values: Object.keys(e).length ? {} : r, errors: e };
|
|
66
|
+
};
|
|
67
|
+
function p() {
|
|
68
|
+
const r = n({
|
|
69
|
+
mode: "onTouched",
|
|
70
|
+
resolver: f,
|
|
71
|
+
defaultValues: { color: "" }
|
|
72
|
+
}), { isValid: e, isSubmitting: t } = r.formState;
|
|
73
|
+
return /* @__PURE__ */ o(s, { ...r, children: /* @__PURE__ */ a(
|
|
74
|
+
"form",
|
|
75
|
+
{
|
|
76
|
+
className: "max-w-sm space-y-4",
|
|
77
|
+
onSubmit: r.handleSubmit(() => alert("Збережено ✅")),
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ o(l, { form: r, name: "color", label: "Колір" }),
|
|
80
|
+
/* @__PURE__ */ o(d, { type: "submit", disabled: !e || t, className: "w-full", children: "Зберегти" })
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
) });
|
|
84
|
+
}
|
|
85
|
+
const C = {
|
|
86
|
+
render: () => /* @__PURE__ */ o(p, {})
|
|
87
|
+
};
|
|
88
|
+
export {
|
|
89
|
+
w as Default,
|
|
90
|
+
C as HybridValidation,
|
|
91
|
+
v as WithAlpha,
|
|
92
|
+
N as WithError,
|
|
93
|
+
y as default
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=FormColorInput.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormColorInput.stories.js","sources":["../../src/FormColorInput/FormColorInput.stories.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport type { Meta, StoryObj } from '@storybook/react';\nimport { FormProvider, useForm } from 'react-hook-form';\n\nimport { FormColorInput } from './FormColorInput';\nimport { Button } from '../Button';\n\ntype FormValues = {\n color: string;\n};\n\ntype ControlledProps = Omit<\n React.ComponentProps<typeof FormColorInput<FormValues>>,\n 'form' | 'name'\n> & {\n initialValue?: string;\n};\n\nfunction ControlledFormColorInput({ initialValue = '#9368FF', ...args }: ControlledProps) {\n const form = useForm<FormValues>({ defaultValues: { color: initialValue } });\n const value = form.watch('color');\n\n return (\n <FormProvider {...form}>\n <div className=\"max-w-sm space-y-3\">\n <FormColorInput<FormValues>\n form={form}\n name=\"color\"\n label=\"Колір бокової панелі\"\n {...args}\n />\n <div className=\"text-xs text-muted-foreground\">\n value: <span className=\"font-mono\">{value}</span>\n </div>\n </div>\n </FormProvider>\n );\n}\n\nconst meta = {\n title: 'FormColorInput',\n component: FormColorInput,\n parameters: { layout: 'centered' },\n args: {\n label: 'Колір',\n withAlpha: false,\n },\n argTypes: {\n form: { control: false },\n name: { control: false },\n onChange: { control: false },\n onBlur: { control: false },\n },\n decorators: [\n (Story) => (\n <div className=\"p-6 w-[420px]\">\n <Story />\n </div>\n ),\n ],\n} satisfies Meta<typeof FormColorInput>;\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {\n render: (args) => <ControlledFormColorInput {...args} />,\n};\n\nexport const WithAlpha: Story = {\n args: { withAlpha: true },\n render: (args) => <ControlledFormColorInput {...args} initialValue=\"#9368FFcc\" />,\n};\n\nfunction FormColorInputWithError(args: ControlledProps) {\n const form = useForm<FormValues>({ defaultValues: { color: '' } });\n\n useEffect(() => {\n form.setError('color', { message: 'Оберіть колір' });\n }, []);\n\n return (\n <FormProvider {...form}>\n <div className=\"max-w-sm\">\n <FormColorInput<FormValues>\n form={form}\n name=\"color\"\n label=\"Колір\"\n {...args}\n />\n </div>\n </FormProvider>\n );\n}\n\nexport const WithError: Story = {\n render: (args) => <FormColorInputWithError {...args} />,\n};\n\n// Валідація onTouched + disabled submit (стандарт feat/1856).\nconst resolver = (values: FormValues) => {\n const errors: Record<string, { type: string; message: string }> = {};\n if (!values.color?.trim()) {\n errors.color = { type: 'required', message: 'Обовʼязкове поле' };\n } else if (!/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(values.color.trim())) {\n errors.color = { type: 'pattern', message: 'Невірний формат кольору' };\n }\n return { values: Object.keys(errors).length ? {} : values, errors };\n};\n\nfunction HybridForm() {\n const form = useForm<FormValues>({\n mode: 'onTouched',\n resolver,\n defaultValues: { color: '' },\n });\n const { isValid, isSubmitting } = form.formState;\n\n return (\n <FormProvider {...form}>\n <form\n className=\"max-w-sm space-y-4\"\n onSubmit={form.handleSubmit(() => alert('Збережено ✅'))}\n >\n <FormColorInput<FormValues> form={form} name=\"color\" label=\"Колір\" />\n <Button type=\"submit\" disabled={!isValid || isSubmitting} className=\"w-full\">\n Зберегти\n </Button>\n </form>\n </FormProvider>\n );\n}\n\nexport const HybridValidation: Story = {\n render: () => <HybridForm />,\n};\n"],"names":["ControlledFormColorInput","initialValue","args","form","useForm","value","FormProvider","jsxs","jsx","FormColorInput","meta","Story","Default","WithAlpha","FormColorInputWithError","useEffect","WithError","resolver","values","errors","HybridForm","isValid","isSubmitting","Button","HybridValidation"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FieldValues } from 'react-hook-form';
|
|
2
|
+
import { ColorInputProps } from '../ColorInput';
|
|
3
|
+
import { FormRenderControlExtendProps } from '../Form';
|
|
4
|
+
export interface FormColorInputProps<Data extends FieldValues> extends FormRenderControlExtendProps<Data>, Omit<ColorInputProps, 'value' | 'onChange' | 'form' | 'name'> {
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=FormColorInput.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormColorInput.types.d.ts","sourceRoot":"","sources":["../../src/FormColorInput/FormColorInput.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,MAAM,WAAW,mBAAmB,CAAC,IAAI,SAAS,WAAW,CAC3D,SAAQ,4BAA4B,CAAC,IAAI,CAAC,EACxC,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormColorInput.types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FormColorInput/index.tsx"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,mBAAmB,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormCombobox.stories.js","sources":["../../src/FormCombobox/FormCombobox.stories.tsx"],"sourcesContent":["import React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react';\nimport { FormProvider, useForm } from 'react-hook-form';\n\nimport { FormCombobox } from './FormCombobox';\nimport { FormInput } from '../FormInput';\nimport { FormTextarea } from '../FormTextarea';\nimport { FormSelect } from '../FormSelect';\nimport { Button } from '../Button';\nimport { ComboboxOption, ComboboxProps } from '../Combobox';\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nconst COUNTRIES: ComboboxOption[] = [\n { value: 'ua', label: 'Ukraine' },\n { value: 'pl', label: 'Poland' },\n { value: 'de', label: 'Germany' },\n { value: 'fr', label: 'France' },\n { value: 'es', label: 'Spain' },\n { value: 'it', label: 'Italy' },\n];\n\nconst loadCountries: ComboboxProps['loadData'] = async ({ search }) => {\n await sleep(200);\n const q = (search ?? '').trim().toLowerCase();\n if (!q) return COUNTRIES;\n return COUNTRIES.filter((o) => String(o.label).toLowerCase().includes(q));\n};\n\nconst ROLE_OPTIONS = [\n { value: 'admin', label: 'Адміністратор' },\n { value: 'manager', label: 'Менеджер' },\n { value: 'user', label: 'Користувач' },\n];\n\nconst meta = {\n title: 'Forms/HybridValidation',\n parameters: {\n layout: 'centered',\n },\n decorators: [\n (Story) => (\n <div className=\"p-6 w-[420px]\">\n <Story />\n </div>\n ),\n ],\n} satisfies Meta;\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\n// Гібридна модель валідації (feat/1856 + feat/3677):\n// - mode: \"onTouched\" — помилка зʼявляється після blur поля\n// - для Combobox: blur спрацьовує на закриття дропдауна (відкрив → закрив без вибору → помилка)\n// - помилка зникає миттєво при виправленні (on change), щойно значення валідне\n// - кнопка submit disabled, поки форма невалідна\ntype FormValues = {\n fullName: string;\n role: string;\n country: string;\n description: string;\n};\n\nconst resolver = (values: FormValues) => {\n const errors: Record<string, { type: string; message: string }> = {};\n\n if (!values.fullName?.trim()) {\n errors.fullName = { type: 'required', message: 'Обовʼязкове поле' };\n }\n if (!values.role) {\n errors.role = { type: 'required', message: 'Оберіть роль' };\n }\n if (!values.country) {\n errors.country = { type: 'required', message: 'Оберіть країну' };\n }\n if (!values.description?.trim()) {\n errors.description = { type: 'required', message: 'Обовʼязкове поле' };\n } else if (values.description.trim().length < 10) {\n errors.description = { type: 'minLength', message: 'Мінімум 10 символів' };\n }\n\n return {\n values: Object.keys(errors).length ? {} : values,\n errors,\n };\n};\n\nfunction HybridForm() {\n const form = useForm<FormValues>({\n mode: 'onTouched',\n resolver,\n defaultValues: { fullName: '', role: '', country: '', description: '' },\n });\n\n const { isValid, isSubmitting } = form.formState;\n\n return (\n <FormProvider {...form}>\n <form\n className=\"space-y-4\"\n onSubmit={form.handleSubmit(() => {\n alert('Форму надіслано ✅');\n })}\n >\n <FormInput<FormValues>\n form={form}\n name=\"fullName\"\n label=\"Імʼя\"\n placeholder=\"Іван Петренко\"\n />\n\n <FormSelect<FormValues, unknown>\n form={form}\n name=\"role\"\n label=\"Роль\"\n placeholder=\"Оберіть роль\"\n options={ROLE_OPTIONS}\n />\n\n <FormCombobox<FormValues>\n form={form}\n name=\"country\"\n label=\"Країна\"\n placeholder=\"Оберіть країну\"\n searchLabel=\"Пошук...\"\n emptyLabel=\"Нічого не знайдено\"\n loadData={loadCountries}\n />\n\n <FormTextarea<FormValues>\n form={form}\n name=\"description\"\n label=\"Опис\"\n placeholder=\"Мінімум 10 символів\"\n />\n\n <Button type=\"submit\" disabled={!isValid || isSubmitting} className=\"w-full\">\n Зберегти\n </Button>\n </form>\n </FormProvider>\n );\n}\n\nexport const AllFields: Story = {\n render: () => <HybridForm />,\n};\n"],"names":["sleep","ms","COUNTRIES","loadCountries","search","q","o","ROLE_OPTIONS","meta","Story","jsx","resolver","values","errors","HybridForm","form","useForm","isValid","isSubmitting","FormProvider","jsxs","FormInput","FormSelect","FormCombobox","FormTextarea","Button","AllFields"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormCombobox.stories.js","sources":["../../src/FormCombobox/FormCombobox.stories.tsx"],"sourcesContent":["import React from 'react';\r\nimport type { Meta, StoryObj } from '@storybook/react';\r\nimport { FormProvider, useForm } from 'react-hook-form';\r\n\r\nimport { FormCombobox } from './FormCombobox';\r\nimport { FormInput } from '../FormInput';\r\nimport { FormTextarea } from '../FormTextarea';\r\nimport { FormSelect } from '../FormSelect';\r\nimport { Button } from '../Button';\r\nimport { ComboboxOption, ComboboxProps } from '../Combobox';\r\n\r\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\r\n\r\nconst COUNTRIES: ComboboxOption[] = [\r\n { value: 'ua', label: 'Ukraine' },\r\n { value: 'pl', label: 'Poland' },\r\n { value: 'de', label: 'Germany' },\r\n { value: 'fr', label: 'France' },\r\n { value: 'es', label: 'Spain' },\r\n { value: 'it', label: 'Italy' },\r\n];\r\n\r\nconst loadCountries: ComboboxProps['loadData'] = async ({ search }) => {\r\n await sleep(200);\r\n const q = (search ?? '').trim().toLowerCase();\r\n if (!q) return COUNTRIES;\r\n return COUNTRIES.filter((o) => String(o.label).toLowerCase().includes(q));\r\n};\r\n\r\nconst ROLE_OPTIONS = [\r\n { value: 'admin', label: 'Адміністратор' },\r\n { value: 'manager', label: 'Менеджер' },\r\n { value: 'user', label: 'Користувач' },\r\n];\r\n\r\nconst meta = {\r\n title: 'Forms/HybridValidation',\r\n parameters: {\r\n layout: 'centered',\r\n },\r\n decorators: [\r\n (Story) => (\r\n <div className=\"p-6 w-[420px]\">\r\n <Story />\r\n </div>\r\n ),\r\n ],\r\n} satisfies Meta;\r\n\r\nexport default meta;\r\n\r\ntype Story = StoryObj<typeof meta>;\r\n\r\n// Гібридна модель валідації (feat/1856 + feat/3677):\r\n// - mode: \"onTouched\" — помилка зʼявляється після blur поля\r\n// - для Combobox: blur спрацьовує на закриття дропдауна (відкрив → закрив без вибору → помилка)\r\n// - помилка зникає миттєво при виправленні (on change), щойно значення валідне\r\n// - кнопка submit disabled, поки форма невалідна\r\ntype FormValues = {\r\n fullName: string;\r\n role: string;\r\n country: string;\r\n description: string;\r\n};\r\n\r\nconst resolver = (values: FormValues) => {\r\n const errors: Record<string, { type: string; message: string }> = {};\r\n\r\n if (!values.fullName?.trim()) {\r\n errors.fullName = { type: 'required', message: 'Обовʼязкове поле' };\r\n }\r\n if (!values.role) {\r\n errors.role = { type: 'required', message: 'Оберіть роль' };\r\n }\r\n if (!values.country) {\r\n errors.country = { type: 'required', message: 'Оберіть країну' };\r\n }\r\n if (!values.description?.trim()) {\r\n errors.description = { type: 'required', message: 'Обовʼязкове поле' };\r\n } else if (values.description.trim().length < 10) {\r\n errors.description = { type: 'minLength', message: 'Мінімум 10 символів' };\r\n }\r\n\r\n return {\r\n values: Object.keys(errors).length ? {} : values,\r\n errors,\r\n };\r\n};\r\n\r\nfunction HybridForm() {\r\n const form = useForm<FormValues>({\r\n mode: 'onTouched',\r\n resolver,\r\n defaultValues: { fullName: '', role: '', country: '', description: '' },\r\n });\r\n\r\n const { isValid, isSubmitting } = form.formState;\r\n\r\n return (\r\n <FormProvider {...form}>\r\n <form\r\n className=\"space-y-4\"\r\n onSubmit={form.handleSubmit(() => {\r\n alert('Форму надіслано ✅');\r\n })}\r\n >\r\n <FormInput<FormValues>\r\n form={form}\r\n name=\"fullName\"\r\n label=\"Імʼя\"\r\n placeholder=\"Іван Петренко\"\r\n />\r\n\r\n <FormSelect<FormValues, unknown>\r\n form={form}\r\n name=\"role\"\r\n label=\"Роль\"\r\n placeholder=\"Оберіть роль\"\r\n options={ROLE_OPTIONS}\r\n />\r\n\r\n <FormCombobox<FormValues>\r\n form={form}\r\n name=\"country\"\r\n label=\"Країна\"\r\n placeholder=\"Оберіть країну\"\r\n searchLabel=\"Пошук...\"\r\n emptyLabel=\"Нічого не знайдено\"\r\n loadData={loadCountries}\r\n />\r\n\r\n <FormTextarea<FormValues>\r\n form={form}\r\n name=\"description\"\r\n label=\"Опис\"\r\n placeholder=\"Мінімум 10 символів\"\r\n />\r\n\r\n <Button type=\"submit\" disabled={!isValid || isSubmitting} className=\"w-full\">\r\n Зберегти\r\n </Button>\r\n </form>\r\n </FormProvider>\r\n );\r\n}\r\n\r\nexport const AllFields: Story = {\r\n render: () => <HybridForm />,\r\n};\r\n"],"names":["sleep","ms","COUNTRIES","loadCountries","search","q","o","ROLE_OPTIONS","meta","Story","jsx","resolver","values","errors","HybridForm","form","useForm","isValid","isSubmitting","FormProvider","jsxs","FormInput","FormSelect","FormCombobox","FormTextarea","Button","AllFields"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './Carousel';
|
|
|
15
15
|
export * from './Chart';
|
|
16
16
|
export * from './Checkbox';
|
|
17
17
|
export * from './Collapsible';
|
|
18
|
+
export * from './ColorInput';
|
|
18
19
|
export * from './Combobox';
|
|
19
20
|
export * from './Command';
|
|
20
21
|
export * from './ContextPopover';
|
|
@@ -25,6 +26,7 @@ export * from './Drawer';
|
|
|
25
26
|
export * from './DropdownMenu';
|
|
26
27
|
export * from './Form';
|
|
27
28
|
export * from './FormCheckbox';
|
|
29
|
+
export * from './FormColorInput';
|
|
28
30
|
export * from './FormCombobox';
|
|
29
31
|
export * from './FormDatePicker';
|
|
30
32
|
export * from './FormInput';
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|