dinocollab-core 2.2.15 → 2.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/filter-bar/index.js +1 -1
- package/dist/src/data-surface/helpers.js.map +1 -1
- package/dist/src/data-surface/view-grid/helpers.js +1 -1
- package/dist/src/data-surface/view-grid/helpers.js.map +1 -1
- package/dist/src/data-surface/view-grid/hooks.js +1 -1
- package/dist/src/data-surface/view-grid/hooks.js.map +1 -1
- package/dist/src/data-surface/view-grid/index.js +1 -1
- package/dist/src/data-surface/view-grid/index.js.map +1 -1
- package/dist/src/filter-bar/components/chip-viewer.js +1 -1
- package/dist/src/filter-bar/components/chip-viewer.js.map +1 -1
- package/dist/src/filter-bar/components/filter-summary.js +1 -1
- package/dist/src/filter-bar/components/filter-summary.js.map +1 -1
- package/dist/src/filter-bar/index.create.js.map +1 -1
- package/dist/src/filter-bar/index.dino.js +1 -1
- package/dist/src/filter-bar/index.dino.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-datetime.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-datetime.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select-multiple.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select-multiple.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-select.js.map +1 -1
- package/dist/src/filter-bar/menu/create-form-field-string.js +1 -1
- package/dist/src/filter-bar/menu/create-form-field-string.js.map +1 -1
- package/dist/src/filter-bar/menu/create.js +1 -1
- package/dist/src/filter-bar/menu/create.js.map +1 -1
- package/dist/src/form/create.form-base.js +1 -1
- package/dist/src/form/create.form-base.js.map +1 -1
- package/dist/src/form/create.form-comfirm.js +1 -1
- package/dist/src/form/create.form-comfirm.js.map +1 -1
- package/dist/src/form/create.form-grid-layout.js +1 -1
- package/dist/src/form/create.form-grid-layout.js.map +1 -1
- package/dist/src/form/create.select-with-api.js +1 -1
- package/dist/src/form/create.select-with-api.js.map +1 -1
- package/dist/src/form/modal-wrapper.js +1 -1
- package/dist/src/form/modal-wrapper.js.map +1 -1
- package/dist/src/table/create.table.js +1 -1
- package/dist/src/table/create.table.js.map +1 -1
- package/dist/src/table/ui.buttons.js +1 -1
- package/dist/src/table/ui.buttons.js.map +1 -1
- package/dist/src/table-grid/create.table-grid.js +1 -1
- package/dist/src/table-grid/create.table-grid.js.map +1 -1
- package/dist/src/table-grid/item-actions.js +1 -1
- package/dist/src/table-grid/item-actions.js.map +1 -1
- package/dist/src/table-grid/toolbar-pannel.js +1 -1
- package/dist/src/table-grid/toolbar-pannel.js.map +1 -1
- package/dist/types/data-surface/view-grid/helpers.d.ts +4 -0
- package/dist/types/data-surface/view-grid/hooks.d.ts +1 -0
- package/dist/types/data-surface/view-grid/types.d.ts +2 -0
- package/dist/types/filter-bar/components/chip-viewer.d.ts +2 -0
- package/dist/types/filter-bar/components/filter-summary.types.d.ts +8 -2
- package/dist/types/filter-bar/index.d.ts +1 -0
- package/dist/types/filter-bar/index.dino.d.ts +2 -1
- package/dist/types/filter-bar/menu/create-form-field-datetime.d.ts +10 -2
- package/dist/types/filter-bar/menu/create-form-field-select-multiple.d.ts +2 -0
- package/dist/types/filter-bar/menu/types.d.ts +10 -0
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createClass as e,classCallCheck as t,defineProperty as r}from"../../_virtual/_rollupPluginBabelHelpers.js";import{createFilterBar as i}from"./index.create.js";import{createLocalFilterBuilder as l}from"./local-filter-builder.js";import{createConvertToGraphQL as o,mapLogic as s,mapSortDirection as m}from"./convert-to-graphql.js";import{isEmptyFilterState as a,removeNullValues as c,isFilterStateEqual as
|
|
1
|
+
import{createClass as e,classCallCheck as t,defineProperty as r}from"../../_virtual/_rollupPluginBabelHelpers.js";import{createFilterBar as i}from"./index.create.js";import{createLocalFilterBuilder as l}from"./local-filter-builder.js";import{createConvertToGraphQL as o,mapLogic as s,mapSortDirection as m}from"./convert-to-graphql.js";import{isEmptyFilterState as a,removeNullValues as c,isFilterStateEqual as f,setFilterToURL as p,getFilterFromURL as h}from"./helpers.js";import n from"./menu/create-form-field-string.js";import u from"./menu/create-form-field-select.js";import F from"./menu/create-form-field-select-multiple.js";import{createFormFieldDateTime as d,formatterDateTime as j}from"./menu/create-form-field-datetime.js";var g=e(function e(){t(this,e),r(this,"createFilterBar",i),r(this,"createConvertToGraphQL",o),r(this,"createLocalFilterBuilder",l),r(this,"createFormFieldString",n),r(this,"createFormFieldSelect",u),r(this,"createFormFieldSelectMultiple",F),r(this,"createFormFieldDateTime",d),r(this,"mapLogic",s),r(this,"mapDirection",m),r(this,"formatterDateTime",j),r(this,"isEmptyFilterState",a),r(this,"removeNullValues",c),r(this,"isFilterStateEqual",f),r(this,"setFilterToURL",p),r(this,"getFilterFromURL",h)}),v=new g;export{g as DinoFilterBar,v as dinoFilterBar};
|
|
2
2
|
//# sourceMappingURL=index.dino.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.dino.js","sources":["../../../src/filter-bar/index.dino.tsx"],"sourcesContent":["import { createFilterBar } from './index.create'\r\nimport { createLocalFilterBuilder } from './local-filter-builder'\r\nimport { createConvertToGraphQL, mapLogic, mapSortDirection } from './convert-to-graphql'\r\nimport { getFilterFromURL, isEmptyFilterState, isFilterStateEqual, removeNullValues, setFilterToURL } from './helpers'\r\nimport createFormFieldString from './menu/create-form-field-string'\r\nimport createFormFieldSelect from './menu/create-form-field-select'\r\nimport createFormFieldSelectMultiple from './menu/create-form-field-select-multiple'\r\nimport createFormFieldDateTime from './menu/create-form-field-datetime'\r\n\r\nexport class DinoFilterBar {\r\n createFilterBar = createFilterBar\r\n createConvertToGraphQL = createConvertToGraphQL\r\n createLocalFilterBuilder = createLocalFilterBuilder\r\n\r\n // Form fields\r\n createFormFieldString = createFormFieldString\r\n createFormFieldSelect = createFormFieldSelect\r\n createFormFieldSelectMultiple = createFormFieldSelectMultiple\r\n createFormFieldDateTime = createFormFieldDateTime\r\n\r\n // support\r\n mapLogic = mapLogic\r\n mapDirection = mapSortDirection\r\n\r\n // helpers\r\n isEmptyFilterState = isEmptyFilterState\r\n removeNullValues = removeNullValues\r\n isFilterStateEqual = isFilterStateEqual\r\n setFilterToURL = setFilterToURL\r\n getFilterFromURL = getFilterFromURL\r\n}\r\n\r\nexport const dinoFilterBar = new DinoFilterBar()\r\n"],"names":["DinoFilterBar","_createClass","_classCallCheck","_defineProperty","createFilterBar","createConvertToGraphQL","createLocalFilterBuilder","createFormFieldString","createFormFieldSelect","createFormFieldSelectMultiple","createFormFieldDateTime","mapLogic","mapSortDirection","isEmptyFilterState","removeNullValues","isFilterStateEqual","setFilterToURL","getFilterFromURL","dinoFilterBar"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.dino.js","sources":["../../../src/filter-bar/index.dino.tsx"],"sourcesContent":["import { createFilterBar } from './index.create'\r\nimport { createLocalFilterBuilder } from './local-filter-builder'\r\nimport { createConvertToGraphQL, mapLogic, mapSortDirection } from './convert-to-graphql'\r\nimport { getFilterFromURL, isEmptyFilterState, isFilterStateEqual, removeNullValues, setFilterToURL } from './helpers'\r\nimport createFormFieldString from './menu/create-form-field-string'\r\nimport createFormFieldSelect from './menu/create-form-field-select'\r\nimport createFormFieldSelectMultiple from './menu/create-form-field-select-multiple'\r\nimport createFormFieldDateTime, { formatterDateTime } from './menu/create-form-field-datetime'\r\n\r\nexport class DinoFilterBar {\r\n createFilterBar = createFilterBar\r\n createConvertToGraphQL = createConvertToGraphQL\r\n createLocalFilterBuilder = createLocalFilterBuilder\r\n\r\n // Form fields\r\n createFormFieldString = createFormFieldString\r\n createFormFieldSelect = createFormFieldSelect\r\n createFormFieldSelectMultiple = createFormFieldSelectMultiple\r\n createFormFieldDateTime = createFormFieldDateTime\r\n\r\n // support\r\n mapLogic = mapLogic\r\n mapDirection = mapSortDirection\r\n\r\n // fortmatter\r\n formatterDateTime = formatterDateTime\r\n\r\n // helpers\r\n isEmptyFilterState = isEmptyFilterState\r\n removeNullValues = removeNullValues\r\n isFilterStateEqual = isFilterStateEqual\r\n setFilterToURL = setFilterToURL\r\n getFilterFromURL = getFilterFromURL\r\n}\r\n\r\nexport const dinoFilterBar = new DinoFilterBar()\r\n"],"names":["DinoFilterBar","_createClass","_classCallCheck","_defineProperty","createFilterBar","createConvertToGraphQL","createLocalFilterBuilder","createFormFieldString","createFormFieldSelect","createFormFieldSelectMultiple","createFormFieldDateTime","mapLogic","mapSortDirection","formatterDateTime","isEmptyFilterState","removeNullValues","isFilterStateEqual","setFilterToURL","getFilterFromURL","dinoFilterBar"],"mappings":"+tBASA,IAAaA,EAAaC,EAAA,SAAAD,IAAAE,OAAAF,GAAAG,yBACNC,GAAeD,gCACRE,GAAsBF,kCACpBG,GAE3BH,+BACwBI,GAAqBJ,+BACrBK,GAAqBL,uCACbM,GAA6BN,iCACnCO,GAE1BP,kBACWQ,GAAQR,sBACJS,GAEfT,2BACoBU,GAEpBV,4BACqBW,GAAkBX,0BACpBY,GAAgBZ,4BACda,GAAkBb,wBACtBc,GAAcd,0BACZe,EAAgB,GAGxBC,EAAgB,IAAInB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{objectSpread2 as e,slicedToArray as
|
|
1
|
+
import{objectSpread2 as e,slicedToArray as n}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{useMemo as t,useState as l}from"react";import{AdapterDayjs as o}from"@mui/x-date-pickers/AdapterDayjs";import{styled as r,Stack as d,Typography as c,Button as u,Box as s}from"@mui/material";import{LocalizationProvider as m,DatePicker as v,TimePicker as f,DateTimePicker as p}from"@mui/x-date-pickers";import g from"dayjs";import{ButtonBack as b,DateLogicToggle as h}from"../components/ui.units.js";import{createChipViewers as y}from"../components/chip-viewer.js";import{PopperContent as x,PopperBody as A,PopperFooter as C}from"../components/popper-custom.js";var S={before:"Before",on:"On",after:"After"},D={date:"MM/DD/YYYY",datetime:"MM/DD/YYYY HH:mm",time:"HH:mm"};function k(r){var k,j,z=y(),w=null!==(k=null==r?void 0:r.pickerType)&&void 0!==k?k:"datetime",T=null!==(j=null==r?void 0:r.mode)&&void 0!==j?j:"single",Y=D[w],F=e(e({},null==r?void 0:r.config),{},{singleValue:!0});return function(y){var D,k,j,O=t(function(){return Object.assign({},y.currentConfig,F)},[y.currentConfig]),V=y.value,B=void 0===V?{values:[]}:V,I=null!==(D=null==O?void 0:O.label)&&void 0!==D?D:O.field.toString(),H=l(null!==(k=B.dateLogic)&&void 0!==k?k:"on"),M=n(H,2),P=M[0],R=M[1],_=l(null),E=n(_,2),N=E[0],W=E[1],q=l(function(){if("range"!==T)return null;var e=Array.isArray(B.values)?B.values[0]:void 0;return e?g(e):null}),G=n(q,2),J=G[0],K=G[1],Q=l(function(){if("range"!==T)return null;var e=Array.isArray(B.values)?B.values[1]:void 0;return e?g(e):null}),U=n(Q,2),X=U[0],Z=U[1],$=function(e){y.onSubmit(O.field,e,O)},ee=t(function(){var e=Array.isArray(B.values)?B.values:[B.values];return{field:O.field,items:e.map(function(e,n){return{value:e,label:(i=e,a=B.dateLogic,t=n,o=g(i),r=o.isValid()?o.format(Y):String(i),"range"===T?0===t?"From: ".concat(r):"To: ".concat(r):a&&"range"!==a?"".concat(null!==(l=S[a])&&void 0!==l?l:a,": ").concat(r):r)};var i,a,t,l,o,r})}},[O.field,B]),ne="range"!==T&&B.values.length>0&&P!==(null!==(j=B.dateLogic)&&void 0!==j?j:"on"),ie="range"===T?!J||!X:!(null!=N&&N.isValid()||ne),ae=t(function(){return"range"===T&&J&&X&&(J.isSame(X)||J.isAfter(X))?'"From" must be earlier than "To"':null},[J,X]),te=ie||Boolean(ae),le=[];y.isLoading&&le.push("disabled");var oe="date"===w?"day":"minute",re=function(n,a,t,l){var o=e(e(e({value:n,onChange:a,label:t},null!=l&&l.minDate?{minDate:l.minDate}:{}),null!=l&&l.maxDate?{maxDate:l.maxDate}:{}),{},{slotProps:{textField:{size:"small",fullWidth:!0},popper:{sx:{zIndex:9999},modifiers:[{name:"preventOverflow",enabled:!0,options:{boundary:"window",altAxis:!0}},{name:"flip",enabled:!0}]}}});return"date"===w?i(v,e(e({},o),{},{format:Y})):"time"===w?i(f,e({},o)):i(p,e(e({},o),{},{format:Y}))};return i(L,{className:le.join(" "),noValidate:!0,onSubmit:function(e){if(e.preventDefault(),"range"===T){var n=[null==J?void 0:J.toISOString(),null==X?void 0:X.toISOString()].filter(Boolean);if(0===n.length||ae)return;$({values:n,dateLogic:"range"})}else null!=N&&N.isValid()?($({values:[N.toISOString()],dateLogic:P}),W(null)):ne&&$({values:B.values,dateLogic:P})},children:a(x,{title:"Filter by ".concat(I),onClose:y.onClose,slots:{beforeTitle:i(b,{size:"small",onClick:y.onBack}),afterTitle:"range"===T?null:i(h,{sx:{ml:1},value:P,onChange:function(e,n){return R(n)}})},children:[a(A,{children:[i(z,{sx:{mb:1,borderBottom:"none!important"},label:"range"===T?"Active range":"Applied",placement:"horizontal",enableMinimalesticView:!0,value:ee,forceShowAll:"range"===T,onRemove:"range"===T?void 0:y.onRemove}),i(m,{dateAdapter:o,children:a(d,"range"===T?{spacing:1.5,children:[i(c,{variant:"caption",color:"text.secondary",children:"Select a date range to filter between two values."}),re(J,K,"From",{maxDate:X?X.subtract(1,oe):void 0}),re(X,Z,"To",{minDate:J?J.add(1,oe):void 0}),ae&&i(c,{variant:"caption",color:"error",children:ae})]}:{gap:1,children:[i(c,{variant:"caption",color:"text.secondary",children:"Pick a date and set the match condition above. Only the latest applied value is kept."}),re(N,W,I)]})})]}),a(C,{children:[i(u,{size:"small",color:"error",variant:"text",disabled:!B.values||0===B.values.length,onClick:function(){var e,n;null===(e=y.onRemoveField)||void 0===e||e.call(y,O.field),!1!==(null==r||null===(n=r.config)||void 0===n?void 0:n.closeAfterClear)&&y.onClose()},children:"Clear All"}),i(s,{sx:{flex:1}}),i(u,{size:"small",color:"inherit",variant:"text",onClick:y.onClose,children:"Cancel"}),i(u,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:te,children:"Apply"})]})]})})}}var L=r("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 j(){var e=D[arguments.length>0&&void 0!==arguments[0]?arguments[0]:"datetime"];return function(n,i,a){var t,l=g(n),o=l.isValid()?l.format(e):String(n);return"range"===a.dateLogic?0===i?"From: ".concat(o):"To: ".concat(o):a.dateLogic?"".concat(null!==(t=S[a.dateLogic])&&void 0!==t?t:a.dateLogic,": ").concat(o):o}}export{k as createFormFieldDateTime,k as default,j as formatterDateTime};
|
|
2
2
|
//# sourceMappingURL=create-form-field-datetime.js.map
|
|
@@ -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\nfunction 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()) return\r\n handleSubmit({ values: [singleDate.toISOString()], dateLogic })\r\n setSingleDate(null)\r\n }\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\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 const isApplyDisabled = mode === 'range' ? !fromDate && !toDate : !singleDate?.isValid()\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 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"],"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","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","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","length","children","_jsxs","PopperContent","title","onClose","slots","beforeTitle","ButtonBack","onClick","onBack","afterTitle","DateLogicToggle","ml","_","PopperBody","mb","borderBottom","placement","enableMinimalesticView","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"],"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)\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,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{slicedToArray as e,defineProperty as l,toConsumableArray as i}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as n,jsxs as o}from"react/jsx-runtime";import{useMemo as r,useState as t}from"react";import{styled as a,FormGroup as u,FormControlLabel as s,Checkbox as c,Button as v,Box as d}from"@mui/material";import{createChipViewers as f}from"../components/chip-viewer.js";import{PopperContent as m,PopperBody as p,PopperFooter as b}from"../components/popper-custom.js";import{ButtonBack as g,ChipDark as h,FilterLogicToggle as y}from"../components/ui.units.js";import{getErrorMessage as C}from"../../form/helpers.js";function x(a){var x=f(),j=(a||{}).options,k=void 0===j?[]:j;return function(f){var j,z,S=r(function(){return Object.assign({},f.currentConfig,null==a?void 0:a.config)},[null==a?void 0:a.config,f.currentConfig]),B=f.value,L=void 0===B?{values:[],logic:null!==(j=null==S?void 0:S.defaultLogic)&&void 0!==j?j:"or"}:B,R=t(L.logic),T=e(R,2),V=T[0],w=T[1],F=null!==(z=null==S?void 0:S.label)&&void 0!==z?z:S.field.toString(),I=r(function(){var e=Array.isArray(L.values)?L.values:[L.values];return k.filter(function(l){return e.includes(l.value)}).map(function(e){return e.value})},[]),N=t(I),O=e(N,2),P=O[0],_=O[1],D=t({}),E=e(D,2),H=E[0],M=E[1],q=function(e){f.onSubmit(S.field,e,S)},G=C(H,S.field),J=r(function(){var e=Array.isArray(L.values)?L.values:[L.values];return{field:S.field,items:e.map(function(e){var l;return{value:e,label:null===(l=k.find(function(l){return l.value===e}))||void 0===l?void 0:l.label}})}},[S.field,L]),K=[];return f.isLoading&&K.push("disabled"),n(A,{className:K.join(" "),noValidate:!0,onSubmit:function(e){var i;e.preventDefault();var n=l({},S.field,P),o=null===(i=f.validator)||void 0===i?void 0:i.run(n);(M(o||{}),o&&0!==Object.keys(o).length)||q({values:P,logic:V})},children:o(m,{title:"Filter by ".concat(F),onClose:f.onClose,slots:{beforeTitle:n(g,{size:"small",onClick:f.onBack}),afterTitle:S.singleValue?n(h,{sx:{ml:1.5},size:"small",label:"Last value only"}):!L.values||L.values.length<2?null:n(y,{sx:{ml:1},value:V,onChange:function(e,l){return function(e){w(e);var l={values:L.values,logic:e};q(l)}(l)}})},children:[o(p,{children:[n(x,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:J,onRemove:f.onRemove}),n(u,{className:G.error?"error":"",children:k.map(function(e,l){var o,r=P.includes(e.value),t=J.items.length>0&&J.items.some(function(l){return l.value===e.value});return n(s,{value:e.value,disabled:t&&!0===(null==a?void 0:a.disabledAfterSubmit),label:null!==(o=e.label)&&void 0!==o?o:e.value,control:n(c,{name:S.field.toString(),checked:r,onChange:function(l){return n=e.value,o=l.target.checked,void _(function(e){return o?[].concat(i(e),[n]):e.filter(function(e){return e!==n})});var n,o}})},e.value.toString()+l)})})]}),o(b,{children:[n(v,{size:"small",color:"error",variant:"text",disabled:!L.values||0===L.values.length,onClick:function(){var e,l;null===(e=f.onRemoveField)||void 0===e||e.call(f,S.field),!1!==(null==a||null===(l=a.config)||void 0===l?void 0:l.closeAfterClear)&&f.onClose()},children:"Clear All"}),n(d,{sx:{flex:1}}),n(v,{size:"small",color:"inherit",variant:"text",onClick:f.onClose,children:"Cancel"}),n(v,{size:"small",type:"submit",color:"primary",variant:"contained",children:"Apply"})]})]})})}}var A=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"}}});export{x 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 { useMemo, useState } from 'react'\r\nimport { Box, Button, Checkbox, FormControlLabel, FormGroup, formGroupClasses, styled } from '@mui/material'\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 } 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 } 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\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}\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 = [] } = 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\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n // Track checked values as controlled state to avoid the uncontrolled→controlled MUI warning\r\n const initialChecked = useMemo<TFieldValid[]>(() => {\r\n const values = Array.isArray(value.values) ? value.values : [value.values]\r\n return options.filter((opt) => values.includes(opt.value)).map((opt) => opt.value)\r\n }, [])\r\n const [checkedValues, setCheckedValues] = useState<TFieldValid[]>(initialChecked)\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 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: filterLogic }\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) => {\r\n return { value: v, label: options.find((o) => o.value === v)?.label }\r\n })\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <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 <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const disabled = filterViewerValue.items.length > 0 && filterViewerValue.items.some((item) => item.value === x.value)\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled}\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'>\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.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 [`.${formGroupClasses.root}`]: {}\r\n})\r\n"],"names":["createFormFieldSelectMultiple","params","ChipViewers","createChipViewers","_ref$options","options","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","initialChecked","Array","isArray","filter","opt","includes","map","_useState3","_useState4","checkedValues","setCheckedValues","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","v","_options$find","find","o","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","length","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","FormGroup","error","x","i","_x$label","isChecked","disabled","some","item","FormControlLabel","control","Checkbox","name","checked","e","optionValue","target","prev","_toConsumableArray","PopperFooter","Button","color","variant","_props$onRemoveField","onRemoveField","call","Box","flex","type","styled","position","content","display","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents","formGroupClasses","root"],"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 { useMemo, useState } from 'react'\r\nimport { Box, Button, Checkbox, FormControlLabel, FormGroup, formGroupClasses, styled } from '@mui/material'\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 } 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 } 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\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 /** If true, disables the field after submission. @default false */\r\n disabledAfterSubmit?: boolean\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 = [] } = 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\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n // Track checked values as controlled state to avoid the uncontrolled→controlled MUI warning\r\n const initialChecked = useMemo<TFieldValid[]>(() => {\r\n const values = Array.isArray(value.values) ? value.values : [value.values]\r\n return options.filter((opt) => values.includes(opt.value)).map((opt) => opt.value)\r\n }, [])\r\n const [checkedValues, setCheckedValues] = useState<TFieldValid[]>(initialChecked)\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 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: filterLogic }\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 handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\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 renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <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 <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const disabled = filterViewerValue.items.length > 0 && filterViewerValue.items.some((item) => item.value === x.value)\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled && params?.disabledAfterSubmit === true}\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'>\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.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 // [`.${formGroupClasses.root}`]: {}\r\n})\r\n"],"names":["createFormFieldSelectMultiple","params","ChipViewers","createChipViewers","_ref$options","options","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","initialChecked","Array","isArray","filter","opt","includes","map","_useState3","_useState4","checkedValues","setCheckedValues","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","v","_options$find","find","o","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","length","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","FormGroup","error","x","i","_x$label","isChecked","disabled","some","item","FormControlLabel","disabledAfterSubmit","control","Checkbox","name","checked","e","optionValue","target","prev","_toConsumableArray","PopperFooter","Button","color","variant","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","position","content","display","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{defineProperty as e,slicedToArray as l}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as o,jsxs as i}from"react/jsx-runtime";import{useMemo as r,useState as n}from"react";import{styled as a,radioGroupClasses as t,RadioGroup as s,FormControlLabel as u,Typography as c,Radio as v,Button as d,Box as m}from"@mui/material";import{getErrorMessage as f,convertFormDataToJson as p}from"../../form/helpers.js";import{createChipViewers as b}from"../components/chip-viewer.js";import{ButtonBack as g,ChipDark as h,FilterLogicToggle as y}from"../components/ui.units.js";import{PopperContent as
|
|
1
|
+
import{defineProperty as e,slicedToArray as l}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as o,jsxs as i}from"react/jsx-runtime";import{useMemo as r,useState as n}from"react";import{styled as a,radioGroupClasses as t,RadioGroup as s,FormControlLabel as u,Typography as c,Radio as v,Button as d,Box as m}from"@mui/material";import{getErrorMessage as f,convertFormDataToJson as p}from"../../form/helpers.js";import{createChipViewers as b}from"../components/chip-viewer.js";import{ButtonBack as g,ChipDark as h,FilterLogicToggle as y}from"../components/ui.units.js";import{PopperContent as C,PopperBody as x,PopperFooter as j}from"../components/popper-custom.js";function z(e){var a=b(),t=e.options;return function(b){var z,k,F=r(function(){return Object.assign({},b.currentConfig,null==e?void 0:e.config)},[null==e?void 0:e.config,b.currentConfig]),L=b.value,S=void 0===L?{values:[],logic:null!==(z=null==F?void 0:F.defaultLogic)&&void 0!==z?z:"or"}:L,M=n(S.logic),R=l(M,2),T=R[0],w=R[1],B=null!==(k=null==F?void 0:F.label)&&void 0!==k?k:F.field.toString(),V=n({}),D=l(V,2),I=D[0],N=D[1],O=function(e){b.onSubmit(F.field,e,F)},P=f(I,F.field),_=r(function(){var e=Array.isArray(S.values)?S.values:[S.values];return{field:F.field,items:e.map(function(e){var l;return{value:e,label:null===(l=t.find(function(l){return l.value===e}))||void 0===l?void 0:l.label}})}},[F.field,S]),E=[];return b.isLoading&&E.push("disabled"),o(A,{className:E.join(" "),noValidate:!0,onSubmit:function(e){var l;e.preventDefault();var o=new FormData(e.currentTarget),i=p(o),r=null===(l=b.validator)||void 0===l?void 0:l.run(i);if(N(r||{}),!r||0===Object.keys(r).length){var n=F.field,a=Array.isArray(i[n])?i[n]:[i[n]];O({values:a,logic:T})}},children:i(C,{title:"Filter by ".concat(B),onClose:b.onClose,slots:{beforeTitle:o(g,{size:"small",onClick:b.onBack}),afterTitle:F.singleValue?o(h,{sx:{ml:1.5},size:"small",label:"Last value only"}):!S.values||S.values.length<2?null:o(y,{sx:{ml:1},value:T,onChange:function(e,l){return function(e){w(e);var l={values:S.values,logic:e};O(l)}(l)}})},children:[i(x,{children:[o(a,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:_,onRemove:b.onRemove}),o(s,{sx:{mx:-1},name:F.field.toString(),className:P.error?"error":"",children:t.map(function(e,l){var i,r=_.items.length>0&&_.items.some(function(l){return l.value===e.value});return o(u,{disabled:r,value:e.value,control:o(v,{size:"small"}),label:o(c,{variant:"body2",children:null!==(i=e.label)&&void 0!==i?i:e.value})},e.value.toString()+l)})}),P.error&&o(c,{variant:"caption",color:"error",sx:{mt:.5},children:P.message})]}),i(j,{children:[o(d,{size:"small",color:"error",variant:"text",disabled:!S.values||0===S.values.length,onClick:function(){var l,o;null===(l=b.onRemoveField)||void 0===l||l.call(b,F.field),!1!==(null==e||null===(o=e.config)||void 0===o?void 0:o.closeAfterClear)&&b.onClose()},children:"Clear All"}),o(m,{sx:{flex:1}}),o(d,{size:"small",color:"inherit",variant:"text",onClick:b.onClose,children:"Cancel"}),o(d,{size:"small",type:"submit",color:"primary",variant:"contained",children:"Apply"})]})]})})}}var A=a("form")(e({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"}}},".".concat(t.root),{"&.error .MuiRadio-root":{color:"#d32f2f"},".MuiFormControlLabel-root":{margin:0},".MuiFormControlLabel-root:hover":{backgroundColor:"rgba(25, 118, 210, 0.04)"}}));export{z as default};
|
|
2
2
|
//# sourceMappingURL=create-form-field-select.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-form-field-select.js","sources":["../../../../src/filter-bar/menu/create-form-field-select.tsx"],"sourcesContent":["import { FC, useMemo, useState } from 'react'\r\nimport { Box, Button, FormControlLabel, Radio, RadioGroup, radioGroupClasses, styled, Typography } from '@mui/material'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldSelect` component returned by `createFormFieldSelect`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** A single option item rendered as a radio button inside the select filter menu. */\r\nexport interface IFieldSelectOption {\r\n value: TFieldValid\r\n label?: string\r\n}\r\n\r\n/** Parameters passed to `createFormFieldSelect` to configure the generated component. */\r\nexport interface IFormFieldSelectParams<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}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldSelect` filter-menu component.\r\n *\r\n * The generated component renders a radio-button list of options inside a\r\n * popper/menu panel. It supports:\r\n * - Single or multi-value selection (controlled by `config.singleValue`)\r\n * - OR / AND logic toggle when more than one value is selected\r\n * - Chip viewers showing the currently applied values\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (option list, optional field config override)\r\n * @returns A React FC ready to be used as a filter-menu field component\r\n */\r\nfunction createFormFieldSelect<T>(params: IFormFieldSelectParams<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options } = params\r\n\r\n const FormFieldSelect: FC<IFormFieldSelectProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n }\r\n }\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 handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <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 <RadioGroup sx={{ mx: -1 }} name={mergedConfig.field.toString()} className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const disabled = filterViewerValue.items.length > 0 && filterViewerValue.items.some((item) => item.value === x.value)\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained'>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.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 [`.${radioGroupClasses.root}`]: {\r\n '&.error .MuiRadio-root': { color: '#d32f2f' },\r\n '.MuiFormControlLabel-root': { margin: 0 },\r\n '.MuiFormControlLabel-root:hover': { backgroundColor: 'rgba(25, 118, 210, 0.04)' }\r\n }\r\n})\r\n"],"names":["createFormFieldSelect","params","ChipViewers","createChipViewers","options","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","_useState3","_useState4","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_options$find","find","o","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","RadioGroup","mx","name","error","x","i","_x$label","disabled","some","item","FormControlLabel","control","Radio","Typography","variant","color","mt","message","PopperFooter","Button","_props$onRemoveField","onRemoveField","call","Box","flex","type","styled","_defineProperty","position","content","display","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","radioGroupClasses","root","margin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-form-field-select.js","sources":["../../../../src/filter-bar/menu/create-form-field-select.tsx"],"sourcesContent":["import { FC, useMemo, useState } from 'react'\r\nimport { Box, Button, FormControlLabel, Radio, RadioGroup, radioGroupClasses, styled, Typography } from '@mui/material'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldSelect` component returned by `createFormFieldSelect`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldSelectProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** A single option item rendered as a radio button inside the select filter menu. */\r\nexport interface IFieldSelectOption {\r\n value: TFieldValid\r\n label?: string\r\n}\r\n\r\n/** Parameters passed to `createFormFieldSelect` to configure the generated component. */\r\nexport interface IFormFieldSelectParams<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}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldSelect` filter-menu component.\r\n *\r\n * The generated component renders a radio-button list of options inside a\r\n * popper/menu panel. It supports:\r\n * - Single or multi-value selection (controlled by `config.singleValue`)\r\n * - OR / AND logic toggle when more than one value is selected\r\n * - Chip viewers showing the currently applied values\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (option list, optional field config override)\r\n * @returns A React FC ready to be used as a filter-menu field component\r\n */\r\nfunction createFormFieldSelect<T>(params: IFormFieldSelectParams<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options } = params\r\n\r\n const FormFieldSelect: FC<IFormFieldSelectProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n }\r\n }\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 handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\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 renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <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 <RadioGroup sx={{ mx: -1 }} name={mergedConfig.field.toString()} className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const disabled = filterViewerValue.items.length > 0 && filterViewerValue.items.some((item) => item.value === x.value)\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained'>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.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 [`.${radioGroupClasses.root}`]: {\r\n '&.error .MuiRadio-root': { color: '#d32f2f' },\r\n '.MuiFormControlLabel-root': { margin: 0 },\r\n '.MuiFormControlLabel-root:hover': { backgroundColor: 'rgba(25, 118, 210, 0.04)' }\r\n }\r\n})\r\n"],"names":["createFormFieldSelect","params","ChipViewers","createChipViewers","options","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","_useState3","_useState4","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_options$find","find","o","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","RadioGroup","mx","name","error","x","i","_x$label","disabled","some","item","FormControlLabel","control","Radio","Typography","variant","color","mt","message","PopperFooter","Button","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","_defineProperty","position","content","display","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","radioGroupClasses","root","margin"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{slicedToArray as e}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as l,jsxs as i}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as n}from"react";import{styled as t,TextField as a,Button as s,Box as u}from"@mui/material";import{createChipViewers as c}from"../components/chip-viewer.js";import{getErrorMessage as
|
|
1
|
+
import{slicedToArray as e}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as l,jsxs as i}from"react/jsx-runtime";import{useMemo as o,useState as r,createRef as n}from"react";import{styled as t,TextField as a,Button as s,Box as u}from"@mui/material";import{createChipViewers as c}from"../components/chip-viewer.js";import{getErrorMessage as v,convertFormDataToJson as d}from"../../form/helpers.js";import{ButtonBack as m,ChipDark as f,FilterLogicToggle as p}from"../components/ui.units.js";import{PopperContent as b,PopperBody as g,PopperFooter as h}from"../components/popper-custom.js";function y(t){var y=c();return function(c){var C,j,z=o(function(){return Object.assign({},c.currentConfig,null==t?void 0:t.config)},[null==t?void 0:t.config,c.currentConfig]),A=n(),k=c.value,T=void 0===k?{values:[],logic:null!==(C=null==z?void 0:z.defaultLogic)&&void 0!==C?C:"or"}:k,B=r(T.logic),F=e(B,2),R=F[0],S=F[1],w=null!==(j=null==z?void 0:z.label)&&void 0!==j?j:z.field.toString(),I=r({}),L=e(I,2),V=L[0],D=L[1],E=function(e){c.onSubmit(z.field,e,z)},H=v(V,z.field),M=o(function(){var e=Array.isArray(T.values)?T.values:[T.values];return{field:z.field,items:e.map(function(e){return{value:e}})}},[z.field,T]),O=[];return c.isLoading&&O.push("disabled"),l(x,{className:O.join(" "),noValidate:!0,onSubmit:function(e){var l;e.preventDefault(),e.stopPropagation();var i=new FormData(e.currentTarget),o=d(i),r=null===(l=c.validator)||void 0===l?void 0:l.run(o);if(D(r||{}),!r||0===Object.keys(r).length){var n=z.field,t=Array.isArray(o[n])?o[n]:[o[n]];E({values:t,logic:R}),A.current&&(A.current.blur(),A.current.value="")}},children:i(b,{title:"Filter by ".concat(w),onClose:c.onClose,slots:{beforeTitle:l(m,{size:"small",onClick:c.onBack}),afterTitle:z.singleValue?l(f,{sx:{ml:1.5},size:"small",label:"Last value only"}):!T.values||T.values.length<2?null:l(p,{sx:{ml:1},value:R,onChange:function(e,l){return function(e){S(e);var l={values:T.values,logic:e};E(l)}(l)}})},children:[i(g,{children:[l(y,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:M,onRemove:c.onRemove}),l(a,{inputRef:A,autoFocus:!0,name:z.field.toString(),size:"small",fullWidth:!0,placeholder:"Enter value",error:H.error,helperText:H.message,sx:{".MuiInputBase-root":{minHeight:"42px"}}})]}),i(h,{children:[l(s,{size:"small",color:"error",variant:"text",disabled:!T.values||0===T.values.length,onClick:function(){var e,l;null===(e=c.onRemoveField)||void 0===e||e.call(c,z.field),!1!==(null==t||null===(l=t.config)||void 0===l?void 0:l.closeAfterClear)&&c.onClose()},children:"Clear All"}),l(u,{sx:{flex:1}}),l(s,{size:"small",color:"inherit",variant:"text",onClick:c.onClose,children:"Cancel"}),l(s,{size:"small",type:"submit",color:"primary",variant:"contained",children:"Apply"})]})]})})}}var x=t("form")({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.2)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}});export{y as default};
|
|
2
2
|
//# sourceMappingURL=create-form-field-string.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-form-field-string.js","sources":["../../../../src/filter-bar/menu/create-form-field-string.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { createRef, useMemo, useState } from 'react'\r\nimport { Box, Button, styled, TextField } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TChipViewerGroup } from '../components/chip-viewer'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldString` component returned by `createFormFieldString`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldStringProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldString` to configure the generated component. */\r\nexport interface IFormFieldStringParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldString` filter-menu component.\r\n *\r\n * The generated component renders a free-text input inside a popper/menu panel,\r\n * letting the user type arbitrary string values as filter criteria. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values\r\n * - Auto-focus and input reset after each successful submission\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (optional field config override)\r\n * @returns A React FC ready to be used as a free-text filter-menu field component\r\n */\r\nfunction createFormFieldString<T>(params?: IFormFieldStringParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldString: FC<IFormFieldStringProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const refInput = createRef<HTMLInputElement>()\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n\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 handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault() // Prevent default form submission behavior\r\n event.stopPropagation() // Stop the event from bubbling up to parent elements (like Popper) which might cause it to close prematurely\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n\r\n if (refInput.current) {\r\n refInput.current.blur()\r\n refInput.current.value = ''\r\n }\r\n }\r\n }\r\n\r\n const error = getErrorMessage(errorData, mergedConfig.field)\r\n\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return { field: mergedConfig.field, items: items.map((v) => ({ value: v })) }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter value'\r\n error={error.error}\r\n helperText={error.message}\r\n 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'>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldString\r\n}\r\n\r\nexport default createFormFieldString\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.2)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n }\r\n})\r\n"],"names":["createFormFieldString","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","_useState3","_useState4","errorData","setErrorData","handleSubmit","newValue","onSubmit","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","stopPropagation","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","current","blur","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","TextField","inputRef","autoFocus","name","fullWidth","placeholder","helperText","message","minHeight","PopperFooter","Button","color","variant","disabled","_props$onRemoveField","onRemoveField","call","Box","flex","type","styled","position","content","display","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-form-field-string.js","sources":["../../../../src/filter-bar/menu/create-form-field-string.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { createRef, useMemo, useState } from 'react'\r\nimport { Box, Button, styled, TextField } from '@mui/material'\r\nimport { createChipViewers } from '../components/chip-viewer'\r\nimport { convertFormDataToJson, getErrorMessage } from '../../form/helpers'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\n// types\r\nimport type { FC } from 'react'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { TChipViewerGroup } from '../components/chip-viewer'\r\nimport type { IFieldMenuConfig, IFilterMenuFormProps } from './types'\r\nimport type { TFieldModelValid, TFieldValid, TFieldValue, TLogic } from '../types'\r\n\r\n/** Props for the `FormFieldString` component returned by `createFormFieldString`. Extends the base filter-menu form props. */\r\nexport interface IFormFieldStringProps<T> extends IFilterMenuFormProps<T> {}\r\n\r\n/** Parameters passed to `createFormFieldString` to configure the generated component. */\r\nexport interface IFormFieldStringParam<T> {\r\n /** Optional configuration for the form field */\r\n config?: IFieldMenuConfig<T>\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldString` filter-menu component.\r\n *\r\n * The generated component renders a free-text input inside a popper/menu panel,\r\n * letting the user type arbitrary string values as filter criteria. It supports:\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values\r\n * - Auto-focus and input reset after each successful submission\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (optional field config override)\r\n * @returns A React FC ready to be used as a free-text filter-menu field component\r\n */\r\nfunction createFormFieldString<T>(params?: IFormFieldStringParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n\r\n const FormFieldString: FC<IFormFieldStringProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const refInput = createRef<HTMLInputElement>()\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n\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 handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault() // Prevent default form submission behavior\r\n event.stopPropagation() // Stop the event from bubbling up to parent elements (like Popper) which might cause it to close prematurely\r\n const formData = new FormData(event.currentTarget)\r\n const obj = convertFormDataToJson<TFieldModelValid<T>>(formData)\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const { field } = mergedConfig\r\n const newValues = (Array.isArray(obj[field]) ? obj[field] : [obj[field]]) as TFieldValid[]\r\n const newValue: TFieldValue = { values: newValues, logic: filterLogic }\r\n handleSubmit(newValue)\r\n\r\n if (refInput.current) {\r\n refInput.current.blur()\r\n refInput.current.value = ''\r\n }\r\n }\r\n }\r\n\r\n const error = getErrorMessage(errorData, mergedConfig.field)\r\n\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return { field: mergedConfig.field, items: items.map((v) => ({ value: v })) }\r\n }, [mergedConfig.field, value])\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n const newValue: TFieldValue = { values: value.values, logic: newLogic }\r\n handleSubmit(newValue)\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 renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (!value.values || value.values.length < 2) 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 <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <TextField\r\n inputRef={refInput}\r\n autoFocus\r\n name={mergedConfig.field.toString()}\r\n size='small'\r\n fullWidth\r\n placeholder='Enter value'\r\n error={error.error}\r\n helperText={error.message}\r\n 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'>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldString\r\n}\r\n\r\nexport default createFormFieldString\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.2)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n }\r\n})\r\n"],"names":["createFormFieldString","params","ChipViewers","createChipViewers","props","_mergedConfig$default","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","refInput","createRef","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","label","field","toString","_useState3","_useState4","errorData","setErrorData","handleSubmit","newValue","onSubmit","error","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","stopPropagation","formData","FormData","currentTarget","obj","convertFormDataToJson","validator","run","keys","length","newValues","current","blur","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","newLogic","handleChangeLogic","PopperBody","mb","borderBottom","placement","enableMinimalesticView","onRemove","TextField","inputRef","autoFocus","name","fullWidth","placeholder","helperText","message","minHeight","PopperFooter","Button","color","variant","disabled","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","position","content","display","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{defineProperty as e,objectWithoutProperties as n,objectSpread2 as r,slicedToArray as o,asyncToGenerator as t,regenerator as i}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as l,jsxs as a}from"react/jsx-runtime";import{useState as u,useContext as c,useMemo as s,createRef as d}from"react";import{styled as m,Box as f,MenuList as p,Tooltip as v,IconButton as
|
|
1
|
+
import{defineProperty as e,objectWithoutProperties as n,objectSpread2 as r,slicedToArray as o,asyncToGenerator as t,regenerator as i}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as l,jsxs as a}from"react/jsx-runtime";import{useState as u,useContext as c,useMemo as s,createRef as d}from"react";import{styled as m,Box as f,MenuList as p,Tooltip as v,IconButton as b,Badge as h,MenuItem as g,Typography as y,Button as j}from"@mui/material";import F from"@mui/icons-material/FilterList";import C from"@mui/material/ClickAwayListener";import{KeySpecial as k}from"../types.js";import{useFilterActions as I}from"../hooks.js";import{FilterBarContext as S}from"../index.context.js";import{FilterMenuNoField as x}from"../components/ui.units.js";import{mapSpecialLabel as w,mapSpecialTexts as P}from"../helpers.js";import{SingleRuleValidate as A,FormValidator as R}from"../../form/validator.js";import{PopperCustom as q,PopperContent as T,PopperFooter as B}from"../components/popper-custom.js";import O from"./create-form-field-string.js";var M=["fields","validation","enableQuickSearch"];function D(m){var f=L,p=function(e){var o=e.fields,t=e.validation,i=e.enableQuickSearch,l=void 0===i||i,a=n(e,M),u=k.quickSearch,c=r({},o);if(l){var s=c[u],d=null!=s&&s.label?s.label:w[u],m=Object.assign({},c[u],{field:u,label:d,singleValue:!0});c[u]=m}else delete c[u];var f=Object.keys(c),p=f.reduce(function(e,n){var o=c[n];return o?(e[n]=r(r({},o),{},{field:n}),e):e},{}),v=r({},t);return f.forEach(function(e){var n,r,o,t=v[e],i=null!==(n=null!==(r=null==t?void 0:t.label)&&void 0!==r?r:null===(o=c[e])||void 0===o?void 0:o.label)&&void 0!==n?n:e.toString();t?t.Rules.some(function(e){return e.rule===A.Required})||(t.label=i,t.Rules.push({rule:A.Required})):v[e]={Rules:[{rule:A.Required}],label:i}}),r(r({},a),{},{fields:p,validation:v,enableQuickSearch:l})}(m),D=function(n){return Object.keys(n.fields).reduce(function(r,o){var t,i=o,l=null===(t=n.validation)||void 0===t?void 0:t[i];return l&&(r[i]=new R(e({},i,l))),r},{})}(p),Q=function(e){var n=e.fields;return Object.keys(n).reduce(function(e,r){var o,t=r,i=n[t];return i&&(e[t]=null!==(o=i.FormComponent)&&void 0!==o?o:O()),e},{})}(p),z=m.quickSearchHint;return function(e){var n=d(),w=u(null),A=o(w,2),R=A[0],O=A[1],M=Boolean(R),L=c(S),E=I(L),H=u(null),_=o(H,2),G=_[0],W=_[1],J=s(function(){var n=m.popperProps,r=m.rootProps;return Object.assign({},{popperProps:n,rootProps:r},e.slots)},[m,e.slots]),K=function(){O(null),setTimeout(function(){W(null)},300)},U=function(){E.clearAllFilters(),K()},X=function(){var e=t(i().m(function e(n,r,o){return i().w(function(e){for(;;)switch(e.n){case 0:if(r){e.n=1;break}return e.a(2);case 1:null!=o&&o.singleValue||null!=o&&o.replaceValue?E.replaceFilter(n,r,{logic:r.logic}):E.upsertManyFilter(n,r,{logic:r.logic}),!1!==(null==m?void 0:m.closeAfterSubmit)&&!1!==(null==o?void 0:o.closeAfterSubmit)&&K();case 2:return e.a(2)}},e)}));return function(n,r,o){return e.apply(this,arguments)}}(),Y=s(function(){var e=Object.values(p.fields);return Array.from(e)},[p.fields]),Z=E.getTotalCount(),$="".concat(Z," Filter").concat(1!==Z?"s":"");return l(C,{onClickAway:K,children:a(N,r(r({className:f.root},J.rootProps),{},{children:[l(v,{title:$,arrow:!0,placement:"top",children:l(b,{size:"small",ref:n,onClick:function(){W(null),O(n.current)},children:l(h,{badgeContent:Z,color:"primary",invisible:0===Z,children:l(F,{fontSize:"small"})})})}),l(q,r(r({open:M,anchorEl:R,placement:"bottom",transition:!0,disablePortal:!0},J.popperProps),{},{children:function(){if(0===Y.length)return l(x,{onClose:K});var e=G?p.fields[G]:void 0;if(G&&e){var n,o=Q[G];if(!o)return null;var t=r({},e);null!=t&&t.FormComponent&&delete t.FormComponent;var i=null===(n=L.filterState.storeFilter)||void 0===n?void 0:n[G];return l(o,{currentConfig:t,value:i,isLoading:L.isLoading,onRemove:E.removeFilterByFieldValue,validator:D[G],onSubmit:X,onClose:K,onRemoveField:function(e){return E.removeFilter(e)},onBack:function(){return W(null)}})}return a(T,{title:"Filter by",onClose:K,children:[l(V,{className:f.menu,children:Y.map(function(e){var n,r,o=e.field.toString();if(!o)return null;var t=E.getFieldInfo(e.field),i=null!==(n=null==t?void 0:t.values.join(", "))&&void 0!==n?n:"",u=t?t.values.length:0,c=u>0?" (".concat(u,")"):"",s=null!==(r=e.label)&&void 0!==r?r:o.toString(),d=u>0?"Filter by ".concat(s,": ").concat(i):void 0;if(e.field===k.quickSearch){var m=P.qsTooltip;d="function"==typeof z?z(m):null!=z?z:m}else if(e.tooltip){var p,b="function"==typeof e.tooltip?e.tooltip(null==t?void 0:t.values):e.tooltip;d=(null!==(p=null==t?void 0:t.values.length)&&void 0!==p?p:0)>0?b:void 0}return l(g,{className:f.menuItem,sx:{justifyContent:"space-between"},onClick:function(){return n=e.field,void W(n);var n},children:l(v,{title:d,placement:"right",arrow:!0,children:a("div",{className:f.menuItemInner,children:[l(y,{variant:"body2",children:s}),l(y,{variant:"caption",sx:{ml:1,color:"text.secondary"},children:c})]})})},o)})}),l(B,{children:l(j,{color:"error",disabled:0===Z,onClick:U,children:"Clear All"})})]})}()}))]}))})}}var L={root:"DinoFilterMenu-root",menu:"DinoFilterMenu-menu",menuItem:"DinoFilterMenu-menuItem",menuItemInner:"DinoFilterMenu-menuItemInner"},N=m(f)(e({},"&.".concat(L.root),{display:"inline-flex",justifyContent:"center",alignItems:"center",flex:"0 0 auto"})),V=m(p)(e(e({},".".concat(L.menuItem),{paddingTop:0,paddingBottom:0}),".".concat(L.menuItemInner),{display:"flex",justifyContent:"space-between",alignItems:"center",width:"100%",gap:"4px",paddingTop:"6px",paddingBottom:"6px"}));export{D as createFilterMenu,L as filterMenuClasses};
|
|
2
2
|
//# sourceMappingURL=create.js.map
|