dinocollab-core 2.2.41 → 2.2.42
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/dist/src/filter-bar/components/filter-input.js +1 -1
- package/dist/src/filter-bar/components/filter-input.js.map +1 -1
- package/dist/src/filter-bar/convert-to-graphql.js +1 -1
- package/dist/src/filter-bar/convert-to-graphql.js.map +1 -1
- package/dist/src/filter-bar/helpers.js +1 -1
- package/dist/src/filter-bar/helpers.js.map +1 -1
- package/dist/src/filter-bar/hooks.js +1 -1
- package/dist/src/filter-bar/hooks.js.map +1 -1
- package/dist/src/filter-bar/index.create.js +1 -1
- package/dist/src/filter-bar/index.create.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-boolean.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-boolean.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-number.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-number.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select-multiple.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select-multiple.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-string.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-string.js.map +1 -1
- package/dist/types/filter-bar/helpers.d.ts +3 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-form-field-select.js","sources":["../../../../src/filter-bar/menu/create-form-field-select.tsx"],"sourcesContent":["import { FC, ReactNode, useEffect, useMemo, useRef, useState } from 'react'\r\nimport { Box, Button, CircularProgress, FormControlLabel, Radio, RadioGroup, radioGroupClasses, styled, Typography } from '@mui/material'\r\nimport InfoIcon from '@mui/icons-material/Info'\r\nimport { getErrorMessage } from '../../form/helpers'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps, TFetchStatus } from './types'\r\n\r\n/** Props for the `FormFieldSelect` component returned by `createFormFieldSelect`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectProps<T> extends IFilterMenuFormProps<T> {\r\n /** Callback function to handle errors */\r\n onError?: () => void\r\n /** Optional content to render at the top of the form */\r\n top?: ReactNode\r\n}\r\n\r\n/** A single option item rendered as a radio button inside the select filter menu. */\r\nexport interface IFieldSelectOption {\r\n value: TFieldValid\r\n label?: string\r\n}\r\n\r\n/** Parameters passed to `createFormFieldSelect` to configure the generated component. */\r\nexport interface IFormFieldSelectParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n /** List of options for the select field */\r\n options?: IFieldSelectOption[]\r\n /** Function to fetch options asynchronously based on user input */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** Force a specific logic (and/or) for this field, overriding the default or user-selected logic */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected for this field */\r\n maxValueCount?: number\r\n /** Optional content to render at the top of the form */\r\n top?: ReactNode\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldSelect` filter-menu component.\r\n *\r\n * The generated component renders a radio-button list of options inside a\r\n * popper/menu panel. It supports:\r\n * - Single or multi-value selection (controlled by `config.singleValue`)\r\n * - OR / AND logic toggle when more than one value is selected\r\n * - Chip viewers showing the currently applied values\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (option list, optional field config override)\r\n * @returns A React FC ready to be used as a filter-menu field component\r\n */\r\nfunction createFormFieldSelect<T>(params: IFormFieldSelectParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options } = params\r\n\r\n const FormFieldSelect: FC<IFormFieldSelectProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n const effectiveLogic = params.forceLogic ?? filterLogic\r\n const [selectedValue, setSelectedValue] = useState<TFieldValid | null>(null)\r\n const [fetchedOptions, setFetchedOptions] = useState<IFieldSelectOption[]>([])\r\n const [fetchStatus, setFetchStatus] = useState<TFetchStatus>(params.fetchOptions ? 'loading' : 'loaded')\r\n const abortRef = useRef<AbortController | null>(null)\r\n\r\n const runFetch = () => {\r\n if (!params.fetchOptions) return\r\n abortRef.current?.abort()\r\n const controller = new AbortController()\r\n abortRef.current = controller\r\n setFetchStatus('loading')\r\n params\r\n .fetchOptions(controller.signal)\r\n .then((data) => {\r\n setFetchedOptions(data)\r\n setFetchStatus('loaded')\r\n })\r\n .catch((err) => {\r\n props.onError?.()\r\n if (err?.name !== 'AbortError') setFetchStatus('error')\r\n })\r\n }\r\n\r\n useEffect(() => {\r\n runFetch()\r\n return () => abortRef.current?.abort()\r\n }, [])\r\n\r\n const effectiveOptions = params.fetchOptions ? fetchedOptions : (options ?? [])\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = selectedValue !== null\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: selectedValue } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: [selectedValue!] as TFieldValid[], logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n setSelectedValue(null)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: effectiveOptions.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value, effectiveOptions])\r\n\r\n const isMaxReached = params.maxValueCount != null && filterViewerValue.items.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field, mergedConfig)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (params.forceLogic) return null\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const renderTop = useMemo(() => {\r\n const topContent = params?.top || props.top\r\n if (topContent) return <Box sx={{ mb: 1 }}>{topContent}</Box>\r\n return null\r\n }, [params?.top, props.top])\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading || fetchStatus === 'loading') rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {renderTop}\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n {fetchStatus === 'loading' && (\r\n <Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>\r\n <CircularProgress size={20} />\r\n </Box>\r\n )}\r\n {fetchStatus === 'error' && (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 2, mb: 3, gap: 1 }}>\r\n <InfoIcon color='error' fontSize='large' />\r\n <Typography variant='body2' color='error'>\r\n Failed to load options\r\n </Typography>\r\n <Button size='small' variant='outlined' color='error' onClick={runFetch}>\r\n Retry\r\n </Button>\r\n </Box>\r\n )}\r\n {effectiveOptions.length === 0 && fetchStatus === 'loaded' && (\r\n <Typography variant='body2' color='text.secondary' sx={{ mt: 2 }}>\r\n No options available\r\n </Typography>\r\n )}\r\n <RadioGroup\r\n sx={{ mx: -1 }}\r\n name={mergedConfig.field.toString()}\r\n value={selectedValue ?? ''}\r\n onChange={(e) => setSelectedValue(e.target.value as TFieldValid)}\r\n className={errorResult.error ? 'error' : ''}\r\n >\r\n {effectiveOptions.map((x, i) => {\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected || isMaxReached\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.12)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n },\r\n [`.${radioGroupClasses.root}`]: {\r\n '&.error .MuiRadio-root': { color: '#d32f2f' },\r\n '.MuiFormControlLabel-root': { margin: 0 },\r\n '.MuiFormControlLabel-root:hover': { backgroundColor: 'rgba(25, 118, 210, 0.04)' }\r\n }\r\n})\r\n"],"names":["createFormFieldSelect","params","ChipViewers","createChipViewers","options","props","_mergedConfig$default","_params$forceLogic","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","_useState3","_useState4","selectedValue","setSelectedValue","_useState5","_useState6","fetchedOptions","setFetchedOptions","_useState7","fetchOptions","_useState8","fetchStatus","setFetchStatus","abortRef","useRef","runFetch","_abortRef$current","current","abort","controller","AbortController","signal","then","data","err","_props$onError","onError","call","name","useEffect","_abortRef$current2","effectiveOptions","hasLogicChange","hasDataChange","isApplyDisabled","label","field","toString","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_effectiveOptions$fin","find","o","isMaxReached","maxValueCount","length","renderTop","topContent","top","_jsx","Box","sx","mb","children","rootClasses","isLoading","push","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","borderBottom","placement","enableMinimalesticView","onRemove","justifyContent","mt","CircularProgress","flexDirection","alignItems","gap","InfoIcon","fontSize","Button","RadioGroup","mx","e","target","error","x","i","_x$label","isSelected","some","item","FormControlLabel","disabled","control","Radio","message","PopperFooter","_props$onRemoveField","onRemoveField","flex","type","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","radioGroupClasses","root","margin"],"mappings":"suBAuDA,SAASA,EAAyBC,GAChC,IAAMC,EAAcC,IACZC,EAAYH,EAAZG,QAsNR,OApNsD,SAACC,GAAS,IAAAC,EAAAC,EAAAC,EAKxDC,EAAeC,EAAQ,WAAA,OAAMC,OAAOC,OAAO,GAAIP,EAAMQ,cAAeZ,eAAAA,EAAQa,OAAO,EAAE,CAACb,aAAAA,EAAAA,EAAQa,OAAQT,EAAMQ,gBAElHE,EAA8EV,EAAtEW,MAAAA,OAAQ,IAAHD,EAAG,CAAEE,OAAQ,GAAIC,MAAiC,QAA5BZ,EAAEG,aAAY,EAAZA,EAAcU,oBAAY,IAAAb,EAAAA,EAAI,MAAMS,EACzEK,EAAsCC,EAAiBL,EAAME,OAAOI,EAAAC,EAAAH,EAAA,GAA7DI,EAAWF,EAAA,GAAEG,EAAcH,EAAA,GAC5BI,EAAkC,QAApBnB,EAAGN,EAAO0B,kBAAU,IAAApB,EAAAA,EAAIiB,EAC5CI,EAA0CP,EAA6B,MAAKQ,EAAAN,EAAAK,EAAA,GAArEE,EAAaD,EAAA,GAAEE,EAAgBF,EAAA,GACtCG,EAA4CX,EAA+B,IAAGY,EAAAV,EAAAS,EAAA,GAAvEE,EAAcD,EAAA,GAAEE,EAAiBF,EAAA,GACxCG,EAAsCf,EAAuBpB,EAAOoC,aAAe,UAAY,UAASC,EAAAf,EAAAa,EAAA,GAAjGG,EAAWD,EAAA,GAAEE,EAAcF,EAAA,GAC5BG,EAAWC,EAA+B,MAE1CC,EAAW,WAAK,IAAAC,EACpB,GAAK3C,EAAOoC,aAAZ,CACgB,QAAhBO,EAAAH,EAASI,eAAO,IAAAD,GAAhBA,EAAkBE,QAClB,IAAMC,EAAa,IAAIC,gBACvBP,EAASI,QAAUE,EACnBP,EAAe,WACfvC,EACGoC,aAAaU,EAAWE,QACxBC,KAAK,SAACC,GACLhB,EAAkBgB,GAClBX,EAAe,SACjB,GAAE,MACK,SAACY,GAAO,IAAAC,EACA,QAAbA,EAAAhD,EAAMiD,eAAO,IAAAD,GAAbA,EAAAE,KAAAlD,GACkB,gBAAd+C,eAAAA,EAAKI,OAAuBhB,EAAe,QACjD,EAdwB,CAe3B,EAEDiB,EAAU,WAER,OADAd,IACO,WAAA,IAAAe,EAAA,OAAsB,QAAtBA,EAAMjB,EAASI,eAAO,IAAAa,OAAA,EAAhBA,EAAkBZ,OAAO,CACvC,EAAE,IAEH,IAAMa,EAAmB1D,EAAOoC,aAAeH,EAAkB9B,QAAAA,EAAW,GACtEwD,GAAiBpC,IAAgBR,EAAME,MACvC2C,GAAkC,OAAlB/B,EAChBgC,IAAmBD,KAAkBD,GAErCG,WAAKvD,EAAGC,aAAAA,EAAAA,EAAcsD,aAAK,IAAAvD,EAAAA,EAAIC,EAAauD,MAAMC,WAExDC,GAAkC7C,EAA6C,IAAG8C,GAAA5C,EAAA2C,GAAA,GAA3EE,GAASD,GAAA,GAAEE,GAAYF,GAAA,GACxBG,GAAe,SAACC,GACpBlE,EAAMmE,SAAS/D,EAAauD,MAAOO,EAAU9D,EAC9C,EA0BKgE,GAAcC,EAAgBN,GAAW3D,EAAauD,OACtDW,GAAoBjE,EAA6B,WACrD,IAAMkE,EAAQC,MAAMC,QAAQ9D,EAAMC,QAAUD,EAAMC,OAAS,CAACD,EAAMC,QAClE,MAAO,CACL+C,MAAOvD,EAAauD,MACpBY,MAAOA,EAAMG,IAAI,SAACC,GAAC,IAAAC,EAAA,MAAM,CAAEjE,MAAOgE,EAAGjB,MAAkDkB,QAA7CA,EAAEtB,EAAiBuB,KAAK,SAACC,GAAC,OAAKA,EAAEnE,QAAUgE,CAAC,UAA1CC,IAA2CA,OAA3CA,EAAAA,EAA6ClB,MAAQ,GAEpG,EAAE,CAACtD,EAAauD,MAAOhD,EAAO2C,IAEzByB,GAAuC,MAAxBnF,EAAOoF,eAAyBV,GAAkBC,MAAMU,QAAUrF,EAAOoF,cAyBxFE,GAAY7E,EAAQ,WACxB,IAAM8E,GAAavF,aAAAA,EAAAA,EAAQwF,MAAOpF,EAAMoF,IACxC,OAAID,EAAmBE,EAACC,EAAI,CAAAC,GAAI,CAAEC,GAAI,GAAMC,SAAAN,IACrC,IACR,EAAE,CAACvF,aAAAA,EAAAA,EAAQwF,IAAKpF,EAAMoF,MAEjBM,GAAwB,GAG9B,OAFI1F,EAAM2F,WAA6B,YAAhBzD,IAA2BwD,GAAYE,KAAK,YAGjEP,EAACQ,EAAU,CAACC,UAAWJ,GAAYK,KAAK,KAAMC,cAAW7B,SApElC,SAAC8B,GAA2C,IAAAC,EAGnE,GAFAD,EAAME,iBAED3C,IAOL,IAAIuB,GAAJ,CAEA,IAAMqB,EAAGC,EAAA,CAAA,EAAMjG,EAAauD,MAAQlC,GAChCsC,EAA2BmC,QAAlBA,EAAGlG,EAAMsG,qBAASJ,SAAfA,EAAiBK,IAAIH,GAIrC,GAFApC,GAAaD,GAAa,KAErBA,GAA+C,IAAlCzD,OAAOkG,KAAKzC,GAAWkB,OAEvChB,GAD8B,CAAErD,OAAQ,CAACa,GAAkCZ,MAAOQ,IAElFK,EAAiB,KAVD,OANZ6B,IACFU,GAAa,CAAErD,OAAQD,EAAMC,OAAQC,MAAOQ,GAiBjD,EA8CoFoE,SACjFgB,EAACC,EAAa,CACZC,MAAKC,aAAAA,OAAelD,IACpBmD,QAAS7G,EAAM6G,QACfC,MAAO,CACLC,YAAa1B,EAAC2B,EAAU,CAACC,KAAK,QAAQC,QAASlH,EAAMmH,SACrDC,WA9BFxH,EAAO0B,WAAmB,KAC1BlB,EAAaiH,YAAoBhC,EAACiC,EAAQ,CAAC/B,GAAI,CAAEgC,GAAI,KAAON,KAAK,QAAQvD,MAAM,oBAC5E2B,EAACmC,EAAkB,CAAAjC,GAAI,CAAEgC,GAAI,GAAK5G,MAAOU,EAAgBoG,SAAU,SAACC,EAAGC,GAV9EvG,EAUyGuG,EAAK,KA6BzGlC,SAAA,CAEDgB,EAACmB,EAAU,CAAAnC,SAAA,CACRP,GACA9E,EAAayH,aACZxC,EAACyC,EAAU,CAACC,QAAQ,UAAUC,MAAM,iBAAiBzC,GAAI,CAAEC,GAAI,EAAGyC,QAAS,SACxExC,SAAArF,EAAayH,cAGO,MAAxBjI,EAAOoF,eACNK,EAACyC,EAAW,CAAAC,QAAQ,UAAUC,MAAOjD,GAAe,eAAiB,iBAAkBQ,GAAI,CAAEC,GAAI,GAAKyC,QAAS,kBAnClHrI,EAAOoF,cACRD,GACF,WAAA6B,OAAkBhH,EAAOoF,wBAAa4B,OAAShH,EAAOoF,cAAgB,EAAI,IAAM,GAAE,6BAElF,SAAA4B,OAAgBhH,EAAOoF,wBAAa4B,OAAShH,EAAOoF,cAAgB,EAAI,IAAM,GAAE,oBAJhD,KAuC5BK,EAACxF,GACC0F,GAAI,CAAEC,GAAI,EAAG0C,aAAc,kBAC3BxE,MAAM,UACNyE,UAAU,aACVC,wBACA,EAAAzH,MAAO2D,GACP+D,SAAUrI,EAAMqI,WAED,YAAhBnG,GACCmD,EAACC,EAAG,CAACC,GAAI,CAAE0C,QAAS,OAAQK,eAAgB,SAAUC,GAAI,GAAG9C,SAC3DJ,EAACmD,EAAgB,CAACvB,KAAM,OAGX,UAAhB/E,GACCuE,EAACnB,EAAG,CAACC,GAAI,CAAE0C,QAAS,OAAQQ,cAAe,SAAUC,WAAY,SAAUH,GAAI,EAAG/C,GAAI,EAAGmD,IAAK,GAC5FlD,SAAA,CAAAJ,EAACuD,EAAS,CAAAZ,MAAM,QAAQa,SAAS,UACjCxD,EAACyC,GAAWC,QAAQ,QAAQC,MAAM,4CAGlC3C,EAACyD,EAAM,CAAC7B,KAAK,QAAQc,QAAQ,WAAWC,MAAM,QAAQd,QAAS5E,EAAQmD,SAAA,aAK9C,IAA5BnC,EAAiB2B,QAAgC,WAAhB/C,GAChCmD,EAACyC,GAAWC,QAAQ,QAAQC,MAAM,iBAAiBzC,GAAI,CAAEgD,GAAI,GAEhD9C,SAAA,yBAEfJ,EAAC0D,GACCxD,GAAI,CAAEyD,IAAI,GACV7F,KAAM/C,EAAauD,MAAMC,WACzBjD,MAAOc,QAAAA,EAAiB,GACxBgG,SAAU,SAACwB,GAAC,OAAKvH,EAAiBuH,EAAEC,OAAOvI,MAAqB,EAChEmF,UAAW1B,GAAY+E,MAAQ,QAAU,GAAE1D,SAE1CnC,EAAiBoB,IAAI,SAAC0E,EAAGC,GAAK,IAAAC,EACvBC,EAAajF,GAAkBC,MAAMiF,KAAK,SAACC,GAAI,OAAKA,EAAK9I,QAAUyI,EAAEzI,QAE3E,OACE0E,EAACqE,EACC,CAAAC,SAHaJ,GAAcxE,GAK3BpE,MAAOyI,EAAEzI,MACTiJ,QAASvE,EAACwE,EAAK,CAAC5C,KAAK,UACrBvD,MAAO2B,EAACyC,EAAU,CAACC,QAAQ,QAAOtC,SAAS6D,QAATA,EAAEF,EAAE1F,aAAK4F,IAAAA,EAAAA,EAAIF,EAAEzI,SAH5CyI,EAAEzI,MAAMiD,WAAayF,EAM/B,KAEFjF,GAAY+E,OACX9D,EAACyC,EAAW,CAAAC,QAAQ,UAAUC,MAAM,QAAQzC,GAAI,CAAEgD,GAAI,IAAK9C,SACxDrB,GAAY0F,aAInBrD,EAACsD,EACC,CAAAtE,SAAA,CAAAJ,EAACyD,EAAM,CAAC7B,KAAK,QAAQe,MAAM,QAAQD,QAAQ,OAAO4B,UAAWhJ,EAAMC,QAAkC,IAAxBD,EAAMC,OAAOqE,OAAciC,QA3GzF,WAAK,IAAA8C,EACP,QAAnBA,EAAAhK,EAAMiK,qBAAND,IAAmBA,GAAnBA,EAAA9G,KAAAlD,EAAsBI,EAAauD,MAAOvD,EAC3C,EA2GgBqF,SAAA,cACTJ,EAACC,EAAI,CAAAC,GAAI,CAAE2E,KAAM,KACjB7E,EAACyD,EAAM,CAAC7B,KAAK,QAAQe,MAAM,UAAUD,QAAQ,OAAOb,QAASlH,EAAM6G,QAE1DpB,SAAA,WACTJ,EAACyD,EAAO,CAAA7B,KAAK,QAAQkD,KAAK,SAASnC,MAAM,UAAUD,QAAQ,YAAY4B,SAAUlG,GAExEgC,SAAA,iBAKlB,CAGH,CAIA,IAAMI,EAAauE,EAAO,OAAPA,CAAc/D,EAAA,CAC/BgE,SAAU,WACV,WAAY,CACVC,QAAS,KACTrC,QAAS,QACToC,SAAU,WACVE,MAAO,EACPC,gBAAiB,sBACjBC,OAAQ,YACRC,QAAU,EACVC,QAAS,EACTC,WAAY,eACZC,WAAY,UAEd,aAAc,CACZC,cAAe,OACf,WAAY,CACVJ,OAAQ,EACRC,QAAS,EACTE,WAAY,aAEf,IAAAjE,OACImE,EAAkBC,MAAS,CAC9B,yBAA0B,CAAEhD,MAAO,WACnC,4BAA6B,CAAEiD,OAAQ,GACvC,kCAAmC,CAAET,gBAAiB"}
|
|
1
|
+
{"version":3,"file":"create-form-field-select.js","sources":["../../../../src/filter-bar/menu/create-form-field-select.tsx"],"sourcesContent":["import { FC, ReactNode, useEffect, useMemo, useRef, useState } from 'react'\r\nimport { Box, Button, CircularProgress, FormControlLabel, Radio, RadioGroup, radioGroupClasses, styled, Typography } from '@mui/material'\r\nimport InfoIcon from '@mui/icons-material/Info'\r\nimport { getErrorMessage } from '../../form/helpers'\r\nimport { DEFAULT_LOGIC } from '../helpers'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps, TFetchStatus } from './types'\r\n\r\n/** Props for the `FormFieldSelect` component returned by `createFormFieldSelect`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectProps<T> extends IFilterMenuFormProps<T> {\r\n /** Callback function to handle errors */\r\n onError?: () => void\r\n /** Optional content to render at the top of the form */\r\n top?: ReactNode\r\n}\r\n\r\n/** A single option item rendered as a radio button inside the select filter menu. */\r\nexport interface IFieldSelectOption {\r\n value: TFieldValid\r\n label?: string\r\n}\r\n\r\n/** Parameters passed to `createFormFieldSelect` to configure the generated component. */\r\nexport interface IFormFieldSelectParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n /** List of options for the select field */\r\n options?: IFieldSelectOption[]\r\n /** Function to fetch options asynchronously based on user input */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** Force a specific logic (and/or) for this field, overriding the default or user-selected logic */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected for this field */\r\n maxValueCount?: number\r\n /** Optional content to render at the top of the form */\r\n top?: ReactNode\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldSelect` filter-menu component.\r\n *\r\n * The generated component renders a radio-button list of options inside a\r\n * popper/menu panel. It supports:\r\n * - Single or multi-value selection (controlled by `config.singleValue`)\r\n * - OR / AND logic toggle when more than one value is selected\r\n * - Chip viewers showing the currently applied values\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (option list, optional field config override)\r\n * @returns A React FC ready to be used as a filter-menu field component\r\n */\r\nfunction createFormFieldSelect<T>(params: IFormFieldSelectParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options } = params\r\n\r\n const FormFieldSelect: FC<IFormFieldSelectProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n const defaultLogic: TLogic = mergedConfig?.defaultLogic ?? DEFAULT_LOGIC\r\n const { value = { values: [] } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic ?? defaultLogic)\r\n const effectiveLogic = params.forceLogic ?? filterLogic\r\n const [selectedValue, setSelectedValue] = useState<TFieldValid | null>(null)\r\n const [fetchedOptions, setFetchedOptions] = useState<IFieldSelectOption[]>([])\r\n const [fetchStatus, setFetchStatus] = useState<TFetchStatus>(params.fetchOptions ? 'loading' : 'loaded')\r\n const abortRef = useRef<AbortController | null>(null)\r\n\r\n const runFetch = () => {\r\n if (!params.fetchOptions) return\r\n abortRef.current?.abort()\r\n const controller = new AbortController()\r\n abortRef.current = controller\r\n setFetchStatus('loading')\r\n params\r\n .fetchOptions(controller.signal)\r\n .then((data) => {\r\n setFetchedOptions(data)\r\n setFetchStatus('loaded')\r\n })\r\n .catch((err) => {\r\n props.onError?.()\r\n if (err?.name !== 'AbortError') setFetchStatus('error')\r\n })\r\n }\r\n\r\n useEffect(() => {\r\n runFetch()\r\n return () => abortRef.current?.abort()\r\n }, [])\r\n\r\n const effectiveOptions = params.fetchOptions ? fetchedOptions : (options ?? [])\r\n const hasLogicChange = filterLogic !== (value.logic ?? defaultLogic)\r\n const hasDataChange = selectedValue !== null\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: selectedValue } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: [selectedValue!] as TFieldValid[], logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n setSelectedValue(null)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: effectiveOptions.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value, effectiveOptions])\r\n\r\n const isMaxReached = params.maxValueCount != null && filterViewerValue.items.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field, mergedConfig)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (params.forceLogic) return null\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const renderTop = useMemo(() => {\r\n const topContent = params?.top || props.top\r\n if (topContent) return <Box sx={{ mb: 1 }}>{topContent}</Box>\r\n return null\r\n }, [params?.top, props.top])\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading || fetchStatus === 'loading') rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {renderTop}\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n {fetchStatus === 'loading' && (\r\n <Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>\r\n <CircularProgress size={20} />\r\n </Box>\r\n )}\r\n {fetchStatus === 'error' && (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 2, mb: 3, gap: 1 }}>\r\n <InfoIcon color='error' fontSize='large' />\r\n <Typography variant='body2' color='error'>\r\n Failed to load options\r\n </Typography>\r\n <Button size='small' variant='outlined' color='error' onClick={runFetch}>\r\n Retry\r\n </Button>\r\n </Box>\r\n )}\r\n {effectiveOptions.length === 0 && fetchStatus === 'loaded' && (\r\n <Typography variant='body2' color='text.secondary' sx={{ mt: 2 }}>\r\n No options available\r\n </Typography>\r\n )}\r\n <RadioGroup\r\n sx={{ mx: -1 }}\r\n name={mergedConfig.field.toString()}\r\n value={selectedValue ?? ''}\r\n onChange={(e) => setSelectedValue(e.target.value as TFieldValid)}\r\n className={errorResult.error ? 'error' : ''}\r\n >\r\n {effectiveOptions.map((x, i) => {\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected || isMaxReached\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.12)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n },\r\n [`.${radioGroupClasses.root}`]: {\r\n '&.error .MuiRadio-root': { color: '#d32f2f' },\r\n '.MuiFormControlLabel-root': { margin: 0 },\r\n '.MuiFormControlLabel-root:hover': { backgroundColor: 'rgba(25, 118, 210, 0.04)' }\r\n }\r\n})\r\n"],"names":["createFormFieldSelect","params","ChipViewers","createChipViewers","options","props","_mergedConfig$default","_value$logic","_params$forceLogic","_value$logic2","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","defaultLogic","DEFAULT_LOGIC","_props$value","value","values","_useState","useState","logic","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","_useState3","_useState4","selectedValue","setSelectedValue","_useState5","_useState6","fetchedOptions","setFetchedOptions","_useState7","fetchOptions","_useState8","fetchStatus","setFetchStatus","abortRef","useRef","runFetch","_abortRef$current","current","abort","controller","AbortController","signal","then","data","err","_props$onError","onError","call","name","useEffect","_abortRef$current2","effectiveOptions","hasLogicChange","hasDataChange","isApplyDisabled","label","field","toString","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_effectiveOptions$fin","find","o","isMaxReached","maxValueCount","length","renderTop","topContent","top","_jsx","Box","sx","mb","children","rootClasses","isLoading","push","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","borderBottom","placement","enableMinimalesticView","onRemove","justifyContent","mt","CircularProgress","flexDirection","alignItems","gap","InfoIcon","fontSize","Button","RadioGroup","mx","e","target","error","x","i","_x$label","isSelected","some","item","FormControlLabel","disabled","control","Radio","message","PopperFooter","_props$onRemoveField","onRemoveField","flex","type","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","radioGroupClasses","root","margin"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{slicedToArray as e}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as i,jsxs as l}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as n}from"react";import{styled as t,Box as a,Typography as s,TextField as u,Button as c}from"@mui/material";import{createChipViewers as d}from"../components/chip-viewer.js";import{getErrorMessage as m,convertFormDataToJson as v}from"../../form/helpers.js";import{ButtonBack as p,ChipDark as f,FilterLogicToggle as b}from"../components/ui.units.js";import{PopperContent as g,PopperBody as h,PopperFooter as y}from"../components/popper-custom.js";function
|
|
1
|
+
import{slicedToArray as e}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as i,jsxs as l}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as n}from"react";import{styled as t,Box as a,Typography as s,TextField as u,Button as c}from"@mui/material";import{createChipViewers as d}from"../components/chip-viewer.js";import{getErrorMessage as m,convertFormDataToJson as v}from"../../form/helpers.js";import{ButtonBack as p,ChipDark as f,FilterLogicToggle as b}from"../components/ui.units.js";import{PopperContent as g,PopperBody as h,PopperFooter as y}from"../components/popper-custom.js";import{DEFAULT_LOGIC as x}from"../helpers.js";function C(t){var C=d();return function(d){var z,k,A,T,B=o(function(){return Object.assign({},d.currentConfig,null==t?void 0:t.config)},[null==t?void 0:t.config,d.currentConfig]),F=n(),R=null!==(z=null==B?void 0:B.defaultLogic)&&void 0!==z?z:x,S=d.value,w=void 0===S?{values:[]}:S,I=r(null!==(k=w.logic)&&void 0!==k?k:R),L=e(I,2),V=L[0],D=L[1],E=r(""),H=e(E,2),M=H[0],O=H[1],P=null!==(A=null==B?void 0:B.label)&&void 0!==A?A:B.field.toString(),_=r({}),N=e(_,2),W=N[0],q=N[1],G=function(e){d.onSubmit(B.field,e,B)},J=V!==(null!==(T=w.logic)&&void 0!==T?T:R),K=!M.trim()&&!J,Q=m(W,B.field),U=o(function(){var e=Array.isArray(w.values)?w.values:[w.values];return{field:B.field,items:e.map(function(e){return{value:e}})}},[B.field,w]),X=o(function(){var e=(null==t?void 0:t.top)||d.top;return e?i(a,{sx:{mb:1},children:e}):null},[null==t?void 0:t.top,d.top]),Y=[];return d.isLoading&&Y.push("disabled"),i(j,{className:Y.join(" "),noValidate:!0,onSubmit:function(e){var i;if(e.preventDefault(),e.stopPropagation(),M.trim()){var l=new FormData(e.currentTarget),o=v(l),r=null===(i=d.validator)||void 0===i?void 0:i.run(o);if(q(r||{}),!r||0===Object.keys(r).length){var n=B.field,t=Array.isArray(o[n])?o[n]:[o[n]];G({values:t,logic:V}),F.current&&(F.current.blur(),F.current.value=""),O("")}}else J&&G({values:w.values,logic:V})},children:l(g,{title:"Filter by ".concat(P),onClose:d.onClose,slots:{beforeTitle:i(p,{size:"small",onClick:d.onBack}),afterTitle:B.singleValue?i(f,{sx:{ml:1.5},size:"small",label:"Last value only"}):i(b,{sx:{ml:1},value:V,onChange:function(e,i){D(i)}})},children:[l(h,{children:[X,B.description&&i(s,{variant:"caption",color:"text.secondary",sx:{display:"block",mb:1},children:B.description}),i(C,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:U,onRemove:d.onRemove}),i(u,{inputRef:F,autoFocus:!0,name:B.field.toString(),size:"small",fullWidth:!0,placeholder:"Enter value",error:Q.error,helperText:Q.message,onChange:function(e){return O(e.target.value)},sx:{".MuiInputBase-root":{minHeight:"42px"}}})]}),l(y,{children:[i(c,{size:"small",color:"error",variant:"text",disabled:!w.values||0===w.values.length,onClick:function(){var e;null===(e=d.onRemoveField)||void 0===e||e.call(d,B.field,B)},children:"Clear All"}),i(a,{sx:{flex:1}}),i(c,{size:"small",color:"inherit",variant:"text",onClick:d.onClose,children:"Cancel"}),i(c,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:K,children:"Apply"})]})]})})}}var j=t("form")({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.2)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}});export{C as default};
|
|
2
2
|
//# sourceMappingURL=create-form-field-string.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-form-field-string.js","sources":["../../../../src/filter-bar/menu/create-form-field-string.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { createRef, useMemo, useState } from 'react'\r\nimport { Box, Button, styled, TextField, Typography } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC, ReactNode } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TChipViewerGroup } from '../components/chip-viewer'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldString` component returned by `createFormFieldString`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldStringProps<T> extends IFilterMenuFormProps<T> {\r\n top?: ReactNode\r\n}\r\n\r\n/** Parameters passed to `createFormFieldString` to configure the generated component. */\r\nexport interface IFormFieldStringParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n top?: ReactNode\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldString` filter-menu component.\r\n *\r\n * The generated component renders a free-text input inside a popper/menu panel,\r\n * letting the user type arbitrary string values as filter criteria. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values\r\n * - Auto-focus and input reset after each successful submission\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (optional field config override)\r\n * @returns A React FC ready to be used as a free-text filter-menu field component\r\n */\r\nfunction createFormFieldString<T>(params?: IFormFieldStringParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldString: FC<IFormFieldStringProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const refInput = createRef<HTMLInputElement>()\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n const [inputValue, setInputValue] = useState('')\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const hasLogicChange = filterLogic !== value.logic\r\n const isApplyDisabled = !inputValue.trim() && !hasLogicChange\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n\r\n if (!inputValue.trim()) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: filterLogic })\r\n }\r\n return\r\n }\r\n\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n\r\n if (refInput.current) {\r\n refInput.current.blur()\r\n refInput.current.value = ''\r\n }\r\n setInputValue('')\r\n }\r\n }\r\n\r\n const error = getErrorMessage(errorData, mergedConfig.field)\r\n\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return { field: mergedConfig.field, items: items.map((v) => ({ value: v })) }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field, mergedConfig)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={filterLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const renderTop = useMemo(() => {\r\n const topContent = params?.top || props.top\r\n if (topContent) return <Box sx={{ mb: 1 }}>{topContent}</Box>\r\n return null\r\n }, [params?.top, props.top])\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {renderTop}\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ display: 'block', mb: 1 }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter value'\r\n error={error.error}\r\n helperText={error.message}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n sx={{ '.MuiInputBase-root': { minHeight: '42px' } }}\r\n />\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldString\r\n}\r\n\r\nexport default createFormFieldString\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.2)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n }\r\n})\r\n"],"names":["createFormFieldString","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","_useState3","_useState4","inputValue","setInputValue","label","field","toString","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","hasLogicChange","isApplyDisabled","trim","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","renderTop","topContent","top","_jsx","Box","sx","mb","children","rootClasses","isLoading","push","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","stopPropagation","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","current","blur","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","borderBottom","placement","enableMinimalesticView","onRemove","TextField","inputRef","autoFocus","name","fullWidth","placeholder","helperText","message","e","target","minHeight","PopperFooter","Button","disabled","_props$onRemoveField","onRemoveField","call","flex","type","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-form-field-string.js","sources":["../../../../src/filter-bar/menu/create-form-field-string.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { createRef, useMemo, useState } from 'react'\r\nimport { Box, Button, styled, TextField, Typography } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport { DEFAULT_LOGIC } from '../helpers'\r\n// types\r\nimport type { FC, ReactNode } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TChipViewerGroup } from '../components/chip-viewer'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldString` component returned by `createFormFieldString`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldStringProps<T> extends IFilterMenuFormProps<T> {\r\n top?: ReactNode\r\n}\r\n\r\n/** Parameters passed to `createFormFieldString` to configure the generated component. */\r\nexport interface IFormFieldStringParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n top?: ReactNode\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldString` filter-menu component.\r\n *\r\n * The generated component renders a free-text input inside a popper/menu panel,\r\n * letting the user type arbitrary string values as filter criteria. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values\r\n * - Auto-focus and input reset after each successful submission\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (optional field config override)\r\n * @returns A React FC ready to be used as a free-text filter-menu field component\r\n */\r\nfunction createFormFieldString<T>(params?: IFormFieldStringParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldString: FC<IFormFieldStringProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const refInput = createRef<HTMLInputElement>()\r\n const defaultLogic: TLogic = mergedConfig?.defaultLogic ?? DEFAULT_LOGIC\r\n const { value = { values: [] } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic ?? defaultLogic)\r\n const [inputValue, setInputValue] = useState('')\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const hasLogicChange = filterLogic !== (value.logic ?? defaultLogic)\r\n const isApplyDisabled = !inputValue.trim() && !hasLogicChange\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n\r\n if (!inputValue.trim()) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: filterLogic })\r\n }\r\n return\r\n }\r\n\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n\r\n if (refInput.current) {\r\n refInput.current.blur()\r\n refInput.current.value = ''\r\n }\r\n setInputValue('')\r\n }\r\n }\r\n\r\n const error = getErrorMessage(errorData, mergedConfig.field)\r\n\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return { field: mergedConfig.field, items: items.map((v) => ({ value: v })) }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field, mergedConfig)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={filterLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const renderTop = useMemo(() => {\r\n const topContent = params?.top || props.top\r\n if (topContent) return <Box sx={{ mb: 1 }}>{topContent}</Box>\r\n return null\r\n }, [params?.top, props.top])\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {renderTop}\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ display: 'block', mb: 1 }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter value'\r\n error={error.error}\r\n helperText={error.message}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n sx={{ '.MuiInputBase-root': { minHeight: '42px' } }}\r\n />\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldString\r\n}\r\n\r\nexport default createFormFieldString\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.2)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n }\r\n})\r\n"],"names":["createFormFieldString","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_value$logic","_mergedConfig$label","_value$logic2","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","defaultLogic","DEFAULT_LOGIC","_props$value","value","values","_useState","useState","logic","_useState2","_slicedToArray","filterLogic","setFilterLogic","_useState3","_useState4","inputValue","setInputValue","label","field","toString","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","hasLogicChange","isApplyDisabled","trim","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","renderTop","topContent","top","_jsx","Box","sx","mb","children","rootClasses","isLoading","push","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","stopPropagation","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","current","blur","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","borderBottom","placement","enableMinimalesticView","onRemove","TextField","inputRef","autoFocus","name","fullWidth","placeholder","helperText","message","e","target","minHeight","PopperFooter","Button","disabled","_props$onRemoveField","onRemoveField","call","flex","type","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { KeySpecial, TFilterState } from './types';
|
|
1
|
+
import { KeySpecial, TFilterState, TLogic } from './types';
|
|
2
|
+
export declare const DEFAULT_LOGIC_ROOT: TLogic;
|
|
3
|
+
export declare const DEFAULT_LOGIC: TLogic;
|
|
2
4
|
export declare const mapSpecialTexts: {
|
|
3
5
|
qsTooltip: string;
|
|
4
6
|
};
|