dinocollab-core 2.2.35 → 2.2.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/data-surface/ui.units.js +1 -1
- package/dist/src/data-surface/ui.units.js.map +1 -1
- package/dist/src/filter-bar/helpers.js +1 -1
- package/dist/src/filter-bar/helpers.js.map +1 -1
- package/dist/src/filter-bar/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/types/data-surface/ui.units.d.ts +1 -1
- package/dist/types/filter-bar/menu/create-form-field-select-multiple.d.ts +3 -1
- package/dist/types/filter-bar/menu/create-form-field-select.d.ts +3 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{objectSpread2 as e,defineProperty as r,objectWithoutProperties as
|
|
1
|
+
import{objectSpread2 as e,defineProperty as r,objectWithoutProperties as t}from"../../_virtual/_rollupPluginBabelHelpers.js";import{jsxs as n,jsx as o}from"react/jsx-runtime";import{colors as i,styled as a,Box as l,alpha as c,typographyClasses as d,Typography as u,Pagination as s,CircularProgress as g,Stack as p}from"@mui/material";import{useMemo as h}from"react";var m=["viewMode"],b={padding:"8px",height:"100%",minHeight:180,width:"100%","& > .inner":{width:"100%",height:"100%",padding:"24px 16px",border:"1px dashed ".concat(i.grey[400]),borderRadius:6,display:"flex",alignItems:"center",justifyContent:"center",textAlign:"center"}},f=function(r){r.viewMode;var i=t(r,m);return o(x,e(e({},i),{},{children:n("div",{className:"inner",children:[o(g,{size:24}),o(u,{variant:"body2",color:"primary",children:"Loading..."})]})}))},x=a(l)(e(e({},b),{},{"& > div":{gap:8,borderColor:i.blue[400],backgroundColor:c(i.blue[50],.12)}}));a(l)(e(e({},b),{},{"& > div":{borderColor:i.red[400],backgroundColor:i.red[50],color:i.red[900],flexDirection:"column"}}));var v=function(){return o(y,{children:n("div",{className:"inner",children:[o(u,{variant:"h6",gutterBottom:!0,children:"No data available"}),o(u,{variant:"body2",children:"Try changing the filter or search keyword"})]})})},y=a(l)(e(e({},b),{},{"& > div":{borderColor:i.grey[400],backgroundColor:i.grey[50],color:i.grey[700],flexDirection:"column"}}));a(l)(e(e({},b),{},{"& > div":{borderColor:i.blue[400],backgroundColor:i.blue[50],color:i.blue[900],flexDirection:"column"}})),a(l)(e(e({},b),{},{"& > div":{borderColor:i.red[700],backgroundColor:i.red[50],color:i.red[900],flexDirection:"column"}}));var C=function(){return o(k,{children:o("div",{children:o(g,{size:28,thickness:4})})})},k=a(l)(function(e){return{position:"absolute",inset:0,backgroundColor:"dark"===e.theme.palette.mode?"rgba(0,0,0,0.24)":"rgba(255,255,255,0.24)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:10,backdropFilter:"blur(1.5px)",transition:"opacity 0.2s","& > div":{display:"flex",alignItems:"center",gap:10}}}),w=function(e){var r,t=e.slots,i=e.loading,a=e.hasNext,l=e.currentCount,c=e.total,d=function(e){return"string"!=typeof e?e:o(u,{variant:"caption",color:"text.secondary",children:e})},s=function(e,r){var t="Loading more...",i="Scroll for more",a="No more items";return e?{currentNode:n(p,{flexDirection:"row",alignItems:"center",gap:1,children:[o(g,{color:"primary",size:12,thickness:3}),o(u,{variant:"caption",color:"primary.main",children:t})]}),rawText:t}:r?{currentNode:i,rawText:i}:{currentNode:a,rawText:a}}(i,a),m=s.currentNode;"function"==typeof(null==t?void 0:t.statusText)?m=t.statusText(d(s.currentNode),s.rawText):null!=t&&t.statusText&&(m=t.statusText);var b=h(function(){return l<=0?"—":null!=c?"".concat(l," of ").concat(c):e.hasNext?"".concat(l," of many"):"".concat(l," results")},[l,c]),f="function"==typeof(null==t?void 0:t.rangeText)?t.rangeText(b,b):null!==(r=null==t?void 0:t.rangeText)&&void 0!==r?r:b;return o(N,{children:n("div",{children:[d(m),d(f)]})})},N=a(l)(function(e){var t=e.theme;return r({"& > div":{display:"flex",alignItems:"center",justifyContent:"space-between",padding:t.spacing(1,1.5),backgroundColor:c(t.palette.grey[500],.08),borderTop:"1px solid ".concat(c(t.palette.common.black,.08))}},".".concat(d.root),{lineHeight:1,fontWeight:500})}),T=function(e){var r=e.page,t=e.pageSize,i=e.total,a=e.hasNext,l=e.loading,c=e.onPrevPage,d=e.onNextPage,g=e.onPageJump,p=r*t+1,h=null!=i?Math.min(p+t-1,i):p+t-1,m=null!=i?Math.ceil(i/t):void 0;return n(P,{children:[o(u,{variant:"caption",color:"text.secondary",children:null!=i?"".concat(p,"–").concat(h," / ").concat(i):"Page ".concat(r+1)}),o(s,{count:m,page:r+1,onChange:function(e,t){var n=t-1;g?g(n):n<r?null==c||c():n>r&&(null==d||d())},disabled:l,size:"small",showFirstButton:null!=m&&m>5,showLastButton:null!=m&&m>5,siblingCount:0,boundaryCount:1,hidePrevButton:null==m&&!a,hideNextButton:null==m&&!a})]})},P=a(l)(function(e){var r=e.theme;return{padding:"8px 16px",display:"flex",alignItems:"center",justifyContent:"space-between",backgroundColor:r.palette.background.paper,borderTop:"1px solid ".concat("dark"===r.palette.mode?"rgba(255, 255, 255, 0.12)":"rgba(0, 0, 0, 0.12)")}});export{w as PanelInfiniteScrollFooter,C as PanelLoadMore,f as PanelLoading,v as PanelNoData,T as PanelPaginationFooter};
|
|
2
2
|
//# sourceMappingURL=ui.units.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.units.js","sources":["../../../src/data-surface/ui.units.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { Box, CircularProgress, Pagination, Typography, colors, styled, alpha, Stack, typographyClasses } from '@mui/material'\r\n// types\r\nimport type { FC, ReactNode } from 'react'\r\nimport type { BoxProps } from '@mui/material'\r\nimport { DataSurfaceViewMode, TRenderableNode } from './types'\r\n\r\nconst stateWrapBase = {\r\n padding: '8px',\r\n height: '100%',\r\n minHeight: 180,\r\n width: '100%',\r\n '& > .inner': {\r\n width: '100%',\r\n height: '100%',\r\n padding: '24px 16px',\r\n border: `1px dashed ${colors.grey[400]}`,\r\n borderRadius: 6,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n textAlign: 'center'\r\n }\r\n} as const\r\n\r\nexport const PanelLoading: FC<BoxProps & { viewMode: DataSurfaceViewMode }> = (props) => {\r\n const { viewMode, ...rest } = props\r\n return (\r\n <PanelLoadingStyled {...rest}>\r\n <div className='inner'>\r\n <CircularProgress size={24} />\r\n <Typography variant='body2' color='primary'>\r\n Loading...\r\n </Typography>\r\n </div>\r\n </PanelLoadingStyled>\r\n )\r\n}\r\n\r\nconst PanelLoadingStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n gap: 8,\r\n borderColor: colors.blue[400],\r\n backgroundColor: alpha(colors.blue[50], 0.12)\r\n }\r\n})\r\n\r\nexport const PanelError: FC<{ error: string }> = ({ error }) => (\r\n <PanelErrorStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' gutterBottom>\r\n An error occurred\r\n </Typography>\r\n {error && <Typography variant='body2'>{error}</Typography>}\r\n </div>\r\n </PanelErrorStyled>\r\n)\r\n\r\nconst PanelErrorStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.red[400],\r\n backgroundColor: colors.red[50],\r\n color: colors.red[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelNoData: FC = () => (\r\n <PanelNoDataStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' gutterBottom>\r\n No data available\r\n </Typography>\r\n <Typography variant='body2'>Try changing the filter or search keyword</Typography>\r\n </div>\r\n </PanelNoDataStyled>\r\n)\r\n\r\nconst PanelNoDataStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.grey[400],\r\n backgroundColor: colors.grey[50],\r\n color: colors.grey[700],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelWaiting: FC = () => (\r\n <PanelWaitingStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' color='text.primary' sx={{ fontWeight: 'bold' }}>\r\n Waiting for data...\r\n </Typography>\r\n <Typography variant='body2' color='text.secondary'>\r\n Please wait while we fetch the data.\r\n </Typography>\r\n </div>\r\n </PanelWaitingStyled>\r\n)\r\n\r\nconst PanelWaitingStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.blue[400],\r\n backgroundColor: colors.blue[50],\r\n color: colors.blue[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelMissingConfig: FC = () => (\r\n <PanelMissingConfigStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' sx={{ fontWeight: 'bold' }}>\r\n Missing Configuration\r\n </Typography>\r\n <Typography variant='body2'>A required configuration is missing for this view to work correctly.</Typography>\r\n </div>\r\n </PanelMissingConfigStyled>\r\n)\r\n\r\nconst PanelMissingConfigStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.red[700],\r\n backgroundColor: colors.red[50],\r\n color: colors.red[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelLoadMore: FC = () => (\r\n <PanelLoadMoreStyled>\r\n <div>\r\n <CircularProgress size={28} thickness={4} />\r\n {/* <Typography variant='body2'>Loading more...</Typography> */}\r\n </div>\r\n </PanelLoadMoreStyled>\r\n)\r\n\r\nconst PanelLoadMoreStyled = styled(Box)(({ theme }) => {\r\n const isDark = theme.palette.mode === 'dark'\r\n const bgColor = isDark ? 'rgba(0,0,0,0.24)' : 'rgba(255,255,255,0.24)'\r\n // const textColor = theme.palette.text.primary\r\n return {\r\n position: 'absolute',\r\n inset: 0,\r\n backgroundColor: bgColor,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n zIndex: 10,\r\n backdropFilter: 'blur(1.5px)',\r\n transition: 'opacity 0.2s',\r\n '& > div': { display: 'flex', alignItems: 'center', gap: 10 }\r\n // [`.${typographyClasses.root}`]: { color: textColor }\r\n }\r\n})\r\n\r\nexport interface IPanelInfiniteScrollFooterSlots {\r\n statusText?: TRenderableNode\r\n rangeText?: TRenderableNode\r\n}\r\n\r\nexport interface IPanelInfiniteScrollFooterProps {\r\n loading?: boolean\r\n hasNext?: boolean\r\n currentCount: number\r\n total?: number\r\n slots?: IPanelInfiniteScrollFooterSlots\r\n}\r\n\r\nconst mapStatusText = (loading?: boolean, hasNext?: boolean): { currentNode: ReactNode; rawText: string } => {\r\n const mapRawText: Record<string, string> = { loading: 'Loading more...', hasNext: 'Scroll for more', noMore: 'No more items' }\r\n if (loading) {\r\n return {\r\n currentNode: (\r\n <Stack flexDirection='row' alignItems='center' gap={1}>\r\n <CircularProgress color='primary' size={12} thickness={3} />\r\n <Typography variant='caption' color='primary.main'>\r\n {mapRawText.loading}\r\n </Typography>\r\n </Stack>\r\n ),\r\n rawText: mapRawText.loading\r\n }\r\n } else if (hasNext) {\r\n return { currentNode: mapRawText.hasNext, rawText: mapRawText.hasNext }\r\n } else {\r\n return { currentNode: mapRawText.noMore, rawText: mapRawText.noMore }\r\n }\r\n}\r\n\r\nexport const PanelInfiniteScrollFooter: FC<IPanelInfiniteScrollFooterProps> = (props) => {\r\n const { slots, loading, hasNext, currentCount, total } = props\r\n\r\n const renderText = (value: ReactNode) => {\r\n if (typeof value !== 'string') return value\r\n return (\r\n <Typography variant='caption' color='text.secondary'>\r\n {value}\r\n </Typography>\r\n )\r\n }\r\n\r\n // Status text on the left\r\n let obj = mapStatusText(loading, hasNext)\r\n let finalStatusText: ReactNode = obj.currentNode\r\n if (typeof slots?.statusText === 'function') {\r\n finalStatusText = slots.statusText(renderText(obj.currentNode), obj.rawText)\r\n } else if (slots?.statusText) {\r\n finalStatusText = slots.statusText\r\n }\r\n\r\n // Range text on the right\r\n const rangeText = currentCount > 0 ? (total != null ? `${currentCount} of ${total}` : `${currentCount} results`) : '—'\r\n const finalRangeText = typeof slots?.rangeText === 'function' ? slots.rangeText(rangeText, rangeText) : (slots?.rangeText ?? rangeText)\r\n\r\n return (\r\n <PanelInfiniteScrollFooterStyled>\r\n <div>\r\n {renderText(finalStatusText)}\r\n {renderText(finalRangeText)}\r\n </div>\r\n </PanelInfiniteScrollFooterStyled>\r\n )\r\n}\r\n\r\nconst PanelInfiniteScrollFooterStyled = styled(Box)(({ theme }) => ({\r\n '& > div': {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n padding: theme.spacing(1, 1.5),\r\n backgroundColor: alpha(theme.palette.grey[500], 0.08),\r\n borderTop: `1px solid ${alpha(theme.palette.common.black, 0.08)}`\r\n },\r\n [`.${typographyClasses.root}`]: { lineHeight: 1, fontWeight: 500 }\r\n}))\r\n\r\nexport interface IPanelPaginationFooterProps {\r\n page: number\r\n pageSize: number\r\n total?: number\r\n hasNext?: boolean\r\n hasPrev?: boolean\r\n loading?: boolean\r\n onPrevPage?: () => void\r\n onNextPage?: () => void\r\n onPageJump?: (page: number) => void\r\n}\r\n\r\nexport const PanelPaginationFooter: FC<IPanelPaginationFooterProps> = (props) => {\r\n const { page, pageSize, total, hasNext, loading, onPrevPage, onNextPage, onPageJump } = props\r\n const from = page * pageSize + 1\r\n const to = total != null ? Math.min(from + pageSize - 1, total) : from + pageSize - 1\r\n\r\n // Calculate page count for MUI Pagination (1-indexed)\r\n const pageCount = total != null ? Math.ceil(total / pageSize) : undefined\r\n\r\n const handlePageChange = (_event: any, value: number) => {\r\n // MUI Pagination uses 1-indexed, convert to 0-indexed\r\n const targetPage = value - 1\r\n\r\n if (onPageJump) {\r\n // Use direct page jump if available\r\n onPageJump(targetPage)\r\n } else {\r\n // Fallback to prev/next if no jump handler\r\n if (targetPage < page) {\r\n onPrevPage?.()\r\n } else if (targetPage > page) {\r\n onNextPage?.()\r\n }\r\n }\r\n }\r\n\r\n return (\r\n <PanelPaginationFooterStyled>\r\n <Typography variant='caption' color='text.secondary'>\r\n {total != null ? `${from}–${to} / ${total}` : `Page ${page + 1}`}\r\n </Typography>\r\n <Pagination\r\n count={pageCount}\r\n page={page + 1}\r\n onChange={handlePageChange}\r\n disabled={loading}\r\n size='small'\r\n showFirstButton={pageCount != null && pageCount > 5}\r\n showLastButton={pageCount != null && pageCount > 5}\r\n siblingCount={0}\r\n boundaryCount={1}\r\n hidePrevButton={pageCount == null && !hasNext}\r\n hideNextButton={pageCount == null && !hasNext}\r\n />\r\n </PanelPaginationFooterStyled>\r\n )\r\n}\r\n\r\nconst PanelPaginationFooterStyled = styled(Box)(({ theme }) => ({\r\n padding: '8px 16px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n backgroundColor: theme.palette.background.paper,\r\n borderTop: `1px solid ${theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)'}`\r\n}))\r\n"],"names":["stateWrapBase","padding","height","minHeight","width","border","concat","colors","grey","borderRadius","display","alignItems","justifyContent","textAlign","PanelLoading","props","viewMode","rest","_objectWithoutProperties","_excluded","_jsx","PanelLoadingStyled","_objectSpread","children","_jsxs","className","CircularProgress","size","Typography","variant","color","styled","Box","gap","borderColor","blue","backgroundColor","alpha","red","flexDirection","PanelNoData","PanelNoDataStyled","gutterBottom","PanelLoadMore","PanelLoadMoreStyled","thickness","_ref2","position","inset","theme","palette","mode","zIndex","backdropFilter","transition","PanelInfiniteScrollFooter","_slots$rangeText","slots","loading","hasNext","currentCount","total","renderText","value","obj","mapRawText","currentNode","Stack","rawText","mapStatusText","finalStatusText","statusText","rangeText","finalRangeText","PanelInfiniteScrollFooterStyled","_ref3","_defineProperty","spacing","borderTop","common","black","typographyClasses","root","lineHeight","fontWeight","PanelPaginationFooter","page","pageSize","onPrevPage","onNextPage","onPageJump","from","to","Math","min","pageCount","ceil","undefined","PanelPaginationFooterStyled","Pagination","count","onChange","_event","targetPage","disabled","showFirstButton","showLastButton","siblingCount","boundaryCount","hidePrevButton","hideNextButton","_ref5","background","paper"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ui.units.js","sources":["../../../src/data-surface/ui.units.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { Box, CircularProgress, Pagination, Typography, colors, styled, alpha, Stack, typographyClasses } from '@mui/material'\r\n// types\r\nimport { useMemo, type FC, type ReactNode } from 'react'\r\nimport type { BoxProps } from '@mui/material'\r\nimport { DataSurfaceViewMode, TRenderableNode } from './types'\r\n\r\nconst stateWrapBase = {\r\n padding: '8px',\r\n height: '100%',\r\n minHeight: 180,\r\n width: '100%',\r\n '& > .inner': {\r\n width: '100%',\r\n height: '100%',\r\n padding: '24px 16px',\r\n border: `1px dashed ${colors.grey[400]}`,\r\n borderRadius: 6,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n textAlign: 'center'\r\n }\r\n} as const\r\n\r\nexport const PanelLoading: FC<BoxProps & { viewMode: DataSurfaceViewMode }> = (props) => {\r\n const { viewMode, ...rest } = props\r\n return (\r\n <PanelLoadingStyled {...rest}>\r\n <div className='inner'>\r\n <CircularProgress size={24} />\r\n <Typography variant='body2' color='primary'>\r\n Loading...\r\n </Typography>\r\n </div>\r\n </PanelLoadingStyled>\r\n )\r\n}\r\n\r\nconst PanelLoadingStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n gap: 8,\r\n borderColor: colors.blue[400],\r\n backgroundColor: alpha(colors.blue[50], 0.12)\r\n }\r\n})\r\n\r\nexport const PanelError: FC<{ error: string }> = ({ error }) => (\r\n <PanelErrorStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' gutterBottom>\r\n An error occurred\r\n </Typography>\r\n {error && <Typography variant='body2'>{error}</Typography>}\r\n </div>\r\n </PanelErrorStyled>\r\n)\r\n\r\nconst PanelErrorStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.red[400],\r\n backgroundColor: colors.red[50],\r\n color: colors.red[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelNoData: FC = () => (\r\n <PanelNoDataStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' gutterBottom>\r\n No data available\r\n </Typography>\r\n <Typography variant='body2'>Try changing the filter or search keyword</Typography>\r\n </div>\r\n </PanelNoDataStyled>\r\n)\r\n\r\nconst PanelNoDataStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.grey[400],\r\n backgroundColor: colors.grey[50],\r\n color: colors.grey[700],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelWaiting: FC = () => (\r\n <PanelWaitingStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' color='text.primary' sx={{ fontWeight: 'bold' }}>\r\n Waiting for data...\r\n </Typography>\r\n <Typography variant='body2' color='text.secondary'>\r\n Please wait while we fetch the data.\r\n </Typography>\r\n </div>\r\n </PanelWaitingStyled>\r\n)\r\n\r\nconst PanelWaitingStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.blue[400],\r\n backgroundColor: colors.blue[50],\r\n color: colors.blue[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelMissingConfig: FC = () => (\r\n <PanelMissingConfigStyled>\r\n <div className='inner'>\r\n <Typography variant='h6' sx={{ fontWeight: 'bold' }}>\r\n Missing Configuration\r\n </Typography>\r\n <Typography variant='body2'>A required configuration is missing for this view to work correctly.</Typography>\r\n </div>\r\n </PanelMissingConfigStyled>\r\n)\r\n\r\nconst PanelMissingConfigStyled = styled(Box)({\r\n ...stateWrapBase,\r\n '& > div': {\r\n borderColor: colors.red[700],\r\n backgroundColor: colors.red[50],\r\n color: colors.red[900],\r\n flexDirection: 'column'\r\n }\r\n})\r\n\r\nexport const PanelLoadMore: FC = () => (\r\n <PanelLoadMoreStyled>\r\n <div>\r\n <CircularProgress size={28} thickness={4} />\r\n {/* <Typography variant='body2'>Loading more...</Typography> */}\r\n </div>\r\n </PanelLoadMoreStyled>\r\n)\r\n\r\nconst PanelLoadMoreStyled = styled(Box)(({ theme }) => {\r\n const isDark = theme.palette.mode === 'dark'\r\n const bgColor = isDark ? 'rgba(0,0,0,0.24)' : 'rgba(255,255,255,0.24)'\r\n // const textColor = theme.palette.text.primary\r\n return {\r\n position: 'absolute',\r\n inset: 0,\r\n backgroundColor: bgColor,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n zIndex: 10,\r\n backdropFilter: 'blur(1.5px)',\r\n transition: 'opacity 0.2s',\r\n '& > div': { display: 'flex', alignItems: 'center', gap: 10 }\r\n // [`.${typographyClasses.root}`]: { color: textColor }\r\n }\r\n})\r\n\r\nexport interface IPanelInfiniteScrollFooterSlots {\r\n statusText?: TRenderableNode\r\n rangeText?: TRenderableNode\r\n}\r\n\r\nexport interface IPanelInfiniteScrollFooterProps {\r\n loading?: boolean\r\n hasNext?: boolean\r\n currentCount: number\r\n total?: number\r\n slots?: IPanelInfiniteScrollFooterSlots\r\n}\r\n\r\nconst mapStatusText = (loading?: boolean, hasNext?: boolean): { currentNode: ReactNode; rawText: string } => {\r\n const mapRawText: Record<string, string> = { loading: 'Loading more...', hasNext: 'Scroll for more', noMore: 'No more items' }\r\n if (loading) {\r\n return {\r\n currentNode: (\r\n <Stack flexDirection='row' alignItems='center' gap={1}>\r\n <CircularProgress color='primary' size={12} thickness={3} />\r\n <Typography variant='caption' color='primary.main'>\r\n {mapRawText.loading}\r\n </Typography>\r\n </Stack>\r\n ),\r\n rawText: mapRawText.loading\r\n }\r\n } else if (hasNext) {\r\n return { currentNode: mapRawText.hasNext, rawText: mapRawText.hasNext }\r\n } else {\r\n return { currentNode: mapRawText.noMore, rawText: mapRawText.noMore }\r\n }\r\n}\r\n\r\nexport const PanelInfiniteScrollFooter: FC<IPanelInfiniteScrollFooterProps> = (props) => {\r\n const { slots, loading, hasNext, currentCount, total } = props\r\n\r\n const renderText = (value: ReactNode) => {\r\n if (typeof value !== 'string') return value\r\n return (\r\n <Typography variant='caption' color='text.secondary'>\r\n {value}\r\n </Typography>\r\n )\r\n }\r\n\r\n // Status text on the left\r\n let obj = mapStatusText(loading, hasNext)\r\n let finalStatusText: ReactNode = obj.currentNode\r\n if (typeof slots?.statusText === 'function') {\r\n finalStatusText = slots.statusText(renderText(obj.currentNode), obj.rawText)\r\n } else if (slots?.statusText) {\r\n finalStatusText = slots.statusText\r\n }\r\n\r\n // Range text on the right\r\n const rangeText = useMemo(() => {\r\n if (currentCount <= 0) return '—'\r\n if (total != null) return `${currentCount} of ${total}`\r\n if (props.hasNext) return `${currentCount} of many`\r\n return `${currentCount} results`\r\n }, [currentCount, total])\r\n\r\n const finalRangeText = typeof slots?.rangeText === 'function' ? slots.rangeText(rangeText, rangeText) : (slots?.rangeText ?? rangeText)\r\n\r\n return (\r\n <PanelInfiniteScrollFooterStyled>\r\n <div>\r\n {renderText(finalStatusText)}\r\n {renderText(finalRangeText)}\r\n </div>\r\n </PanelInfiniteScrollFooterStyled>\r\n )\r\n}\r\n\r\nconst PanelInfiniteScrollFooterStyled = styled(Box)(({ theme }) => ({\r\n '& > div': {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n padding: theme.spacing(1, 1.5),\r\n backgroundColor: alpha(theme.palette.grey[500], 0.08),\r\n borderTop: `1px solid ${alpha(theme.palette.common.black, 0.08)}`\r\n },\r\n [`.${typographyClasses.root}`]: { lineHeight: 1, fontWeight: 500 }\r\n}))\r\n\r\nexport interface IPanelPaginationFooterProps {\r\n page: number\r\n pageSize: number\r\n total?: number\r\n hasNext?: boolean\r\n hasPrev?: boolean\r\n loading?: boolean\r\n onPrevPage?: () => void\r\n onNextPage?: () => void\r\n onPageJump?: (page: number) => void\r\n}\r\n\r\nexport const PanelPaginationFooter: FC<IPanelPaginationFooterProps> = (props) => {\r\n const { page, pageSize, total, hasNext, loading, onPrevPage, onNextPage, onPageJump } = props\r\n const from = page * pageSize + 1\r\n const to = total != null ? Math.min(from + pageSize - 1, total) : from + pageSize - 1\r\n\r\n // Calculate page count for MUI Pagination (1-indexed)\r\n const pageCount = total != null ? Math.ceil(total / pageSize) : undefined\r\n\r\n const handlePageChange = (_event: any, value: number) => {\r\n // MUI Pagination uses 1-indexed, convert to 0-indexed\r\n const targetPage = value - 1\r\n\r\n if (onPageJump) {\r\n // Use direct page jump if available\r\n onPageJump(targetPage)\r\n } else {\r\n // Fallback to prev/next if no jump handler\r\n if (targetPage < page) {\r\n onPrevPage?.()\r\n } else if (targetPage > page) {\r\n onNextPage?.()\r\n }\r\n }\r\n }\r\n\r\n return (\r\n <PanelPaginationFooterStyled>\r\n <Typography variant='caption' color='text.secondary'>\r\n {total != null ? `${from}–${to} / ${total}` : `Page ${page + 1}`}\r\n </Typography>\r\n <Pagination\r\n count={pageCount}\r\n page={page + 1}\r\n onChange={handlePageChange}\r\n disabled={loading}\r\n size='small'\r\n showFirstButton={pageCount != null && pageCount > 5}\r\n showLastButton={pageCount != null && pageCount > 5}\r\n siblingCount={0}\r\n boundaryCount={1}\r\n hidePrevButton={pageCount == null && !hasNext}\r\n hideNextButton={pageCount == null && !hasNext}\r\n />\r\n </PanelPaginationFooterStyled>\r\n )\r\n}\r\n\r\nconst PanelPaginationFooterStyled = styled(Box)(({ theme }) => ({\r\n padding: '8px 16px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n backgroundColor: theme.palette.background.paper,\r\n borderTop: `1px solid ${theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)'}`\r\n}))\r\n"],"names":["stateWrapBase","padding","height","minHeight","width","border","concat","colors","grey","borderRadius","display","alignItems","justifyContent","textAlign","PanelLoading","props","viewMode","rest","_objectWithoutProperties","_excluded","_jsx","PanelLoadingStyled","_objectSpread","children","_jsxs","className","CircularProgress","size","Typography","variant","color","styled","Box","gap","borderColor","blue","backgroundColor","alpha","red","flexDirection","PanelNoData","PanelNoDataStyled","gutterBottom","PanelLoadMore","PanelLoadMoreStyled","thickness","_ref2","position","inset","theme","palette","mode","zIndex","backdropFilter","transition","PanelInfiniteScrollFooter","_slots$rangeText","slots","loading","hasNext","currentCount","total","renderText","value","obj","mapRawText","currentNode","Stack","rawText","mapStatusText","finalStatusText","statusText","rangeText","useMemo","finalRangeText","PanelInfiniteScrollFooterStyled","_ref3","_defineProperty","spacing","borderTop","common","black","typographyClasses","root","lineHeight","fontWeight","PanelPaginationFooter","page","pageSize","onPrevPage","onNextPage","onPageJump","from","to","Math","min","pageCount","ceil","undefined","PanelPaginationFooterStyled","Pagination","count","onChange","_event","targetPage","disabled","showFirstButton","showLastButton","siblingCount","boundaryCount","hidePrevButton","hideNextButton","_ref5","background","paper"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{defineProperty as r,typeof as e}from"../../_virtual/_rollupPluginBabelHelpers.js";import{QueryParam as
|
|
1
|
+
import{defineProperty as r,typeof as e,objectWithoutProperties as t}from"../../_virtual/_rollupPluginBabelHelpers.js";import{QueryParam as i}from"../utils/query-param.js";import{KeySpecial as o}from"./types.js";var n=["filterLogic"],f=["filterLogic"],c={qsTooltip:"Type to search — the suggestion list shows matching values and the current value."},s=r(r({},o.quickSearch,"Quick Search"),o.sortShuffle,"Shuffle Arrangement");function a(r){if(null!=r){if("object"!==e(r))return r;if(Array.isArray(r)){var t=r.map(a).filter(function(r){return void 0!==r});return t.length>0?t:void 0}var i={},o=!1;for(var n in r)if(r.hasOwnProperty(n)){var f=a(r[n]);void 0!==f&&(i[n]=f,o=!0)}return o?i:void 0}}function u(r){if(!r)return!0;var e=a(r);return!e||0===Object.keys(e).length}function l(r,e){if(r===e)return!0;try{var t=a(r),i=a(e);return t===i||!(!t||!i)&&JSON.stringify(t)===JSON.stringify(i)}catch(r){return console.error("Error comparing filter states:",r),!1}}function d(r,e){if("undefined"!=typeof window)try{var o=r||{},c=(o.filterLogic,t(o,n)),s=e||{},a=(s.filterLogic,l(c,t(s,f))),d=u(c);if(a||d)return void i.replaceDeletes("filter");var p={filter:JSON.stringify(c)};i.replacePatch(p)}catch(r){console.error("Error syncing filter state to URL:",r)}}function p(r){if("undefined"==typeof window)return r;try{var e=i.gets("filter");if(!e.filter)return r;var t=JSON.parse(e.filter);return u(t)?r:t}catch(e){return console.error("Error getting filter state from URL:",e),r}}var y=function(r){if("undefined"!=typeof window)try{if(!r)return void i.replaceDeletes("seed");i.replacePatch({seed:r})}catch(r){console.error("Error syncing seed to URL:",r)}},g=function(){if("undefined"!=typeof window)try{return i.gets("seed").seed}catch(r){return void console.error("Error getting seed from URL:",r)}},v=function(){if("undefined"!=typeof window)try{i.replaceDeletes("seed")}catch(r){console.error("Error removing seed from URL:",r)}};export{p as getFilterFromURL,g as getSeedFromURL,u as isEmptyFilterState,l as isFilterStateEqual,s as mapSpecialLabel,c as mapSpecialTexts,a as removeNullValues,v as removeSeedFromURL,d as setFilterToURL,y as setSeedToURL};
|
|
2
2
|
//# sourceMappingURL=helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sources":["../../../src/filter-bar/helpers.ts"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\nimport { QueryParam } from '../utils/query-param'\r\nimport { KeySpecial, TFilterState } from './types'\r\n\r\nexport const mapSpecialTexts = {\r\n qsTooltip: 'Type to search — the suggestion list shows matching values and the current value.'\r\n}\r\n\r\nexport const mapSpecialLabel: Record<KeySpecial, string> = {\r\n [KeySpecial.quickSearch]: 'Quick Search',\r\n [KeySpecial.sortShuffle]: 'Shuffle Arrangement'\r\n}\r\n\r\nexport interface IFilterStateQueryParams {\r\n filter?: string\r\n}\r\n\r\n/**\r\n * @en Remove null/undefined values from object recursively for accurate comparison.\r\n * @vi Loai bo cac gia tri null/undefined khoi object mot cach de quy de so sanh chinh xac.\r\n */\r\nexport function removeNullValues<T = any>(obj: T): T | undefined {\r\n if (obj === null || obj === undefined) {\r\n return undefined\r\n }\r\n\r\n if (typeof obj !== 'object') {\r\n return obj\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n const cleaned = obj.map(removeNullValues).filter((v) => v !== undefined)\r\n return cleaned.length > 0 ? (cleaned as any) : undefined\r\n }\r\n\r\n const cleaned: any = {}\r\n let hasValue = false\r\n\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n const value = removeNullValues(obj[key])\r\n if (value !== undefined) {\r\n cleaned[key] = value\r\n hasValue = true\r\n }\r\n }\r\n }\r\n\r\n return hasValue ? cleaned : undefined\r\n}\r\n\r\n/**\r\n * @en Check if filter state is empty (no filters applied). Null/undefined values are ignored in this check.\r\n * @vi Kiem tra xem filter state co rong khong (khong co filter nao duoc ap dung). Gia tri null/undefined se duoc bo qua trong kiem tra nay.\r\n */\r\nexport function isEmptyFilterState<T>(state?: TFilterState<T>): boolean {\r\n if (!state) return true\r\n const cleaned = removeNullValues(state)\r\n return !cleaned || Object.keys(cleaned).length === 0\r\n}\r\n\r\n/**\r\n * @en Deep comparison of two filter states to check if they are equal.\r\n * @vi So sanh sau hai filter state de kiem tra xem chung co bang nhau khong.\r\n */\r\nexport function isFilterStateEqual<T>(state1?: TFilterState<T>, state2?: TFilterState<T>): boolean {\r\n if (state1 === state2) return true\r\n\r\n try {\r\n // Remove null/undefined values before comparison\r\n const cleaned1 = removeNullValues(state1)\r\n const cleaned2 = removeNullValues(state2)\r\n\r\n if (cleaned1 === cleaned2) return true\r\n if (!cleaned1 || !cleaned2) return false\r\n\r\n return JSON.stringify(cleaned1) === JSON.stringify(cleaned2)\r\n } catch (error) {\r\n console.error('Error comparing filter states:', error)\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * @en Synchronize filter state to URL query parameters. If state equals defaultState, remove from URL to keep it clean.\r\n * @vi Dong bo filter state vao URL query parameters. Neu state bang defaultState, xoa khoi URL de giu URL sach.\r\n *\r\n * @param state - Current filter state to sync\r\n * @param defaultState - Default filter state (if current equals this, don't save to URL)\r\n */\r\nexport function setFilterToURL<T>(state?: TFilterState<T>, defaultState?: TFilterState<T>) {\r\n // If window is undefined (e.g., during SSR), do nothing\r\n if (typeof window === 'undefined') return\r\n\r\n try {\r\n const isEqualToDefault = isFilterStateEqual(
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../../src/filter-bar/helpers.ts"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\nimport { QueryParam } from '../utils/query-param'\r\nimport { KeySpecial, TFilterState } from './types'\r\n\r\nexport const mapSpecialTexts = {\r\n qsTooltip: 'Type to search — the suggestion list shows matching values and the current value.'\r\n}\r\n\r\nexport const mapSpecialLabel: Record<KeySpecial, string> = {\r\n [KeySpecial.quickSearch]: 'Quick Search',\r\n [KeySpecial.sortShuffle]: 'Shuffle Arrangement'\r\n}\r\n\r\nexport interface IFilterStateQueryParams {\r\n filter?: string\r\n}\r\n\r\n/**\r\n * @en Remove null/undefined values from object recursively for accurate comparison.\r\n * @vi Loai bo cac gia tri null/undefined khoi object mot cach de quy de so sanh chinh xac.\r\n */\r\nexport function removeNullValues<T = any>(obj: T): T | undefined {\r\n if (obj === null || obj === undefined) {\r\n return undefined\r\n }\r\n\r\n if (typeof obj !== 'object') {\r\n return obj\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n const cleaned = obj.map(removeNullValues).filter((v) => v !== undefined)\r\n return cleaned.length > 0 ? (cleaned as any) : undefined\r\n }\r\n\r\n const cleaned: any = {}\r\n let hasValue = false\r\n\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n const value = removeNullValues(obj[key])\r\n if (value !== undefined) {\r\n cleaned[key] = value\r\n hasValue = true\r\n }\r\n }\r\n }\r\n\r\n return hasValue ? cleaned : undefined\r\n}\r\n\r\n/**\r\n * @en Check if filter state is empty (no filters applied). Null/undefined values are ignored in this check.\r\n * @vi Kiem tra xem filter state co rong khong (khong co filter nao duoc ap dung). Gia tri null/undefined se duoc bo qua trong kiem tra nay.\r\n */\r\nexport function isEmptyFilterState<T>(state?: TFilterState<T>): boolean {\r\n if (!state) return true\r\n const cleaned = removeNullValues(state)\r\n return !cleaned || Object.keys(cleaned).length === 0\r\n}\r\n\r\n/**\r\n * @en Deep comparison of two filter states to check if they are equal.\r\n * @vi So sanh sau hai filter state de kiem tra xem chung co bang nhau khong.\r\n */\r\nexport function isFilterStateEqual<T>(state1?: TFilterState<T>, state2?: TFilterState<T>): boolean {\r\n if (state1 === state2) return true\r\n\r\n try {\r\n // Remove null/undefined values before comparison\r\n const cleaned1 = removeNullValues(state1)\r\n const cleaned2 = removeNullValues(state2)\r\n\r\n if (cleaned1 === cleaned2) return true\r\n if (!cleaned1 || !cleaned2) return false\r\n\r\n return JSON.stringify(cleaned1) === JSON.stringify(cleaned2)\r\n } catch (error) {\r\n console.error('Error comparing filter states:', error)\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * @en Synchronize filter state to URL query parameters. If state equals defaultState, remove from URL to keep it clean.\r\n * @vi Dong bo filter state vao URL query parameters. Neu state bang defaultState, xoa khoi URL de giu URL sach.\r\n *\r\n * @param state - Current filter state to sync\r\n * @param defaultState - Default filter state (if current equals this, don't save to URL)\r\n */\r\nexport function setFilterToURL<T>(state?: TFilterState<T>, defaultState?: TFilterState<T>) {\r\n // If window is undefined (e.g., during SSR), do nothing\r\n if (typeof window === 'undefined') return\r\n\r\n try {\r\n // Extract filterLogic to avoid including it in URL since it's not part of the actual filter criteria\r\n const { filterLogic: fl, ...st } = state || {}\r\n const { filterLogic: dfl, ...dst } = defaultState || {}\r\n\r\n const isEqualToDefault = isFilterStateEqual(st, dst)\r\n const isEmpty = isEmptyFilterState(st)\r\n // If state equals default or is empty, remove from URL\r\n if (isEqualToDefault || isEmpty) {\r\n QueryParam.replaceDeletes<IFilterStateQueryParams>('filter')\r\n return\r\n }\r\n\r\n // Serialize state to JSON and save to URL\r\n const updateParams: IFilterStateQueryParams = { filter: JSON.stringify(st) }\r\n\r\n QueryParam.replacePatch<IFilterStateQueryParams>(updateParams)\r\n } catch (error) {\r\n console.error('Error syncing filter state to URL:', error)\r\n }\r\n}\r\n\r\n/**\r\n * @en Retrieve filter state from URL query parameters.\r\n * @vi Lay filter state tu URL query parameters.\r\n *\r\n * @param defaultState - Default filter state to return if URL has no filter state\r\n * @returns Filter state from URL or defaultState\r\n */\r\nexport function getFilterFromURL<T>(defaultState?: TFilterState<T>): TFilterState<T> | undefined {\r\n // If window is undefined (e.g., during SSR), return defaultState\r\n if (typeof window === 'undefined') return defaultState\r\n\r\n try {\r\n const q = QueryParam.gets<IFilterStateQueryParams>('filter')\r\n\r\n if (!q.filter) return defaultState\r\n\r\n // Parse JSON from URL\r\n const state = JSON.parse(q.filter) as TFilterState<T>\r\n const isEmpty = isEmptyFilterState(state)\r\n return isEmpty ? defaultState : state\r\n } catch (error) {\r\n console.error('Error getting filter state from URL:', error)\r\n return defaultState\r\n }\r\n}\r\n\r\n/**\r\n * @en Set seed value to URL for shuffle sorting. If seed is undefined, remove from URL.\r\n * @vi Dat gia tri seed vao URL de sap xep shuffle. Neu seed khong xac dinh, xoa khoi URL.\r\n * @param seed - Seed value for shuffle sorting\r\n */\r\nexport const setSeedToURL = (seed?: string) => {\r\n if (typeof window === 'undefined') return\r\n try {\r\n if (!seed) {\r\n QueryParam.replaceDeletes('seed')\r\n return\r\n }\r\n QueryParam.replacePatch({ seed })\r\n } catch (error) {\r\n console.error('Error syncing seed to URL:', error)\r\n }\r\n}\r\n\r\n/**\r\n * @en Get seed value from URL for shuffle sorting. Returns undefined if not set or on error.\r\n * @vi Lay gia tri seed tu URL de sap xep shuffle. Tra ve undefined neu khong duoc dat hoac co loi.\r\n * @returns Seed value from URL or undefined\r\n */\r\nexport const getSeedFromURL = (): string | undefined => {\r\n if (typeof window === 'undefined') return undefined\r\n try {\r\n const q = QueryParam.gets<{ seed?: string }>('seed')\r\n return q.seed\r\n } catch (error) {\r\n console.error('Error getting seed from URL:', error)\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * @en Remove seed value from URL.\r\n * @vi Xoa gia tri seed khoi URL.\r\n */\r\nexport const removeSeedFromURL = () => {\r\n if (typeof window === 'undefined') return\r\n try {\r\n QueryParam.replaceDeletes('seed')\r\n } catch (error) {\r\n console.error('Error removing seed from URL:', error)\r\n }\r\n}\r\n"],"names":["mapSpecialTexts","qsTooltip","mapSpecialLabel","_defineProperty","KeySpecial","quickSearch","sortShuffle","removeNullValues","obj","_typeof","Array","isArray","cleaned","map","filter","v","undefined","length","hasValue","key","hasOwnProperty","value","isEmptyFilterState","state","Object","keys","isFilterStateEqual","state1","state2","cleaned1","cleaned2","JSON","stringify","error","console","setFilterToURL","defaultState","window","_ref","st","filterLogic","_objectWithoutProperties","_excluded","_ref2","isEqualToDefault","_excluded2","isEmpty","QueryParam","replaceDeletes","updateParams","replacePatch","getFilterFromURL","q","gets","parse","setSeedToURL","seed","getSeedFromURL","removeSeedFromURL"],"mappings":"2PAKaA,EAAkB,CAC7BC,UAAW,qFAGAC,EAAeC,EAAAA,KACzBC,EAAWC,YAAc,gBACzBD,EAAWE,YAAc,uBAWtB,SAAUC,EAA0BC,GACxC,GAAIA,QAAJ,CAIA,GAAmB,WAAfC,EAAOD,GACT,OAAOA,EAGT,GAAIE,MAAMC,QAAQH,GAAM,CACtB,IAAMI,EAAUJ,EAAIK,IAAIN,GAAkBO,OAAO,SAACC,GAAC,YAAWC,IAAND,IACxD,OAAOH,EAAQK,OAAS,EAAKL,OAAkBI,CAChD,CAED,IAAMJ,EAAe,CAAE,EACnBM,GAAW,EAEf,IAAK,IAAMC,KAAOX,EAChB,GAAIA,EAAIY,eAAeD,GAAM,CAC3B,IAAME,EAAQd,EAAiBC,EAAIW,SACrBH,IAAVK,IACFT,EAAQO,GAAOE,EACfH,GAAW,EAEd,CAGH,OAAOA,EAAWN,OAAUI,CAxB3B,CAyBH,CAMM,SAAUM,EAAsBC,GACpC,IAAKA,EAAO,OAAO,EACnB,IAAMX,EAAUL,EAAiBgB,GACjC,OAAQX,GAA2C,IAAhCY,OAAOC,KAAKb,GAASK,MAC1C,CAMgB,SAAAS,EAAsBC,EAA0BC,GAC9D,GAAID,IAAWC,EAAQ,OAAO,EAE9B,IAEE,IAAMC,EAAWtB,EAAiBoB,GAC5BG,EAAWvB,EAAiBqB,GAElC,OAAIC,IAAaC,MACZD,IAAaC,IAEXC,KAAKC,UAAUH,KAAcE,KAAKC,UAAUF,EACpD,CAAC,MAAOG,GAEP,OADAC,QAAQD,MAAM,iCAAkCA,IACzC,CACR,CACH,CASgB,SAAAE,EAAkBZ,EAAyBa,GAEzD,GAAsB,oBAAXC,OAEX,IAEE,IAAAC,EAAmCf,GAAS,CAAE,EAAlBgB,GAALD,EAAfE,YAAsBC,EAAAH,EAAAI,IAC9BC,EAAqCP,GAAgB,CAAE,EAEjDQ,GAFkBD,EAAhBH,YAEiBd,EAAmBa,EAFZE,EAAAE,EAAAE,KAG1BC,EAAUxB,EAAmBiB,GAEnC,GAAIK,GAAoBE,EAEtB,YADAC,EAAWC,eAAwC,UAKrD,IAAMC,EAAwC,CAAEnC,OAAQiB,KAAKC,UAAUO,IAEvEQ,EAAWG,aAAsCD,EAClD,CAAC,MAAOhB,GACPC,QAAQD,MAAM,qCAAsCA,EACrD,CACH,CASM,SAAUkB,EAAoBf,GAElC,GAAsB,oBAAXC,OAAwB,OAAOD,EAE1C,IACE,IAAMgB,EAAIL,EAAWM,KAA8B,UAEnD,IAAKD,EAAEtC,OAAQ,OAAOsB,EAGtB,IAAMb,EAAQQ,KAAKuB,MAAMF,EAAEtC,QAE3B,OADgBQ,EAAmBC,GAClBa,EAAeb,CACjC,CAAC,MAAOU,GAEP,OADAC,QAAQD,MAAM,uCAAwCA,GAC/CG,CACR,CACH,KAOamB,EAAe,SAACC,GAC3B,GAAsB,oBAAXnB,OACX,IACE,IAAKmB,EAEH,YADAT,EAAWC,eAAe,QAG5BD,EAAWG,aAAa,CAAEM,KAAAA,GAC3B,CAAC,MAAOvB,GACPC,QAAQD,MAAM,6BAA8BA,EAC7C,CACH,EAOawB,EAAiB,WAC5B,GAAsB,oBAAXpB,OACX,IAEE,OADUU,EAAWM,KAAwB,QACpCG,IACV,CAAC,MAAOvB,GAEP,YADAC,QAAQD,MAAM,+BAAgCA,EAE/C,CACH,EAMayB,EAAoB,WAC/B,GAAsB,oBAAXrB,OACX,IACEU,EAAWC,eAAe,OAC3B,CAAC,MAAOf,GACPC,QAAQD,MAAM,gCAAiCA,EAChD,CACH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{slicedToArray as e,defineProperty as l,toConsumableArray as n}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as
|
|
1
|
+
import{slicedToArray as e,defineProperty as l,toConsumableArray as n}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as o,jsxs as i}from"react/jsx-runtime";import{useMemo as t,useState as r,useEffect as a}from"react";import{styled as u,Typography as c,Box as s,CircularProgress as d,FormGroup as v,FormControlLabel as m,Checkbox as f,Button as p}from"@mui/material";import"../../form/validator.js";import"../../form/dino-form.js";import{getErrorMessage as b}from"../../form/helpers.js";import"../../../_virtual/Reflect.js";import"../../form/decorator.form.js";import"../../form/create.form-grid-layout.units.js";import{createChipViewers as g}from"../components/chip-viewer.js";import{PopperContent as h,PopperBody as x,PopperFooter as y}from"../components/popper-custom.js";import{ButtonBack as C,ChipDark as j,FilterLogicToggle as A}from"../components/ui.units.js";function V(u){var V=g(),z=(u||{}).options,S=void 0===z?[]:z;return function(g){var z,L,O,w=t(function(){return Object.assign({},g.currentConfig,null==u?void 0:u.config)},[null==u?void 0:u.config,g.currentConfig]),R=g.value,B=void 0===R?{values:[],logic:null!==(z=null==w?void 0:w.defaultLogic)&&void 0!==z?z:"or"}:R,N=r(B.logic),T=e(N,2),_=T[0],E=T[1],F=null!==(L=null==u?void 0:u.forceLogic)&&void 0!==L?L:_,I=null!==(O=null==w?void 0:w.label)&&void 0!==O?O:w.field.toString(),M=r([]),P=e(M,2),D=P[0],H=P[1],U=r(!1),q=e(U,2),G=q[0],J=q[1];a(function(){if(null!=u&&u.fetchOptions){var e=new AbortController;return J(!0),u.fetchOptions(e.signal).then(H).catch(function(e){"AbortError"!==(null==e?void 0:e.name)&&console.error(e)}).finally(function(){return J(!1)}),function(){return e.abort()}}},[]);var K=null!=u&&u.fetchOptions?D:S,Q=t(function(){var e=Array.isArray(B.values)?B.values:[B.values];return K.filter(function(l){return e.includes(l.value)}).map(function(e){return e.value})},[]),W=r(Q),X=e(W,2),Y=X[0],Z=X[1],$=Array.isArray(B.values)?B.values:[],ee=_!==B.logic,le=Y.length!==$.length||Y.some(function(e){return!$.includes(e)}),ne=!le&&!ee,oe=r({}),ie=e(oe,2),te=ie[0],re=ie[1],ae=function(e){g.onSubmit(w.field,e,w)},ue=b(te,w.field),ce=t(function(){var e=Array.isArray(B.values)?B.values:[B.values];return{field:w.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}})}},[w.field,B]),se=null!=(null==u?void 0:u.maxValueCount)&&Y.length>u.maxValueCount,de=null!=(null==u?void 0:u.maxValueCount)&&Y.length>=u.maxValueCount,ve=[];return(g.isLoading||G)&&ve.push("disabled"),o(k,{className:ve.join(" "),noValidate:!0,onSubmit:function(e){var n;if(e.preventDefault(),le){if(!se){var o=l({},w.field,Y),i=null===(n=g.validator)||void 0===n?void 0:n.run(o);if(re(i||{}),!i||0===Object.keys(i).length)ae({values:Y,logic:F})}}else ee&&ae({values:B.values,logic:F})},children:i(h,{title:"Filter by ".concat(I),onClose:g.onClose,slots:{beforeTitle:o(C,{size:"small",onClick:g.onBack}),afterTitle:null!=u&&u.forceLogic?null:w.singleValue?o(j,{sx:{ml:1.5},size:"small",label:"Last value only"}):o(A,{sx:{ml:1},value:F,onChange:function(e,l){E(l)}})},children:[i(x,{children:[w.description&&o(c,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:w.description}),null!=(null==u?void 0:u.maxValueCount)&&o(c,{variant:"caption",color:se?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:null!=u&&u.maxValueCount?se?"Maximum ".concat(u.maxValueCount," value").concat(u.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(u.maxValueCount," value").concat(u.maxValueCount>1?"s":""," can be selected"):""}),o(V,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:ce,onRemove:g.onRemove}),0===K.length&&G&&o(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:o(d,{size:20})}),0===K.length&&!G&&o(c,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),o(v,{className:ue.error?"error":"",children:K.map(function(e,l){var i,t=Y.includes(e.value),r=ce.items.some(function(l){return l.value===e.value})&&!0===(null==u?void 0:u.disabledAfterSubmit),a=!t&&de;return o(m,{value:e.value,disabled:r||a,label:null!==(i=e.label)&&void 0!==i?i:e.value,control:o(f,{name:w.field.toString(),checked:t,onChange:function(l){return o=e.value,i=l.target.checked,void Z(function(e){return i?[].concat(n(e),[o]):e.filter(function(e){return e!==o})});var o,i}})},e.value.toString()+l)})})]}),i(y,{children:[o(p,{size:"small",color:"error",variant:"text",disabled:!B.values||0===B.values.length,onClick:function(){var e,l;null===(e=g.onRemoveField)||void 0===e||e.call(g,w.field),!1!==(null==u||null===(l=u.config)||void 0===l?void 0:l.closeAfterClear)&&g.onClose()},children:"Clear All"}),o(s,{sx:{flex:1}}),o(p,{size:"small",color:"inherit",variant:"text",onClick:g.onClose,children:"Cancel"}),o(p,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:ne,children:"Apply"})]})]})})}}var k=u("form")({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}});export{V 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, Typography } 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 /** Force a fixed logic value, hiding the logic toggle */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected */\r\n maxValueCount?: number\r\n}\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 const effectiveLogic = params?.forceLogic ?? filterLogic\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 appliedValues = Array.isArray(value.values) ? value.values : []\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = checkedValues.length !== appliedValues.length || checkedValues.some(v => !appliedValues.includes(v))\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleCheckboxChange = (optionValue: TFieldValid, checked: boolean) => {\r\n setCheckedValues((prev) => (checked ? [...prev, optionValue] : prev.filter((v) => v !== optionValue)))\r\n }\r\n\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: checkedValues } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: checkedValues, logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: options.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const isMaxReached = params?.maxValueCount != null && checkedValues.length > params.maxValueCount\r\n const isMaxReachedValid = params?.maxValueCount != null && checkedValues.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params?.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n if (params?.forceLogic) return null\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params?.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected && params?.disabledAfterSubmit === true\r\n const disableDueToMax = !isChecked && isMaxReachedValid\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled || disableDueToMax}\r\n label={x.label ?? x.value}\r\n control={\r\n <Checkbox\r\n name={mergedConfig.field.toString()}\r\n checked={isChecked}\r\n onChange={(e) => handleCheckboxChange(x.value as TFieldValid, e.target.checked)}\r\n />\r\n }\r\n />\r\n )\r\n })}\r\n </FormGroup>\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelectMultiple\r\n}\r\n\r\nexport default createFormFieldSelectMultiple\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.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","_params$forceLogic","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","label","field","toString","initialChecked","Array","isArray","filter","opt","includes","map","_useState3","_useState4","checkedValues","setCheckedValues","appliedValues","hasLogicChange","hasDataChange","length","some","v","isApplyDisabled","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","_options$find","find","o","isMaxReached","maxValueCount","isMaxReachedValid","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","mb","display","borderBottom","placement","enableMinimalesticView","onRemove","FormGroup","error","x","i","_x$label","isChecked","disabled","item","disabledAfterSubmit","disableDueToMax","FormControlLabel","control","Checkbox","name","checked","e","optionValue","target","prev","_toConsumableArray","PopperFooter","Button","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","position","content","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-form-field-select-multiple.js","sources":["../../../../src/filter-bar/menu/create-form-field-select-multiple.tsx"],"sourcesContent":["// Copyright (c) 2024-present, Dinocollab Technologies, Inc. and its affiliates. All rights reserved.\r\n\r\n// imports\r\nimport { useEffect, useMemo, useState } from 'react'\r\nimport { Box, Button, Checkbox, CircularProgress, FormControlLabel, FormGroup, formGroupClasses, styled, Typography } 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 /** Function to fetch options asynchronously */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** If true, disables the field after submission. @default false */\r\n disabledAfterSubmit?: boolean\r\n /** Force a fixed logic value, hiding the logic toggle */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected */\r\n maxValueCount?: number\r\n}\r\n\r\n/**\r\n * Factory function that creates a `FormFieldSelectMultiple` filter-menu component.\r\n *\r\n * The generated component renders a checkbox list of options inside a\r\n * popper/menu panel, allowing the user to select **multiple values** at once.\r\n * It supports:\r\n * - Controlled checkbox state to prevent uncontrolled→controlled React warnings\r\n * - OR / AND logic toggle when more than one value is applied\r\n * - Chip viewers showing the currently applied values\r\n * - Built-in validation via an optional `validator` prop\r\n * - A loading overlay that disables interaction while `isLoading` is true\r\n *\r\n * @param params - Static configuration (option list, optional field config override)\r\n * @returns A React FC ready to be used as a multi-select filter-menu field component\r\n */\r\nfunction createFormFieldSelectMultiple<T>(params?: IFormFieldSelectMultipleParam<T>) {\r\n const ChipViewers = createChipViewers<T>()\r\n const { options: staticOptions = [] } = params || {}\r\n\r\n const FormFieldSelectMultiple: FC<IFormFieldSelectMultipleProps<T>> = (props) => {\r\n /** Merge `props.currentConfig` with `params.config` (if provided).\r\n * Fields from `params.config` override the corresponding keys in `props.currentConfig`.\r\n * Any keys not present in `params.config` are preserved from `props.currentConfig`.\r\n */\r\n const mergedConfig = useMemo(() => Object.assign({}, props.currentConfig, params?.config), [params?.config, props.currentConfig])\r\n\r\n const { value = { values: [], logic: mergedConfig?.defaultLogic ?? 'or' } } = props\r\n const [filterLogic, setFilterLogic] = useState<TLogic>(value.logic!)\r\n const effectiveLogic = params?.forceLogic ?? filterLogic\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [fetchedOptions, setFetchedOptions] = useState<IFieldSelectOption[]>([])\r\n const [isFetchLoading, setIsFetchLoading] = useState(false)\r\n\r\n useEffect(() => {\r\n if (!params?.fetchOptions) return\r\n const controller = new AbortController()\r\n setIsFetchLoading(true)\r\n params\r\n .fetchOptions(controller.signal)\r\n .then(setFetchedOptions)\r\n .catch((err) => {\r\n if (err?.name !== 'AbortError') console.error(err)\r\n })\r\n .finally(() => setIsFetchLoading(false))\r\n return () => controller.abort()\r\n }, [])\r\n\r\n const options = params?.fetchOptions ? fetchedOptions : staticOptions\r\n\r\n // Track checked values as controlled state to avoid the uncontrolled→controlled MUI warning\r\n 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 appliedValues = Array.isArray(value.values) ? value.values : []\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = checkedValues.length !== appliedValues.length || checkedValues.some((v) => !appliedValues.includes(v))\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n\r\n const handleCheckboxChange = (optionValue: TFieldValid, checked: boolean) => {\r\n setCheckedValues((prev) => (checked ? [...prev, optionValue] : prev.filter((v) => v !== optionValue)))\r\n }\r\n\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: checkedValues } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: checkedValues, logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: options.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const isMaxReached = params?.maxValueCount != null && checkedValues.length > params.maxValueCount\r\n const isMaxReachedValid = params?.maxValueCount != null && checkedValues.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params?.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (params?.forceLogic) return null\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading || isFetchLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params?.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n {options.length === 0 && isFetchLoading && (\r\n <Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>\r\n <CircularProgress size={20} />\r\n </Box>\r\n )}\r\n {options.length === 0 && !isFetchLoading && (\r\n <Typography variant='body2' color='text.secondary' sx={{ mt: 2 }}>\r\n No options available\r\n </Typography>\r\n )}\r\n <FormGroup className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isChecked = checkedValues.includes(x.value as TFieldValid)\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected && params?.disabledAfterSubmit === true\r\n const disableDueToMax = !isChecked && isMaxReachedValid\r\n return (\r\n <FormControlLabel\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n disabled={disabled || disableDueToMax}\r\n label={x.label ?? x.value}\r\n control={\r\n <Checkbox\r\n name={mergedConfig.field.toString()}\r\n checked={isChecked}\r\n onChange={(e) => handleCheckboxChange(x.value as TFieldValid, e.target.checked)}\r\n />\r\n }\r\n />\r\n )\r\n })}\r\n </FormGroup>\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelectMultiple\r\n}\r\n\r\nexport default createFormFieldSelectMultiple\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.12)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n }\r\n // [`.${formGroupClasses.root}`]: {}\r\n})\r\n"],"names":["createFormFieldSelectMultiple","params","ChipViewers","createChipViewers","_ref$options","options","staticOptions","props","_mergedConfig$default","_params$forceLogic","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","label","field","toString","_useState3","_useState4","fetchedOptions","setFetchedOptions","_useState5","_useState6","isFetchLoading","setIsFetchLoading","useEffect","fetchOptions","controller","AbortController","signal","then","err","name","console","error","abort","initialChecked","Array","isArray","filter","opt","includes","map","_useState7","_useState8","checkedValues","setCheckedValues","appliedValues","hasLogicChange","hasDataChange","length","some","v","isApplyDisabled","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","_options$find","find","o","isMaxReached","maxValueCount","isMaxReachedValid","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","mb","display","borderBottom","placement","enableMinimalesticView","onRemove","Box","justifyContent","mt","CircularProgress","FormGroup","x","i","_x$label","isChecked","disabled","item","disabledAfterSubmit","disableDueToMax","FormControlLabel","control","Checkbox","checked","e","optionValue","target","prev","_toConsumableArray","PopperFooter","Button","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","flex","type","styled","position","content","inset","backgroundColor","zIndex","opacity","transition","visibility","pointerEvents"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{defineProperty as
|
|
1
|
+
import{defineProperty as e,slicedToArray as l}from"../../../_virtual/_rollupPluginBabelHelpers.js";import{jsx as o,jsxs as n}from"react/jsx-runtime";import{useMemo as i,useState as r,useEffect as t}from"react";import{styled as a,radioGroupClasses as u,Typography as c,Box as s,CircularProgress as d,RadioGroup as m,FormControlLabel as v,Radio as f,Button as p}from"@mui/material";import{getErrorMessage as b}from"../../form/helpers.js";import{createChipViewers as g}from"../components/chip-viewer.js";import{ButtonBack as h,ChipDark as x,FilterLogicToggle as C}from"../components/ui.units.js";import{PopperContent as y,PopperBody as V,PopperFooter as j}from"../components/popper-custom.js";function k(a){var u=g(),k=a.options;return function(g){var A,L,M,O=i(function(){return Object.assign({},g.currentConfig,null==a?void 0:a.config)},[null==a?void 0:a.config,g.currentConfig]),S=g.value,w=void 0===S?{values:[],logic:null!==(A=null==O?void 0:O.defaultLogic)&&void 0!==A?A:"or"}:S,F=r(w.logic),R=l(F,2),B=R[0],N=R[1],T=null!==(L=a.forceLogic)&&void 0!==L?L:B,E=r(null),I=l(E,2),P=I[0],_=I[1],D=r([]),H=l(D,2),U=H[0],q=H[1],G=r(!1),J=l(G,2),K=J[0],Q=J[1];t(function(){if(a.fetchOptions){var e=new AbortController;return Q(!0),a.fetchOptions(e.signal).then(q).catch(function(e){"AbortError"!==(null==e?void 0:e.name)&&console.error(e)}).finally(function(){return Q(!1)}),function(){return e.abort()}}},[]);var W=a.fetchOptions?U:null!=k?k:[],X=B!==w.logic,Y=null!==P,Z=!Y&&!X,$=null!==(M=null==O?void 0:O.label)&&void 0!==M?M:O.field.toString(),ee=r({}),le=l(ee,2),oe=le[0],ne=le[1],ie=function(e){g.onSubmit(O.field,e,O)},re=b(oe,O.field),te=i(function(){var e=Array.isArray(w.values)?w.values:[w.values];return{field:O.field,items:e.map(function(e){var l;return{value:e,label:null===(l=W.find(function(l){return l.value===e}))||void 0===l?void 0:l.label}})}},[O.field,w,W]),ae=null!=a.maxValueCount&&te.items.length>=a.maxValueCount,ue=[];return(g.isLoading||K)&&ue.push("disabled"),o(z,{className:ue.join(" "),noValidate:!0,onSubmit:function(l){var o;if(l.preventDefault(),Y){if(!ae){var n=e({},O.field,P),i=null===(o=g.validator)||void 0===o?void 0:o.run(n);if(ne(i||{}),!i||0===Object.keys(i).length)ie({values:[P],logic:T}),_(null)}}else X&&ie({values:w.values,logic:T})},children:n(y,{title:"Filter by ".concat($),onClose:g.onClose,slots:{beforeTitle:o(h,{size:"small",onClick:g.onBack}),afterTitle:a.forceLogic?null:O.singleValue?o(x,{sx:{ml:1.5},size:"small",label:"Last value only"}):o(C,{sx:{ml:1},value:T,onChange:function(e,l){N(l)}})},children:[n(V,{children:[O.description&&o(c,{variant:"caption",color:"text.secondary",sx:{mb:1,display:"block"},children:O.description}),null!=a.maxValueCount&&o(c,{variant:"caption",color:ae?"warning.main":"text.secondary",sx:{mb:.5,display:"block"},children:a.maxValueCount?ae?"Maximum ".concat(a.maxValueCount," value").concat(a.maxValueCount>1?"s":""," selected (limit reached)"):"Up to ".concat(a.maxValueCount," value").concat(a.maxValueCount>1?"s":""," can be selected"):""}),o(u,{sx:{mb:1,borderBottom:"none!important"},label:"Applied",placement:"horizontal",enableMinimalesticView:!0,value:te,onRemove:g.onRemove}),0===W.length&&K&&o(s,{sx:{display:"flex",justifyContent:"center",mt:2},children:o(d,{size:20})}),0===W.length&&!K&&o(c,{variant:"body2",color:"text.secondary",sx:{mt:2},children:"No options available"}),o(m,{sx:{mx:-1},name:O.field.toString(),value:null!=P?P:"",onChange:function(e){return _(e.target.value)},className:re.error?"error":"",children:W.map(function(e,l){var n,i=te.items.some(function(l){return l.value===e.value});return o(v,{disabled:i||ae,value:e.value,control:o(f,{size:"small"}),label:o(c,{variant:"body2",children:null!==(n=e.label)&&void 0!==n?n:e.value})},e.value.toString()+l)})}),re.error&&o(c,{variant:"caption",color:"error",sx:{mt:.5},children:re.message})]}),n(j,{children:[o(p,{size:"small",color:"error",variant:"text",disabled:!w.values||0===w.values.length,onClick:function(){var e,l;null===(e=g.onRemoveField)||void 0===e||e.call(g,O.field),!1!==(null==a||null===(l=a.config)||void 0===l?void 0:l.closeAfterClear)&&g.onClose()},children:"Clear All"}),o(s,{sx:{flex:1}}),o(p,{size:"small",color:"inherit",variant:"text",onClick:g.onClose,children:"Cancel"}),o(p,{size:"small",type:"submit",color:"primary",variant:"contained",disabled:Z,children:"Apply"})]})]})})}}var z=a("form")(e({position:"relative","&::after":{content:'""',display:"block",position:"absolute",inset:0,backgroundColor:"rgba(0, 0, 0, 0.12)",filter:"blur(2px)",zIndex:-1,opacity:0,transition:"opacity 0.3s",visibility:"hidden"},"&.disabled":{pointerEvents:"none","&::after":{zIndex:1,opacity:1,visibility:"visible"}}},".".concat(u.root),{"&.error .MuiRadio-root":{color:"#d32f2f"},".MuiFormControlLabel-root":{margin:0},".MuiFormControlLabel-root:hover":{backgroundColor:"rgba(25, 118, 210, 0.04)"}}));export{k 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 { 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 /** Force a specific logic (and/or) for this field, overriding the default or user-selected logic */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected for this field */\r\n maxValueCount?: number\r\n}\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 const effectiveLogic = params.forceLogic ?? filterLogic\r\n const [selectedValue, setSelectedValue] = useState<TFieldValid | null>(null)\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = selectedValue !== null\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: selectedValue } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: [selectedValue!] as TFieldValid[], logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n setSelectedValue(null)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: options.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value])\r\n\r\n const isMaxReached = params.maxValueCount != null && filterViewerValue.items.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\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 (params.forceLogic) return null\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n <RadioGroup sx={{ mx: -1 }} name={mergedConfig.field.toString()} value={selectedValue ?? ''} onChange={(e) => setSelectedValue(e.target.value as TFieldValid)} className={errorResult.error ? 'error' : ''}>\r\n {options.map((x, i) => {\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected || isMaxReached\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.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","_params$forceLogic","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","_useState3","_useState4","selectedValue","setSelectedValue","hasLogicChange","hasDataChange","isApplyDisabled","label","field","toString","_useState5","_useState6","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_options$find","find","o","isMaxReached","maxValueCount","length","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","mb","display","borderBottom","placement","enableMinimalesticView","onRemove","RadioGroup","mx","name","e","target","error","x","i","_x$label","isSelected","some","item","FormControlLabel","disabled","control","Radio","mt","message","PopperFooter","Button","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","Box","flex","type","styled","position","content","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, useEffect, useMemo, useState } from 'react'\r\nimport { Box, Button, CircularProgress, FormControlLabel, Radio, RadioGroup, radioGroupClasses, styled, Typography } from '@mui/material'\r\nimport { getErrorMessage } from '../../form/helpers'\r\nimport { createChipViewers, TChipViewerGroup } from '../components/chip-viewer'\r\nimport { ButtonBack, ChipDark, FilterLogicToggle } from '../components/ui.units'\r\nimport { PopperBody, PopperContent, PopperFooter } from '../components/popper-custom'\r\nimport type { IPartialError } from '../../form/validator'\r\nimport type { 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 /** Function to fetch options asynchronously based on user input */\r\n fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>\r\n /** Force a specific logic (and/or) for this field, overriding the default or user-selected logic */\r\n forceLogic?: TLogic\r\n /** Maximum number of values that can be selected for this field */\r\n maxValueCount?: number\r\n}\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 const effectiveLogic = params.forceLogic ?? filterLogic\r\n const [selectedValue, setSelectedValue] = useState<TFieldValid | null>(null)\r\n const [fetchedOptions, setFetchedOptions] = useState<IFieldSelectOption[]>([])\r\n const [isFetchLoading, setIsFetchLoading] = useState(false)\r\n\r\n useEffect(() => {\r\n if (!params.fetchOptions) return\r\n const controller = new AbortController()\r\n setIsFetchLoading(true)\r\n params\r\n .fetchOptions(controller.signal)\r\n .then(setFetchedOptions)\r\n .catch((err) => {\r\n if (err?.name !== 'AbortError') console.error(err)\r\n })\r\n .finally(() => setIsFetchLoading(false))\r\n return () => controller.abort()\r\n }, [])\r\n\r\n const effectiveOptions = params.fetchOptions ? fetchedOptions : (options ?? [])\r\n const hasLogicChange = filterLogic !== value.logic\r\n const hasDataChange = selectedValue !== null\r\n const isApplyDisabled = !hasDataChange && !hasLogicChange\r\n\r\n const label = mergedConfig?.label ?? mergedConfig.field.toString()\r\n\r\n const [errorData, setErrorData] = useState<IPartialError<TFieldModelValid<T>>>({})\r\n const handleSubmit = (newValue: TFieldValue) => {\r\n props.onSubmit(mergedConfig.field, newValue, mergedConfig)\r\n }\r\n\r\n const handleSubmitForm = (event: React.FormEvent<HTMLFormElement>) => {\r\n event.preventDefault()\r\n\r\n if (!hasDataChange) {\r\n if (hasLogicChange) {\r\n handleSubmit({ values: value.values, logic: effectiveLogic })\r\n }\r\n return\r\n }\r\n\r\n if (isMaxReached) return\r\n\r\n const obj = { [mergedConfig.field]: selectedValue } as Partial<TFieldModelValid<T>>\r\n let errorData = props.validator?.run(obj) as IPartialError<TFieldModelValid<T>>\r\n\r\n setErrorData(errorData || {})\r\n\r\n if (!errorData || Object.keys(errorData).length === 0) {\r\n const newValue: TFieldValue = { values: [selectedValue!] as TFieldValid[], logic: effectiveLogic }\r\n handleSubmit(newValue)\r\n setSelectedValue(null)\r\n }\r\n }\r\n\r\n const errorResult = getErrorMessage(errorData, mergedConfig.field)\r\n const filterViewerValue = useMemo<TChipViewerGroup<T>>(() => {\r\n const items = Array.isArray(value.values) ? value.values : [value.values]\r\n return {\r\n field: mergedConfig.field,\r\n items: items.map((v) => ({ value: v, label: effectiveOptions.find((o) => o.value === v)?.label }))\r\n }\r\n }, [mergedConfig.field, value, effectiveOptions])\r\n\r\n const isMaxReached = params.maxValueCount != null && filterViewerValue.items.length >= params.maxValueCount\r\n\r\n const handleChangeLogic = (newLogic: TLogic) => {\r\n setFilterLogic(newLogic)\r\n }\r\n\r\n const handleClearAll = () => {\r\n props.onRemoveField?.(mergedConfig.field)\r\n if (params?.config?.closeAfterClear !== false) props.onClose()\r\n }\r\n\r\n const renderAfterTitle = () => {\r\n if (params.forceLogic) return null\r\n if (mergedConfig.singleValue) return <ChipDark sx={{ ml: 1.5 }} size='small' label='Last value only' />\r\n return <FilterLogicToggle sx={{ ml: 1 }} value={effectiveLogic} onChange={(_, nVal) => handleChangeLogic(nVal)} />\r\n }\r\n\r\n const getMaxReachedText = () => {\r\n if (!params.maxValueCount) return ''\r\n if (isMaxReached) {\r\n return `Maximum ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} selected (limit reached)`\r\n } else {\r\n return `Up to ${params.maxValueCount} value${params.maxValueCount > 1 ? 's' : ''} can be selected`\r\n }\r\n }\r\n\r\n const rootClasses: string[] = []\r\n if (props.isLoading || isFetchLoading) rootClasses.push('disabled')\r\n\r\n return (\r\n <RootStyled className={rootClasses.join(' ')} noValidate onSubmit={handleSubmitForm}>\r\n <PopperContent\r\n title={`Filter by ${label}`}\r\n onClose={props.onClose}\r\n slots={{\r\n beforeTitle: <ButtonBack size='small' onClick={props.onBack} />,\r\n afterTitle: renderAfterTitle()\r\n }}\r\n >\r\n <PopperBody>\r\n {mergedConfig.description && (\r\n <Typography variant='caption' color='text.secondary' sx={{ mb: 1, display: 'block' }}>\r\n {mergedConfig.description}\r\n </Typography>\r\n )}\r\n {params.maxValueCount != null && (\r\n <Typography variant='caption' color={isMaxReached ? 'warning.main' : 'text.secondary'} sx={{ mb: 0.5, display: 'block' }}>\r\n {getMaxReachedText()}\r\n </Typography>\r\n )}\r\n <ChipViewers\r\n sx={{ mb: 1, borderBottom: 'none!important' }}\r\n label='Applied'\r\n placement='horizontal'\r\n enableMinimalesticView\r\n value={filterViewerValue}\r\n onRemove={props.onRemove}\r\n />\r\n {effectiveOptions.length === 0 && isFetchLoading && (\r\n <Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>\r\n <CircularProgress size={20} />\r\n </Box>\r\n )}\r\n {effectiveOptions.length === 0 && !isFetchLoading && (\r\n <Typography variant='body2' color='text.secondary' sx={{ mt: 2 }}>\r\n No options available\r\n </Typography>\r\n )}\r\n <RadioGroup\r\n sx={{ mx: -1 }}\r\n name={mergedConfig.field.toString()}\r\n value={selectedValue ?? ''}\r\n onChange={(e) => setSelectedValue(e.target.value as TFieldValid)}\r\n className={errorResult.error ? 'error' : ''}\r\n >\r\n {effectiveOptions.map((x, i) => {\r\n const isSelected = filterViewerValue.items.some((item) => item.value === x.value)\r\n const disabled = isSelected || isMaxReached\r\n return (\r\n <FormControlLabel\r\n disabled={disabled}\r\n key={x.value.toString() + i}\r\n value={x.value}\r\n control={<Radio size='small' />}\r\n label={<Typography variant='body2'>{x.label ?? x.value}</Typography>}\r\n />\r\n )\r\n })}\r\n </RadioGroup>\r\n {errorResult.error && (\r\n <Typography variant='caption' color='error' sx={{ mt: 0.5 }}>\r\n {errorResult.message}\r\n </Typography>\r\n )}\r\n </PopperBody>\r\n <PopperFooter>\r\n <Button size='small' color='error' variant='text' disabled={!value.values || value.values.length === 0} onClick={handleClearAll}>\r\n Clear All\r\n </Button>\r\n <Box sx={{ flex: 1 }} />\r\n <Button size='small' color='inherit' variant='text' onClick={props.onClose}>\r\n Cancel\r\n </Button>\r\n <Button size='small' type='submit' color='primary' variant='contained' disabled={isApplyDisabled}>\r\n Apply\r\n </Button>\r\n </PopperFooter>\r\n </PopperContent>\r\n </RootStyled>\r\n )\r\n }\r\n\r\n return FormFieldSelect\r\n}\r\n\r\nexport default createFormFieldSelect\r\n\r\nconst RootStyled = styled('form')({\r\n position: 'relative',\r\n '&::after': {\r\n content: '\"\"',\r\n display: 'block',\r\n position: 'absolute',\r\n inset: 0, // top: 0, left: 0, right: 0, bottom: 0\r\n backgroundColor: 'rgba(0, 0, 0, 0.12)',\r\n filter: 'blur(2px)',\r\n zIndex: -1,\r\n opacity: 0,\r\n transition: 'opacity 0.3s',\r\n visibility: 'hidden'\r\n },\r\n '&.disabled': {\r\n pointerEvents: 'none',\r\n '&::after': {\r\n zIndex: 1,\r\n opacity: 1,\r\n visibility: 'visible'\r\n }\r\n },\r\n [`.${radioGroupClasses.root}`]: {\r\n '&.error .MuiRadio-root': { color: '#d32f2f' },\r\n '.MuiFormControlLabel-root': { margin: 0 },\r\n '.MuiFormControlLabel-root:hover': { backgroundColor: 'rgba(25, 118, 210, 0.04)' }\r\n }\r\n})\r\n"],"names":["createFormFieldSelect","params","ChipViewers","createChipViewers","options","props","_mergedConfig$default","_params$forceLogic","_mergedConfig$label","mergedConfig","useMemo","Object","assign","currentConfig","config","_props$value","value","values","logic","defaultLogic","_useState","useState","_useState2","_slicedToArray","filterLogic","setFilterLogic","effectiveLogic","forceLogic","_useState3","_useState4","selectedValue","setSelectedValue","_useState5","_useState6","fetchedOptions","setFetchedOptions","_useState7","_useState8","isFetchLoading","setIsFetchLoading","useEffect","fetchOptions","controller","AbortController","signal","then","err","name","console","error","abort","effectiveOptions","hasLogicChange","hasDataChange","isApplyDisabled","label","field","toString","_useState9","_useState0","errorData","setErrorData","handleSubmit","newValue","onSubmit","errorResult","getErrorMessage","filterViewerValue","items","Array","isArray","map","v","_effectiveOptions$fin","find","o","isMaxReached","maxValueCount","length","rootClasses","isLoading","push","_jsx","RootStyled","className","join","noValidate","event","_props$validator","preventDefault","obj","_defineProperty","validator","run","keys","children","_jsxs","PopperContent","title","concat","onClose","slots","beforeTitle","ButtonBack","size","onClick","onBack","afterTitle","singleValue","ChipDark","sx","ml","FilterLogicToggle","onChange","_","nVal","PopperBody","description","Typography","variant","color","mb","display","borderBottom","placement","enableMinimalesticView","onRemove","Box","justifyContent","mt","CircularProgress","RadioGroup","mx","e","target","x","i","_x$label","isSelected","some","item","FormControlLabel","disabled","control","Radio","message","PopperFooter","Button","_props$onRemoveField","_params$config","onRemoveField","call","closeAfterClear","flex","type","styled","position","content","inset","backgroundColor","filter","zIndex","opacity","transition","visibility","pointerEvents","radioGroupClasses","root","margin"],"mappings":"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"}
|
|
@@ -10,7 +10,9 @@ export interface IFormFieldSelectMultipleParam<T> {
|
|
|
10
10
|
/** Optional configuration for the form field */
|
|
11
11
|
config?: IFieldMenuConfig<T>;
|
|
12
12
|
/** List of options for the select field */
|
|
13
|
-
options
|
|
13
|
+
options?: IFieldSelectOption[];
|
|
14
|
+
/** Function to fetch options asynchronously */
|
|
15
|
+
fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>;
|
|
14
16
|
/** If true, disables the field after submission. @default false */
|
|
15
17
|
disabledAfterSubmit?: boolean;
|
|
16
18
|
/** Force a fixed logic value, hiding the logic toggle */
|
|
@@ -14,7 +14,9 @@ export interface IFormFieldSelectParams<T> {
|
|
|
14
14
|
/** Optional configuration for the form field */
|
|
15
15
|
config?: IFieldMenuConfig<T>;
|
|
16
16
|
/** List of options for the select field */
|
|
17
|
-
options
|
|
17
|
+
options?: IFieldSelectOption[];
|
|
18
|
+
/** Function to fetch options asynchronously based on user input */
|
|
19
|
+
fetchOptions?: (signal?: AbortSignal) => Promise<IFieldSelectOption[]>;
|
|
18
20
|
/** Force a specific logic (and/or) for this field, overriding the default or user-selected logic */
|
|
19
21
|
forceLogic?: TLogic;
|
|
20
22
|
/** Maximum number of values that can be selected for this field */
|