@shefing/quickfilter 1.0.78 → 1.0.84

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.
@@ -1 +1 @@
1
- {"version":3,"file":"QuickFilter.d.ts","sourceRoot":"","sources":["../src/QuickFilter.tsx"],"names":[],"mappings":"AAyGA,QAAA,MAAM,WAAW,0BAGd;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,EAAE,CAAA;CAChF,gCAiTA,CAAA;AAED,eAAe,WAAW,CAAA"}
1
+ {"version":3,"file":"QuickFilter.d.ts","sourceRoot":"","sources":["../src/QuickFilter.tsx"],"names":[],"mappings":"AA2GA,QAAA,MAAM,WAAW,0BAGd;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,EAAE,CAAC;CACjF,gCAsTA,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -111,7 +111,12 @@ const QuickFilter = ({ slug, filterList })=>{
111
111
  });
112
112
  const sortedFields = flattenedFieldConfigs.map(({ field })=>{
113
113
  const fieldName = typeof field === 'string' ? field : field.name;
114
- return simplifiedFields.find((f)=>f.name === fieldName);
114
+ return simplifiedFields.find((f)=>{
115
+ if (typeof f.virtual === 'string') {
116
+ return f.virtual === fieldName;
117
+ }
118
+ return f.name === fieldName;
119
+ });
115
120
  }).filter((f)=>!!f);
116
121
  setFields(sortedFields);
117
122
  setFilterRows(groupFiltersByRow(sortedFields));
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/QuickFilter.tsx"],"sourcesContent":["'use client'\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useConfig, useListQuery, useTranslation } from '@payloadcms/ui'\nimport type { ClientField, FieldAffectingData, ListQuery, OptionObject, SelectField } from 'payload'\nimport { getTranslation } from '@payloadcms/translations'\nimport FilterField from './FilterField'\nimport { getLabel, SupportedLocale } from './labels'\nimport type {\n DateFilterValue,\n FilterDetaild,\n FilterRow,\n SelectFilterValue,\n} from './filters/types/filters-type'\nimport { groupFiltersByRow } from './filters/utils/layout-helpers'\nimport { ChevronDown, ChevronUp, Filter, RefreshCw, X } from 'lucide-react'\nimport { isEqual } from 'lodash'\nimport { getDateFilterOptions } from './filters/constants/date-filter-options'\nimport { Button } from './ui/button'\nimport {\n buildQuickFilterConditions,\n parseWhereClauseToFilterValues,\n} from './lib/utils'\n\n// Helper function to get localized label\nconst getLocalizedLabel = (label: any, locale: SupportedLocale): string => {\n if (typeof label === 'object' && label !== null) {\n return label[locale] || label['en'] || Object.values(label)[0] || ''\n }\n return label || ''\n}\n\n// Recursive function to find fields by name\nfunction findFieldsByName(fields: ClientField[], fieldNames: string[]): ClientField[] {\n const results: ClientField[] = []\n function recursiveSearch(currentFields: ClientField[]) {\n const filteredFields = currentFields.filter(\n (field) =>\n ('name' in field && fieldNames.includes(field.name as string)) ||\n ('virtual' in field &&\n fieldNames.includes(field.virtual as string)),\n )\n results.push(...filteredFields)\n currentFields.forEach((item) => {\n if (\n (item.type === 'array' || item.type === 'row' || item.type === 'collapsible') &&\n 'fields' in item &&\n Array.isArray(item.fields)\n ) {\n recursiveSearch(item.fields)\n } else if (item.type === 'tabs' && Array.isArray(item.tabs)) {\n item.tabs.forEach((tab) => {\n if ('fields' in tab && Array.isArray(tab.fields)) {\n recursiveSearch(tab.fields)\n }\n })\n } else if (item.type === 'blocks' && Array.isArray(item.blocks)) {\n item.blocks.forEach((block) => {\n if ('fields' in block && Array.isArray(block.fields)) {\n recursiveSearch(block.fields)\n }\n })\n }\n })\n }\n recursiveSearch(fields)\n return results\n}\n\n// Helper function to remove quick filter conditions from a 'where' clause\nconst cleanWhereClause = (clause: any, fieldsToClean: Set<string>): any => {\n if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {\n return clause\n }\n\n const newClause: Record<string, any> = {}\n\n for (const key in clause) {\n if (key === 'and' || key === 'or') {\n const cleanedSubClauses = clause[key]\n .map((subClause: any) => cleanWhereClause(subClause, fieldsToClean))\n .filter(Boolean)\n\n if (cleanedSubClauses.length > 0) {\n newClause[key] = cleanedSubClauses\n }\n } else if (!fieldsToClean.has(key)) {\n newClause[key] = clause[key]\n }\n }\n\n if (Object.keys(newClause).length === 0) {\n return null\n }\n\n if (newClause.and?.length === 1 && Object.keys(newClause).length === 1) {\n return newClause.and[0]\n }\n if (newClause.or?.length === 1 && Object.keys(newClause).length === 1) {\n return newClause.or[0]\n }\n\n return newClause\n}\n\nconst QuickFilter = ({\n slug,\n filterList,\n}: {\n slug: string\n filterList: (string | { name: string; width: string; virtualName: string })[][]\n}) => {\n const [fields, setFields] = useState<FilterDetaild[]>([])\n const [filterRows, setFilterRows] = useState<FilterRow[]>([])\n const [showFilters, setShowFilters] = useState(false)\n const { refineListData, query } = useListQuery()\n const { getEntityConfig } = useConfig()\n const { i18n } = useTranslation()\n const locale = i18n.language as SupportedLocale\n\n const [filterValues, setFilterValues] = useState<Record<string, any>>({})\n\n // Build the list of filter fields from config\n useEffect(() => {\n const collection = getEntityConfig({ collectionSlug: slug })\n const flattenedFieldConfigs = filterList.flatMap((row, rowIndex) =>\n row.map((field, fieldIndex) => ({\n field,\n rowIndex,\n fieldIndex,\n })),\n )\n const fieldNames = flattenedFieldConfigs.map(({ field }) =>\n typeof field === 'string' ? field : field.virtualName ? field.virtualName : field.name,\n )\n\n const matchedFields = findFieldsByName(collection?.fields || [], fieldNames)\n const simplifiedFields: FilterDetaild[] = matchedFields.map((field) => {\n const label = (field as FieldAffectingData).label\n const translatedLabel = getTranslation(label as string, i18n)\n const fieldName = (field as FieldAffectingData).name as string\n const fieldConfig = flattenedFieldConfigs.find(({ field: f }) =>\n typeof f === 'string' ? f === fieldName : f.name === fieldName,\n )\n const virtualFieldName = 'virtual' in field ? (field.virtual as string | boolean) : undefined\n return {\n name: fieldName || (virtualFieldName as string),\n label: translatedLabel as string,\n type: field.type,\n options: (field as SelectField).options as OptionObject[],\n row: fieldConfig ? fieldConfig.rowIndex : 0,\n virtual: virtualFieldName,\n width:\n typeof fieldConfig?.field === 'object' && 'width' in fieldConfig.field\n ? fieldConfig.field.width\n : undefined,\n }\n })\n const sortedFields = flattenedFieldConfigs\n .map(({ field }) => {\n const fieldName = typeof field === 'string' ? field : field.name\n return simplifiedFields.find((f) => f.name === fieldName)\n })\n .filter((f): f is FilterDetaild => !!f)\n setFields(sortedFields)\n setFilterRows(groupFiltersByRow(sortedFields))\n }, [slug, filterList, getEntityConfig, i18n])\n // Sync from URL (query.where) into internal state\n useEffect(() => {\n if (fields.length === 0) return\n const valuesFromQuery: Record<string, any> = parseWhereClauseToFilterValues(\n query.where,\n fields,\n locale,\n )\n if (!isEqual(filterValues, valuesFromQuery)) {\n // Lock to prevent feedback loop when internal state changes\n setFilterValues(valuesFromQuery)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [query.where, fields])\n\n // Sync internal state (filterValues) back into the URL\n useEffect(() => {\n if (fields.length === 0) return\n const valuesFromQuery: Record<string, any> = parseWhereClauseToFilterValues(\n query.where,\n fields,\n locale,\n )\n if (Object.keys(filterValues).length == 0 && !query.where) {\n }\n if (isEqual(filterValues, valuesFromQuery)) {\n return\n }\n const quickFilterConditions = buildQuickFilterConditions(filterValues, fields, locale)\n const quickFilterFieldNames = new Set(\n fields.map((f) => {\n let name = f.name\n if (typeof f.virtual === 'string') {\n name = f.virtual\n }\n return name\n }),\n )\n const otherFilters = cleanWhereClause(query.where, quickFilterFieldNames)\n\n const allConditions = [...quickFilterConditions]\n if (otherFilters) {\n if (otherFilters.and && Array.isArray(otherFilters.and)) {\n allConditions.push(...otherFilters.and)\n } else if (Object.keys(otherFilters).length > 0) {\n allConditions.push(otherFilters)\n }\n }\n\n let newWhere: Record<string, any> = {}\n if (allConditions.length > 1) {\n newWhere = { and: allConditions }\n } else if (allConditions.length === 1) {\n newWhere = allConditions[0]\n }\n\n // Only update if the query has actually changed to avoid unnecessary updates\n if (!(isEqual(newWhere, query.where) || (Object.keys(newWhere).length == 0 && !query.where))) {\n const refinedData = {\n where: newWhere,\n page: 1,\n } as ListQuery\n\n refineListData(refinedData).then((r) => {\n console.log('Query refreshed', refinedData)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filterValues])\n\n // Updates only the internal state\n const handleFilterChange = useCallback((fieldName: string, value: any) => {\n setFilterValues((prev) => {\n const newValues = { ...prev }\n if (\n value === undefined ||\n value === null ||\n value === 'indeterminate' ||\n (value && value.type === 'none')\n ) {\n delete newValues[fieldName]\n } else {\n newValues[fieldName] = value\n }\n return newValues\n })\n }, [])\n\n // This function remains largely the same.\n const getActiveFiltersDetails = () => {\n const activeFilters: string[] = []\n const locale = i18n.language as SupportedLocale\n Object.entries(filterValues).forEach(([fieldName, value]) => {\n const field = fields.find((f) => {\n let name = f.name\n if (typeof f.virtual === 'string') {\n name = f.virtual\n }\n return name === fieldName\n })\n if (!field) return\n\n switch (field.type) {\n case 'date':\n if (value !== undefined) {\n const dateValue = value as DateFilterValue\n let dateDescription = ''\n\n if (dateValue.type === 'predefined' && dateValue.predefinedValue) {\n const { pastOptions, futureOptions } = getDateFilterOptions(locale)\n const allOptions = [...pastOptions, ...futureOptions]\n const option = allOptions.find((opt) => opt.value === dateValue.predefinedValue)\n dateDescription = option ? option.label : getLabel('custom', locale)\n } else if (dateValue.type === 'custom' || dateValue.customRange) {\n dateDescription = getLabel('custom', locale)\n }\n\n if (dateDescription) {\n activeFilters.push(`${field.label} (${dateDescription})`)\n }\n }\n break\n case 'select': {\n const selectValue = value as SelectFilterValue\n if (selectValue && selectValue.selectedValues && selectValue.selectedValues.length > 0) {\n const totalOptions = field.options?.length || 0\n\n if (selectValue.selectedValues.length === totalOptions) {\n activeFilters.push(`${field.label} (${getLabel('all', locale)})`)\n } else if (selectValue.selectedValues.length === 1) {\n // Show the actual option name when only one is selected\n const selectedOption = field.options?.find(\n (opt: any) => opt.value === selectValue.selectedValues[0],\n )\n const optionLabel = selectedOption\n ? getLocalizedLabel(selectedOption.label, locale)\n : selectValue.selectedValues[0]\n activeFilters.push(`${field.label} (${optionLabel})`)\n } else {\n // Show count for multiple selections\n activeFilters.push(`${field.label} (${selectValue.selectedValues.length})`)\n }\n }\n break\n }\n case 'checkbox':\n if (value !== 'indeterminate') {\n const checkboxValue =\n value === 'checked' ? getLabel('yes', locale) : getLabel('no', locale)\n activeFilters.push(`${field.label} (${checkboxValue})`)\n }\n break\n }\n })\n\n return activeFilters\n }\n\n const clearAllFilters = () => {\n setFilterValues({})\n }\n\n const refreshFilters = () => {\n refineListData(query)\n }\n\n const memoizedFilterRows = useMemo(() => {\n return filterRows.map((row) => (\n <div key={row.rowNumber}>\n <div className=\"flex flex-wrap gap-6 mb-4\">\n {row.filters.map((field) => {\n let fieldName = field.name\n if (typeof field.virtual === 'string') {\n fieldName = field.virtual\n }\n return (\n <FilterField\n key={field.name}\n field={field}\n onFilterChange={handleFilterChange}\n value={filterValues[fieldName]}\n />\n )\n })}\n </div>\n </div>\n ))\n }, [filterRows, handleFilterChange, filterValues])\n\n const toggleFilters = () => {\n setShowFilters((prev) => !prev)\n }\n\n const activeFiltersDetails = getActiveFiltersDetails()\n const hasActiveFilters = activeFiltersDetails.length > 0\n\n if (!fields.length) return null\n\n return (\n <div className=\"filter-container useTw\">\n <div style={{ position: 'relative', top: '-24px', height: '0px' }}>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={toggleFilters}\n className={`flex items-center gap-2 bg-background border-muted-muted hover:bg-muted ${\n hasActiveFilters ? 'w-auto min-w-fit' : ''\n }`}\n >\n <Filter className={`h-4 w-4 ${hasActiveFilters ? 'fill-current' : ''}`} />\n\n {hasActiveFilters ? (\n <>\n <span className=\"text-sm truncate\">\n <strong>\n {`${activeFiltersDetails.length === 1 ? getLabel('activeFilterSingular', locale) : getLabel('activeFilterPlural', locale)}: `}\n </strong>{' '}\n {activeFiltersDetails.join(' • ')}\n </span>\n\n <span\n onClick={(e) => {\n e.stopPropagation()\n clearAllFilters()\n }}\n className=\"ml-1 p-0.5 hover:bg-muted rounded-sm transition-colors flex-shrink-0\"\n >\n <X className=\"h-3 w-3 text-gray-500\" />\n </span>\n <span\n onClick={(e) => {\n e.stopPropagation()\n refreshFilters()\n }}\n className=\"ml-1 p-0.5 hover:bg-muted rounded-sm transition-colors flex-shrink-0\"\n >\n <RefreshCw className=\"h-3 w-3 text-gray-500\" />\n </span>\n </>\n ) : (\n <span className=\"text-sm truncate\">{getLabel('quickFilters', locale)}</span>\n )}\n\n {showFilters ? <ChevronUp className=\"h-4 w-4\" /> : <ChevronDown className=\"h-4 w-4\" />}\n </Button>\n </div>\n {showFilters && <div className={'p-4 pb-2 bg-muted'}>{memoizedFilterRows}</div>}\n </div>\n )\n}\n\nexport default QuickFilter\n"],"names":["useCallback","useEffect","useMemo","useState","useConfig","useListQuery","useTranslation","getTranslation","FilterField","getLabel","groupFiltersByRow","ChevronDown","ChevronUp","Filter","RefreshCw","X","isEqual","getDateFilterOptions","Button","buildQuickFilterConditions","parseWhereClauseToFilterValues","getLocalizedLabel","label","locale","Object","values","findFieldsByName","fields","fieldNames","results","recursiveSearch","currentFields","filteredFields","filter","field","includes","name","virtual","push","forEach","item","type","Array","isArray","tabs","tab","blocks","block","cleanWhereClause","clause","fieldsToClean","newClause","key","cleanedSubClauses","map","subClause","Boolean","length","has","keys","and","or","QuickFilter","slug","filterList","setFields","filterRows","setFilterRows","showFilters","setShowFilters","refineListData","query","getEntityConfig","i18n","language","filterValues","setFilterValues","collection","collectionSlug","flattenedFieldConfigs","flatMap","row","rowIndex","fieldIndex","virtualName","matchedFields","simplifiedFields","translatedLabel","fieldName","fieldConfig","find","f","virtualFieldName","undefined","options","width","sortedFields","valuesFromQuery","where","quickFilterConditions","quickFilterFieldNames","Set","otherFilters","allConditions","newWhere","refinedData","page","then","r","console","log","handleFilterChange","value","prev","newValues","getActiveFiltersDetails","activeFilters","entries","dateValue","dateDescription","predefinedValue","pastOptions","futureOptions","allOptions","option","opt","customRange","selectValue","selectedValues","totalOptions","selectedOption","optionLabel","checkboxValue","clearAllFilters","refreshFilters","memoizedFilterRows","div","className","filters","onFilterChange","rowNumber","toggleFilters","activeFiltersDetails","hasActiveFilters","style","position","top","height","variant","size","onClick","span","strong","join","e","stopPropagation"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/QuickFilter.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useConfig, useListQuery, useTranslation } from '@payloadcms/ui';\nimport type {\n ClientField,\n FieldAffectingData,\n ListQuery,\n OptionObject,\n SelectField,\n} from 'payload';\nimport { getTranslation } from '@payloadcms/translations';\nimport FilterField from './FilterField';\nimport { getLabel, SupportedLocale } from './labels';\nimport type {\n DateFilterValue,\n FilterDetaild,\n FilterRow,\n SelectFilterValue,\n} from './filters/types/filters-type';\nimport { groupFiltersByRow } from './filters/utils/layout-helpers';\nimport { ChevronDown, ChevronUp, Filter, RefreshCw, X } from 'lucide-react';\nimport { isEqual } from 'lodash';\nimport { getDateFilterOptions } from './filters/constants/date-filter-options';\nimport { Button } from './ui/button';\nimport { buildQuickFilterConditions, parseWhereClauseToFilterValues } from './lib/utils';\n\n// Helper function to get localized label\nconst getLocalizedLabel = (label: any, locale: SupportedLocale): string => {\n if (typeof label === 'object' && label !== null) {\n return label[locale] || label['en'] || Object.values(label)[0] || '';\n }\n return label || '';\n};\n\n// Recursive function to find fields by name\nfunction findFieldsByName(fields: ClientField[], fieldNames: string[]): ClientField[] {\n const results: ClientField[] = [];\n function recursiveSearch(currentFields: ClientField[]) {\n const filteredFields = currentFields.filter(\n (field) =>\n ('name' in field && fieldNames.includes(field.name as string)) ||\n ('virtual' in field && fieldNames.includes(field.virtual as string)),\n );\n results.push(...filteredFields);\n currentFields.forEach((item) => {\n if (\n (item.type === 'array' || item.type === 'row' || item.type === 'collapsible') &&\n 'fields' in item &&\n Array.isArray(item.fields)\n ) {\n recursiveSearch(item.fields);\n } else if (item.type === 'tabs' && Array.isArray(item.tabs)) {\n item.tabs.forEach((tab) => {\n if ('fields' in tab && Array.isArray(tab.fields)) {\n recursiveSearch(tab.fields);\n }\n });\n } else if (item.type === 'blocks' && Array.isArray(item.blocks)) {\n item.blocks.forEach((block) => {\n if ('fields' in block && Array.isArray(block.fields)) {\n recursiveSearch(block.fields);\n }\n });\n }\n });\n }\n recursiveSearch(fields);\n return results;\n}\n\n// Helper function to remove quick filter conditions from a 'where' clause\nconst cleanWhereClause = (clause: any, fieldsToClean: Set<string>): any => {\n if (!clause || typeof clause !== 'object' || Array.isArray(clause)) {\n return clause;\n }\n\n const newClause: Record<string, any> = {};\n\n for (const key in clause) {\n if (key === 'and' || key === 'or') {\n const cleanedSubClauses = clause[key]\n .map((subClause: any) => cleanWhereClause(subClause, fieldsToClean))\n .filter(Boolean);\n\n if (cleanedSubClauses.length > 0) {\n newClause[key] = cleanedSubClauses;\n }\n } else if (!fieldsToClean.has(key)) {\n newClause[key] = clause[key];\n }\n }\n\n if (Object.keys(newClause).length === 0) {\n return null;\n }\n\n if (newClause.and?.length === 1 && Object.keys(newClause).length === 1) {\n return newClause.and[0];\n }\n if (newClause.or?.length === 1 && Object.keys(newClause).length === 1) {\n return newClause.or[0];\n }\n\n return newClause;\n};\n\nconst QuickFilter = ({\n slug,\n filterList,\n}: {\n slug: string;\n filterList: (string | { name: string; width: string; virtualName: string })[][];\n}) => {\n const [fields, setFields] = useState<FilterDetaild[]>([]);\n const [filterRows, setFilterRows] = useState<FilterRow[]>([]);\n const [showFilters, setShowFilters] = useState(false);\n const { refineListData, query } = useListQuery();\n const { getEntityConfig } = useConfig();\n const { i18n } = useTranslation();\n const locale = i18n.language as SupportedLocale;\n\n const [filterValues, setFilterValues] = useState<Record<string, any>>({});\n\n // Build the list of filter fields from config\n useEffect(() => {\n const collection = getEntityConfig({ collectionSlug: slug });\n const flattenedFieldConfigs = filterList.flatMap((row, rowIndex) =>\n row.map((field, fieldIndex) => ({\n field,\n rowIndex,\n fieldIndex,\n })),\n );\n const fieldNames = flattenedFieldConfigs.map(({ field }) =>\n typeof field === 'string' ? field : field.virtualName ? field.virtualName : field.name,\n );\n\n const matchedFields = findFieldsByName(collection?.fields || [], fieldNames);\n const simplifiedFields: FilterDetaild[] = matchedFields.map((field) => {\n const label = (field as FieldAffectingData).label;\n const translatedLabel = getTranslation(label as string, i18n);\n const fieldName = (field as FieldAffectingData).name as string;\n const fieldConfig = flattenedFieldConfigs.find(({ field: f }) =>\n typeof f === 'string' ? f === fieldName : f.name === fieldName,\n );\n const virtualFieldName = 'virtual' in field ? (field.virtual as string | boolean) : undefined;\n return {\n name: fieldName || (virtualFieldName as string),\n label: translatedLabel as string,\n type: field.type,\n options: (field as SelectField).options as OptionObject[],\n row: fieldConfig ? fieldConfig.rowIndex : 0,\n virtual: virtualFieldName,\n width:\n typeof fieldConfig?.field === 'object' && 'width' in fieldConfig.field\n ? fieldConfig.field.width\n : undefined,\n };\n });\n const sortedFields = flattenedFieldConfigs\n .map(({ field }) => {\n const fieldName = typeof field === 'string' ? field : field.name;\n return simplifiedFields.find((f) => {\n if (typeof f.virtual === 'string') {\n return f.virtual === fieldName;\n }\n return f.name === fieldName;\n });\n })\n .filter((f): f is FilterDetaild => !!f);\n setFields(sortedFields);\n setFilterRows(groupFiltersByRow(sortedFields));\n }, [slug, filterList, getEntityConfig, i18n]);\n // Sync from URL (query.where) into internal state\n useEffect(() => {\n if (fields.length === 0) return;\n const valuesFromQuery: Record<string, any> = parseWhereClauseToFilterValues(\n query.where,\n fields,\n locale,\n );\n if (!isEqual(filterValues, valuesFromQuery)) {\n // Lock to prevent feedback loop when internal state changes\n setFilterValues(valuesFromQuery);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [query.where, fields]);\n\n // Sync internal state (filterValues) back into the URL\n useEffect(() => {\n if (fields.length === 0) return;\n const valuesFromQuery: Record<string, any> = parseWhereClauseToFilterValues(\n query.where,\n fields,\n locale,\n );\n if (Object.keys(filterValues).length == 0 && !query.where) {\n }\n if (isEqual(filterValues, valuesFromQuery)) {\n return;\n }\n const quickFilterConditions = buildQuickFilterConditions(filterValues, fields, locale);\n const quickFilterFieldNames = new Set(\n fields.map((f) => {\n let name = f.name;\n if (typeof f.virtual === 'string') {\n name = f.virtual;\n }\n return name;\n }),\n );\n const otherFilters = cleanWhereClause(query.where, quickFilterFieldNames);\n\n const allConditions = [...quickFilterConditions];\n if (otherFilters) {\n if (otherFilters.and && Array.isArray(otherFilters.and)) {\n allConditions.push(...otherFilters.and);\n } else if (Object.keys(otherFilters).length > 0) {\n allConditions.push(otherFilters);\n }\n }\n\n let newWhere: Record<string, any> = {};\n if (allConditions.length > 1) {\n newWhere = { and: allConditions };\n } else if (allConditions.length === 1) {\n newWhere = allConditions[0];\n }\n\n // Only update if the query has actually changed to avoid unnecessary updates\n if (!(isEqual(newWhere, query.where) || (Object.keys(newWhere).length == 0 && !query.where))) {\n const refinedData = {\n where: newWhere,\n page: 1,\n } as ListQuery;\n\n refineListData(refinedData).then((r) => {\n console.log('Query refreshed', refinedData);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filterValues]);\n\n // Updates only the internal state\n const handleFilterChange = useCallback((fieldName: string, value: any) => {\n setFilterValues((prev) => {\n const newValues = { ...prev };\n if (\n value === undefined ||\n value === null ||\n value === 'indeterminate' ||\n (value && value.type === 'none')\n ) {\n delete newValues[fieldName];\n } else {\n newValues[fieldName] = value;\n }\n return newValues;\n });\n }, []);\n\n // This function remains largely the same.\n const getActiveFiltersDetails = () => {\n const activeFilters: string[] = [];\n const locale = i18n.language as SupportedLocale;\n Object.entries(filterValues).forEach(([fieldName, value]) => {\n const field = fields.find((f) => {\n let name = f.name;\n if (typeof f.virtual === 'string') {\n name = f.virtual;\n }\n return name === fieldName;\n });\n if (!field) return;\n\n switch (field.type) {\n case 'date':\n if (value !== undefined) {\n const dateValue = value as DateFilterValue;\n let dateDescription = '';\n\n if (dateValue.type === 'predefined' && dateValue.predefinedValue) {\n const { pastOptions, futureOptions } = getDateFilterOptions(locale);\n const allOptions = [...pastOptions, ...futureOptions];\n const option = allOptions.find((opt) => opt.value === dateValue.predefinedValue);\n dateDescription = option ? option.label : getLabel('custom', locale);\n } else if (dateValue.type === 'custom' || dateValue.customRange) {\n dateDescription = getLabel('custom', locale);\n }\n\n if (dateDescription) {\n activeFilters.push(`${field.label} (${dateDescription})`);\n }\n }\n break;\n case 'select': {\n const selectValue = value as SelectFilterValue;\n if (selectValue && selectValue.selectedValues && selectValue.selectedValues.length > 0) {\n const totalOptions = field.options?.length || 0;\n\n if (selectValue.selectedValues.length === totalOptions) {\n activeFilters.push(`${field.label} (${getLabel('all', locale)})`);\n } else if (selectValue.selectedValues.length === 1) {\n // Show the actual option name when only one is selected\n const selectedOption = field.options?.find(\n (opt: any) => opt.value === selectValue.selectedValues[0],\n );\n const optionLabel = selectedOption\n ? getLocalizedLabel(selectedOption.label, locale)\n : selectValue.selectedValues[0];\n activeFilters.push(`${field.label} (${optionLabel})`);\n } else {\n // Show count for multiple selections\n activeFilters.push(`${field.label} (${selectValue.selectedValues.length})`);\n }\n }\n break;\n }\n case 'checkbox':\n if (value !== 'indeterminate') {\n const checkboxValue =\n value === 'checked' ? getLabel('yes', locale) : getLabel('no', locale);\n activeFilters.push(`${field.label} (${checkboxValue})`);\n }\n break;\n }\n });\n\n return activeFilters;\n };\n\n const clearAllFilters = () => {\n setFilterValues({});\n };\n\n const refreshFilters = () => {\n refineListData(query);\n };\n\n const memoizedFilterRows = useMemo(() => {\n return filterRows.map((row) => (\n <div key={row.rowNumber}>\n <div className='flex flex-wrap gap-6 mb-4'>\n {row.filters.map((field) => {\n let fieldName = field.name;\n if (typeof field.virtual === 'string') {\n fieldName = field.virtual;\n }\n return (\n <FilterField\n key={field.name}\n field={field}\n onFilterChange={handleFilterChange}\n value={filterValues[fieldName]}\n />\n );\n })}\n </div>\n </div>\n ));\n }, [filterRows, handleFilterChange, filterValues]);\n\n const toggleFilters = () => {\n setShowFilters((prev) => !prev);\n };\n\n const activeFiltersDetails = getActiveFiltersDetails();\n const hasActiveFilters = activeFiltersDetails.length > 0;\n\n if (!fields.length) return null;\n\n return (\n <div className='filter-container useTw'>\n <div style={{ position: 'relative', top: '-24px', height: '0px' }}>\n <Button\n variant='outline'\n size='sm'\n onClick={toggleFilters}\n className={`flex items-center gap-2 bg-background border-muted-muted hover:bg-muted ${\n hasActiveFilters ? 'w-auto min-w-fit' : ''\n }`}\n >\n <Filter className={`h-4 w-4 ${hasActiveFilters ? 'fill-current' : ''}`} />\n\n {hasActiveFilters ? (\n <>\n <span className='text-sm truncate'>\n <strong>\n {`${activeFiltersDetails.length === 1 ? getLabel('activeFilterSingular', locale) : getLabel('activeFilterPlural', locale)}: `}\n </strong>{' '}\n {activeFiltersDetails.join(' • ')}\n </span>\n\n <span\n onClick={(e) => {\n e.stopPropagation();\n clearAllFilters();\n }}\n className='ml-1 p-0.5 hover:bg-muted rounded-sm transition-colors flex-shrink-0'\n >\n <X className='h-3 w-3 text-gray-500' />\n </span>\n <span\n onClick={(e) => {\n e.stopPropagation();\n refreshFilters();\n }}\n className='ml-1 p-0.5 hover:bg-muted rounded-sm transition-colors flex-shrink-0'\n >\n <RefreshCw className='h-3 w-3 text-gray-500' />\n </span>\n </>\n ) : (\n <span className='text-sm truncate'>{getLabel('quickFilters', locale)}</span>\n )}\n\n {showFilters ? <ChevronUp className='h-4 w-4' /> : <ChevronDown className='h-4 w-4' />}\n </Button>\n </div>\n {showFilters && <div className={'p-4 pb-2 bg-muted'}>{memoizedFilterRows}</div>}\n </div>\n );\n};\n\nexport default QuickFilter;\n"],"names":["useCallback","useEffect","useMemo","useState","useConfig","useListQuery","useTranslation","getTranslation","FilterField","getLabel","groupFiltersByRow","ChevronDown","ChevronUp","Filter","RefreshCw","X","isEqual","getDateFilterOptions","Button","buildQuickFilterConditions","parseWhereClauseToFilterValues","getLocalizedLabel","label","locale","Object","values","findFieldsByName","fields","fieldNames","results","recursiveSearch","currentFields","filteredFields","filter","field","includes","name","virtual","push","forEach","item","type","Array","isArray","tabs","tab","blocks","block","cleanWhereClause","clause","fieldsToClean","newClause","key","cleanedSubClauses","map","subClause","Boolean","length","has","keys","and","or","QuickFilter","slug","filterList","setFields","filterRows","setFilterRows","showFilters","setShowFilters","refineListData","query","getEntityConfig","i18n","language","filterValues","setFilterValues","collection","collectionSlug","flattenedFieldConfigs","flatMap","row","rowIndex","fieldIndex","virtualName","matchedFields","simplifiedFields","translatedLabel","fieldName","fieldConfig","find","f","virtualFieldName","undefined","options","width","sortedFields","valuesFromQuery","where","quickFilterConditions","quickFilterFieldNames","Set","otherFilters","allConditions","newWhere","refinedData","page","then","r","console","log","handleFilterChange","value","prev","newValues","getActiveFiltersDetails","activeFilters","entries","dateValue","dateDescription","predefinedValue","pastOptions","futureOptions","allOptions","option","opt","customRange","selectValue","selectedValues","totalOptions","selectedOption","optionLabel","checkboxValue","clearAllFilters","refreshFilters","memoizedFilterRows","div","className","filters","onFilterChange","rowNumber","toggleFilters","activeFiltersDetails","hasActiveFilters","style","position","top","height","variant","size","onClick","span","strong","join","e","stopPropagation"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"date-filter.d.ts","sourceRoot":"","sources":["../../../src/filters/components/date-filter.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAa,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAW3E,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAyC,EACzC,SAAS,EACT,KAAK,GACN,EAAE,eAAe,+BAmVjB"}
1
+ {"version":3,"file":"date-filter.d.ts","sourceRoot":"","sources":["../../../src/filters/components/date-filter.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAa,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAW3E,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAyC,EACzC,SAAS,EACT,KAAK,GACN,EAAE,eAAe,+BAqVjB"}
@@ -24,17 +24,22 @@ export function DateFilter({ label, value, onChange, locale = {
24
24
  const [isOpen, setIsOpen] = useState(false);
25
25
  const [openFromCalendar, setOpenFromCalendar] = useState(false);
26
26
  const [openToCalendar, setOpenToCalendar] = useState(false);
27
+ const [isInitialized, setIsInitialized] = useState(false);
27
28
  const isRTL = locale.direction === 'rtl';
28
29
  const localeCode = locale.code;
29
30
  const { pastOptions, futureOptions } = getDateFilterOptions(localeCode);
30
- // Sync internal state with external value prop
31
+ // Initialize internal state only once on mount
31
32
  useEffect(()=>{
32
- setInternalValue(value);
33
- if (value?.type === 'custom' && value.customRange) {
34
- setCustomRange(value.customRange);
33
+ if (!isInitialized) {
34
+ setInternalValue(value);
35
+ if (value?.type === 'custom' && value.customRange) {
36
+ setCustomRange(value.customRange);
37
+ }
38
+ setIsInitialized(true);
35
39
  }
36
40
  }, [
37
- value
41
+ value,
42
+ isInitialized
38
43
  ]);
39
44
  const labels = {
40
45
  selectOption: getLabel('selectOption', localeCode),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/filters/components/date-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { CalendarIcon, ChevronDown, X } from 'lucide-react';\n\nimport { formatDate, getDateRangeForOption } from '../utils/date-helpers';\nimport { DateFilterValue, DateRange, Locale } from '../types/filters-type';\nimport { Button } from '../../ui/button';\nimport { cn } from '../../lib/utils';\nimport { Label } from '../../ui/label';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover';\nimport { Separator } from '../../ui/separator';\nimport { Calendar } from '../../ui/calendar';\nimport { getDateFilterOptions } from '../constants/date-filter-options';\nimport { SupportedLocale, getLabel } from '../../labels';\n\n\ninterface DateFilterProps {\n label?: string;\n value?: DateFilterValue;\n onChange: (value: DateFilterValue) => void;\n locale?: Locale;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function DateFilter({\n label,\n value,\n onChange,\n locale = { code: 'he', direction: 'rtl' },\n className,\n style,\n}: DateFilterProps) {\n const [internalValue, setInternalValue] = useState<DateFilterValue | undefined>(value);\n const [customRange, setCustomRange] = useState<DateRange>({ from: undefined, to: undefined });\n const [showCustom, setShowCustom] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [openFromCalendar, setOpenFromCalendar] = useState(false);\n const [openToCalendar, setOpenToCalendar] = useState(false);\n\n const isRTL = locale.direction === 'rtl';\n const localeCode = locale.code as SupportedLocale;\n const { pastOptions, futureOptions } = getDateFilterOptions(localeCode);\n\n // Sync internal state with external value prop\n useEffect(() => {\n setInternalValue(value);\n if (value?.type === 'custom' && value.customRange) {\n setCustomRange(value.customRange);\n }\n }, [value]);\n\n const labels = {\n selectOption: getLabel('selectOption', localeCode),\n from: getLabel('from', localeCode),\n to: getLabel('to', localeCode),\n selectDate: getLabel('selectDate', localeCode),\n past: getLabel('past', localeCode),\n future: getLabel('future', localeCode),\n presentFuture: getLabel('presentFuture', localeCode),\n custom: getLabel('customRange', localeCode),\n apply: getLabel('apply', localeCode),\n cancel: getLabel('cancel', localeCode),\n };\n\n const handlePredefinedSelect = (optionValue: string) => {\n setShowCustom(false);\n setIsOpen(false);\n\n const dateRange = getDateRangeForOption(optionValue, locale.code);\n const newValue: DateFilterValue = {\n type: 'predefined',\n predefinedValue: optionValue,\n customRange: { from: dateRange.from, to: dateRange.to },\n };\n\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleCustomSelect = () => {\n setShowCustom(true);\n };\n\n const handleCustomRangeChange = (newRange: DateRange) => {\n setCustomRange(newRange);\n };\n\n const handleApplyCustomRange = () => {\n const newValue: DateFilterValue = {\n type: 'custom',\n customRange,\n };\n\n setInternalValue(newValue);\n onChange(newValue);\n setIsOpen(false);\n setShowCustom(false);\n };\n\n const handleCancelCustomRange = () => {\n setIsOpen(false);\n setShowCustom(false);\n setCustomRange({ from: undefined, to: undefined });\n };\n\n const handleClearAll = () => {\n setInternalValue(undefined);\n setCustomRange({ from: undefined, to: undefined });\n setShowCustom(false);\n onChange({} as DateFilterValue);\n };\n\n const hasValue = () => {\n return (\n internalValue && (internalValue.type === 'predefined' || internalValue.type === 'custom')\n );\n };\n\n const getDisplayValue = () => {\n if (internalValue?.type === 'custom' && internalValue.customRange) {\n const { from, to } = internalValue.customRange;\n if (from && to) {\n return `${formatDate(from, 'dd/MM/yyyy')}-${formatDate(to, 'dd/MM/yyyy')}`;\n } else if (from) {\n return `${labels.from}:${formatDate(from, 'dd/MM/yyyy')}`;\n } else if (to) {\n return `${labels.to}:${formatDate(to, 'dd/MM/yyyy')}`;\n }\n return labels.custom;\n }\n\n if (internalValue?.type === 'predefined' && internalValue.predefinedValue) {\n const allOptions = [...pastOptions, ...futureOptions];\n const option = allOptions.find((opt) => opt.value === internalValue.predefinedValue);\n const dateRange = getDateRangeForOption(internalValue.predefinedValue, locale.code);\n return `${option?.label || internalValue.predefinedValue}${dateRange.description}`;\n }\n\n return labels.selectOption;\n };\n\n const formatDateRange = (description: string) => {\n // Check if description contains a date range (has \" - \" in it)\n if (description.includes(' - ') && isRTL) {\n // Split by \" - \" and reverse the order for RTL\n const parts = description.replace(/[()]/g, '').split(' - ');\n if (parts.length === 2) {\n return `(${parts[1]}-${parts[0]})`;\n }\n }\n return description;\n };\n\n const renderOptionWithDate = (option: { value: string; label: string }) => {\n const dateRange = getDateRangeForOption(option.value, locale.code);\n const formattedDescription = formatDateRange(dateRange.description);\n\n return (\n <Button\n key={option.value}\n variant='ghost'\n className={cn(\n ' w-full h-auto py-1 px-2 text-xs leading-tight justify-start',\n isRTL ? ' text-right' : ' text-left',\n internalValue?.predefinedValue === option.value && 'bg-accent',\n )}\n onClick={() => handlePredefinedSelect(option.value)}\n >\n <div className={cn('flex flex-col')}>\n <span className='font-medium'>{option.label}</span>\n <span className='text-[10px] text-muted-foreground' dir={locale.direction}>\n {formattedDescription}\n </span>\n </div>\n </Button>\n );\n };\n\n return (\n <div className={cn('useTw space-y-1', className)} dir={locale.direction} style={style}>\n {label && (\n <Label className={cn('useTw text-sm font-medium', isRTL && 'text-right block')}>\n {label}\n </Label>\n )}\n\n <div className='relative useTw'>\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n role='combobox'\n aria-expanded={isOpen}\n className='useTw w-full justify-between bg-background relative min-w-70 px-2'\n >\n <span className={`useTw truncate ${isRTL && 'text-right'}`}>{getDisplayValue()}</span>\n <ChevronDown className='useTw h-4 w-4 shrink-0 opacity-50' />\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-80 p-0'>\n <div className='p-4'>\n <div className='grid grid-cols-2 gap-4'>\n\n {/* Past Options - Right column */}\n <div className='space-y-1'>\n <div\n className={cn(\n 'text-sm font-semibold text-muted-foreground mb-2',\n isRTL && 'text-right',\n )}\n >\n {labels.past}\n </div>\n <div className='space-y-0.5'>\n {pastOptions.map((option) => (\n <div key={option.value}>{renderOptionWithDate(option)}</div>\n ))}\n </div>\n </div>\n {/* Future Options - Left column */}\n <div className='space-y-1'>\n <div\n className={cn(\n 'text-sm font-semibold text-muted-foreground mb-2',\n isRTL && 'text-right',\n )}\n >\n {labels.presentFuture}\n </div>\n <div className='space-y-0.5'>\n {futureOptions.map((option) => (\n <div key={option.value}>{renderOptionWithDate(option)}</div>\n ))}\n </div>\n </div>\n\n </div>\n\n <Separator className='my-4' />\n\n {/* Custom Option */}\n <div className='space-y-3'>\n <Button\n variant='ghost'\n className={cn(\n 'useTw w-full justify-start h-auto py-2 px-2',\n (showCustom || internalValue?.type === 'custom') && 'bg-accent',\n isRTL && 'justify-start text-right',\n )}\n onClick={handleCustomSelect}\n >\n {labels.custom}\n </Button>\n\n {/* Custom Date Range - appears next to custom label */}\n {showCustom && (\n <div className='space-y-3 pl-2'>\n <div className='grid grid-cols-1 gap-3'>\n {/* From Date */}\n <div className={cn('flex items-center gap-2')}>\n <Label className={cn('useTw text-xs w-[20%]', isRTL && 'text-right')}>\n {labels.from}\n </Label>\n <Popover open={openFromCalendar} onOpenChange={setOpenFromCalendar}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n className={cn(\n 'useTw w-[60%] justify-start text-left font-normal text-xs h-8 bg-background',\n !customRange.from && 'text-muted-foreground',\n )}\n >\n <CalendarIcon className='useTw mr-1 h-3 w-3' />\n <span dir={locale.direction}>\n {customRange.from\n ? formatDate(customRange.from, 'dd/MM/yyyy')\n : labels.selectDate}\n </span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-auto p-0' align='start'>\n <Calendar\n mode='single'\n selected={customRange.from}\n onSelect={(date) => {\n handleCustomRangeChange({ ...customRange, from: date });\n setOpenFromCalendar(false);\n }}\n initialFocus\n className='useTw'\n />\n </PopoverContent>\n </Popover>\n </div>\n\n {/* To Date */}\n <div className={cn('flex items-center gap-2')}>\n <Label className={cn('useTw text-xs w-[20%]', isRTL && 'text-right')}>\n {labels.to}\n </Label>\n <Popover open={openToCalendar} onOpenChange={setOpenToCalendar}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n className={cn(\n 'useTw w-[60%] justify-start text-left font-normal text-xs h-8 bg-background',\n !customRange.to && 'text-muted-foreground',\n )}\n >\n <CalendarIcon className='useTw mr-1 h-3 w-3' />\n <span dir={locale.direction}>\n {customRange.to\n ? formatDate(customRange.to, 'dd/MM/yyyy')\n : labels.selectDate}\n </span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-auto p-0' align='start'>\n <Calendar\n mode='single'\n selected={customRange.to}\n onSelect={(date) => {\n handleCustomRangeChange({ ...customRange, to: date });\n setOpenToCalendar(false);\n }}\n initialFocus\n className='useTw'\n />\n </PopoverContent>\n </Popover>\n </div>\n </div>\n\n {/* Action Buttons */}\n <div className='flex gap-2'>\n <Button\n onClick={handleApplyCustomRange}\n className='useTw flex-1 text-xs h-8'\n disabled={!customRange.from && !customRange.to}\n >\n {labels.apply}\n </Button>\n <Button\n onClick={handleCancelCustomRange}\n variant='outline'\n className='useTw flex-1 text-xs h-8 bg-transparent'\n >\n {labels.cancel}\n </Button>\n </div>\n </div>\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {hasValue() && (\n <button\n className={`useTw absolute ${isRTL ? 'left-8' : 'right-8'} top-1/2 -translate-y-1/2 h-4 w-4 p-0 hover:bg-muted rounded-sm flex items-center justify-center z-10 `}\n onClick={(e) => {\n e.stopPropagation();\n handleClearAll();\n }}\n >\n <X className='useTw h-3 w-3' />\n </button>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useEffect","useState","CalendarIcon","ChevronDown","X","formatDate","getDateRangeForOption","Button","cn","Label","Popover","PopoverContent","PopoverTrigger","Separator","Calendar","getDateFilterOptions","getLabel","DateFilter","label","value","onChange","locale","code","direction","className","style","internalValue","setInternalValue","customRange","setCustomRange","from","undefined","to","showCustom","setShowCustom","isOpen","setIsOpen","openFromCalendar","setOpenFromCalendar","openToCalendar","setOpenToCalendar","isRTL","localeCode","pastOptions","futureOptions","type","labels","selectOption","selectDate","past","future","presentFuture","custom","apply","cancel","handlePredefinedSelect","optionValue","dateRange","newValue","predefinedValue","handleCustomSelect","handleCustomRangeChange","newRange","handleApplyCustomRange","handleCancelCustomRange","handleClearAll","hasValue","getDisplayValue","allOptions","option","find","opt","description","formatDateRange","includes","parts","replace","split","length","renderOptionWithDate","formattedDescription","variant","onClick","div","span","dir","open","onOpenChange","asChild","role","aria-expanded","map","align","mode","selected","onSelect","date","initialFocus","disabled","button","e","stopPropagation"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/filters/components/date-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { CalendarIcon, ChevronDown, X } from 'lucide-react';\n\nimport { formatDate, getDateRangeForOption } from '../utils/date-helpers';\nimport { DateFilterValue, DateRange, Locale } from '../types/filters-type';\nimport { Button } from '../../ui/button';\nimport { cn } from '../../lib/utils';\nimport { Label } from '../../ui/label';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover';\nimport { Separator } from '../../ui/separator';\nimport { Calendar } from '../../ui/calendar';\nimport { getDateFilterOptions } from '../constants/date-filter-options';\nimport { SupportedLocale, getLabel } from '../../labels';\n\n\ninterface DateFilterProps {\n label?: string;\n value?: DateFilterValue;\n onChange: (value: DateFilterValue) => void;\n locale?: Locale;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function DateFilter({\n label,\n value,\n onChange,\n locale = { code: 'he', direction: 'rtl' },\n className,\n style,\n}: DateFilterProps) {\n const [internalValue, setInternalValue] = useState<DateFilterValue | undefined>(value);\n const [customRange, setCustomRange] = useState<DateRange>({ from: undefined, to: undefined });\n const [showCustom, setShowCustom] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [openFromCalendar, setOpenFromCalendar] = useState(false);\n const [openToCalendar, setOpenToCalendar] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n\n const isRTL = locale.direction === 'rtl';\n const localeCode = locale.code as SupportedLocale;\n const { pastOptions, futureOptions } = getDateFilterOptions(localeCode);\n\n // Initialize internal state only once on mount\n useEffect(() => {\n if (!isInitialized) {\n setInternalValue(value);\n if (value?.type === 'custom' && value.customRange) {\n setCustomRange(value.customRange);\n }\n setIsInitialized(true);\n }\n }, [value, isInitialized]);\n\n const labels = {\n selectOption: getLabel('selectOption', localeCode),\n from: getLabel('from', localeCode),\n to: getLabel('to', localeCode),\n selectDate: getLabel('selectDate', localeCode),\n past: getLabel('past', localeCode),\n future: getLabel('future', localeCode),\n presentFuture: getLabel('presentFuture', localeCode),\n custom: getLabel('customRange', localeCode),\n apply: getLabel('apply', localeCode),\n cancel: getLabel('cancel', localeCode),\n };\n\n const handlePredefinedSelect = (optionValue: string) => {\n setShowCustom(false);\n setIsOpen(false);\n\n const dateRange = getDateRangeForOption(optionValue, locale.code);\n const newValue: DateFilterValue = {\n type: 'predefined',\n predefinedValue: optionValue,\n customRange: { from: dateRange.from, to: dateRange.to },\n };\n\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleCustomSelect = () => {\n setShowCustom(true);\n };\n\n const handleCustomRangeChange = (newRange: DateRange) => {\n setCustomRange(newRange);\n };\n\n const handleApplyCustomRange = () => {\n const newValue: DateFilterValue = {\n type: 'custom',\n customRange,\n };\n\n setInternalValue(newValue);\n onChange(newValue);\n setIsOpen(false);\n setShowCustom(false);\n };\n\n const handleCancelCustomRange = () => {\n setIsOpen(false);\n setShowCustom(false);\n setCustomRange({ from: undefined, to: undefined });\n };\n\n const handleClearAll = () => {\n setInternalValue(undefined);\n setCustomRange({ from: undefined, to: undefined });\n setShowCustom(false);\n onChange({} as DateFilterValue);\n };\n\n const hasValue = () => {\n return (\n internalValue && (internalValue.type === 'predefined' || internalValue.type === 'custom')\n );\n };\n\n const getDisplayValue = () => {\n if (internalValue?.type === 'custom' && internalValue.customRange) {\n const { from, to } = internalValue.customRange;\n if (from && to) {\n return `${formatDate(from, 'dd/MM/yyyy')}-${formatDate(to, 'dd/MM/yyyy')}`;\n } else if (from) {\n return `${labels.from}:${formatDate(from, 'dd/MM/yyyy')}`;\n } else if (to) {\n return `${labels.to}:${formatDate(to, 'dd/MM/yyyy')}`;\n }\n return labels.custom;\n }\n\n if (internalValue?.type === 'predefined' && internalValue.predefinedValue) {\n const allOptions = [...pastOptions, ...futureOptions];\n const option = allOptions.find((opt) => opt.value === internalValue.predefinedValue);\n const dateRange = getDateRangeForOption(internalValue.predefinedValue, locale.code);\n return `${option?.label || internalValue.predefinedValue}${dateRange.description}`;\n }\n\n return labels.selectOption;\n };\n\n const formatDateRange = (description: string) => {\n // Check if description contains a date range (has \" - \" in it)\n if (description.includes(' - ') && isRTL) {\n // Split by \" - \" and reverse the order for RTL\n const parts = description.replace(/[()]/g, '').split(' - ');\n if (parts.length === 2) {\n return `(${parts[1]}-${parts[0]})`;\n }\n }\n return description;\n };\n\n const renderOptionWithDate = (option: { value: string; label: string }) => {\n const dateRange = getDateRangeForOption(option.value, locale.code);\n const formattedDescription = formatDateRange(dateRange.description);\n\n return (\n <Button\n key={option.value}\n variant='ghost'\n className={cn(\n ' w-full h-auto py-1 px-2 text-xs leading-tight justify-start',\n isRTL ? ' text-right' : ' text-left',\n internalValue?.predefinedValue === option.value && 'bg-accent',\n )}\n onClick={() => handlePredefinedSelect(option.value)}\n >\n <div className={cn('flex flex-col')}>\n <span className='font-medium'>{option.label}</span>\n <span className='text-[10px] text-muted-foreground' dir={locale.direction}>\n {formattedDescription}\n </span>\n </div>\n </Button>\n );\n };\n\n return (\n <div className={cn('useTw space-y-1', className)} dir={locale.direction} style={style}>\n {label && (\n <Label className={cn('useTw text-sm font-medium', isRTL && 'text-right block')}>\n {label}\n </Label>\n )}\n\n <div className='relative useTw'>\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n role='combobox'\n aria-expanded={isOpen}\n className='useTw w-full justify-between bg-background relative min-w-70 px-2'\n >\n <span className={`useTw truncate ${isRTL && 'text-right'}`}>{getDisplayValue()}</span>\n <ChevronDown className='useTw h-4 w-4 shrink-0 opacity-50' />\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-80 p-0'>\n <div className='p-4'>\n <div className='grid grid-cols-2 gap-4'>\n {/* Past Options - Right column */}\n <div className='space-y-1'>\n <div\n className={cn(\n 'text-sm font-semibold text-muted-foreground mb-2',\n isRTL && 'text-right',\n )}\n >\n {labels.past}\n </div>\n <div className='space-y-0.5'>\n {pastOptions.map((option) => (\n <div key={option.value}>{renderOptionWithDate(option)}</div>\n ))}\n </div>\n </div>\n {/* Future Options - Left column */}\n <div className='space-y-1'>\n <div\n className={cn(\n 'text-sm font-semibold text-muted-foreground mb-2',\n isRTL && 'text-right',\n )}\n >\n {labels.presentFuture}\n </div>\n <div className='space-y-0.5'>\n {futureOptions.map((option) => (\n <div key={option.value}>{renderOptionWithDate(option)}</div>\n ))}\n </div>\n </div>\n </div>\n\n <Separator className='my-4' />\n\n {/* Custom Option */}\n <div className='space-y-3'>\n <Button\n variant='ghost'\n className={cn(\n 'useTw w-full justify-start h-auto py-2 px-2',\n (showCustom || internalValue?.type === 'custom') && 'bg-accent',\n isRTL && 'justify-start text-right',\n )}\n onClick={handleCustomSelect}\n >\n {labels.custom}\n </Button>\n\n {/* Custom Date Range - appears next to custom label */}\n {showCustom && (\n <div className='space-y-3 pl-2'>\n <div className='grid grid-cols-1 gap-3'>\n {/* From Date */}\n <div className={cn('flex items-center gap-2')}>\n <Label className={cn('useTw text-xs w-[20%]', isRTL && 'text-right')}>\n {labels.from}\n </Label>\n <Popover open={openFromCalendar} onOpenChange={setOpenFromCalendar}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n className={cn(\n 'useTw w-[60%] justify-start text-left font-normal text-xs h-8 bg-background',\n !customRange.from && 'text-muted-foreground',\n )}\n >\n <CalendarIcon className='useTw mr-1 h-3 w-3' />\n <span dir={locale.direction}>\n {customRange.from\n ? formatDate(customRange.from, 'dd/MM/yyyy')\n : labels.selectDate}\n </span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-auto p-0' align='start'>\n <Calendar\n mode='single'\n selected={customRange.from}\n onSelect={(date) => {\n handleCustomRangeChange({ ...customRange, from: date });\n setOpenFromCalendar(false);\n }}\n initialFocus\n className='useTw'\n />\n </PopoverContent>\n </Popover>\n </div>\n\n {/* To Date */}\n <div className={cn('flex items-center gap-2')}>\n <Label className={cn('useTw text-xs w-[20%]', isRTL && 'text-right')}>\n {labels.to}\n </Label>\n <Popover open={openToCalendar} onOpenChange={setOpenToCalendar}>\n <PopoverTrigger asChild className='useTw'>\n <Button\n variant='outline'\n className={cn(\n 'useTw w-[60%] justify-start text-left font-normal text-xs h-8 bg-background',\n !customRange.to && 'text-muted-foreground',\n )}\n >\n <CalendarIcon className='useTw mr-1 h-3 w-3' />\n <span dir={locale.direction}>\n {customRange.to\n ? formatDate(customRange.to, 'dd/MM/yyyy')\n : labels.selectDate}\n </span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-auto p-0' align='start'>\n <Calendar\n mode='single'\n selected={customRange.to}\n onSelect={(date) => {\n handleCustomRangeChange({ ...customRange, to: date });\n setOpenToCalendar(false);\n }}\n initialFocus\n className='useTw'\n />\n </PopoverContent>\n </Popover>\n </div>\n </div>\n\n {/* Action Buttons */}\n <div className='flex gap-2'>\n <Button\n onClick={handleApplyCustomRange}\n className='useTw flex-1 text-xs h-8'\n disabled={!customRange.from && !customRange.to}\n >\n {labels.apply}\n </Button>\n <Button\n onClick={handleCancelCustomRange}\n variant='outline'\n className='useTw flex-1 text-xs h-8 bg-transparent'\n >\n {labels.cancel}\n </Button>\n </div>\n </div>\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {hasValue() && (\n <button\n className={`useTw absolute ${isRTL ? 'left-8' : 'right-8'} top-1/2 -translate-y-1/2 h-4 w-4 p-0 hover:bg-muted rounded-sm flex items-center justify-center z-10 `}\n onClick={(e) => {\n e.stopPropagation();\n handleClearAll();\n }}\n >\n <X className='useTw h-3 w-3' />\n </button>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useEffect","useState","CalendarIcon","ChevronDown","X","formatDate","getDateRangeForOption","Button","cn","Label","Popover","PopoverContent","PopoverTrigger","Separator","Calendar","getDateFilterOptions","getLabel","DateFilter","label","value","onChange","locale","code","direction","className","style","internalValue","setInternalValue","customRange","setCustomRange","from","undefined","to","showCustom","setShowCustom","isOpen","setIsOpen","openFromCalendar","setOpenFromCalendar","openToCalendar","setOpenToCalendar","isInitialized","setIsInitialized","isRTL","localeCode","pastOptions","futureOptions","type","labels","selectOption","selectDate","past","future","presentFuture","custom","apply","cancel","handlePredefinedSelect","optionValue","dateRange","newValue","predefinedValue","handleCustomSelect","handleCustomRangeChange","newRange","handleApplyCustomRange","handleCancelCustomRange","handleClearAll","hasValue","getDisplayValue","allOptions","option","find","opt","description","formatDateRange","includes","parts","replace","split","length","renderOptionWithDate","formattedDescription","variant","onClick","div","span","dir","open","onOpenChange","asChild","role","aria-expanded","map","align","mode","selected","onSelect","date","initialFocus","disabled","button","e","stopPropagation"],"mappings":"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"}
@@ -97,7 +97,8 @@ export function SmallSelectFilter({ label, options, value, onChange, locale = {
97
97
  children: limitedOptions.map((option, index)=>/*#__PURE__*/ _jsx(Button, {
98
98
  variant: "ghost",
99
99
  size: "sm",
100
- className: cn('px-3 py-1 text-xs rounded-none border-0', index > 0 && 'border-l', getButtonColor(option.value, index)),
100
+ className: cn('px-3 py-1 text-xs rounded-none border-0', // index > 0 && 'border-l',
101
+ getButtonColor(option.value, index)),
101
102
  onClick: ()=>handleOptionToggle(option.value),
102
103
  children: option.label
103
104
  }, option.value))
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/filters/components/small-select-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nimport { X } from 'lucide-react';\nimport { Locale, SelectFilterValue } from '../types/filters-type';\nimport { Label } from '../../ui/label';\nimport { cn } from '../../lib/utils';\nimport { Button } from '../../ui/button';\nimport { SupportedLocale } from '../../labels';\n\ninterface SmallSelectOption {\n value: string;\n label: string;\n}\n\ninterface SmallSelectFilterProps {\n label?: string;\n options: SmallSelectOption[];\n value?: SelectFilterValue;\n onChange: (value: SelectFilterValue) => void;\n locale?: Locale;\n className?: string;\n multiSelect?: boolean;\n maxOptions?: number;\n style?: React.CSSProperties;\n}\n\nexport function SmallSelectFilter({\n label,\n options,\n value,\n onChange,\n locale = { code: 'he', direction: 'rtl' },\n className,\n multiSelect = true,\n maxOptions = 3,\n style,\n}: SmallSelectFilterProps) {\n const [internalValue, setInternalValue] = useState<SelectFilterValue>(\n value || { type: 'none', selectedValues: [] },\n );\n\n const isRtl = locale?.direction === 'rtl';\n\n // Limit options to maxOptions\n const limitedOptions = options.slice(0, maxOptions);\n\n // Sync internal state with external value prop\n useEffect(() => {\n setInternalValue(value || { type: 'none', selectedValues: [] });\n }, [value]);\n\n const handleOptionToggle = (optionValue: string) => {\n let newSelectedValues: string[];\n\n if (multiSelect) {\n // Multiple selection mode - allow multiple choices\n if (internalValue.selectedValues.includes(optionValue)) {\n newSelectedValues = internalValue.selectedValues.filter((val) => val !== optionValue);\n } else {\n newSelectedValues = [...internalValue.selectedValues, optionValue];\n }\n } else {\n // Single selection mode\n if (internalValue.selectedValues.includes(optionValue)) {\n newSelectedValues = []; // Deselect if already selected\n } else {\n newSelectedValues = [optionValue]; // Select only this option\n }\n }\n\n const newValue: SelectFilterValue = {\n type:\n newSelectedValues.length === 0\n ? 'none'\n : newSelectedValues.length === options.length\n ? 'all'\n : 'some',\n selectedValues: newSelectedValues,\n };\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleClear = () => {\n const newValue: SelectFilterValue = { type: 'none', selectedValues: [] };\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const hasSelection = internalValue.selectedValues.length > 0;\n\n const isOptionSelected = (optionValue: string) => {\n return internalValue.selectedValues.includes(optionValue);\n };\n\n const getButtonColor = (optionValue: string, index: number) => {\n if (!isOptionSelected(optionValue)) {\n return 'useTw bg-background text-muted-foreground hover:bg-muted';\n }\n\n // Different colors for different options when selected\n const colors = [\n 'bg-blue-600 text-white hover:bg-blue-700', // First option - blue\n 'bg-green-600 text-white hover:bg-green-700', // Second option - green\n 'bg-purple-600 text-white hover:bg-purple-700', // Third option - purple\n ];\n return colors[index] || 'bg-accent text-accent-foreground hover:bg-accent/80';\n };\n\n return (\n <div className={cn('space-y-1', className)} dir={locale.direction} style={style}>\n {label && (\n <Label className={cn('useTw text-sm font-medium', isRtl && 'text-right block')}>\n {label}\n </Label>\n )}\n\n <div\n className={cn(\n 'flex items-center gap-1 transition-colors py-0.5',\n locale.direction === 'rtl' && 'justify-start',\n )}\n >\n <div className={cn('flex items-center', locale.direction === 'rtl' && 'order-first')}>\n {/* Toggle Options */}\n <div className='flex rounded-md border overflow-hidden'>\n {limitedOptions.map((option, index) => (\n <Button\n key={option.value}\n variant='ghost'\n size='sm'\n className={cn(\n 'px-3 py-1 text-xs rounded-none border-0',\n index > 0 && 'border-l',\n getButtonColor(option.value, index),\n )}\n onClick={() => handleOptionToggle(option.value)}\n >\n {option.label}\n </Button>\n ))}\n </div>\n </div>\n\n {hasSelection && (\n <Button\n variant='ghost'\n size='sm'\n className={cn(\n 'h-5 w-5 p-0 hover:bg-muted rounded-full -mt-1 -ml-1',\n locale.direction === 'rtl' ? 'order-last' : 'order-last',\n )}\n onClick={handleClear}\n >\n <X className='useTw h-3 w-3' />\n </Button>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useEffect","useState","X","Label","cn","Button","SmallSelectFilter","label","options","value","onChange","locale","code","direction","className","multiSelect","maxOptions","style","internalValue","setInternalValue","type","selectedValues","isRtl","limitedOptions","slice","handleOptionToggle","optionValue","newSelectedValues","includes","filter","val","newValue","length","handleClear","hasSelection","isOptionSelected","getButtonColor","index","colors","div","dir","map","option","variant","size","onClick"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/filters/components/small-select-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nimport { X } from 'lucide-react';\nimport { Locale, SelectFilterValue } from '../types/filters-type';\nimport { Label } from '../../ui/label';\nimport { cn } from '../../lib/utils';\nimport { Button } from '../../ui/button';\nimport { SupportedLocale } from '../../labels';\n\ninterface SmallSelectOption {\n value: string;\n label: string;\n}\n\ninterface SmallSelectFilterProps {\n label?: string;\n options: SmallSelectOption[];\n value?: SelectFilterValue;\n onChange: (value: SelectFilterValue) => void;\n locale?: Locale;\n className?: string;\n multiSelect?: boolean;\n maxOptions?: number;\n style?: React.CSSProperties;\n}\n\nexport function SmallSelectFilter({\n label,\n options,\n value,\n onChange,\n locale = { code: 'he', direction: 'rtl' },\n className,\n multiSelect = true,\n maxOptions = 3,\n style,\n}: SmallSelectFilterProps) {\n const [internalValue, setInternalValue] = useState<SelectFilterValue>(\n value || { type: 'none', selectedValues: [] },\n );\n\n const isRtl = locale?.direction === 'rtl';\n\n // Limit options to maxOptions\n const limitedOptions = options.slice(0, maxOptions);\n\n // Sync internal state with external value prop\n useEffect(() => {\n setInternalValue(value || { type: 'none', selectedValues: [] });\n }, [value]);\n\n const handleOptionToggle = (optionValue: string) => {\n let newSelectedValues: string[];\n\n if (multiSelect) {\n // Multiple selection mode - allow multiple choices\n if (internalValue.selectedValues.includes(optionValue)) {\n newSelectedValues = internalValue.selectedValues.filter((val) => val !== optionValue);\n } else {\n newSelectedValues = [...internalValue.selectedValues, optionValue];\n }\n } else {\n // Single selection mode\n if (internalValue.selectedValues.includes(optionValue)) {\n newSelectedValues = []; // Deselect if already selected\n } else {\n newSelectedValues = [optionValue]; // Select only this option\n }\n }\n\n const newValue: SelectFilterValue = {\n type:\n newSelectedValues.length === 0\n ? 'none'\n : newSelectedValues.length === options.length\n ? 'all'\n : 'some',\n selectedValues: newSelectedValues,\n };\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleClear = () => {\n const newValue: SelectFilterValue = { type: 'none', selectedValues: [] };\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const hasSelection = internalValue.selectedValues.length > 0;\n\n const isOptionSelected = (optionValue: string) => {\n return internalValue.selectedValues.includes(optionValue);\n };\n\n const getButtonColor = (optionValue: string, index: number) => {\n if (!isOptionSelected(optionValue)) {\n return 'useTw bg-background text-muted-foreground hover:bg-muted';\n }\n\n // Different colors for different options when selected\n const colors = [\n 'bg-blue-600 text-white hover:bg-blue-700', // First option - blue\n 'bg-green-600 text-white hover:bg-green-700', // Second option - green\n 'bg-purple-600 text-white hover:bg-purple-700', // Third option - purple\n ];\n return colors[index] || 'bg-accent text-accent-foreground hover:bg-accent/80';\n };\n\n return (\n <div className={cn('space-y-1', className)} dir={locale.direction} style={style}>\n {label && (\n <Label className={cn('useTw text-sm font-medium', isRtl && 'text-right block')}>\n {label}\n </Label>\n )}\n\n <div\n className={cn(\n 'flex items-center gap-1 transition-colors py-0.5',\n locale.direction === 'rtl' && 'justify-start',\n )}\n >\n <div className={cn('flex items-center', locale.direction === 'rtl' && 'order-first')}>\n {/* Toggle Options */}\n <div className='flex rounded-md border overflow-hidden'>\n {limitedOptions.map((option, index) => (\n <Button\n key={option.value}\n variant='ghost'\n size='sm'\n className={cn(\n 'px-3 py-1 text-xs rounded-none border-0',\n // index > 0 && 'border-l',\n getButtonColor(option.value, index),\n )}\n onClick={() => handleOptionToggle(option.value)}\n >\n {option.label}\n </Button>\n ))}\n </div>\n </div>\n\n {hasSelection && (\n <Button\n variant='ghost'\n size='sm'\n className={cn(\n 'h-5 w-5 p-0 hover:bg-muted rounded-full -mt-1 -ml-1',\n locale.direction === 'rtl' ? 'order-last' : 'order-last',\n )}\n onClick={handleClear}\n >\n <X className='useTw h-3 w-3' />\n </Button>\n )}\n </div>\n </div>\n );\n}\n"],"names":["useEffect","useState","X","Label","cn","Button","SmallSelectFilter","label","options","value","onChange","locale","code","direction","className","multiSelect","maxOptions","style","internalValue","setInternalValue","type","selectedValues","isRtl","limitedOptions","slice","handleOptionToggle","optionValue","newSelectedValues","includes","filter","val","newValue","length","handleClear","hasSelection","isOptionSelected","getButtonColor","index","colors","div","dir","map","option","variant","size","onClick"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shefing/quickfilter",
3
- "version": "1.0.78",
3
+ "version": "1.0.84",
4
4
  "private": false,
5
5
  "bugs": "https://github.com/shefing/payload-tools/issues",
6
6
  "repository": "https://github.com/shefing/payload-tools",
@@ -32,9 +32,9 @@
32
32
  }
33
33
  },
34
34
  "devDependencies": {
35
- "@payloadcms/next": "3.56.0",
36
- "@payloadcms/translations": "3.56.0",
37
- "@payloadcms/ui": "3.56.0",
35
+ "@payloadcms/next": "3.61.0",
36
+ "@payloadcms/translations": "3.61.0",
37
+ "@payloadcms/ui": "3.61.0",
38
38
  "@swc/cli": "^0.1.65",
39
39
  "@swc/core": "^1.6.3",
40
40
  "@types/react": "19.1.12",
@@ -43,7 +43,7 @@
43
43
  "copyfiles": "^2.4.1",
44
44
  "lucide-react": "^0.475.0",
45
45
  "next": "15.4.4",
46
- "payload": "3.56.0",
46
+ "payload": "3.61.0",
47
47
  "postcss": "^8.5.2",
48
48
  "react": "19.1.1",
49
49
  "react-dom": "19.1.1",