dinocollab-core 2.2.40 → 2.2.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/src/data-surface/view-list/helpers.js +1 -1
  2. package/dist/src/data-surface/view-list/helpers.js.map +1 -1
  3. package/dist/src/data-surface/view-list/index.js +1 -1
  4. package/dist/src/data-surface/view-list/index.js.map +1 -1
  5. package/dist/src/data-surface/view-list/styled.js.map +1 -1
  6. package/dist/src/filter-bar/components/filter-summary.js +1 -1
  7. package/dist/src/filter-bar/components/filter-summary.js.map +1 -1
  8. package/dist/src/filter-bar/convert-to-graphql.js +1 -1
  9. package/dist/src/filter-bar/convert-to-graphql.js.map +1 -1
  10. package/dist/src/filter-bar/helpers.js.map +1 -1
  11. package/dist/src/filter-bar/hooks.js +1 -1
  12. package/dist/src/filter-bar/hooks.js.map +1 -1
  13. package/dist/src/filter-bar/index.create.js.map +1 -1
  14. package/dist/src/filter-bar/index.dino.js +1 -1
  15. package/dist/src/filter-bar/index.dino.js.map +1 -1
  16. package/dist/src/filter-bar/menu/create-form-field-boolean.js +2 -0
  17. package/dist/src/filter-bar/menu/create-form-field-boolean.js.map +1 -0
  18. package/dist/src/filter-bar/menu/create-form-field-datetime.js +1 -1
  19. package/dist/src/filter-bar/menu/create-form-field-datetime.js.map +1 -1
  20. package/dist/src/filter-bar/menu/create-form-field-number.js +1 -1
  21. package/dist/src/filter-bar/menu/create-form-field-number.js.map +1 -1
  22. package/dist/src/filter-bar/menu/create-form-field-select-multiple.js +1 -1
  23. package/dist/src/filter-bar/menu/create-form-field-select-multiple.js.map +1 -1
  24. package/dist/src/filter-bar/menu/create-form-field-select.js +1 -1
  25. package/dist/src/filter-bar/menu/create-form-field-select.js.map +1 -1
  26. package/dist/src/filter-bar/menu/create-form-field-string.js +1 -1
  27. package/dist/src/filter-bar/menu/create-form-field-string.js.map +1 -1
  28. package/dist/src/filter-bar/menu/create.js +1 -1
  29. package/dist/src/filter-bar/menu/create.js.map +1 -1
  30. package/dist/src/filter-bar/menu/ui.units.js.map +1 -1
  31. package/dist/src/form/helpers.js +1 -1
  32. package/dist/src/form/helpers.js.map +1 -1
  33. package/dist/src/http-service/graphql/request-param.js +1 -1
  34. package/dist/src/http-service/graphql/request-param.js.map +1 -1
  35. package/dist/src/utils/helpers.js +1 -1
  36. package/dist/src/utils/helpers.js.map +1 -1
  37. package/dist/types/filter-bar/convert-to-graphql.d.ts +2 -1
  38. package/dist/types/filter-bar/helpers.d.ts +8 -24
  39. package/dist/types/filter-bar/index.dino.d.ts +3 -0
  40. package/dist/types/filter-bar/menu/create-form-field-boolean.d.ts +55 -0
  41. package/dist/types/filter-bar/menu/types.d.ts +1 -1
  42. package/dist/types/http-service/graphql/request-param.d.ts +9 -3
  43. package/dist/types/utils/helpers.d.ts +30 -0
  44. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"create-form-field-datetime.js","sources":["../../../../src/filter-bar/menu/create-form-field-datetime.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { useMemo, useState } from 'react'\r\nimport { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'\r\nimport { Box, Button, Stack, styled, Typography } from '@mui/material'\r\nimport { DatePicker, DateTimePicker, LocalizationProvider, TimePicker } from '@mui/x-date-pickers'\r\nimport dayjs, { Dayjs } from 'dayjs'\r\nimport { ButtonBack, DateLogicToggle } from '../components/ui.units'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } from 'react'\r\nimport type { TDateLogic, TFieldValid, TFieldValue } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Enums / constants\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Date logic options available in `single` mode. */\r\nexport type TDateSingleLogic = Exclude<TDateLogic, 'range'>\r\n\r\nconst DATE_LOGIC_LABELS: Record<TDateSingleLogic, string> = {\r\n before: 'Before',\r\n on: 'On',\r\n after: 'After'\r\n}\r\n\r\n/** The MUI picker variant to render inside the filter menu. */\r\nexport type TDateTimePickerType = 'date' | 'datetime' | 'time'\r\n\r\n/**\r\n * Selection mode for the DateTime filter.\r\n * - `'single'` — one value per Apply; values accumulate with OR / AND logic.\r\n * - `'range'` — two pickers (From / To); always stores exactly `[fromISO, toISO]`.\r\n */\r\nexport type TDateTimeMode = 'single' | 'range'\r\n\r\nconst DISPLAY_FORMAT: Record<TDateTimePickerType, string> = {\r\n date: 'MM/DD/YYYY',\r\n datetime: 'MM/DD/YYYY HH:mm',\r\n time: 'HH:mm'\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Props for the `FormFieldDateTime` component returned by `createFormFieldDateTime`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldDateTimeProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldDateTime` to configure the generated component. */\r\nexport interface IFormFieldDateTimeParam<T> {\r\n /** Optional field-level configuration overrides. */\r\n config?: IFieldMenuConfig<T>\r\n /**\r\n * Controls which MUI picker is rendered.\r\n * - `'date'` → `DatePicker` (default)\r\n * - `'datetime'` → `DateTimePicker`\r\n * - `'time'` → `TimePicker`\r\n * @default 'datetime'\r\n */\r\n pickerType?: TDateTimePickerType\r\n /**\r\n * Controls the selection mode.\r\n * - `'single'` (default) — one value per Apply click; multiple values accumulate with OR / AND logic.\r\n * - `'range'` — two pickers (From / To); always stores exactly `[fromISO, toISO]`.\r\n * @default 'single'\r\n */\r\n mode?: TDateTimeMode\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Factory function that creates a `FormFieldDateTime` filter-menu component.\r\n *\r\n * The generated component renders a date / time picker inside a popper/menu panel.\r\n * It supports two selection modes:\r\n * - **single** (default) — user picks one value per submission; values accumulate\r\n * and an OR / AND logic toggle appears when more than one value is active.\r\n * - **range** — two pickers rendered (From / To); always stores exactly\r\n * `[fromISO, toISO]`, replacing any previous range on each Apply.\r\n *\r\n * All stored values are ISO 8601 strings (`TFieldValid = string`).\r\n *\r\n * @param params - Static configuration (picker type, mode, optional field config override)\r\n * @returns A React FC ready to be used as a date/time filter-menu field component\r\n */\r\nexport function createFormFieldDateTime<T>(params?: IFormFieldDateTimeParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const pickerType = params?.pickerType ?? 'datetime'\r\n const mode = params?.mode ?? 'single'\r\n const displayFormat = DISPLAY_FORMAT[pickerType]\r\n\r\n // Force singleValue so the parent filter system always replaces (not accumulates) the value.\r\n const forcedConfig: IFieldMenuConfig<T> = { ...(params?.config as IFieldMenuConfig<T>), singleValue: true } as IFieldMenuConfig<T>\r\n\r\n /** Format an ISO string into a human-readable chip label, prefixed with date logic context. */\r\n const formatLabel = (iso: TFieldValid, logic?: TDateLogic, index?: number): string => {\r\n const d = dayjs(iso as string)\r\n const dateStr = d.isValid() ? d.format(displayFormat) : String(iso)\r\n if (mode === 'range') return index === 0 ? `From: ${dateStr}` : `To: ${dateStr}`\r\n if (logic && logic !== 'range') return `${DATE_LOGIC_LABELS[logic as TDateSingleLogic] ?? logic}: ${dateStr}`\r\n return dateStr\r\n }\r\n\r\n const FormFieldDateTime: FC<IFormFieldDateTimeProps<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, forcedConfig), [props.currentConfig])\r\n\r\n const { value = { values: [] } } = props\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n // --- single mode: date logic (before / after / on) ---\r\n const [dateLogic, setDateLogic] = useState<TDateSingleLogic>((value.dateLogic as TDateSingleLogic) ?? 'on')\r\n\r\n // --- single mode: the currently staged (not yet applied) date ---\r\n const [singleDate, setSingleDate] = useState<Dayjs | null>(null)\r\n\r\n // --- range mode: from/to pickers, pre-populated from the active filter value ---\r\n const [fromDate, setFromDate] = useState<Dayjs | null>(() => {\r\n if (mode !== 'range') return null\r\n const first = Array.isArray(value.values) ? value.values[0] : undefined\r\n return first ? dayjs(first as string) : null\r\n })\r\n const [toDate, setToDate] = useState<Dayjs | null>(() => {\r\n if (mode !== 'range') return null\r\n const second = Array.isArray(value.values) ? value.values[1] : undefined\r\n return second ? dayjs(second as string) : null\r\n })\r\n\r\n // -----------------------------------------------------------------------\r\n // Handlers\r\n // -----------------------------------------------------------------------\r\n\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 if (mode === 'range') {\r\n const newValues = [fromDate?.toISOString(), toDate?.toISOString()].filter(Boolean) as string[]\r\n if (newValues.length === 0 || rangeError) return\r\n handleSubmit({ values: newValues, dateLogic: 'range' })\r\n } else {\r\n if (singleDate?.isValid()) {\r\n handleSubmit({ values: [singleDate.toISOString()], dateLogic })\r\n setSingleDate(null)\r\n } else if (isLogicChanged) {\r\n handleSubmit({ values: value.values as string[], dateLogic })\r\n }\r\n }\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\r\n }\r\n\r\n // -----------------------------------------------------------------------\r\n // Derived state\r\n // -----------------------------------------------------------------------\r\n\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, i) => ({ value: v, label: formatLabel(v, value.dateLogic, i) }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n // Single mode: logic is considered changed only when existing values are present and the logic differs from applied\r\n const isLogicChanged = mode !== 'range' && value.values.length > 0 && dateLogic !== (value.dateLogic ?? 'on')\r\n\r\n const isApplyDisabled = mode === 'range' ? !fromDate || !toDate : !singleDate?.isValid() && !isLogicChanged\r\n\r\n // Range validation: \"From\" must be strictly before \"To\"\r\n const rangeError: string | null = useMemo(() => {\r\n if (mode !== 'range' || !fromDate || !toDate) return null\r\n return fromDate.isSame(toDate) || fromDate.isAfter(toDate) ? '\"From\" must be earlier than \"To\"' : null\r\n }, [fromDate, toDate])\r\n\r\n const isSubmitDisabled = isApplyDisabled || Boolean(rangeError)\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n // -----------------------------------------------------------------------\r\n // Render helpers\r\n // -----------------------------------------------------------------------\r\n\r\n const dateUnit = pickerType === 'date' ? 'day' : 'minute'\r\n\r\n const renderPicker = (\r\n pickerValue: Dayjs | null,\r\n onChange: (v: Dayjs | null) => void,\r\n pickerLabel: string,\r\n constraints?: { minDate?: Dayjs; maxDate?: Dayjs }\r\n ) => {\r\n const commonProps = {\r\n value: pickerValue,\r\n onChange,\r\n label: pickerLabel,\r\n ...(constraints?.minDate ? { minDate: constraints.minDate } : {}),\r\n ...(constraints?.maxDate ? { maxDate: constraints.maxDate } : {}),\r\n slotProps: {\r\n textField: { size: 'small' as const, fullWidth: true },\r\n popper: {\r\n sx: { zIndex: 9999 },\r\n modifiers: [\r\n { name: 'preventOverflow', enabled: true, options: { boundary: 'window', altAxis: true } },\r\n { name: 'flip', enabled: true }\r\n ]\r\n }\r\n }\r\n }\r\n if (pickerType === 'date') return <DatePicker {...commonProps} format={displayFormat} />\r\n if (pickerType === 'time') return <TimePicker {...commonProps} />\r\n return <DateTimePicker {...commonProps} format={displayFormat} />\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mode === 'range') return null\r\n return <DateLogicToggle sx={{ ml: 1 }} value={dateLogic} onChange={(_, v) => setDateLogic(v)} />\r\n }\r\n\r\n // -----------------------------------------------------------------------\r\n // Main render\r\n // -----------------------------------------------------------------------\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 <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label={mode === 'range' ? 'Active range' : 'Applied'}\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n forceShowAll={mode === 'range'}\r\n onRemove={mode === 'range' ? undefined : props.onRemove}\r\n />\r\n <LocalizationProvider dateAdapter={AdapterDayjs}>\r\n {mode === 'range' ? (\r\n <Stack spacing={1.5}>\r\n <Typography variant='caption' color='text.secondary'>\r\n Select a date range to filter between two values.\r\n </Typography>\r\n {renderPicker(fromDate, setFromDate, 'From', { maxDate: toDate ? toDate.subtract(1, dateUnit) : undefined })}\r\n {renderPicker(toDate, setToDate, 'To', { minDate: fromDate ? fromDate.add(1, dateUnit) : undefined })}\r\n {rangeError && (\r\n <Typography variant='caption' color='error'>\r\n {rangeError}\r\n </Typography>\r\n )}\r\n </Stack>\r\n ) : (\r\n <Stack gap={1}>\r\n <Typography variant='caption' color='text.secondary'>\r\n Pick a date and set the match condition above. Only the latest applied value is kept.\r\n </Typography>\r\n {renderPicker(singleDate, setSingleDate, label)}\r\n </Stack>\r\n )}\r\n </LocalizationProvider>\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={isSubmitDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldDateTime\r\n}\r\n\r\nexport default createFormFieldDateTime\r\n\r\n// ---------------------------------------------------------------------------\r\n// Styles\r\n// ---------------------------------------------------------------------------\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,\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\r\n// ---------------------------------------------------------------------------\r\n// Utilities\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Creates a labelFormatter for use in summaryConfig.\r\n * Formats ISO date strings to a human-readable format.\r\n * For range fields, values are displayed as-is (no From/To prefix since index is unavailable).\r\n */\r\nexport function formatterDateTime(pickerType: TDateTimePickerType = 'datetime') {\r\n const format = DISPLAY_FORMAT[pickerType]\r\n return (value: TFieldValid, index: number, fieldValue: { dateLogic?: TDateLogic }): string | undefined => {\r\n const d = dayjs(value as string)\r\n const dateStr = d.isValid() ? d.format(format) : String(value)\r\n if (fieldValue.dateLogic === 'range') return index === 0 ? `From: ${dateStr}` : `To: ${dateStr}`\r\n if (fieldValue.dateLogic) return `${DATE_LOGIC_LABELS[fieldValue.dateLogic as TDateSingleLogic] ?? fieldValue.dateLogic}: ${dateStr}`\r\n return dateStr\r\n }\r\n}\r\n"],"names":["DATE_LOGIC_LABELS","before","on","after","DISPLAY_FORMAT","date","datetime","time","createFormFieldDateTime","params","_params$pickerType","_params$mode","ChipViewers","createChipViewers","pickerType","mode","displayFormat","forcedConfig","_objectSpread","config","singleValue","props","_mergedConfig$label","_value$dateLogic","_value$dateLogic2","mergedConfig","useMemo","Object","assign","currentConfig","_props$value","value","values","label","field","toString","_useState","useState","dateLogic","_useState2","_slicedToArray","setDateLogic","_useState3","_useState4","singleDate","setSingleDate","_useState5","first","Array","isArray","undefined","dayjs","_useState6","fromDate","setFromDate","_useState7","second","_useState8","toDate","setToDate","handleSubmit","newValue","onSubmit","filterViewerValue","items","map","v","i","iso","logic","index","d","dateStr","isValid","format","String","concat","_DATE_LOGIC_LABELS$lo","isLogicChanged","length","isApplyDisabled","rangeError","isSame","isAfter","isSubmitDisabled","Boolean","rootClasses","isLoading","push","dateUnit","renderPicker","pickerValue","onChange","pickerLabel","constraints","commonProps","minDate","maxDate","slotProps","textField","size","fullWidth","popper","sx","zIndex","modifiers","name","enabled","options","boundary","altAxis","_jsx","DatePicker","TimePicker","DateTimePicker","RootStyled","className","join","noValidate","event","preventDefault","newValues","toISOString","filter","children","_jsxs","PopperContent","title","onClose","slots","beforeTitle","ButtonBack","onClick","onBack","afterTitle","DateLogicToggle","ml","_","PopperBody","mb","borderBottom","placement","enableMinimalesticView","forceShowAll","onRemove","LocalizationProvider","dateAdapter","AdapterDayjs","Stack","spacing","Typography","variant","color","subtract","add","gap","PopperFooter","Button","disabled","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","position","content","display","inset","backgroundColor","opacity","transition","visibility","pointerEvents","formatterDateTime","arguments","fieldValue","_DATE_LOGIC_LABELS$fi"],"mappings":"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"}
1
+ {"version":3,"file":"create-form-field-datetime.js","sources":["../../../../src/filter-bar/menu/create-form-field-datetime.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { useMemo, useState } from 'react'\r\nimport { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'\r\nimport { Box, Button, Stack, styled, Typography } from '@mui/material'\r\nimport { DatePicker, DateTimePicker, LocalizationProvider, TimePicker } from '@mui/x-date-pickers'\r\nimport dayjs, { Dayjs } from 'dayjs'\r\nimport { ButtonBack, DateLogicToggle } from '../components/ui.units'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } from 'react'\r\nimport type { TDateLogic, TFieldValid, TFieldValue } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Enums / constants\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Date logic options available in `single` mode. */\r\nexport type TDateSingleLogic = Exclude<TDateLogic, 'range'>\r\n\r\nconst DATE_LOGIC_LABELS: Record<TDateSingleLogic, string> = {\r\n before: 'Before',\r\n on: 'On',\r\n after: 'After'\r\n}\r\n\r\n/** The MUI picker variant to render inside the filter menu. */\r\nexport type TDateTimePickerType = 'date' | 'datetime' | 'time'\r\n\r\n/**\r\n * Selection mode for the DateTime filter.\r\n * - `'single'` — one value per Apply; values accumulate with OR / AND logic.\r\n * - `'range'` — two pickers (From / To); always stores exactly `[fromISO, toISO]`.\r\n */\r\nexport type TDateTimeMode = 'single' | 'range'\r\n\r\nconst DISPLAY_FORMAT: Record<TDateTimePickerType, string> = {\r\n date: 'MM/DD/YYYY',\r\n datetime: 'MM/DD/YYYY HH:mm',\r\n time: 'HH:mm'\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Props for the `FormFieldDateTime` component returned by `createFormFieldDateTime`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldDateTimeProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldDateTime` to configure the generated component. */\r\nexport interface IFormFieldDateTimeParam<T> {\r\n /** Optional field-level configuration overrides. */\r\n config?: IFieldMenuConfig<T>\r\n /**\r\n * Controls which MUI picker is rendered.\r\n * - `'date'` → `DatePicker` (default)\r\n * - `'datetime'` → `DateTimePicker`\r\n * - `'time'` → `TimePicker`\r\n * @default 'datetime'\r\n */\r\n pickerType?: TDateTimePickerType\r\n /**\r\n * Controls the selection mode.\r\n * - `'single'` (default) — one value per Apply click; multiple values accumulate with OR / AND logic.\r\n * - `'range'` — two pickers (From / To); always stores exactly `[fromISO, toISO]`.\r\n * @default 'single'\r\n */\r\n mode?: TDateTimeMode\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Factory function that creates a `FormFieldDateTime` filter-menu component.\r\n *\r\n * The generated component renders a date / time picker inside a popper/menu panel.\r\n * It supports two selection modes:\r\n * - **single** (default) — user picks one value per submission; values accumulate\r\n * and an OR / AND logic toggle appears when more than one value is active.\r\n * - **range** — two pickers rendered (From / To); always stores exactly\r\n * `[fromISO, toISO]`, replacing any previous range on each Apply.\r\n *\r\n * All stored values are ISO 8601 strings (`TFieldValid = string`).\r\n *\r\n * @param params - Static configuration (picker type, mode, optional field config override)\r\n * @returns A React FC ready to be used as a date/time filter-menu field component\r\n */\r\nexport function createFormFieldDateTime<T>(params?: IFormFieldDateTimeParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const pickerType = params?.pickerType ?? 'datetime'\r\n const mode = params?.mode ?? 'single'\r\n const displayFormat = DISPLAY_FORMAT[pickerType]\r\n\r\n // Force singleValue so the parent filter system always replaces (not accumulates) the value.\r\n const forcedConfig: IFieldMenuConfig<T> = { ...(params?.config as IFieldMenuConfig<T>), singleValue: true } as IFieldMenuConfig<T>\r\n\r\n /** Format an ISO string into a human-readable chip label, prefixed with date logic context. */\r\n const formatLabel = (iso: TFieldValid, logic?: TDateLogic, index?: number): string => {\r\n const d = dayjs(iso as string)\r\n const dateStr = d.isValid() ? d.format(displayFormat) : String(iso)\r\n if (mode === 'range') return index === 0 ? `From: ${dateStr}` : `To: ${dateStr}`\r\n if (logic && logic !== 'range') return `${DATE_LOGIC_LABELS[logic as TDateSingleLogic] ?? logic}: ${dateStr}`\r\n return dateStr\r\n }\r\n\r\n const FormFieldDateTime: FC<IFormFieldDateTimeProps<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, forcedConfig), [props.currentConfig])\r\n\r\n const { value = { values: [] } } = props\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n // --- single mode: date logic (before / after / on) ---\r\n const [dateLogic, setDateLogic] = useState<TDateSingleLogic>((value.dateLogic as TDateSingleLogic) ?? 'on')\r\n\r\n // --- single mode: the currently staged (not yet applied) date ---\r\n const [singleDate, setSingleDate] = useState<Dayjs | null>(null)\r\n\r\n // --- range mode: from/to pickers, pre-populated from the active filter value ---\r\n const [fromDate, setFromDate] = useState<Dayjs | null>(() => {\r\n if (mode !== 'range') return null\r\n const first = Array.isArray(value.values) ? value.values[0] : undefined\r\n return first ? dayjs(first as string) : null\r\n })\r\n const [toDate, setToDate] = useState<Dayjs | null>(() => {\r\n if (mode !== 'range') return null\r\n const second = Array.isArray(value.values) ? value.values[1] : undefined\r\n return second ? dayjs(second as string) : null\r\n })\r\n\r\n // -----------------------------------------------------------------------\r\n // Handlers\r\n // -----------------------------------------------------------------------\r\n\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 if (mode === 'range') {\r\n const newValues = [fromDate?.toISOString(), toDate?.toISOString()].filter(Boolean) as string[]\r\n if (newValues.length === 0 || rangeError) return\r\n handleSubmit({ values: newValues, dateLogic: 'range' })\r\n } else {\r\n if (singleDate?.isValid()) {\r\n handleSubmit({ values: [singleDate.toISOString()], dateLogic })\r\n setSingleDate(null)\r\n } else if (isLogicChanged) {\r\n handleSubmit({ values: value.values as string[], dateLogic })\r\n }\r\n }\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field, mergedConfig)\r\n }\r\n\r\n // -----------------------------------------------------------------------\r\n // Derived state\r\n // -----------------------------------------------------------------------\r\n\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, i) => ({ value: v, label: formatLabel(v, value.dateLogic, i) }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n // Single mode: logic is considered changed only when existing values are present and the logic differs from applied\r\n const isLogicChanged = mode !== 'range' && value.values.length > 0 && dateLogic !== (value.dateLogic ?? 'on')\r\n\r\n const isApplyDisabled = mode === 'range' ? !fromDate || !toDate : !singleDate?.isValid() && !isLogicChanged\r\n\r\n // Range validation: \"From\" must be strictly before \"To\"\r\n const rangeError: string | null = useMemo(() => {\r\n if (mode !== 'range' || !fromDate || !toDate) return null\r\n return fromDate.isSame(toDate) || fromDate.isAfter(toDate) ? '\"From\" must be earlier than \"To\"' : null\r\n }, [fromDate, toDate])\r\n\r\n const isSubmitDisabled = isApplyDisabled || Boolean(rangeError)\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n // -----------------------------------------------------------------------\r\n // Render helpers\r\n // -----------------------------------------------------------------------\r\n\r\n const dateUnit = pickerType === 'date' ? 'day' : 'minute'\r\n\r\n const renderPicker = (\r\n pickerValue: Dayjs | null,\r\n onChange: (v: Dayjs | null) => void,\r\n pickerLabel: string,\r\n constraints?: { minDate?: Dayjs; maxDate?: Dayjs }\r\n ) => {\r\n const commonProps = {\r\n value: pickerValue,\r\n onChange,\r\n label: pickerLabel,\r\n ...(constraints?.minDate ? { minDate: constraints.minDate } : {}),\r\n ...(constraints?.maxDate ? { maxDate: constraints.maxDate } : {}),\r\n slotProps: {\r\n textField: { size: 'small' as const, fullWidth: true },\r\n popper: {\r\n sx: { zIndex: 9999 },\r\n modifiers: [\r\n { name: 'preventOverflow', enabled: true, options: { boundary: 'window', altAxis: true } },\r\n { name: 'flip', enabled: true }\r\n ]\r\n }\r\n }\r\n }\r\n if (pickerType === 'date') return <DatePicker {...commonProps} format={displayFormat} />\r\n if (pickerType === 'time') return <TimePicker {...commonProps} />\r\n return <DateTimePicker {...commonProps} format={displayFormat} />\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mode === 'range') return null\r\n return <DateLogicToggle sx={{ ml: 1 }} value={dateLogic} onChange={(_, v) => setDateLogic(v)} />\r\n }\r\n\r\n // -----------------------------------------------------------------------\r\n // Main render\r\n // -----------------------------------------------------------------------\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 <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label={mode === 'range' ? 'Active range' : 'Applied'}\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n forceShowAll={mode === 'range'}\r\n onRemove={mode === 'range' ? undefined : props.onRemove}\r\n />\r\n <LocalizationProvider dateAdapter={AdapterDayjs}>\r\n {mode === 'range' ? (\r\n <Stack spacing={1.5}>\r\n <Typography variant='caption' color='text.secondary'>\r\n Select a date range to filter between two values.\r\n </Typography>\r\n {renderPicker(fromDate, setFromDate, 'From', { maxDate: toDate ? toDate.subtract(1, dateUnit) : undefined })}\r\n {renderPicker(toDate, setToDate, 'To', { minDate: fromDate ? fromDate.add(1, dateUnit) : undefined })}\r\n {rangeError && (\r\n <Typography variant='caption' color='error'>\r\n {rangeError}\r\n </Typography>\r\n )}\r\n </Stack>\r\n ) : (\r\n <Stack gap={1}>\r\n <Typography variant='caption' color='text.secondary'>\r\n Pick a date and set the match condition above. Only the latest applied value is kept.\r\n </Typography>\r\n {renderPicker(singleDate, setSingleDate, label)}\r\n </Stack>\r\n )}\r\n </LocalizationProvider>\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={isSubmitDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldDateTime\r\n}\r\n\r\nexport default createFormFieldDateTime\r\n\r\n// ---------------------------------------------------------------------------\r\n// Styles\r\n// ---------------------------------------------------------------------------\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,\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\r\n// ---------------------------------------------------------------------------\r\n// Utilities\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Creates a labelFormatter for use in summaryConfig.\r\n * Formats ISO date strings to a human-readable format.\r\n * For range fields, values are displayed as-is (no From/To prefix since index is unavailable).\r\n */\r\nexport function formatterDateTime(pickerType: TDateTimePickerType = 'datetime') {\r\n const format = DISPLAY_FORMAT[pickerType]\r\n return (value: TFieldValid, index: number, fieldValue: { dateLogic?: TDateLogic }): string | undefined => {\r\n const d = dayjs(value as string)\r\n const dateStr = d.isValid() ? d.format(format) : String(value)\r\n if (fieldValue.dateLogic === 'range') return index === 0 ? `From: ${dateStr}` : `To: ${dateStr}`\r\n if (fieldValue.dateLogic) return `${DATE_LOGIC_LABELS[fieldValue.dateLogic as TDateSingleLogic] ?? fieldValue.dateLogic}: ${dateStr}`\r\n return dateStr\r\n }\r\n}\r\n"],"names":["DATE_LOGIC_LABELS","before","on","after","DISPLAY_FORMAT","date","datetime","time","createFormFieldDateTime","params","_params$pickerType","_params$mode","ChipViewers","createChipViewers","pickerType","mode","displayFormat","forcedConfig","_objectSpread","config","singleValue","props","_mergedConfig$label","_value$dateLogic","_value$dateLogic2","mergedConfig","useMemo","Object","assign","currentConfig","_props$value","value","values","label","field","toString","_useState","useState","dateLogic","_useState2","_slicedToArray","setDateLogic","_useState3","_useState4","singleDate","setSingleDate","_useState5","first","Array","isArray","undefined","dayjs","_useState6","fromDate","setFromDate","_useState7","second","_useState8","toDate","setToDate","handleSubmit","newValue","onSubmit","filterViewerValue","items","map","v","i","iso","logic","index","d","dateStr","isValid","format","String","concat","_DATE_LOGIC_LABELS$lo","isLogicChanged","length","isApplyDisabled","rangeError","isSame","isAfter","isSubmitDisabled","Boolean","rootClasses","isLoading","push","dateUnit","renderPicker","pickerValue","onChange","pickerLabel","constraints","commonProps","minDate","maxDate","slotProps","textField","size","fullWidth","popper","sx","zIndex","modifiers","name","enabled","options","boundary","altAxis","_jsx","DatePicker","TimePicker","DateTimePicker","RootStyled","className","join","noValidate","event","preventDefault","newValues","toISOString","filter","children","_jsxs","PopperContent","title","onClose","slots","beforeTitle","ButtonBack","onClick","onBack","afterTitle","DateLogicToggle","ml","_","PopperBody","mb","borderBottom","placement","enableMinimalesticView","forceShowAll","onRemove","LocalizationProvider","dateAdapter","AdapterDayjs","Stack","spacing","Typography","variant","color","subtract","add","gap","PopperFooter","Button","disabled","_props$onRemoveField","onRemoveField","call","Box","flex","type","styled","position","content","display","inset","backgroundColor","opacity","transition","visibility","pointerEvents","formatterDateTime","arguments","fieldValue","_DATE_LOGIC_LABELS$fi"],"mappings":"2sBAuBA,IAAMA,EAAsD,CAC1DC,OAAQ,SACRC,GAAI,KACJC,MAAO,SAaHC,EAAsD,CAC1DC,KAAM,aACNC,SAAU,mBACVC,KAAM,SAkDF,SAAUC,EAA2BC,GAAmC,IAAAC,EAAAC,EACtEC,EAAcC,IACdC,EAA+BJ,QAArBA,EAAGD,aAAM,EAANA,EAAQK,kBAAUJ,IAAAA,EAAAA,EAAI,WACnCK,EAAmBJ,QAAfA,EAAGF,aAAM,EAANA,EAAQM,YAAIJ,IAAAA,EAAAA,EAAI,SACvBK,EAAgBZ,EAAeU,GAG/BG,EAAYC,EAAAA,EAAA,CAAA,EAA8BT,aAAM,EAANA,EAAQU,QAA8B,CAAA,EAAA,CAAEC,aAAa,IAuMrG,OA5L0D,SAACC,GAAS,IAAAC,EAAAC,EAAAC,EAK5DC,EAAeC,EAAQ,WAAA,OAAMC,OAAOC,OAAO,CAAA,EAAIP,EAAMQ,cAAeZ,EAAa,EAAE,CAACI,EAAMQ,gBAEhGC,EAAmCT,EAA3BU,MAAAA,OAAQ,IAAHD,EAAG,CAAEE,OAAQ,IAAIF,EACxBG,UAAKX,EAAGG,aAAAA,EAAAA,EAAcQ,aAAK,IAAAX,EAAAA,EAAIG,EAAaS,MAAMC,WAGxDC,EAAkCC,UAAQd,EAAoBQ,EAAMO,iBAA8B,IAAAf,EAAAA,EAAI,MAAKgB,EAAAC,EAAAJ,EAAA,GAApGE,EAASC,EAAA,GAAEE,EAAYF,EAAA,GAG9BG,EAAoCL,EAAuB,MAAKM,EAAAH,EAAAE,EAAA,GAAzDE,EAAUD,EAAA,GAAEE,EAAaF,EAAA,GAGhCG,EAAgCT,EAAuB,WACrD,GAAa,UAATtB,EAAkB,OAAO,KAC7B,IAAMgC,EAAQC,MAAMC,QAAQlB,EAAMC,QAAUD,EAAMC,OAAO,QAAKkB,EAC9D,OAAOH,EAAQI,EAAMJ,GAAmB,IAC1C,GAAEK,EAAAZ,EAAAM,EAAA,GAJKO,EAAQD,EAAA,GAAEE,EAAWF,EAAA,GAK5BG,EAA4BlB,EAAuB,WACjD,GAAa,UAATtB,EAAkB,OAAO,KAC7B,IAAMyC,EAASR,MAAMC,QAAQlB,EAAMC,QAAUD,EAAMC,OAAO,QAAKkB,EAC/D,OAAOM,EAASL,EAAMK,GAAoB,IAC5C,GAAEC,EAAAjB,EAAAe,EAAA,GAJKG,EAAMD,EAAA,GAAEE,EAASF,EAAA,GAUlBG,EAAe,SAACC,GACpBxC,EAAMyC,SAASrC,EAAaS,MAAO2B,EAAUpC,EAC9C,EA0BKsC,EAAoBrC,EAA6B,WACrD,IAAMsC,EAAQhB,MAAMC,QAAQlB,EAAMC,QAAUD,EAAMC,OAAS,CAACD,EAAMC,QAClE,MAAO,CACLE,MAAOT,EAAaS,MACpB8B,MAAOA,EAAMC,IAAI,SAACC,EAAGC,GAAC,MAAM,CAAEpC,MAAOmC,EAAGjC,OAxEzBmC,EAwE4CF,EAxE1BG,EAwE6BtC,EAAMO,UAxEfgC,EAwE0BH,EAvE7EI,EAAIpB,EAAMiB,GACVI,EAAUD,EAAEE,UAAYF,EAAEG,OAAO1D,GAAiB2D,OAAOP,GAClD,UAATrD,EAAmC,IAAVuD,EAAWM,SAAAA,OAAYJ,GAAO,OAAAI,OAAYJ,GACnEH,GAAmB,UAAVA,EAAmBO,GAAAA,OAAsDC,QAAtDA,EAAU7E,EAAkBqE,UAA0BQ,IAAAA,EAAAA,EAAIR,EAAK,MAAAO,OAAKJ,GAC7FA,IALW,IAACJ,EAAkBC,EAAoBC,EAA0BO,EAC7EN,EACAC,CAsEkF,GAEvF,EAAE,CAAC/C,EAAaS,MAAOH,IAGlB+C,GAA0B,UAAT/D,GAAoBgB,EAAMC,OAAO+C,OAAS,GAAKzC,KAA8Bd,QAArBA,EAAMO,EAAMO,iBAASd,IAAAA,EAAAA,EAAI,MAElGwD,GAA2B,UAATjE,GAAoBsC,IAAaK,IAAUd,SAAAA,EAAY6B,WAAcK,IAGvFG,GAA4BvD,EAAQ,WACxC,MAAa,UAATX,GAAqBsC,GAAaK,IAC/BL,EAAS6B,OAAOxB,IAAWL,EAAS8B,QAAQzB,IAAU,mCADR,IAEvD,EAAG,CAACL,EAAUK,IAER0B,GAAmBJ,IAAmBK,QAAQJ,IAE9CK,GAAwB,GAC1BjE,EAAMkE,WAAWD,GAAYE,KAAK,YAMtC,IAAMC,GAA0B,SAAf3E,EAAwB,MAAQ,SAE3C4E,GAAe,SACnBC,EACAC,EACAC,EACAC,GAEA,IAAMC,EAAW7E,EAAAA,EAAAA,EAAA,CACfa,MAAO4D,EACPC,SAAAA,EACA3D,MAAO4D,GACHC,SAAAA,EAAaE,QAAU,CAAEA,QAASF,EAAYE,SAAY,CAAA,GAC1DF,SAAAA,EAAaG,QAAU,CAAEA,QAASH,EAAYG,SAAY,CAAA,GAAE,GAAA,CAChEC,UAAW,CACTC,UAAW,CAAEC,KAAM,QAAkBC,WAAW,GAChDC,OAAQ,CACNC,GAAI,CAAEC,OAAQ,MACdC,UAAW,CACT,CAAEC,KAAM,kBAAmBC,SAAS,EAAMC,QAAS,CAAEC,SAAU,SAAUC,SAAS,IAClF,CAAEJ,KAAM,OAAQC,SAAS,QAKjC,MAAmB,SAAf7F,EAA8BiG,EAACC,EAAU9F,EAAAA,KAAK6E,GAAW,GAAA,CAAErB,OAAQ1D,KACpD,SAAfF,EAA8BiG,EAACE,EAAU/F,EAAK6E,CAAAA,EAAAA,IAC3CgB,EAACG,EAAchG,EAAAA,KAAK6E,GAAW,GAAA,CAAErB,OAAQ1D,IACjD,EAWD,OACE+F,EAACI,EAAU,CAACC,UAAW9B,GAAY+B,KAAK,KAAMC,cAAWxD,SA5FlC,SAACyD,GAExB,GADAA,EAAMC,iBACO,UAATzG,EAAkB,CACpB,IAAM0G,EAAY,CAACpE,aAAQ,EAARA,EAAUqE,cAAehE,aAAM,EAANA,EAAQgE,eAAeC,OAAOtC,SAC1E,GAAyB,IAArBoC,EAAU1C,QAAgBE,GAAY,OAC1CrB,EAAa,CAAE5B,OAAQyF,EAAWnF,UAAW,SAC9C,MACKM,SAAAA,EAAY6B,WACdb,EAAa,CAAE5B,OAAQ,CAACY,EAAW8E,eAAgBpF,UAAAA,IACnDO,EAAc,OACLiC,IACTlB,EAAa,CAAE5B,OAAQD,EAAMC,OAAoBM,UAAAA,GAGtD,EA8EoFsF,SACjFC,EAACC,EAAa,CACZC,MAAKnD,aAAAA,OAAe3C,GACpB+F,QAAS3G,EAAM2G,QACfC,MAAO,CACLC,YAAanB,EAACoB,EAAU,CAAC/B,KAAK,QAAQgC,QAAS/G,EAAMgH,SACrDC,WAfO,UAATvH,EAAyB,KACtBgG,EAACwB,EAAgB,CAAAhC,GAAI,CAAEiC,GAAI,GAAKzG,MAAOO,EAAWsD,SAAU,SAAC6C,EAAGvE,GAAC,OAAKzB,EAAayB,EAAE,KAevF0D,SAAA,CAEDC,EAACa,EACC,CAAAd,SAAA,CAAAb,EAACnG,EACC,CAAA2F,GAAI,CAAEoC,GAAI,EAAGC,aAAc,kBAC3B3G,MAAgB,UAATlB,EAAmB,eAAiB,UAC3C8H,UAAU,aACVC,wBACA,EAAA/G,MAAOgC,EACPgF,aAAuB,UAAThI,EACdiI,SAAmB,UAATjI,OAAmBmC,EAAY7B,EAAM2H,WAEjDjC,EAACkC,EAAqB,CAAAC,YAAaC,EAAYvB,SAE3CC,EAACuB,EADO,UAATrI,EACQ,CAAAsI,QAAS,IAAGzB,SAAA,CACjBb,EAACuC,GAAWC,QAAQ,UAAUC,MAAM,iBAEvB5B,SAAA,sDACZlC,GAAarC,EAAUC,EAAa,OAAQ,CAAE2C,QAASvC,EAASA,EAAO+F,SAAS,EAAGhE,SAAYvC,IAC/FwC,GAAahC,EAAQC,EAAW,KAAM,CAAEqC,QAAS3C,EAAWA,EAASqG,IAAI,EAAGjE,SAAYvC,IACxF+B,IACC8B,EAACuC,EAAW,CAAAC,QAAQ,UAAUC,MAAM,QAAO5B,SACxC3C,OAKA,CAAA0E,IAAK,YACV5C,EAACuC,EAAW,CAAAC,QAAQ,UAAUC,MAAM,iBAEvB5B,SAAA,0FACZlC,GAAa9C,EAAYC,EAAeZ,WAKjD4F,EAAC+B,EACC,CAAAhC,SAAA,CAAAb,EAAC8C,EAAO,CAAAzD,KAAK,QAAQoD,MAAM,QAAQD,QAAQ,OAAOO,UAAW/H,EAAMC,QAAkC,IAAxBD,EAAMC,OAAO+C,OAAcqD,QAxHzF,WAAK,IAAA2B,EACP,QAAnBA,EAAA1I,EAAM2I,qBAAND,IAAmBA,GAAnBA,EAAAE,KAAA5I,EAAsBI,EAAaS,MAAOT,EAC3C,EAwHgBmG,SAAA,cACTb,EAACmD,EAAG,CAAC3D,GAAI,CAAE4D,KAAM,KACjBpD,EAAC8C,EAAM,CAACzD,KAAK,QAAQoD,MAAM,UAAUD,QAAQ,OAAOnB,QAAS/G,EAAM2G,QAAOJ,SAAA,WAG1Eb,EAAC8C,EAAO,CAAAzD,KAAK,QAAQgE,KAAK,SAASZ,MAAM,UAAUD,QAAQ,YAAYO,SAAU1E,GAExEwC,SAAA,iBAKlB,CAGH,CAQA,IAAMT,EAAakD,EAAO,OAAPA,CAAe,CAChCC,SAAU,WACV,WAAY,CACVC,QAAS,KACTC,QAAS,QACTF,SAAU,WACVG,MAAO,EACPC,gBAAiB,qBACjB/C,OAAQ,YACRnB,QAAU,EACVmE,QAAS,EACTC,WAAY,eACZC,WAAY,UAEd,aAAc,CACZC,cAAe,OACf,WAAY,CACVtE,OAAQ,EACRmE,QAAS,EACTE,WAAY,cAcF,SAAAE,IAA8D,IACtErG,EAAStE,EADiB4K,UAAAjG,OAAA,QAAA7B,IAAA8H,UAAA,GAAAA,UAAA,GAAkC,YAElE,OAAO,SAACjJ,EAAoBuC,EAAe2G,GAA8D,IAAAC,EACjG3G,EAAIpB,EAAMpB,GACVyC,EAAUD,EAAEE,UAAYF,EAAEG,OAAOA,GAAUC,OAAO5C,GACxD,MAA6B,UAAzBkJ,EAAW3I,UAAwC,IAAVgC,EAAW,SAAAM,OAAYJ,UAAOI,OAAYJ,GACnFyG,EAAW3I,UAAW,GAAAsC,OAAqE,QAArEsG,EAAUlL,EAAkBiL,EAAW3I,kBAA8B,IAAA4I,EAAAA,EAAID,EAAW3I,UAAS,MAAAsC,OAAKJ,GACrHA,CACR,CACH"}
@@ -1,2 +1,2 @@
1
- import{slicedToArray as e,defineProperty as l}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as i,jsxs as n}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as t}from"react";import{styled as a,Typography as u,ToggleButtonGroup as s,ToggleButton as c,TextField as d,Button as v,Box as p}from"@mui/material";import{createChipViewers as f}from"../components/chip-viewer.js";import{getErrorMessage as m}from"../../form/helpers.js";import{ButtonBack as g,FilterLogicToggle as b}from"../components/ui.units.js";import{PopperContent as h,PopperBody as x,PopperFooter as y}from"../components/popper-custom.js";var C={eq:"=",lt:"<",lte:"≤",gt:">",gte:"≥"},z=["eq","lt","lte","gt","gte"];function j(e,l){return"".concat(e,":").concat(l)}function k(e){if("string"!=typeof e)return null;var l=e.indexOf(":");if(-1===l)return null;var i=e.slice(0,l),n=parseFloat(e.slice(l+1));return!z.includes(i)||isNaN(n)?null:{operator:i,num:n}}function A(e){var l=k(e);return l?"".concat(C[l.operator]," ").concat(l.num):String(e)}function N(a){var k=f();return function(f){var N,S,B,T,O=o(function(){return Object.assign({},f.currentConfig,null==a?void 0:a.config)},[null==a?void 0:a.config,f.currentConfig]),P=t(),R=f.value,q=void 0===R?{values:[],logic:null!==(N=null==O?void 0:O.defaultLogic)&&void 0!==N?N:"or"}:R,w=r(q.logic),I=e(w,2),M=I[0],V=I[1],E=r(null!==(S=null==a?void 0:a.defaultOperator)&&void 0!==S?S:"eq"),H=e(E,2),L=H[0],_=H[1],D=r(""),W=e(D,2),G=W[0],J=W[1],K=null!==(B=null==O?void 0:O.label)&&void 0!==B?B:O.field.toString(),Q=r({}),U=e(Q,2),X=U[0],Y=U[1],Z=function(e){f.onSubmit(O.field,e,O)},$=M!==q.logic,ee=m(X,O.field),le=o(function(){var e=Array.isArray(q.values)?q.values:[q.values];return{field:O.field,items:e.map(function(e){return{value:e,label:A(e)}})}},[O.field,q]),ie=!(""!==G.trim()&&!isNaN(parseFloat(G)))&&!$,ne=[];return f.isLoading&&ne.push("disabled"),i(F,{className:ne.join(" "),noValidate:!0,onSubmit:function(e){var i,n,o;e.preventDefault(),e.stopPropagation();var r=parseFloat(null!==(i=null===(n=P.current)||void 0===n?void 0:n.value)&&void 0!==i?i:"");if(isNaN(r))$&&Z({values:q.values,logic:M});else{var t=l({},O.field,r),a=null===(o=f.validator)||void 0===o?void 0:o.run(t);if(Y(a||{}),!a||0===Object.keys(a).length){var u=j(L,r);Z({values:[u],logic:M}),P.current&&(P.current.blur(),P.current.value=""),J("")}}},children:n(h,{title:"Filter by ".concat(K),onClose:f.onClose,slots:{beforeTitle:i(g,{size:"small",onClick:f.onBack}),afterTitle:O.singleValue?null:i(b,{sx:{ml:1},value:M,onChange:function(e,l){V(l)}})},children:[n(x,{children:[O.description&&i(u,{variant:"caption",color:"text.secondary",sx:{display:"block",mb:1},children:O.description}),i(k,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:le,onRemove:f.onRemove}),i(s,{exclusive:!0,size:"small",value:L,onChange:function(e,l){l&&_(l)},sx:{mb:1,width:"100%",".MuiToggleButton-root":{flex:1,py:.25,fontSize:"0.8rem"}},children:z.map(function(e){return i(c,{value:e,children:C[e]},e)})}),i(d,{inputRef:P,autoFocus:!0,type:"number",name:O.field.toString(),size:"small",fullWidth:!0,placeholder:"Enter number",error:ee.error,helperText:ee.message,inputProps:{step:null!==(T=null==a?void 0:a.step)&&void 0!==T?T:1,min:null==a?void 0:a.min,max:null==a?void 0:a.max},onChange:function(e){return J(e.target.value)},sx:{".MuiInputBase-root":{minHeight:"42px"}}})]}),n(y,{children:[i(v,{size:"small",color:"error",variant:"text",disabled:!q.values||0===q.values.length,onClick:function(){var e,l;null===(e=f.onRemoveField)||void 0===e||e.call(f,O.field),!1!==(null==a||null===(l=a.config)||void 0===l?void 0:l.closeAfterClear)&&f.onClose()},children:"Clear All"}),i(p,{sx:{flex:1}}),i(v,{size:"small",color:"inherit",variant:"text",onClick:f.onClose,children:"Cancel"}),i(v,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:ie,children:"Apply"})]})]})})}}var F=a("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"}}});function S(){return function(e){return A(e)}}export{k as decodeNumberValue,N as default,j as encodeNumberValue,A as formatNumberChipLabel,S as formatterNumber};
1
+ import{slicedToArray as e,defineProperty as i}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as l,jsxs as n}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as t}from"react";import{styled as a,Typography as u,ToggleButtonGroup as s,ToggleButton as c,TextField as d,Button as v,Box as p}from"@mui/material";import{createChipViewers as m}from"../components/chip-viewer.js";import{getErrorMessage as f}from"../../form/helpers.js";import{ButtonBack as g,FilterLogicToggle as b}from"../components/ui.units.js";import{PopperContent as h,PopperBody as x,PopperFooter as y}from"../components/popper-custom.js";var C={eq:"=",lt:"<",lte:"≤",gt:">",gte:"≥"},z=["eq","lt","lte","gt","gte"];function j(e,i){return"".concat(e,":").concat(i)}function k(e){if("string"!=typeof e)return null;var i=e.indexOf(":");if(-1===i)return null;var l=e.slice(0,i),n=parseFloat(e.slice(i+1));return!z.includes(l)||isNaN(n)?null:{operator:l,num:n}}function N(e){var i=k(e);return i?"".concat(C[i.operator]," ").concat(i.num):String(e)}function A(a){var k=m();return function(m){var A,S,B,T,O=o(function(){return Object.assign({},m.currentConfig,null==a?void 0:a.config)},[null==a?void 0:a.config,m.currentConfig]),P=t(),R=m.value,q=void 0===R?{values:[],logic:null!==(A=null==O?void 0:O.defaultLogic)&&void 0!==A?A:"or"}:R,w=r(q.logic),I=e(w,2),M=I[0],V=I[1],E=r(null!==(S=null==a?void 0:a.defaultOperator)&&void 0!==S?S:"eq"),H=e(E,2),L=H[0],_=H[1],D=r(""),W=e(D,2),G=W[0],J=W[1],K=null!==(B=null==O?void 0:O.label)&&void 0!==B?B:O.field.toString(),Q=r({}),U=e(Q,2),X=U[0],Y=U[1],Z=function(e){m.onSubmit(O.field,e,O)},$=M!==q.logic,ee=f(X,O.field),ie=o(function(){var e=Array.isArray(q.values)?q.values:[q.values];return{field:O.field,items:e.map(function(e){return{value:e,label:N(e)}})}},[O.field,q]),le=!(""!==G.trim()&&!isNaN(parseFloat(G)))&&!$,ne=[];return m.isLoading&&ne.push("disabled"),l(F,{className:ne.join(" "),noValidate:!0,onSubmit:function(e){var l,n,o;e.preventDefault(),e.stopPropagation();var r=parseFloat(null!==(l=null===(n=P.current)||void 0===n?void 0:n.value)&&void 0!==l?l:"");if(isNaN(r))$&&Z({values:q.values,logic:M});else{var t=i({},O.field,r),a=null===(o=m.validator)||void 0===o?void 0:o.run(t);if(Y(a||{}),!a||0===Object.keys(a).length){var u=j(L,r);Z({values:[u],logic:M}),P.current&&(P.current.blur(),P.current.value=""),J("")}}},children:n(h,{title:"Filter by ".concat(K),onClose:m.onClose,slots:{beforeTitle:l(g,{size:"small",onClick:m.onBack}),afterTitle:O.singleValue?null:l(b,{sx:{ml:1},value:M,onChange:function(e,i){V(i)}})},children:[n(x,{children:[O.description&&l(u,{variant:"caption",color:"text.secondary",sx:{display:"block",mb:1},children:O.description}),l(k,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:ie,onRemove:m.onRemove}),l(s,{exclusive:!0,size:"small",value:L,onChange:function(e,i){i&&_(i)},sx:{mb:1,width:"100%",".MuiToggleButton-root":{flex:1,py:.25,fontSize:"0.8rem"}},children:z.map(function(e){return l(c,{value:e,children:C[e]},e)})}),l(d,{inputRef:P,autoFocus:!0,type:"number",name:O.field.toString(),size:"small",fullWidth:!0,placeholder:"Enter number",error:ee.error,helperText:ee.message,inputProps:{step:null!==(T=null==a?void 0:a.step)&&void 0!==T?T:1,min:null==a?void 0:a.min,max:null==a?void 0:a.max},onChange:function(e){return J(e.target.value)},sx:{".MuiInputBase-root":{minHeight:"42px"}}})]}),n(y,{children:[l(v,{size:"small",color:"error",variant:"text",disabled:!q.values||0===q.values.length,onClick:function(){var e;null===(e=m.onRemoveField)||void 0===e||e.call(m,O.field,O)},children:"Clear All"}),l(p,{sx:{flex:1}}),l(v,{size:"small",color:"inherit",variant:"text",onClick:m.onClose,children:"Cancel"}),l(v,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:le,children:"Apply"})]})]})})}}var F=a("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"}}});function S(){return function(e){return N(e)}}export{k as decodeNumberValue,A as default,j as encodeNumberValue,N as formatNumberChipLabel,S as formatterNumber};
2
2
  //# sourceMappingURL=create-form-field-number.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-form-field-number.js","sources":["../../../../src/filter-bar/menu/create-form-field-number.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, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } 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, TNumberOperator } from '../types'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Constants\r\n// ---------------------------------------------------------------------------\r\n\r\nconst OPERATOR_SYMBOLS: Record<TNumberOperator, string> = {\r\n eq: '=',\r\n lt: '<',\r\n lte: '≤',\r\n gt: '>',\r\n gte: '≥'\r\n}\r\n\r\nconst OPERATORS: TNumberOperator[] = ['eq', 'lt', 'lte', 'gt', 'gte']\r\n\r\n// ---------------------------------------------------------------------------\r\n// Encode / decode helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Encodes operator + number into a single string stored in `values[]`. e.g. `\"gt:18\"` */\r\nexport function encodeNumberValue(operator: TNumberOperator, num: number): string {\r\n return `${operator}:${num}`\r\n}\r\n\r\n/** Decodes an encoded number value back into its parts. Returns `null` if invalid. */\r\nexport function decodeNumberValue(encoded: TFieldValid): { operator: TNumberOperator; num: number } | null {\r\n if (typeof encoded !== 'string') return null\r\n const colonIdx = encoded.indexOf(':')\r\n if (colonIdx === -1) return null\r\n const op = encoded.slice(0, colonIdx) as TNumberOperator\r\n const num = parseFloat(encoded.slice(colonIdx + 1))\r\n if (!OPERATORS.includes(op) || isNaN(num)) return null\r\n return { operator: op, num }\r\n}\r\n\r\n/** Returns a human-readable chip label for an encoded number value, e.g. `\"> 18\"`. */\r\nexport function formatNumberChipLabel(encoded: TFieldValid): string {\r\n const decoded = decodeNumberValue(encoded)\r\n if (!decoded) return String(encoded)\r\n return `${OPERATOR_SYMBOLS[decoded.operator]} ${decoded.num}`\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Props for the `FormFieldNumber` component returned by `createFormFieldNumber`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldNumberProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldNumber` to configure the generated component. */\r\nexport interface IFormFieldNumberParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n /** Default operator shown when the menu first opens. @default 'eq' */\r\n defaultOperator?: TNumberOperator\r\n /** Step for the number input. @default 1 */\r\n step?: number\r\n /** Min allowed value */\r\n min?: number\r\n /** Max allowed value */\r\n max?: number\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Factory function that creates a `FormFieldNumber` filter-menu component.\r\n *\r\n * The generated component renders a number input with a comparison-operator\r\n * toggle (`=`, `<`, `≤`, `>`, `≥`) inside a popper/menu panel. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values with operator labels\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 * Each submitted value is encoded as `\"<operator>:<number>\"` (e.g. `\"gt:18\"`)\r\n * and stored in `TFieldValue.values[]`. Use `decodeNumberValue` / `formatNumberChipLabel`\r\n * to decode them when building query logic.\r\n *\r\n * @param params - Static configuration (optional field config override, default operator, step, min, max)\r\n * @returns A React FC ready to be used as a number filter-menu field component\r\n */\r\nfunction createFormFieldNumber<T>(params?: IFormFieldNumberParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldNumber: FC<IFormFieldNumberProps<T>> = (props) => {\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 [operator, setOperator] = useState<TNumberOperator>(params?.defaultOperator ?? 'eq')\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\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n\r\n const rawNum = parseFloat(refInput.current?.value ?? '')\r\n\r\n // Submit logic change only (no new value)\r\n if (isNaN(rawNum)) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: filterLogic })\r\n }\r\n return\r\n }\r\n\r\n const obj = { [mergedConfig.field]: rawNum } as Partial<TFieldModelValid<T>>\r\n const validationError = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(validationError || {})\r\n\r\n if (!validationError || Object.keys(validationError).length === 0) {\r\n const encoded = encodeNumberValue(operator, rawNum)\r\n const newValue: TFieldValue = { values: [encoded], 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 {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: formatNumberChipLabel(v) }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const hasValidInput = inputValue.trim() !== '' && !isNaN(parseFloat(inputValue))\r\n const isApplyDisabled = !hasValidInput && !hasLogicChange\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return null\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={filterLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\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 {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 <ToggleButtonGroup\r\n exclusive\r\n size='small'\r\n value={operator}\r\n onChange={(_, val) => {\r\n if (val) setOperator(val)\r\n }}\r\n sx={{ mb: 1, width: '100%', '.MuiToggleButton-root': { flex: 1, py: 0.25, fontSize: '0.8rem' } }}\r\n >\r\n {OPERATORS.map((op) => (\r\n <ToggleButton key={op} value={op}>\r\n {OPERATOR_SYMBOLS[op]}\r\n </ToggleButton>\r\n ))}\r\n </ToggleButtonGroup>\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n type='number'\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter number'\r\n error={error.error}\r\n helperText={error.message}\r\n inputProps={{ step: params?.step ?? 1, min: params?.min, max: params?.max }}\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 FormFieldNumber\r\n}\r\n\r\nexport default createFormFieldNumber\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,\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\r\n// ---------------------------------------------------------------------------\r\n// Utilities\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Creates a labelFormatter for use in summaryConfig.\r\n * Formats encoded number values (e.g. `\"gt:18\"`) to a human-readable label (e.g. `\"> 18\"`).\r\n *\r\n * @example\r\n * summaryConfig: {\r\n * labelFormatter: { age: formatterNumber() }\r\n * }\r\n */\r\nexport function formatterNumber() {\r\n return (value: TFieldValid): string | undefined => {\r\n return formatNumberChipLabel(value)\r\n }\r\n}\r\n"],"names":["OPERATOR_SYMBOLS","eq","lt","lte","gt","gte","OPERATORS","encodeNumberValue","operator","num","concat","decodeNumberValue","encoded","colonIdx","indexOf","op","slice","parseFloat","includes","isNaN","formatNumberChipLabel","decoded","String","createFormFieldNumber","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_params$defaultOperat","_mergedConfig$label","_params$step","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","_useState3","defaultOperator","_useState4","setOperator","_useState5","_useState6","inputValue","setInputValue","label","field","toString","_useState7","_useState8","errorData","setErrorData","handleSubmit","newValue","onSubmit","hasLogicChange","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","isApplyDisabled","trim","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_refInput$current$val","_refInput$current","_props$validator","preventDefault","stopPropagation","rawNum","current","obj","_defineProperty","validationError","validator","run","keys","length","blur","children","_jsxs","PopperContent","title","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","FilterLogicToggle","sx","ml","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","mb","borderBottom","placement","enableMinimalesticView","onRemove","ToggleButtonGroup","exclusive","val","width","flex","py","fontSize","ToggleButton","TextField","inputRef","autoFocus","type","name","fullWidth","placeholder","helperText","message","inputProps","step","min","max","e","target","minHeight","PopperFooter","Button","disabled","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","formatterNumber"],"mappings":"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"}
1
+ {"version":3,"file":"create-form-field-number.js","sources":["../../../../src/filter-bar/menu/create-form-field-number.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, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } 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, TNumberOperator } from '../types'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Constants\r\n// ---------------------------------------------------------------------------\r\n\r\nconst OPERATOR_SYMBOLS: Record<TNumberOperator, string> = {\r\n eq: '=',\r\n lt: '<',\r\n lte: '≤',\r\n gt: '>',\r\n gte: '≥'\r\n}\r\n\r\nconst OPERATORS: TNumberOperator[] = ['eq', 'lt', 'lte', 'gt', 'gte']\r\n\r\n// ---------------------------------------------------------------------------\r\n// Encode / decode helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Encodes operator + number into a single string stored in `values[]`. e.g. `\"gt:18\"` */\r\nexport function encodeNumberValue(operator: TNumberOperator, num: number): string {\r\n return `${operator}:${num}`\r\n}\r\n\r\n/** Decodes an encoded number value back into its parts. Returns `null` if invalid. */\r\nexport function decodeNumberValue(encoded: TFieldValid): { operator: TNumberOperator; num: number } | null {\r\n if (typeof encoded !== 'string') return null\r\n const colonIdx = encoded.indexOf(':')\r\n if (colonIdx === -1) return null\r\n const op = encoded.slice(0, colonIdx) as TNumberOperator\r\n const num = parseFloat(encoded.slice(colonIdx + 1))\r\n if (!OPERATORS.includes(op) || isNaN(num)) return null\r\n return { operator: op, num }\r\n}\r\n\r\n/** Returns a human-readable chip label for an encoded number value, e.g. `\"> 18\"`. */\r\nexport function formatNumberChipLabel(encoded: TFieldValid): string {\r\n const decoded = decodeNumberValue(encoded)\r\n if (!decoded) return String(encoded)\r\n return `${OPERATOR_SYMBOLS[decoded.operator]} ${decoded.num}`\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public interfaces\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Props for the `FormFieldNumber` component returned by `createFormFieldNumber`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldNumberProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldNumber` to configure the generated component. */\r\nexport interface IFormFieldNumberParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n /** Default operator shown when the menu first opens. @default 'eq' */\r\n defaultOperator?: TNumberOperator\r\n /** Step for the number input. @default 1 */\r\n step?: number\r\n /** Min allowed value */\r\n min?: number\r\n /** Max allowed value */\r\n max?: number\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Factory function that creates a `FormFieldNumber` filter-menu component.\r\n *\r\n * The generated component renders a number input with a comparison-operator\r\n * toggle (`=`, `<`, `≤`, `>`, `≥`) inside a popper/menu panel. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values with operator labels\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 * Each submitted value is encoded as `\"<operator>:<number>\"` (e.g. `\"gt:18\"`)\r\n * and stored in `TFieldValue.values[]`. Use `decodeNumberValue` / `formatNumberChipLabel`\r\n * to decode them when building query logic.\r\n *\r\n * @param params - Static configuration (optional field config override, default operator, step, min, max)\r\n * @returns A React FC ready to be used as a number filter-menu field component\r\n */\r\nfunction createFormFieldNumber<T>(params?: IFormFieldNumberParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldNumber: FC<IFormFieldNumberProps<T>> = (props) => {\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 [operator, setOperator] = useState<TNumberOperator>(params?.defaultOperator ?? 'eq')\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\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n\r\n const rawNum = parseFloat(refInput.current?.value ?? '')\r\n\r\n // Submit logic change only (no new value)\r\n if (isNaN(rawNum)) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: filterLogic })\r\n }\r\n return\r\n }\r\n\r\n const obj = { [mergedConfig.field]: rawNum } as Partial<TFieldModelValid<T>>\r\n const validationError = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(validationError || {})\r\n\r\n if (!validationError || Object.keys(validationError).length === 0) {\r\n const encoded = encodeNumberValue(operator, rawNum)\r\n const newValue: TFieldValue = { values: [encoded], 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 {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: formatNumberChipLabel(v) }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const hasValidInput = inputValue.trim() !== '' && !isNaN(parseFloat(inputValue))\r\n const isApplyDisabled = !hasValidInput && !hasLogicChange\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 null\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={filterLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\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 {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 <ToggleButtonGroup\r\n exclusive\r\n size='small'\r\n value={operator}\r\n onChange={(_, val) => {\r\n if (val) setOperator(val)\r\n }}\r\n sx={{ mb: 1, width: '100%', '.MuiToggleButton-root': { flex: 1, py: 0.25, fontSize: '0.8rem' } }}\r\n >\r\n {OPERATORS.map((op) => (\r\n <ToggleButton key={op} value={op}>\r\n {OPERATOR_SYMBOLS[op]}\r\n </ToggleButton>\r\n ))}\r\n </ToggleButtonGroup>\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n type='number'\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter number'\r\n error={error.error}\r\n helperText={error.message}\r\n inputProps={{ step: params?.step ?? 1, min: params?.min, max: params?.max }}\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 FormFieldNumber\r\n}\r\n\r\nexport default createFormFieldNumber\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,\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\r\n// ---------------------------------------------------------------------------\r\n// Utilities\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Creates a labelFormatter for use in summaryConfig.\r\n * Formats encoded number values (e.g. `\"gt:18\"`) to a human-readable label (e.g. `\"> 18\"`).\r\n *\r\n * @example\r\n * summaryConfig: {\r\n * labelFormatter: { age: formatterNumber() }\r\n * }\r\n */\r\nexport function formatterNumber() {\r\n return (value: TFieldValid): string | undefined => {\r\n return formatNumberChipLabel(value)\r\n }\r\n}\r\n"],"names":["OPERATOR_SYMBOLS","eq","lt","lte","gt","gte","OPERATORS","encodeNumberValue","operator","num","concat","decodeNumberValue","encoded","colonIdx","indexOf","op","slice","parseFloat","includes","isNaN","formatNumberChipLabel","decoded","String","createFormFieldNumber","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_params$defaultOperat","_mergedConfig$label","_params$step","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","_useState3","defaultOperator","_useState4","setOperator","_useState5","_useState6","inputValue","setInputValue","label","field","toString","_useState7","_useState8","errorData","setErrorData","handleSubmit","newValue","onSubmit","hasLogicChange","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","isApplyDisabled","trim","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_refInput$current$val","_refInput$current","_props$validator","preventDefault","stopPropagation","rawNum","current","obj","_defineProperty","validationError","validator","run","keys","length","blur","children","_jsxs","PopperContent","title","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","FilterLogicToggle","sx","ml","onChange","_","nVal","PopperBody","description","Typography","variant","color","display","mb","borderBottom","placement","enableMinimalesticView","onRemove","ToggleButtonGroup","exclusive","val","width","flex","py","fontSize","ToggleButton","TextField","inputRef","autoFocus","type","name","fullWidth","placeholder","helperText","message","inputProps","step","min","max","e","target","minHeight","PopperFooter","Button","disabled","_props$onRemoveField","onRemoveField","call","Box","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","formatterNumber"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{slicedToArray as l,toConsumableArray as e,defineProperty as n}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as o,jsxs as i}from"react/jsx-runtime";import{useMemo as r,useState as t,useRef as a,useEffect as u}from"react";import{styled as c,Box as s,Typography as d,CircularProgress as v,Button as m,FormGroup as f,FormControlLabel as p,Checkbox as b}from"@mui/material";import g from"@mui/icons-material/Info";import{createChipViewers as h}from"../components/chip-viewer.js";import{PopperContent as x,PopperBody as y,PopperFooter as C}from"../components/popper-custom.js";import{ButtonBack as A,ChipDark as V,FilterLogicToggle as k}from"../components/ui.units.js";import{getErrorMessage as z}from"../../form/helpers.js";function j(c){var j=h(),O=(c||{}).options,L=void 0===O?[]:O;return function(h){var O,w,I,R=r(function(){return Object.assign({},h.currentConfig,null==c?void 0:c.config)},[null==c?void 0:c.config,h.currentConfig]),B=h.value,E=void 0===B?{values:[],logic:null!==(O=null==R?void 0:R.defaultLogic)&&void 0!==O?O:"or"}:B,F=t(E.logic),N=l(F,2),T=N[0],D=N[1],M=null!==(w=null==c?void 0:c.forceLogic)&&void 0!==w?w:T,P=null!==(I=null==R?void 0:R.label)&&void 0!==I?I:R.field.toString(),_=t([]),H=l(_,2),U=H[0],q=H[1],G=t(null!=c&&c.fetchOptions?"loading":"loaded"),J=l(G,2),K=J[0],Q=J[1],W=a(null),X=function(){var l;if(null!=c&&c.fetchOptions){null===(l=W.current)||void 0===l||l.abort();var e=new AbortController;W.current=e,Q("loading"),c.fetchOptions(e.signal).then(function(l){q(l),Q("loaded")}).catch(function(l){var e;null===(e=h.onError)||void 0===e||e.call(h),"AbortError"!==(null==l?void 0:l.name)&&Q("error")})}};u(function(){return X(),function(){var l;return null===(l=W.current)||void 0===l?void 0:l.abort()}},[]);var Y=null!=c&&c.fetchOptions?U:L,Z=t(function(){return Array.isArray(E.values)?e(E.values):[]}),$=l(Z,2),ll=$[0],el=$[1],nl=Array.isArray(E.values)?E.values:[],ol=T!==E.logic,il=ll.length!==nl.length||ll.some(function(l){return!nl.includes(l)}),rl=!il&&!ol,tl=t({}),al=l(tl,2),ul=al[0],cl=al[1],sl=function(l){h.onSubmit(R.field,l,R)},dl=z(ul,R.field),vl=r(function(){var l=Array.isArray(E.values)?E.values:[E.values];return{field:R.field,items:l.map(function(l){var e;return{value:l,label:null===(e=Y.find(function(e){return e.value===l}))||void 0===e?void 0:e.label}})}},[R.field,E]),ml=null!=(null==c?void 0:c.maxValueCount)&&ll.length>c.maxValueCount,fl=null!=(null==c?void 0:c.maxValueCount)&&ll.length>=c.maxValueCount;r(function(){var l=(null==c?void 0:c.top)||h.top;return l?o(s,{sx:{mb:1},children:l}):null},[null==c?void 0:c.top,h.top]);var pl=[];return(h.isLoading||"loading"===K)&&pl.push("disabled"),o(S,{className:pl.join(" "),noValidate:!0,onSubmit:function(l){var e;if(l.preventDefault(),il){if(!ml){var o=n({},R.field,ll),i=null===(e=h.validator)||void 0===e?void 0:e.run(o);if(cl(i||{}),!i||0===Object.keys(i).length)sl({values:ll,logic:M})}}else ol&&sl({values:E.values,logic:M})},children:i(x,{title:"Filter by ".concat(P),onClose:h.onClose,slots:{beforeTitle:o(A,{size:"small",onClick:h.onBack}),afterTitle:null!=c&&c.forceLogic?null:R.singleValue?o(V,{sx:{ml:1.5},size:"small",label:"Last value only"}):o(k,{sx:{ml:1},value:M,onChange:function(l,e){D(e)}})},children:[i(y,{children:[R.description&&o(d,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:R.description}),null!=(null==c?void 0:c.maxValueCount)&&o(d,{variant:"caption",color:ml?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:null!=c&&c.maxValueCount?ml?"Maximum ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," can be selected"):""}),o(j,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:vl,onRemove:h.onRemove}),"loading"===K&&o(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:o(v,{size:20})}),"error"===K&&i(s,{sx:{display:"flex",flexDirection:"column",alignItems:"center",mt:2,mb:3,gap:1},children:[o(g,{color:"error",fontSize:"large"}),o(d,{variant:"body2",color:"error",children:"Failed to load options"}),o(m,{size:"small",variant:"outlined",color:"error",onClick:X,children:"Retry"})]}),0===Y.length&&"loaded"===K&&o(d,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),o(f,{className:dl.error?"error":"",children:Y.map(function(l,n){var i,r=ll.includes(l.value),t=vl.items.some(function(e){return e.value===l.value})&&!0===(null==c?void 0:c.disabledAfterSubmit),a=!r&&fl;return o(p,{value:l.value,disabled:t||a,label:null!==(i=l.label)&&void 0!==i?i:l.value,control:o(b,{name:R.field.toString(),checked:r,onChange:function(n){return o=l.value,i=n.target.checked,void el(function(l){return i?[].concat(e(l),[o]):l.filter(function(l){return l!==o})});var o,i}})},l.value.toString()+n)})})]}),i(C,{children:[o(m,{size:"small",color:"error",variant:"text",disabled:!E.values||0===E.values.length,onClick:function(){var l,e;null===(l=h.onRemoveField)||void 0===l||l.call(h,R.field),!1!==(null==c||null===(e=c.config)||void 0===e?void 0:e.closeAfterClear)&&h.onClose()},children:"Clear All"}),o(s,{sx:{flex:1}}),o(m,{size:"small",color:"inherit",variant:"text",onClick:h.onClose,children:"Cancel"}),o(m,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:rl,children:"Apply"})]})]})})}}var S=c("form")({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}});export{j as default};
1
+ import{slicedToArray as l,toConsumableArray as e,defineProperty as o}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as n,jsxs as i}from"react/jsx-runtime";import{useMemo as r,useState as t,useRef as a,useEffect as u}from"react";import{styled as c,Box as s,Typography as d,CircularProgress as m,Button as v,FormGroup as f,FormControlLabel as p,Checkbox as b}from"@mui/material";import g from"@mui/icons-material/Info";import"../../form/validator.js";import"../../form/dino-form.js";import{getErrorMessage as h}from"../../form/helpers.js";import"../../../_virtual/Reflect.js";import"../../form/decorator.form.js";import"../../form/create.form-grid-layout.units.js";import{createChipViewers as x}from"../components/chip-viewer.js";import{PopperContent as y,PopperBody as C,PopperFooter as j}from"../components/popper-custom.js";import{ButtonBack as A,ChipDark as V,FilterLogicToggle as k}from"../components/ui.units.js";function z(c){var z=x(),O=(c||{}).options,L=void 0===O?[]:O;return function(x){var O,R,w,I=r(function(){return Object.assign({},x.currentConfig,null==c?void 0:c.config)},[null==c?void 0:c.config,x.currentConfig]),B=x.value,E=void 0===B?{values:[],logic:null!==(O=null==I?void 0:I.defaultLogic)&&void 0!==O?O:"or"}:B,F=t(E.logic),N=l(F,2),T=N[0],_=N[1],D=null!==(R=null==c?void 0:c.forceLogic)&&void 0!==R?R:T,M=null!==(w=null==I?void 0:I.label)&&void 0!==w?w:I.field.toString(),P=t([]),H=l(P,2),U=H[0],q=H[1],G=t(null!=c&&c.fetchOptions?"loading":"loaded"),J=l(G,2),K=J[0],Q=J[1],W=a(null),X=function(){var l;if(null!=c&&c.fetchOptions){null===(l=W.current)||void 0===l||l.abort();var e=new AbortController;W.current=e,Q("loading"),c.fetchOptions(e.signal).then(function(l){q(l),Q("loaded")}).catch(function(l){var e;null===(e=x.onError)||void 0===e||e.call(x),"AbortError"!==(null==l?void 0:l.name)&&Q("error")})}};u(function(){return X(),function(){var l;return null===(l=W.current)||void 0===l?void 0:l.abort()}},[]);var Y=null!=c&&c.fetchOptions?U:L,Z=t(function(){return Array.isArray(E.values)?e(E.values):[]}),$=l(Z,2),ll=$[0],el=$[1],ol=Array.isArray(E.values)?E.values:[],nl=T!==E.logic,il=ll.length!==ol.length||ll.some(function(l){return!ol.includes(l)}),rl=!il&&!nl,tl=t({}),al=l(tl,2),ul=al[0],cl=al[1],sl=function(l){x.onSubmit(I.field,l,I)},dl=h(ul,I.field),ml=r(function(){var l=Array.isArray(E.values)?E.values:[E.values];return{field:I.field,items:l.map(function(l){var e;return{value:l,label:null===(e=Y.find(function(e){return e.value===l}))||void 0===e?void 0:e.label}})}},[I.field,E]),vl=null!=(null==c?void 0:c.maxValueCount)&&ll.length>c.maxValueCount,fl=null!=(null==c?void 0:c.maxValueCount)&&ll.length>=c.maxValueCount,pl=r(function(){var l=(null==c?void 0:c.top)||x.top;return l?n(s,{sx:{mb:1},children:l}):null},[null==c?void 0:c.top,x.top]),bl=[];return(x.isLoading||"loading"===K)&&bl.push("disabled"),n(S,{className:bl.join(" "),noValidate:!0,onSubmit:function(l){var e;if(l.preventDefault(),il){if(!vl){var n=o({},I.field,ll),i=null===(e=x.validator)||void 0===e?void 0:e.run(n);if(cl(i||{}),!i||0===Object.keys(i).length)sl({values:ll,logic:D})}}else nl&&sl({values:E.values,logic:D})},children:i(y,{title:"Filter by ".concat(M),onClose:x.onClose,slots:{beforeTitle:n(A,{size:"small",onClick:x.onBack}),afterTitle:null!=c&&c.forceLogic?null:I.singleValue?n(V,{sx:{ml:1.5},size:"small",label:"Last value only"}):n(k,{sx:{ml:1},value:D,onChange:function(l,e){_(e)}})},children:[i(C,{children:[pl,I.description&&n(d,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:I.description}),null!=(null==c?void 0:c.maxValueCount)&&n(d,{variant:"caption",color:vl?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:null!=c&&c.maxValueCount?vl?"Maximum ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," can be selected"):""}),n(z,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:ml,onRemove:x.onRemove}),"loading"===K&&n(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:n(m,{size:20})}),"error"===K&&i(s,{sx:{display:"flex",flexDirection:"column",alignItems:"center",mt:2,mb:3,gap:1},children:[n(g,{color:"error",fontSize:"large"}),n(d,{variant:"body2",color:"error",children:"Failed to load options"}),n(v,{size:"small",variant:"outlined",color:"error",onClick:X,children:"Retry"})]}),0===Y.length&&"loaded"===K&&n(d,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),n(f,{className:dl.error?"error":"",children:Y.map(function(l,o){var i,r=ll.includes(l.value),t=ml.items.some(function(e){return e.value===l.value})&&!0===(null==c?void 0:c.disabledAfterSubmit),a=!r&&fl;return n(p,{value:l.value,disabled:t||a,label:null!==(i=l.label)&&void 0!==i?i:l.value,control:n(b,{name:I.field.toString(),checked:r,onChange:function(o){return n=l.value,i=o.target.checked,void el(function(l){return i?[].concat(e(l),[n]):l.filter(function(l){return l!==n})});var n,i}})},l.value.toString()+o)})})]}),i(j,{children:[n(v,{size:"small",color:"error",variant:"text",disabled:!E.values||0===E.values.length,onClick:function(){var l;null===(l=x.onRemoveField)||void 0===l||l.call(x,I.field,I)},children:"Clear All"}),n(s,{sx:{flex:1}}),n(v,{size:"small",color:"inherit",variant:"text",onClick:x.onClose,children:"Cancel"}),n(v,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:rl,children:"Apply"})]})]})})}}var S=c("form")({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}});export{z as default};
2
2
  //# sourceMappingURL=create-form-field-select-multiple.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-form-field-select-multiple.js","sources":["../../../../src/filter-bar/menu/create-form-field-select-multiple.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { useEffect, useMemo, useRef, useState } from 'react'\r\nimport { Box, Button, Checkbox, CircularProgress, FormControlLabel, FormGroup, formGroupClasses, styled, Typography } from '@mui/material'\r\nimport InfoIcon from '@mui/icons-material/Info'\r\nimport { getErrorMessage } from '../../form'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\n// types\r\nimport type { FC, ReactNode } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { IFieldSelectOption } from './create-form-field-select'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps, TFetchStatus } from './types'\r\n\r\n/** Props for the `FormFieldSelectMultiple` component returned by `createFormFieldSelectMultiple`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectMultipleProps<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/** Parameters passed to `createFormFieldSelectMultiple` to configure the generated component. */\r\nexport interface IFormFieldSelectMultipleParam<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 */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** If true, disables the field after submission. @default false */\r\n disabledAfterSubmit?: boolean\r\n /** Force a fixed logic value, hiding the logic toggle */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected */\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 `FormFieldSelectMultiple` filter-menu component.\r\n *\r\n * The generated component renders a checkbox list of options inside a\r\n * popper/menu panel, allowing the user to select **multiple values** at once.\r\n * It supports:\r\n * - Controlled checkbox state to prevent uncontrolled→controlled React warnings\r\n * - OR / AND logic toggle when more than one value is applied\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 multi-select filter-menu field component\r\n */\r\nfunction createFormFieldSelectMultiple<T>(params?: IFormFieldSelectMultipleParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options: staticOptions = [] } = params || {}\r\n\r\n const FormFieldSelectMultiple: FC<IFormFieldSelectMultipleProps<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\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\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 options = params?.fetchOptions ? fetchedOptions : staticOptions\r\n\r\n // Track checked values as controlled state to avoid the uncontrolled→controlled MUI warning\r\n // Initialize directly from value.values so pre-selected values are visible even before fetchOptions resolves\r\n const [checkedValues, setCheckedValues] = useState<TFieldValid[]>(() => {\r\n return Array.isArray(value.values) ? [...value.values] : []\r\n })\r\n\r\n const appliedValues = Array.isArray(value.values) ? value.values : []\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = checkedValues.length !== appliedValues.length || checkedValues.some((v) => !appliedValues.includes(v))\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleCheckboxChange = (optionValue: TFieldValid, checked: boolean) => {\r\n setCheckedValues((prev) => (checked ? [...prev, optionValue] : prev.filter((v) => v !== optionValue)))\r\n }\r\n\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) handleSubmit({ values: value.values, logic: effectiveLogic })\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: checkedValues } 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: checkedValues, logic: effectiveLogic }\r\n handleSubmit(newValue)\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: options.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const isMaxReached = params?.maxValueCount != null && checkedValues.length > params.maxValueCount\r\n const isMaxReachedValid = params?.maxValueCount != null && checkedValues.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)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\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 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 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 {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 {options.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 <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected && params?.disabledAfterSubmit === true\r\n const disableDueToMax = !isChecked && isMaxReachedValid\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled || disableDueToMax}\r\n label={x.label ?? x.value}\r\n control={\r\n <Checkbox\r\n name={mergedConfig.field.toString()}\r\n checked={isChecked}\r\n onChange={(e) => handleCheckboxChange(x.value as TFieldValid, e.target.checked)}\r\n />\r\n }\r\n />\r\n )\r\n })}\r\n </FormGroup>\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 FormFieldSelectMultiple\r\n}\r\n\r\nexport default createFormFieldSelectMultiple\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 // [`.${formGroupClasses.root}`]: {}\r\n})\r\n"],"names":["createFormFieldSelectMultiple","params","ChipViewers","createChipViewers","_ref$options","options","staticOptions","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","label","field","toString","_useState3","_useState4","fetchedOptions","setFetchedOptions","_useState5","fetchOptions","_useState6","fetchStatus","setFetchStatus","abortRef","useRef","runFetch","_abortRef$current","current","abort","controller","AbortController","signal","then","data","err","_props$onError","onError","call","name","useEffect","_abortRef$current2","_useState7","Array","isArray","_toConsumableArray","_useState8","checkedValues","setCheckedValues","appliedValues","hasLogicChange","hasDataChange","length","some","v","includes","isApplyDisabled","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","map","_options$find","find","o","isMaxReached","maxValueCount","isMaxReachedValid","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","FormGroup","error","x","i","_x$label","isChecked","disabled","item","disabledAfterSubmit","disableDueToMax","FormControlLabel","control","Checkbox","checked","e","optionValue","target","prev","filter","PopperFooter","_props$onRemoveField","_params$config","onRemoveField","closeAfterClear","flex","type","styled","position","content","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
1
+ {"version":3,"file":"create-form-field-select-multiple.js","sources":["../../../../src/filter-bar/menu/create-form-field-select-multiple.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { useEffect, useMemo, useRef, useState } from 'react'\r\nimport { Box, Button, Checkbox, CircularProgress, FormControlLabel, FormGroup, formGroupClasses, styled, Typography } from '@mui/material'\r\nimport InfoIcon from '@mui/icons-material/Info'\r\nimport { getErrorMessage } from '../../form'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\n// types\r\nimport type { FC, ReactNode } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { IFieldSelectOption } from './create-form-field-select'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps, TFetchStatus } from './types'\r\n\r\n/** Props for the `FormFieldSelectMultiple` component returned by `createFormFieldSelectMultiple`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectMultipleProps<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/** Parameters passed to `createFormFieldSelectMultiple` to configure the generated component. */\r\nexport interface IFormFieldSelectMultipleParam<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 */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** If true, disables the field after submission. @default false */\r\n disabledAfterSubmit?: boolean\r\n /** Force a fixed logic value, hiding the logic toggle */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected */\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 `FormFieldSelectMultiple` filter-menu component.\r\n *\r\n * The generated component renders a checkbox list of options inside a\r\n * popper/menu panel, allowing the user to select **multiple values** at once.\r\n * It supports:\r\n * - Controlled checkbox state to prevent uncontrolled→controlled React warnings\r\n * - OR / AND logic toggle when more than one value is applied\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 multi-select filter-menu field component\r\n */\r\nfunction createFormFieldSelectMultiple<T>(params?: IFormFieldSelectMultipleParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options: staticOptions = [] } = params || {}\r\n\r\n const FormFieldSelectMultiple: FC<IFormFieldSelectMultipleProps<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\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\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 options = params?.fetchOptions ? fetchedOptions : staticOptions\r\n\r\n // Track checked values as controlled state to avoid the uncontrolled→controlled MUI warning\r\n // Initialize directly from value.values so pre-selected values are visible even before fetchOptions resolves\r\n const [checkedValues, setCheckedValues] = useState<TFieldValid[]>(() => {\r\n return Array.isArray(value.values) ? [...value.values] : []\r\n })\r\n\r\n const appliedValues = Array.isArray(value.values) ? value.values : []\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = checkedValues.length !== appliedValues.length || checkedValues.some((v) => !appliedValues.includes(v))\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleCheckboxChange = (optionValue: TFieldValid, checked: boolean) => {\r\n setCheckedValues((prev) => (checked ? [...prev, optionValue] : prev.filter((v) => v !== optionValue)))\r\n }\r\n\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) handleSubmit({ values: value.values, logic: effectiveLogic })\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: checkedValues } 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: checkedValues, logic: effectiveLogic }\r\n handleSubmit(newValue)\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: options.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const isMaxReached = params?.maxValueCount != null && checkedValues.length > params.maxValueCount\r\n const isMaxReachedValid = params?.maxValueCount != null && checkedValues.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 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 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 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 {options.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 <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected && params?.disabledAfterSubmit === true\r\n const disableDueToMax = !isChecked && isMaxReachedValid\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled || disableDueToMax}\r\n label={x.label ?? x.value}\r\n control={\r\n <Checkbox\r\n name={mergedConfig.field.toString()}\r\n checked={isChecked}\r\n onChange={(e) => handleCheckboxChange(x.value as TFieldValid, e.target.checked)}\r\n />\r\n }\r\n />\r\n )\r\n })}\r\n </FormGroup>\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 FormFieldSelectMultiple\r\n}\r\n\r\nexport default createFormFieldSelectMultiple\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 // [`.${formGroupClasses.root}`]: {}\r\n})\r\n"],"names":["createFormFieldSelectMultiple","params","ChipViewers","createChipViewers","_ref$options","options","staticOptions","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","label","field","toString","_useState3","_useState4","fetchedOptions","setFetchedOptions","_useState5","fetchOptions","_useState6","fetchStatus","setFetchStatus","abortRef","useRef","runFetch","_abortRef$current","current","abort","controller","AbortController","signal","then","data","err","_props$onError","onError","call","name","useEffect","_abortRef$current2","_useState7","Array","isArray","_toConsumableArray","_useState8","checkedValues","setCheckedValues","appliedValues","hasLogicChange","hasDataChange","length","some","v","includes","isApplyDisabled","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","map","_options$find","find","o","isMaxReached","maxValueCount","isMaxReachedValid","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","FormGroup","error","x","i","_x$label","isChecked","disabled","item","disabledAfterSubmit","disableDueToMax","FormControlLabel","control","Checkbox","checked","e","optionValue","target","prev","filter","PopperFooter","_props$onRemoveField","onRemoveField","flex","type","styled","position","content","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{defineProperty as l,slicedToArray as o}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{useMemo as i,useState as r,useRef as t,useEffect as a}from"react";import{styled as c,radioGroupClasses as u,Box as s,Typography as d,CircularProgress as m,Button as v,RadioGroup as f,FormControlLabel as p,Radio as b}from"@mui/material";import g from"@mui/icons-material/Info";import{getErrorMessage as h}from"../../form/helpers.js";import{createChipViewers as x}from"../components/chip-viewer.js";import{ButtonBack as C,ChipDark as y,FilterLogicToggle as z}from"../components/ui.units.js";import{PopperContent as k,PopperBody as V,PopperFooter as j}from"../components/popper-custom.js";function A(c){var u=x(),A=c.options;return function(x){var O,S,F,M=i(function(){return Object.assign({},x.currentConfig,null==c?void 0:c.config)},[null==c?void 0:c.config,x.currentConfig]),R=x.value,w=void 0===R?{values:[],logic:null!==(O=null==M?void 0:M.defaultLogic)&&void 0!==O?O:"or"}:R,I=r(w.logic),B=o(I,2),E=B[0],N=B[1],T=null!==(S=c.forceLogic)&&void 0!==S?S:E,D=r(null),P=o(D,2),_=P[0],H=P[1],U=r([]),q=o(U,2),G=q[0],J=q[1],K=r(c.fetchOptions?"loading":"loaded"),Q=o(K,2),W=Q[0],X=Q[1],Y=t(null),Z=function(){var l;if(c.fetchOptions){null===(l=Y.current)||void 0===l||l.abort();var o=new AbortController;Y.current=o,X("loading"),c.fetchOptions(o.signal).then(function(l){J(l),X("loaded")}).catch(function(l){var o;null===(o=x.onError)||void 0===o||o.call(x),"AbortError"!==(null==l?void 0:l.name)&&X("error")})}};a(function(){return Z(),function(){var l;return null===(l=Y.current)||void 0===l?void 0:l.abort()}},[]);var $=c.fetchOptions?G:null!=A?A:[],ll=E!==w.logic,ol=null!==_,el=!ol&&!ll,nl=null!==(F=null==M?void 0:M.label)&&void 0!==F?F:M.field.toString(),il=r({}),rl=o(il,2),tl=rl[0],al=rl[1],cl=function(l){x.onSubmit(M.field,l,M)},ul=h(tl,M.field),sl=i(function(){var l=Array.isArray(w.values)?w.values:[w.values];return{field:M.field,items:l.map(function(l){var o;return{value:l,label:null===(o=$.find(function(o){return o.value===l}))||void 0===o?void 0:o.label}})}},[M.field,w,$]),dl=null!=c.maxValueCount&&sl.items.length>=c.maxValueCount,ml=i(function(){var l=(null==c?void 0:c.top)||x.top;return l?e(s,{sx:{mb:1},children:l}):null},[null==c?void 0:c.top,x.top]),vl=[];return(x.isLoading||"loading"===W)&&vl.push("disabled"),e(L,{className:vl.join(" "),noValidate:!0,onSubmit:function(o){var e;if(o.preventDefault(),ol){if(!dl){var n=l({},M.field,_),i=null===(e=x.validator)||void 0===e?void 0:e.run(n);if(al(i||{}),!i||0===Object.keys(i).length)cl({values:[_],logic:T}),H(null)}}else ll&&cl({values:w.values,logic:T})},children:n(k,{title:"Filter by ".concat(nl),onClose:x.onClose,slots:{beforeTitle:e(C,{size:"small",onClick:x.onBack}),afterTitle:c.forceLogic?null:M.singleValue?e(y,{sx:{ml:1.5},size:"small",label:"Last value only"}):e(z,{sx:{ml:1},value:T,onChange:function(l,o){N(o)}})},children:[n(V,{children:[ml,M.description&&e(d,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:M.description}),null!=c.maxValueCount&&e(d,{variant:"caption",color:dl?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:c.maxValueCount?dl?"Maximum ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," can be selected"):""}),e(u,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:sl,onRemove:x.onRemove}),"loading"===W&&e(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:e(m,{size:20})}),"error"===W&&n(s,{sx:{display:"flex",flexDirection:"column",alignItems:"center",mt:2,mb:3,gap:1},children:[e(g,{color:"error",fontSize:"large"}),e(d,{variant:"body2",color:"error",children:"Failed to load options"}),e(v,{size:"small",variant:"outlined",color:"error",onClick:Z,children:"Retry"})]}),0===$.length&&"loaded"===W&&e(d,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),e(f,{sx:{mx:-1},name:M.field.toString(),value:null!=_?_:"",onChange:function(l){return H(l.target.value)},className:ul.error?"error":"",children:$.map(function(l,o){var n,i=sl.items.some(function(o){return o.value===l.value});return e(p,{disabled:i||dl,value:l.value,control:e(b,{size:"small"}),label:e(d,{variant:"body2",children:null!==(n=l.label)&&void 0!==n?n:l.value})},l.value.toString()+o)})}),ul.error&&e(d,{variant:"caption",color:"error",sx:{mt:.5},children:ul.message})]}),n(j,{children:[e(v,{size:"small",color:"error",variant:"text",disabled:!w.values||0===w.values.length,onClick:function(){var l,o;null===(l=x.onRemoveField)||void 0===l||l.call(x,M.field),!1!==(null==c||null===(o=c.config)||void 0===o?void 0:o.closeAfterClear)&&x.onClose()},children:"Clear All"}),e(s,{sx:{flex:1}}),e(v,{size:"small",color:"inherit",variant:"text",onClick:x.onClose,children:"Cancel"}),e(v,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:el,children:"Apply"})]})]})})}}var L=c("form")(l({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}},".".concat(u.root),{"&.error .MuiRadio-root":{color:"#d32f2f"},".MuiFormControlLabel-root":{margin:0},".MuiFormControlLabel-root:hover":{backgroundColor:"rgba(25, 118, 210, 0.04)"}}));export{A as default};
1
+ import{defineProperty as o,slicedToArray as l}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{useMemo as i,useState as r,useRef as t,useEffect as a}from"react";import{styled as c,radioGroupClasses as u,Box as s,Typography as d,CircularProgress as m,Button as v,RadioGroup as f,FormControlLabel as p,Radio as b}from"@mui/material";import g from"@mui/icons-material/Info";import{getErrorMessage as h}from"../../form/helpers.js";import{createChipViewers as x}from"../components/chip-viewer.js";import{ButtonBack as y,ChipDark as C,FilterLogicToggle as z}from"../components/ui.units.js";import{PopperContent as k,PopperBody as V,PopperFooter as j}from"../components/popper-custom.js";function A(c){var u=x(),A=c.options;return function(x){var O,S,F,M=i(function(){return Object.assign({},x.currentConfig,null==c?void 0:c.config)},[null==c?void 0:c.config,x.currentConfig]),R=x.value,w=void 0===R?{values:[],logic:null!==(O=null==M?void 0:M.defaultLogic)&&void 0!==O?O:"or"}:R,I=r(w.logic),B=l(I,2),E=B[0],N=B[1],T=null!==(S=c.forceLogic)&&void 0!==S?S:E,D=r(null),P=l(D,2),_=P[0],H=P[1],U=r([]),q=l(U,2),G=q[0],J=q[1],K=r(c.fetchOptions?"loading":"loaded"),Q=l(K,2),W=Q[0],X=Q[1],Y=t(null),Z=function(){var o;if(c.fetchOptions){null===(o=Y.current)||void 0===o||o.abort();var l=new AbortController;Y.current=l,X("loading"),c.fetchOptions(l.signal).then(function(o){J(o),X("loaded")}).catch(function(o){var l;null===(l=x.onError)||void 0===l||l.call(x),"AbortError"!==(null==o?void 0:o.name)&&X("error")})}};a(function(){return Z(),function(){var o;return null===(o=Y.current)||void 0===o?void 0:o.abort()}},[]);var $=c.fetchOptions?G:null!=A?A:[],oo=E!==w.logic,lo=null!==_,eo=!lo&&!oo,no=null!==(F=null==M?void 0:M.label)&&void 0!==F?F:M.field.toString(),io=r({}),ro=l(io,2),to=ro[0],ao=ro[1],co=function(o){x.onSubmit(M.field,o,M)},uo=h(to,M.field),so=i(function(){var o=Array.isArray(w.values)?w.values:[w.values];return{field:M.field,items:o.map(function(o){var l;return{value:o,label:null===(l=$.find(function(l){return l.value===o}))||void 0===l?void 0:l.label}})}},[M.field,w,$]),mo=null!=c.maxValueCount&&so.items.length>=c.maxValueCount,vo=i(function(){var o=(null==c?void 0:c.top)||x.top;return o?e(s,{sx:{mb:1},children:o}):null},[null==c?void 0:c.top,x.top]),fo=[];return(x.isLoading||"loading"===W)&&fo.push("disabled"),e(L,{className:fo.join(" "),noValidate:!0,onSubmit:function(l){var e;if(l.preventDefault(),lo){if(!mo){var n=o({},M.field,_),i=null===(e=x.validator)||void 0===e?void 0:e.run(n);if(ao(i||{}),!i||0===Object.keys(i).length)co({values:[_],logic:T}),H(null)}}else oo&&co({values:w.values,logic:T})},children:n(k,{title:"Filter by ".concat(no),onClose:x.onClose,slots:{beforeTitle:e(y,{size:"small",onClick:x.onBack}),afterTitle:c.forceLogic?null:M.singleValue?e(C,{sx:{ml:1.5},size:"small",label:"Last value only"}):e(z,{sx:{ml:1},value:T,onChange:function(o,l){N(l)}})},children:[n(V,{children:[vo,M.description&&e(d,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:M.description}),null!=c.maxValueCount&&e(d,{variant:"caption",color:mo?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:c.maxValueCount?mo?"Maximum ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(c.maxValueCount," value").concat(c.maxValueCount>1?"s":""," can be selected"):""}),e(u,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:so,onRemove:x.onRemove}),"loading"===W&&e(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:e(m,{size:20})}),"error"===W&&n(s,{sx:{display:"flex",flexDirection:"column",alignItems:"center",mt:2,mb:3,gap:1},children:[e(g,{color:"error",fontSize:"large"}),e(d,{variant:"body2",color:"error",children:"Failed to load options"}),e(v,{size:"small",variant:"outlined",color:"error",onClick:Z,children:"Retry"})]}),0===$.length&&"loaded"===W&&e(d,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),e(f,{sx:{mx:-1},name:M.field.toString(),value:null!=_?_:"",onChange:function(o){return H(o.target.value)},className:uo.error?"error":"",children:$.map(function(o,l){var n,i=so.items.some(function(l){return l.value===o.value});return e(p,{disabled:i||mo,value:o.value,control:e(b,{size:"small"}),label:e(d,{variant:"body2",children:null!==(n=o.label)&&void 0!==n?n:o.value})},o.value.toString()+l)})}),uo.error&&e(d,{variant:"caption",color:"error",sx:{mt:.5},children:uo.message})]}),n(j,{children:[e(v,{size:"small",color:"error",variant:"text",disabled:!w.values||0===w.values.length,onClick:function(){var o;null===(o=x.onRemoveField)||void 0===o||o.call(x,M.field,M)},children:"Clear All"}),e(s,{sx:{flex:1}}),e(v,{size:"small",color:"inherit",variant:"text",onClick:x.onClose,children:"Cancel"}),e(v,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:eo,children:"Apply"})]})]})})}}var L=c("form")(o({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}},".".concat(u.root),{"&.error .MuiRadio-root":{color:"#d32f2f"},".MuiFormControlLabel-root":{margin:0},".MuiFormControlLabel-root:hover":{backgroundColor:"rgba(25, 118, 210, 0.04)"}}));export{A as default};
2
2
  //# sourceMappingURL=create-form-field-select.js.map