@shefing/quickfilter 1.0.29 → 1.0.32
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":"
|
|
1
|
+
{"version":3,"file":"QuickFilter.d.ts","sourceRoot":"","sources":["../src/QuickFilter.tsx"],"names":[],"mappings":"AA6QA,QAAA,MAAM,WAAW,0BAGd;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,EAAE,CAAA;CAC3D,gCA0RA,CAAA;AAED,eAAe,WAAW,CAAA"}
|
package/dist/QuickFilter.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useMemo,
|
|
3
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { useConfig, useListQuery, useTranslation } from '@payloadcms/ui';
|
|
5
5
|
import { getTranslation } from '@payloadcms/translations';
|
|
6
6
|
import FilterField from './FilterField';
|
|
7
7
|
import { getLabel } from './labels';
|
|
8
|
-
import { groupFiltersByRow
|
|
9
|
-
import { ChevronDown, ChevronUp, Filter, X } from 'lucide-react';
|
|
8
|
+
import { groupFiltersByRow } from './filters/utils/layout-helpers';
|
|
9
|
+
import { ChevronDown, ChevronUp, Filter, RefreshCw, X } from 'lucide-react';
|
|
10
10
|
import { getDateRangeForOption } from './filters/utils/date-helpers';
|
|
11
11
|
import { isEqual } from 'lodash';
|
|
12
12
|
import { futureOptionKeys, getDateFilterOptions, pastOptionKeys } from './filters/constants/date-filter-options';
|
|
@@ -162,6 +162,9 @@ const parseWhereClauseToFilterValues = (where, fields, locale)=>{
|
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
if (clause.or) {
|
|
165
|
+
if (clause.or.length > 1) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
165
168
|
clause.or.forEach(recursiveParse);
|
|
166
169
|
return;
|
|
167
170
|
}
|
|
@@ -240,9 +243,6 @@ const parseWhereClauseToFilterValues = (where, fields, locale)=>{
|
|
|
240
243
|
return values;
|
|
241
244
|
};
|
|
242
245
|
const QuickFilter = ({ slug, filterList })=>{
|
|
243
|
-
const localStorageKey = useMemo(()=>`direct-filter-${slug}`, [
|
|
244
|
-
slug
|
|
245
|
-
]);
|
|
246
246
|
const [fields, setFields] = useState([]);
|
|
247
247
|
const [filterRows, setFilterRows] = useState([]);
|
|
248
248
|
const [showFilters, setShowFilters] = useState(false);
|
|
@@ -250,25 +250,7 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
250
250
|
const { getEntityConfig } = useConfig();
|
|
251
251
|
const { i18n } = useTranslation();
|
|
252
252
|
const locale = i18n.language;
|
|
253
|
-
const
|
|
254
|
-
const [filterValues, setFilterValues] = useState(()=>{
|
|
255
|
-
if (typeof window == 'undefined') return {};
|
|
256
|
-
try {
|
|
257
|
-
const item = window.localStorage.getItem(localStorageKey);
|
|
258
|
-
if (!item) return {};
|
|
259
|
-
const dateTimeReviver = (key, value)=>{
|
|
260
|
-
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
|
|
261
|
-
if (typeof value === 'string' && isoDateRegex.test(value)) {
|
|
262
|
-
return new Date(value);
|
|
263
|
-
}
|
|
264
|
-
return value;
|
|
265
|
-
};
|
|
266
|
-
return JSON.parse(item, dateTimeReviver);
|
|
267
|
-
} catch (error) {
|
|
268
|
-
console.error('Error reading and parsing filters from localStorage.', error);
|
|
269
|
-
return {};
|
|
270
|
-
}
|
|
271
|
-
});
|
|
253
|
+
const [filterValues, setFilterValues] = useState({});
|
|
272
254
|
// Build the list of filter fields from config
|
|
273
255
|
useEffect(()=>{
|
|
274
256
|
const collection = getEntityConfig({
|
|
@@ -311,9 +293,8 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
311
293
|
useEffect(()=>{
|
|
312
294
|
if (fields.length === 0) return;
|
|
313
295
|
const valuesFromQuery = parseWhereClauseToFilterValues(query.where, fields, locale);
|
|
314
|
-
if (!isEqual(
|
|
296
|
+
if (!isEqual(filterValues, valuesFromQuery)) {
|
|
315
297
|
// Lock to prevent feedback loop when internal state changes
|
|
316
|
-
isSyncingFromQuery.current = true;
|
|
317
298
|
setFilterValues(valuesFromQuery);
|
|
318
299
|
}
|
|
319
300
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -323,12 +304,12 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
323
304
|
]);
|
|
324
305
|
// Sync internal state (filterValues) back into the URL
|
|
325
306
|
useEffect(()=>{
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
307
|
+
if (fields.length === 0) return;
|
|
308
|
+
const valuesFromQuery = parseWhereClauseToFilterValues(query.where, fields, locale);
|
|
309
|
+
if (Object.keys(filterValues).length == 0 && !query.where) {}
|
|
310
|
+
if (isEqual(filterValues, valuesFromQuery)) {
|
|
329
311
|
return;
|
|
330
312
|
}
|
|
331
|
-
if (fields.length === 0) return;
|
|
332
313
|
const quickFilterConditions = buildQuickFilterConditions(filterValues, fields, locale);
|
|
333
314
|
const quickFilterFieldNames = new Set(fields.map((f)=>f.name));
|
|
334
315
|
const otherFilters = cleanWhereClause(query.where, quickFilterFieldNames);
|
|
@@ -351,40 +332,18 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
351
332
|
newWhere = allConditions[0];
|
|
352
333
|
}
|
|
353
334
|
// Only update if the query has actually changed to avoid unnecessary updates
|
|
354
|
-
if (!isEqual(newWhere, query.where)) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
refineListData(refinedData).then((r)=>{
|
|
364
|
-
console.log("Query refreshed", refinedData);
|
|
365
|
-
});
|
|
366
|
-
}
|
|
335
|
+
if (!(isEqual(newWhere, query.where) || Object.keys(newWhere).length == 0 && !query.where)) {
|
|
336
|
+
const refinedData = {
|
|
337
|
+
where: newWhere,
|
|
338
|
+
page: 1
|
|
339
|
+
};
|
|
340
|
+
refineListData(refinedData).then((r)=>{
|
|
341
|
+
console.log('Query refreshed', refinedData);
|
|
342
|
+
});
|
|
367
343
|
}
|
|
368
344
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
369
345
|
}, [
|
|
370
|
-
filterValues
|
|
371
|
-
fields,
|
|
372
|
-
i18n.language
|
|
373
|
-
]);
|
|
374
|
-
// Effect for persisting to localStorage
|
|
375
|
-
useEffect(()=>{
|
|
376
|
-
try {
|
|
377
|
-
if (Object.keys(filterValues).length > 0) {
|
|
378
|
-
localStorage.setItem(localStorageKey, JSON.stringify(filterValues));
|
|
379
|
-
} else {
|
|
380
|
-
localStorage.removeItem(localStorageKey);
|
|
381
|
-
}
|
|
382
|
-
} catch (error) {
|
|
383
|
-
console.error('Failed to save filters to localStorage', error);
|
|
384
|
-
}
|
|
385
|
-
}, [
|
|
386
|
-
filterValues,
|
|
387
|
-
localStorageKey
|
|
346
|
+
filterValues
|
|
388
347
|
]);
|
|
389
348
|
// Updates only the internal state
|
|
390
349
|
const handleFilterChange = useCallback((fieldName, value)=>{
|
|
@@ -460,6 +419,9 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
460
419
|
const clearAllFilters = ()=>{
|
|
461
420
|
setFilterValues({});
|
|
462
421
|
};
|
|
422
|
+
const refreshFilters = ()=>{
|
|
423
|
+
refineListData(query);
|
|
424
|
+
};
|
|
463
425
|
const memoizedFilterRows = useMemo(()=>{
|
|
464
426
|
return filterRows.map((row)=>/*#__PURE__*/ _jsx("div", {
|
|
465
427
|
children: /*#__PURE__*/ _jsx("div", {
|
|
@@ -521,6 +483,16 @@ const QuickFilter = ({ slug, filterList })=>{
|
|
|
521
483
|
children: /*#__PURE__*/ _jsx(X, {
|
|
522
484
|
className: "h-3 w-3 text-gray-500"
|
|
523
485
|
})
|
|
486
|
+
}),
|
|
487
|
+
/*#__PURE__*/ _jsx("span", {
|
|
488
|
+
onClick: (e)=>{
|
|
489
|
+
e.stopPropagation();
|
|
490
|
+
refreshFilters();
|
|
491
|
+
},
|
|
492
|
+
className: "ml-1 p-0.5 hover:bg-muted rounded-sm transition-colors flex-shrink-0",
|
|
493
|
+
children: /*#__PURE__*/ _jsx(RefreshCw, {
|
|
494
|
+
className: "h-3 w-3 text-gray-500"
|
|
495
|
+
})
|
|
524
496
|
})
|
|
525
497
|
]
|
|
526
498
|
}) : /*#__PURE__*/ _jsx("span", {
|
package/dist/QuickFilter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/QuickFilter.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, 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 CheckboxFilterState,\n DateFilterValue,\n FilterDetaild,\n FilterRow,\n SelectFilterValue,\n} from './filters/types/filters-type';\nimport { groupFiltersByRow, parseColumns } from './filters/utils/layout-helpers';\nimport { ChevronDown, ChevronUp, Filter, X } from 'lucide-react';\n\nimport { getDateRangeForOption } from './filters/utils/date-helpers';\nimport { isEqual } from 'lodash';\nimport {\n futureOptionKeys,\n getDateFilterOptions,\n pastOptionKeys,\n} from './filters/constants/date-filter-options';\nimport { Button } from './ui/button';\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) => 'name' in field && fieldNames.includes(field.name 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// Builds an array of condition objects from the quick filter values\nconst buildQuickFilterConditions = (\n values: Record<string, any>,\n fieldDefs: FilterDetaild[],\n locale: SupportedLocale,\n): Record<string, any>[] => {\n const conditions: Record<string, any>[] = [];\n\n Object.entries(values).forEach(([fieldName, value]) => {\n if (!value) return;\n const fieldDef = fieldDefs.find((f) => f.name === fieldName);\n if (!fieldDef) return;\n\n let condition: Record<string, any> | null = null;\n\n switch (fieldDef.type) {\n case 'date': {\n const dateValue = value as DateFilterValue;\n let from: Date | undefined;\n let to: Date | undefined;\n\n if (dateValue.predefinedValue) {\n const range = getDateRangeForOption(dateValue.predefinedValue, locale);\n from = range.from;\n to = range.to;\n } else if (dateValue.customRange) {\n if (dateValue.customRange.from) from = new Date(dateValue.customRange.from);\n if (dateValue.customRange.to) to = new Date(dateValue.customRange.to);\n }\n\n if (from || to) {\n const dateQuery: any = {};\n if (from) dateQuery.greater_than_equal = from;\n if (to) dateQuery.less_than_equal = to;\n if (Object.keys(dateQuery).length > 0) {\n condition = { [fieldName]: dateQuery };\n }\n }\n break;\n }\n case 'select': {\n const selectValue = value as SelectFilterValue;\n if (selectValue.selectedValues && selectValue.selectedValues.length > 0) {\n if (selectValue.selectedValues.length === 1) {\n condition = { [fieldName]: { equals: selectValue.selectedValues[0] } };\n } else {\n condition = { [fieldName]: { in: selectValue.selectedValues } };\n }\n }\n break;\n }\n case 'checkbox': {\n const checkboxState = value as CheckboxFilterState;\n if (checkboxState === 'checked') {\n condition = { [fieldName]: { equals: 'true' } };\n } else if (checkboxState === 'unchecked') {\n condition = { [fieldName]: { equals: 'false' } };\n }\n break;\n }\n }\n if (condition) {\n conditions.push(condition);\n }\n });\n return conditions;\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\n// Translates URL query conditions to the quick filter's internal state\nconst parseWhereClauseToFilterValues = (\n where: any,\n fields: FilterDetaild[],\n locale: SupportedLocale,\n): Record<string, any> => {\n const values: Record<string, any> = {};\n const fieldNames = new Set(fields.map((f) => f.name));\n\n const recursiveParse = (clause: any) => {\n if (!clause || typeof clause !== 'object') return;\n\n if (clause.and) {\n clause.and.forEach(recursiveParse);\n return;\n }\n if (clause.or) {\n clause.or.forEach(recursiveParse);\n return;\n }\n\n for (const fieldName in clause) {\n if (fieldNames.has(fieldName)) {\n const fieldDef = fields.find((f) => f.name === fieldName);\n const condition = clause[fieldName];\n\n if (fieldDef && condition && typeof condition === 'object') {\n if ('equals' in condition) {\n if (fieldDef.type === 'checkbox') {\n values[fieldName] = condition.equals == 'true' ? 'checked' : 'unchecked';\n } else if (fieldDef.type === 'select') {\n values[fieldName] = { selectedValues: [condition.equals] };\n }\n } else if ('in' in condition && Array.isArray(condition.in)) {\n if (fieldDef.type === 'select') {\n values[fieldName] = { selectedValues: condition.in };\n }\n } else if ('greater_than_equal' in condition || 'less_than_equal' in condition) {\n if (fieldDef.type === 'date') {\n const fromDate = condition.greater_than_equal\n ? new Date(condition.greater_than_equal)\n : null;\n const toDate = condition.less_than_equal ? new Date(condition.less_than_equal) : null;\n const allDateOptions = [...pastOptionKeys, ...futureOptionKeys];\n let matchedOption = null;\n\n for (const option of allDateOptions) {\n const range = getDateRangeForOption(option, locale);\n let isFromMatch;\n if (fromDate) {\n isFromMatch = range.from?.toDateString() === fromDate.toDateString();\n } else if (fromDate == null && range.to == undefined) {\n // all future: fromDate == null & range.to == undefined\n isFromMatch = true;\n }\n let isToMatch;\n if (toDate) {\n isToMatch = range.to?.toDateString() === toDate.toDateString();\n } else if (toDate == null && range.to == undefined) {\n // all future: fromDate == null & range.to == undefined\n isToMatch = true;\n }\n\n if (isFromMatch && isToMatch) {\n matchedOption = option;\n break;\n }\n }\n\n if (matchedOption) {\n values[fieldName] = {\n type: 'predefined',\n predefinedValue: matchedOption,\n };\n } else {\n values[fieldName] = {\n type: 'custom',\n customRange: {\n from: fromDate,\n to: toDate,\n },\n };\n }\n }\n }\n }\n }\n }\n };\n\n recursiveParse(where);\n return values;\n};\n\nconst QuickFilter = ({\n slug,\n filterList,\n }: {\n slug: string;\n filterList: (string | { name: string; width: string })[][];\n}) => {\n const localStorageKey = useMemo(() => `direct-filter-${slug}`, [slug]);\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 const isSyncingFromQuery = useRef(false);\n\n const [filterValues, setFilterValues] = useState<Record<string, any>>(() => {\n if (typeof window == 'undefined') return {};\n try {\n const item = window.localStorage.getItem(localStorageKey);\n if (!item) return {};\n const dateTimeReviver = (key: string, value: any) => {\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$/;\n if (typeof value === 'string' && isoDateRegex.test(value)) {\n return new Date(value);\n }\n return value;\n };\n return JSON.parse(item, dateTimeReviver);\n } catch (error) {\n console.error('Error reading and parsing filters from localStorage.', error);\n return {};\n }\n });\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.name,\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 return {\n name: fieldName,\n label: translatedLabel as string,\n type: field.type,\n options: (field as SelectField).options as OptionObject[],\n row: fieldConfig ? fieldConfig.rowIndex : 0,\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\n const valuesFromQuery: Record<string, any> = parseWhereClauseToFilterValues(\n query.where,\n fields,\n locale,\n );\n\n if (!isEqual(valuesFromQuery, filterValues)) {\n // Lock to prevent feedback loop when internal state changes\n isSyncingFromQuery.current = true;\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 the change originated from the first effect, skip to avoid infinite loop\n if (isSyncingFromQuery.current) {\n isSyncingFromQuery.current = false;\n return;\n }\n\n if (fields.length === 0) return;\n\n const quickFilterConditions = buildQuickFilterConditions(filterValues, fields, locale);\n const quickFilterFieldNames = new Set(fields.map((f) => f.name));\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)) {\n if(newWhere && Object.keys(newWhere).length > 0){\n const refinedData = {\n where: newWhere,\n page: 1,\n } as ListQuery;\n\n if (query.columns) {\n refinedData.columns = parseColumns(query.columns);\n }\n\n refineListData(refinedData).then(r => {\n console.log(\"Query refreshed\",refinedData)\n });\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filterValues, fields, i18n.language]);\n // Effect for persisting to localStorage\n useEffect(() => {\n try {\n if (Object.keys(filterValues).length > 0) {\n localStorage.setItem(localStorageKey, JSON.stringify(filterValues));\n } else {\n localStorage.removeItem(localStorageKey);\n }\n } catch (error) {\n console.error('Failed to save filters to localStorage', error);\n }\n }, [filterValues, localStorageKey]);\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) => f.name === fieldName);\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 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 <FilterField\n key={field.name}\n field={field}\n onFilterChange={handleFilterChange}\n value={filterValues[field.name]}\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 </>\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","useRef","useState","useConfig","useListQuery","useTranslation","getTranslation","FilterField","getLabel","groupFiltersByRow","parseColumns","ChevronDown","ChevronUp","Filter","X","getDateRangeForOption","isEqual","futureOptionKeys","getDateFilterOptions","pastOptionKeys","Button","getLocalizedLabel","label","locale","Object","values","findFieldsByName","fields","fieldNames","results","recursiveSearch","currentFields","filteredFields","filter","field","includes","name","push","forEach","item","type","Array","isArray","tabs","tab","blocks","block","buildQuickFilterConditions","fieldDefs","conditions","entries","fieldName","value","fieldDef","find","f","condition","dateValue","from","to","predefinedValue","range","customRange","Date","dateQuery","greater_than_equal","less_than_equal","keys","length","selectValue","selectedValues","equals","in","checkboxState","cleanWhereClause","clause","fieldsToClean","newClause","key","cleanedSubClauses","map","subClause","Boolean","has","and","or","parseWhereClauseToFilterValues","where","Set","recursiveParse","fromDate","toDate","allDateOptions","matchedOption","option","isFromMatch","toDateString","undefined","isToMatch","QuickFilter","slug","filterList","localStorageKey","setFields","filterRows","setFilterRows","showFilters","setShowFilters","refineListData","query","getEntityConfig","i18n","language","isSyncingFromQuery","filterValues","setFilterValues","window","localStorage","getItem","dateTimeReviver","isoDateRegex","test","JSON","parse","error","console","collection","collectionSlug","flattenedFieldConfigs","flatMap","row","rowIndex","fieldIndex","matchedFields","simplifiedFields","translatedLabel","fieldConfig","options","width","sortedFields","valuesFromQuery","current","quickFilterConditions","quickFilterFieldNames","otherFilters","allConditions","newWhere","refinedData","page","columns","then","r","log","setItem","stringify","removeItem","handleFilterChange","prev","newValues","getActiveFiltersDetails","activeFilters","dateDescription","pastOptions","futureOptions","allOptions","opt","totalOptions","selectedOption","optionLabel","checkboxValue","clearAllFilters","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 { ClientField, FieldAffectingData, ListQuery, OptionObject, SelectField } from 'payload'\nimport { getTranslation } from '@payloadcms/translations'\nimport FilterField from './FilterField'\nimport { getLabel, SupportedLocale } from './labels'\nimport type {\n CheckboxFilterState,\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'\n\nimport { getDateRangeForOption } from './filters/utils/date-helpers'\nimport { isEqual } from 'lodash'\nimport {\n futureOptionKeys,\n getDateFilterOptions,\n pastOptionKeys,\n} from './filters/constants/date-filter-options'\nimport { Button } from './ui/button'\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) => 'name' in field && fieldNames.includes(field.name 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// Builds an array of condition objects from the quick filter values\nconst buildQuickFilterConditions = (\n values: Record<string, any>,\n fieldDefs: FilterDetaild[],\n locale: SupportedLocale,\n): Record<string, any>[] => {\n const conditions: Record<string, any>[] = []\n\n Object.entries(values).forEach(([fieldName, value]) => {\n if (!value) return\n const fieldDef = fieldDefs.find((f) => f.name === fieldName)\n if (!fieldDef) return\n\n let condition: Record<string, any> | null = null\n\n switch (fieldDef.type) {\n case 'date': {\n const dateValue = value as DateFilterValue\n let from: Date | undefined\n let to: Date | undefined\n\n if (dateValue.predefinedValue) {\n const range = getDateRangeForOption(dateValue.predefinedValue, locale)\n from = range.from\n to = range.to\n } else if (dateValue.customRange) {\n if (dateValue.customRange.from) from = new Date(dateValue.customRange.from)\n if (dateValue.customRange.to) to = new Date(dateValue.customRange.to)\n }\n\n if (from || to) {\n const dateQuery: any = {}\n if (from) dateQuery.greater_than_equal = from\n if (to) dateQuery.less_than_equal = to\n if (Object.keys(dateQuery).length > 0) {\n condition = { [fieldName]: dateQuery }\n }\n }\n break\n }\n case 'select': {\n const selectValue = value as SelectFilterValue\n if (selectValue.selectedValues && selectValue.selectedValues.length > 0) {\n if (selectValue.selectedValues.length === 1) {\n condition = { [fieldName]: { equals: selectValue.selectedValues[0] } }\n } else {\n condition = { [fieldName]: { in: selectValue.selectedValues } }\n }\n }\n break\n }\n case 'checkbox': {\n const checkboxState = value as CheckboxFilterState\n if (checkboxState === 'checked') {\n condition = { [fieldName]: { equals: 'true' } }\n } else if (checkboxState === 'unchecked') {\n condition = { [fieldName]: { equals: 'false' } }\n }\n break\n }\n }\n if (condition) {\n conditions.push(condition)\n }\n })\n return conditions\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\n// Translates URL query conditions to the quick filter's internal state\nconst parseWhereClauseToFilterValues = (\n where: any,\n fields: FilterDetaild[],\n locale: SupportedLocale,\n): Record<string, any> => {\n const values: Record<string, any> = {}\n const fieldNames = new Set(fields.map((f) => f.name))\n\n const recursiveParse = (clause: any) => {\n if (!clause || typeof clause !== 'object') return\n\n if (clause.and) {\n clause.and.forEach(recursiveParse)\n return\n }\n if (clause.or) {\n if (clause.or.length > 1) {\n return\n }\n clause.or.forEach(recursiveParse)\n return\n }\n for (const fieldName in clause) {\n if (fieldNames.has(fieldName)) {\n const fieldDef = fields.find((f) => f.name === fieldName)\n const condition = clause[fieldName]\n\n if (fieldDef && condition && typeof condition === 'object') {\n if ('equals' in condition) {\n if (fieldDef.type === 'checkbox') {\n values[fieldName] = condition.equals == 'true' ? 'checked' : 'unchecked'\n } else if (fieldDef.type === 'select') {\n values[fieldName] = { selectedValues: [condition.equals] }\n }\n } else if ('in' in condition && Array.isArray(condition.in)) {\n if (fieldDef.type === 'select') {\n values[fieldName] = { selectedValues: condition.in }\n }\n } else if ('greater_than_equal' in condition || 'less_than_equal' in condition) {\n if (fieldDef.type === 'date') {\n const fromDate = condition.greater_than_equal\n ? new Date(condition.greater_than_equal)\n : null\n const toDate = condition.less_than_equal ? new Date(condition.less_than_equal) : null\n const allDateOptions = [...pastOptionKeys, ...futureOptionKeys]\n let matchedOption = null\n\n for (const option of allDateOptions) {\n const range = getDateRangeForOption(option, locale)\n let isFromMatch\n if (fromDate) {\n isFromMatch = range.from?.toDateString() === fromDate.toDateString()\n } else if (fromDate == null && range.to == undefined) {\n // all future: fromDate == null & range.to == undefined\n isFromMatch = true\n }\n let isToMatch\n if (toDate) {\n isToMatch = range.to?.toDateString() === toDate.toDateString()\n } else if (toDate == null && range.to == undefined) {\n // all future: fromDate == null & range.to == undefined\n isToMatch = true\n }\n\n if (isFromMatch && isToMatch) {\n matchedOption = option\n break\n }\n }\n\n if (matchedOption) {\n values[fieldName] = {\n type: 'predefined',\n predefinedValue: matchedOption,\n }\n } else {\n values[fieldName] = {\n type: 'custom',\n customRange: {\n from: fromDate,\n to: toDate,\n },\n }\n }\n }\n }\n }\n }\n }\n }\n\n recursiveParse(where)\n return values\n}\n\nconst QuickFilter = ({\n slug,\n filterList,\n}: {\n slug: string\n filterList: (string | { name: string; width: 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.name,\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 return {\n name: fieldName,\n label: translatedLabel as string,\n type: field.type,\n options: (field as SelectField).options as OptionObject[],\n row: fieldConfig ? fieldConfig.rowIndex : 0,\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(fields.map((f) => f.name))\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) => f.name === fieldName)\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 <FilterField\n key={field.name}\n field={field}\n onFilterChange={handleFilterChange}\n value={filterValues[field.name]}\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","getDateRangeForOption","isEqual","futureOptionKeys","getDateFilterOptions","pastOptionKeys","Button","getLocalizedLabel","label","locale","Object","values","findFieldsByName","fields","fieldNames","results","recursiveSearch","currentFields","filteredFields","filter","field","includes","name","push","forEach","item","type","Array","isArray","tabs","tab","blocks","block","buildQuickFilterConditions","fieldDefs","conditions","entries","fieldName","value","fieldDef","find","f","condition","dateValue","from","to","predefinedValue","range","customRange","Date","dateQuery","greater_than_equal","less_than_equal","keys","length","selectValue","selectedValues","equals","in","checkboxState","cleanWhereClause","clause","fieldsToClean","newClause","key","cleanedSubClauses","map","subClause","Boolean","has","and","or","parseWhereClauseToFilterValues","where","Set","recursiveParse","fromDate","toDate","allDateOptions","matchedOption","option","isFromMatch","toDateString","undefined","isToMatch","QuickFilter","slug","filterList","setFields","filterRows","setFilterRows","showFilters","setShowFilters","refineListData","query","getEntityConfig","i18n","language","filterValues","setFilterValues","collection","collectionSlug","flattenedFieldConfigs","flatMap","row","rowIndex","fieldIndex","matchedFields","simplifiedFields","translatedLabel","fieldConfig","options","width","sortedFields","valuesFromQuery","quickFilterConditions","quickFilterFieldNames","otherFilters","allConditions","newWhere","refinedData","page","then","r","console","log","handleFilterChange","prev","newValues","getActiveFiltersDetails","activeFilters","dateDescription","pastOptions","futureOptions","allOptions","opt","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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"}
|
|
@@ -203,7 +203,7 @@ export function SelectFilter({ label, options, value, onChange, placeholder, loc
|
|
|
203
203
|
}),
|
|
204
204
|
multiSelect && selectedValues.length > 0 && selectedValues.length < options.length && /*#__PURE__*/ _jsx("div", {
|
|
205
205
|
className: "flex flex-wrap gap-1 mt-2",
|
|
206
|
-
children: selectedValues.map((value)=>{
|
|
206
|
+
children: selectedValues.map((value, index)=>{
|
|
207
207
|
const option = options.find((opt)=>opt.value === value);
|
|
208
208
|
return /*#__PURE__*/ _jsxs(Badge, {
|
|
209
209
|
variant: "secondary",
|
|
@@ -216,7 +216,7 @@ export function SelectFilter({ label, options, value, onChange, placeholder, loc
|
|
|
216
216
|
children: "×"
|
|
217
217
|
})
|
|
218
218
|
]
|
|
219
|
-
}, value);
|
|
219
|
+
}, value + index);
|
|
220
220
|
})
|
|
221
221
|
})
|
|
222
222
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/filters/components/select-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { Check, ChevronsUpDown, X } from 'lucide-react';\nimport { Locale, SelectFilterOption, SelectFilterValue } from '../types/filters-type';\nimport { Label } from '../../ui/label';\nimport { cn } from '../../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover';\nimport { Button } from '../../ui/button';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../../ui/command';\nimport { Checkbox } from '../../ui/checkbox';\nimport { Badge } from '../../ui/badge';\nimport { SupportedLocale, getLabel } from '../../labels';\n\ninterface SelectFilterProps {\n label?: string;\n options: SelectFilterOption[];\n value?: SelectFilterValue;\n onChange: (value: SelectFilterValue) => void;\n placeholder?: string;\n locale?: Locale;\n className?: string;\n multiSelect?: boolean;\n style?: React.CSSProperties;\n}\n\nexport function SelectFilter({\n label,\n options,\n value,\n onChange,\n placeholder,\n locale = { code: 'he', direction: 'rtl' },\n className,\n multiSelect = true,\n style,\n}: SelectFilterProps) {\n const [open, setOpen] = useState(false);\n const [internalValue, setInternalValue] = useState<SelectFilterValue | undefined>(value);\n\n const isRtl = locale?.direction === 'rtl';\n const showSearch = options.length > 10;\n const showSelectAll = multiSelect && options.length > 3;\n\n // Sync internal state with external value prop\n useEffect(() => {\n setInternalValue(value);\n }, [value]);\n\n const selectedValues = internalValue?.selectedValues || [];\n const allSelected = selectedValues.length === options.length;\n\n const labels = {\n selectAll: getLabel('all', locale.code),\n deselectAll: getLabel('all', locale.code),\n search: getLabel('selectOption', locale.code),\n noResults: getLabel('custom', locale.code),\n selected: getLabel('selectOption', locale.code),\n selectedOne: getLabel('selectOption', locale.code),\n };\n\n const getFilterValue = (values: string[]): SelectFilterValue => {\n if (values.length === 0) {\n return { type: 'none', selectedValues: [] };\n } else if (values.length === options.length) {\n return { type: 'all', selectedValues: values };\n } else {\n return { type: 'some', selectedValues: values };\n }\n };\n\n const handleSelectAll = () => {\n const allValues = options.map((option) => option.value);\n const newValue = getFilterValue(allValues);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleClearAll = () => {\n const newValue = getFilterValue([]);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleToggleSelectAll = () => {\n if (allSelected) {\n handleClearAll();\n } else {\n handleSelectAll();\n }\n };\n\n const handleToggleOption = (optionValue: string) => {\n let newValues: string[];\n\n if (multiSelect) {\n newValues = selectedValues.includes(optionValue)\n ? selectedValues.filter((val) => val !== optionValue)\n : [...selectedValues, optionValue];\n } else {\n newValues = [optionValue];\n setOpen(false);\n }\n\n const newValue = getFilterValue(newValues);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const getDisplayText = () => {\n if (selectedValues.length === 0) {\n return placeholder || getLabel('selectOption', locale.code);\n } else if (selectedValues.length === options.length) {\n return labels.selectAll;\n } else {\n return `${selectedValues.length} ${selectedValues.length > 1 ? labels.selected : labels.selectedOne} `;\n }\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 className='relative'>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant='outline'\n role='combobox'\n aria-expanded={open}\n className='w-full justify-between bg-background relative'\n >\n <span className='truncate'>{getDisplayText()}</span>\n <ChevronsUpDown className='h-4 w-4 shrink-0 opacity-50' />\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-80 p-0' align='start'>\n <Command>\n {showSearch && <CommandInput placeholder={labels.search} />}\n <CommandList>\n <CommandEmpty>{labels.noResults}</CommandEmpty>\n <CommandGroup>\n {showSelectAll && (\n <CommandItem onSelect={handleToggleSelectAll}>\n <div\n className={cn(\n 'useTw flex items-center w-full justify-between',\n isRtl && 'flex-row-reverse',\n )}\n >\n <Checkbox\n checked={allSelected}\n className={cn(isRtl ? 'useTw ml-2' : 'useTw mr-2')}\n />\n <span className={cn(isRtl && 'useTw text-right flex-1 mr-2')}>\n {allSelected ? labels.deselectAll : labels.selectAll}\n </span>\n </div>\n </CommandItem>\n )}\n {options.map((option) => (\n <CommandItem\n key={option.value}\n onSelect={() => handleToggleOption(option.value)}\n >\n <div\n className={cn(\n 'flex items-center w-full justify-between',\n isRtl && 'flex-row-reverse',\n )}\n >\n {multiSelect ? (\n <Checkbox\n checked={selectedValues.includes(option.value)}\n className={cn(isRtl ? 'useTw ml-2' : 'useTw mx-2')}\n />\n ) : (\n <Check\n className={cn(\n 'useTw h-4 w-4',\n isRtl ? 'ml-2' : 'mr-2',\n selectedValues.includes(option.value) ? 'opacity-100' : 'opacity-0',\n )}\n />\n )}\n <span className={cn(isRtl && 'text-right flex-1')}>{option.label}</span>\n </div>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n {selectedValues.length > 0 && (\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='h-3 w-3' />\n </button>\n )}\n </div>\n\n {multiSelect && selectedValues.length > 0 && selectedValues.length < options.length && (\n <div className='flex flex-wrap gap-1 mt-2'>\n {selectedValues.map((value) => {\n const option = options.find((opt) => opt.value === value);\n return (\n <Badge key={value} variant='secondary' className='text-xs bg-background border'>\n {option?.label || value}\n <button\n className='ml-1 hover:bg-muted rounded-full'\n onClick={() => handleToggleOption(value)}\n >\n ×\n </button>\n </Badge>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"names":["useEffect","useState","Check","ChevronsUpDown","X","Label","cn","Popover","PopoverContent","PopoverTrigger","Button","Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","Checkbox","Badge","getLabel","SelectFilter","label","options","value","onChange","placeholder","locale","code","direction","className","multiSelect","style","open","setOpen","internalValue","setInternalValue","isRtl","showSearch","length","showSelectAll","selectedValues","allSelected","labels","selectAll","deselectAll","search","noResults","selected","selectedOne","getFilterValue","values","type","handleSelectAll","allValues","map","option","newValue","handleClearAll","handleToggleSelectAll","handleToggleOption","optionValue","newValues","includes","filter","val","getDisplayText","div","dir","onOpenChange","asChild","variant","role","aria-expanded","span","align","onSelect","checked","button","onClick","e","stopPropagation","find","opt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/filters/components/select-filter.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { Check, ChevronsUpDown, X } from 'lucide-react';\nimport { Locale, SelectFilterOption, SelectFilterValue } from '../types/filters-type';\nimport { Label } from '../../ui/label';\nimport { cn } from '../../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover';\nimport { Button } from '../../ui/button';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../../ui/command';\nimport { Checkbox } from '../../ui/checkbox';\nimport { Badge } from '../../ui/badge';\nimport { SupportedLocale, getLabel } from '../../labels';\n\ninterface SelectFilterProps {\n label?: string;\n options: SelectFilterOption[];\n value?: SelectFilterValue;\n onChange: (value: SelectFilterValue) => void;\n placeholder?: string;\n locale?: Locale;\n className?: string;\n multiSelect?: boolean;\n style?: React.CSSProperties;\n}\n\nexport function SelectFilter({\n label,\n options,\n value,\n onChange,\n placeholder,\n locale = { code: 'he', direction: 'rtl' },\n className,\n multiSelect = true,\n style,\n}: SelectFilterProps) {\n const [open, setOpen] = useState(false);\n const [internalValue, setInternalValue] = useState<SelectFilterValue | undefined>(value);\n\n const isRtl = locale?.direction === 'rtl';\n const showSearch = options.length > 10;\n const showSelectAll = multiSelect && options.length > 3;\n\n // Sync internal state with external value prop\n useEffect(() => {\n setInternalValue(value);\n }, [value]);\n\n const selectedValues = internalValue?.selectedValues || [];\n const allSelected = selectedValues.length === options.length;\n\n const labels = {\n selectAll: getLabel('all', locale.code),\n deselectAll: getLabel('all', locale.code),\n search: getLabel('selectOption', locale.code),\n noResults: getLabel('custom', locale.code),\n selected: getLabel('selectOption', locale.code),\n selectedOne: getLabel('selectOption', locale.code),\n };\n\n const getFilterValue = (values: string[]): SelectFilterValue => {\n if (values.length === 0) {\n return { type: 'none', selectedValues: [] };\n } else if (values.length === options.length) {\n return { type: 'all', selectedValues: values };\n } else {\n return { type: 'some', selectedValues: values };\n }\n };\n\n const handleSelectAll = () => {\n const allValues = options.map((option) => option.value);\n const newValue = getFilterValue(allValues);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleClearAll = () => {\n const newValue = getFilterValue([]);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const handleToggleSelectAll = () => {\n if (allSelected) {\n handleClearAll();\n } else {\n handleSelectAll();\n }\n };\n\n const handleToggleOption = (optionValue: string) => {\n let newValues: string[];\n\n if (multiSelect) {\n newValues = selectedValues.includes(optionValue)\n ? selectedValues.filter((val) => val !== optionValue)\n : [...selectedValues, optionValue];\n } else {\n newValues = [optionValue];\n setOpen(false);\n }\n\n const newValue = getFilterValue(newValues);\n setInternalValue(newValue);\n onChange(newValue);\n };\n\n const getDisplayText = () => {\n if (selectedValues.length === 0) {\n return placeholder || getLabel('selectOption', locale.code);\n } else if (selectedValues.length === options.length) {\n return labels.selectAll;\n } else {\n return `${selectedValues.length} ${selectedValues.length > 1 ? labels.selected : labels.selectedOne} `;\n }\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 className='relative'>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant='outline'\n role='combobox'\n aria-expanded={open}\n className='w-full justify-between bg-background relative'\n >\n <span className='truncate'>{getDisplayText()}</span>\n <ChevronsUpDown className='h-4 w-4 shrink-0 opacity-50' />\n </Button>\n </PopoverTrigger>\n <PopoverContent className='useTw w-80 p-0' align='start'>\n <Command>\n {showSearch && <CommandInput placeholder={labels.search} />}\n <CommandList>\n <CommandEmpty>{labels.noResults}</CommandEmpty>\n <CommandGroup>\n {showSelectAll && (\n <CommandItem onSelect={handleToggleSelectAll}>\n <div\n className={cn(\n 'useTw flex items-center w-full justify-between',\n isRtl && 'flex-row-reverse',\n )}\n >\n <Checkbox\n checked={allSelected}\n className={cn(isRtl ? 'useTw ml-2' : 'useTw mr-2')}\n />\n <span className={cn(isRtl && 'useTw text-right flex-1 mr-2')}>\n {allSelected ? labels.deselectAll : labels.selectAll}\n </span>\n </div>\n </CommandItem>\n )}\n {options.map((option) => (\n <CommandItem\n key={option.value}\n onSelect={() => handleToggleOption(option.value)}\n >\n <div\n className={cn(\n 'flex items-center w-full justify-between',\n isRtl && 'flex-row-reverse',\n )}\n >\n {multiSelect ? (\n <Checkbox\n checked={selectedValues.includes(option.value)}\n className={cn(isRtl ? 'useTw ml-2' : 'useTw mx-2')}\n />\n ) : (\n <Check\n className={cn(\n 'useTw h-4 w-4',\n isRtl ? 'ml-2' : 'mr-2',\n selectedValues.includes(option.value) ? 'opacity-100' : 'opacity-0',\n )}\n />\n )}\n <span className={cn(isRtl && 'text-right flex-1')}>{option.label}</span>\n </div>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n {selectedValues.length > 0 && (\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='h-3 w-3' />\n </button>\n )}\n </div>\n\n {multiSelect && selectedValues.length > 0 && selectedValues.length < options.length && (\n <div className='flex flex-wrap gap-1 mt-2'>\n {selectedValues.map((value, index) => {\n const option = options.find((opt) => opt.value === value);\n return (\n <Badge key={value+index} variant='secondary' className='text-xs bg-background border'>\n {option?.label || value}\n <button\n className='ml-1 hover:bg-muted rounded-full'\n onClick={() => handleToggleOption(value)}\n >\n ×\n </button>\n </Badge>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"names":["useEffect","useState","Check","ChevronsUpDown","X","Label","cn","Popover","PopoverContent","PopoverTrigger","Button","Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","Checkbox","Badge","getLabel","SelectFilter","label","options","value","onChange","placeholder","locale","code","direction","className","multiSelect","style","open","setOpen","internalValue","setInternalValue","isRtl","showSearch","length","showSelectAll","selectedValues","allSelected","labels","selectAll","deselectAll","search","noResults","selected","selectedOne","getFilterValue","values","type","handleSelectAll","allValues","map","option","newValue","handleClearAll","handleToggleSelectAll","handleToggleOption","optionValue","newValues","includes","filter","val","getDisplayText","div","dir","onOpenChange","asChild","variant","role","aria-expanded","span","align","onSelect","checked","button","onClick","e","stopPropagation","index","find","opt"],"mappings":"AAAA;;AAEA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAC5C,SAASC,KAAK,EAAEC,cAAc,EAAEC,CAAC,QAAQ,eAAe;AAExD,SAASC,KAAK,QAAQ,iBAAiB;AACvC,SAASC,EAAE,QAAQ,kBAAkB;AACrC,SAASC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAQ,mBAAmB;AAC3E,SAASC,MAAM,QAAQ,kBAAkB;AACzC,SACEC,OAAO,EACPC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,WAAW,EACXC,WAAW,QACN,mBAAmB;AAC1B,SAASC,QAAQ,QAAQ,oBAAoB;AAC7C,SAASC,KAAK,QAAQ,iBAAiB;AACvC,SAA0BC,QAAQ,QAAQ,eAAe;AAczD,OAAO,SAASC,aAAa,EAC3BC,KAAK,EACLC,OAAO,EACPC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXC,SAAS;IAAEC,MAAM;IAAMC,WAAW;AAAM,CAAC,EACzCC,SAAS,EACTC,cAAc,IAAI,EAClBC,KAAK,EACa;IAClB,MAAM,CAACC,MAAMC,QAAQ,GAAGhC,SAAS;IACjC,MAAM,CAACiC,eAAeC,iBAAiB,GAAGlC,SAAwCsB;IAElF,MAAMa,QAAQV,QAAQE,cAAc;IACpC,MAAMS,aAAaf,QAAQgB,MAAM,GAAG;IACpC,MAAMC,gBAAgBT,eAAeR,QAAQgB,MAAM,GAAG;IAEtD,+CAA+C;IAC/CtC,UAAU;QACRmC,iBAAiBZ;IACnB,GAAG;QAACA;KAAM;IAEV,MAAMiB,iBAAiBN,eAAeM,kBAAkB,EAAE;IAC1D,MAAMC,cAAcD,eAAeF,MAAM,KAAKhB,QAAQgB,MAAM;IAE5D,MAAMI,SAAS;QACbC,WAAWxB,SAAS,OAAOO,OAAOC,IAAI;QACtCiB,aAAazB,SAAS,OAAOO,OAAOC,IAAI;QACxCkB,QAAQ1B,SAAS,gBAAgBO,OAAOC,IAAI;QAC5CmB,WAAW3B,SAAS,UAAUO,OAAOC,IAAI;QACzCoB,UAAU5B,SAAS,gBAAgBO,OAAOC,IAAI;QAC9CqB,aAAa7B,SAAS,gBAAgBO,OAAOC,IAAI;IACnD;IAEA,MAAMsB,iBAAiB,CAACC;QACtB,IAAIA,OAAOZ,MAAM,KAAK,GAAG;YACvB,OAAO;gBAAEa,MAAM;gBAAQX,gBAAgB,EAAE;YAAC;QAC5C,OAAO,IAAIU,OAAOZ,MAAM,KAAKhB,QAAQgB,MAAM,EAAE;YAC3C,OAAO;gBAAEa,MAAM;gBAAOX,gBAAgBU;YAAO;QAC/C,OAAO;YACL,OAAO;gBAAEC,MAAM;gBAAQX,gBAAgBU;YAAO;QAChD;IACF;IAEA,MAAME,kBAAkB;QACtB,MAAMC,YAAY/B,QAAQgC,GAAG,CAAC,CAACC,SAAWA,OAAOhC,KAAK;QACtD,MAAMiC,WAAWP,eAAeI;QAChClB,iBAAiBqB;QACjBhC,SAASgC;IACX;IAEA,MAAMC,iBAAiB;QACrB,MAAMD,WAAWP,eAAe,EAAE;QAClCd,iBAAiBqB;QACjBhC,SAASgC;IACX;IAEA,MAAME,wBAAwB;QAC5B,IAAIjB,aAAa;YACfgB;QACF,OAAO;YACLL;QACF;IACF;IAEA,MAAMO,qBAAqB,CAACC;QAC1B,IAAIC;QAEJ,IAAI/B,aAAa;YACf+B,YAAYrB,eAAesB,QAAQ,CAACF,eAChCpB,eAAeuB,MAAM,CAAC,CAACC,MAAQA,QAAQJ,eACvC;mBAAIpB;gBAAgBoB;aAAY;QACtC,OAAO;YACLC,YAAY;gBAACD;aAAY;YACzB3B,QAAQ;QACV;QAEA,MAAMuB,WAAWP,eAAeY;QAChC1B,iBAAiBqB;QACjBhC,SAASgC;IACX;IAEA,MAAMS,iBAAiB;QACrB,IAAIzB,eAAeF,MAAM,KAAK,GAAG;YAC/B,OAAOb,eAAeN,SAAS,gBAAgBO,OAAOC,IAAI;QAC5D,OAAO,IAAIa,eAAeF,MAAM,KAAKhB,QAAQgB,MAAM,EAAE;YACnD,OAAOI,OAAOC,SAAS;QACzB,OAAO;YACL,OAAO,GAAGH,eAAeF,MAAM,CAAC,CAAC,EAAEE,eAAeF,MAAM,GAAG,IAAII,OAAOK,QAAQ,GAAGL,OAAOM,WAAW,CAAC,CAAC,CAAC;QACxG;IACF;IAEA,qBACE,MAACkB;QAAIrC,WAAWvB,GAAG,aAAauB;QAAYsC,KAAKzC,OAAOE,SAAS;QAAEG,OAAOA;;YACvEV,uBACC,KAAChB;gBAAMwB,WAAWvB,GAAG,6BAA6B8B,SAAS;0BACxDf;;0BAIL,MAAC6C;gBAAIrC,WAAU;;kCACb,MAACtB;wBAAQyB,MAAMA;wBAAMoC,cAAcnC;;0CACjC,KAACxB;gCAAe4D,OAAO;0CACrB,cAAA,MAAC3D;oCACC4D,SAAQ;oCACRC,MAAK;oCACLC,iBAAexC;oCACfH,WAAU;;sDAEV,KAAC4C;4CAAK5C,WAAU;sDAAYoC;;sDAC5B,KAAC9D;4CAAe0B,WAAU;;;;;0CAG9B,KAACrB;gCAAeqB,WAAU;gCAAiB6C,OAAM;0CAC/C,cAAA,MAAC/D;;wCACE0B,4BAAc,KAACvB;4CAAaW,aAAaiB,OAAOG,MAAM;;sDACvD,MAAC7B;;8DACC,KAACJ;8DAAc8B,OAAOI,SAAS;;8DAC/B,MAACjC;;wDACE0B,+BACC,KAACxB;4DAAY4D,UAAUjB;sEACrB,cAAA,MAACQ;gEACCrC,WAAWvB,GACT,kDACA8B,SAAS;;kFAGX,KAACnB;wEACC2D,SAASnC;wEACTZ,WAAWvB,GAAG8B,QAAQ,eAAe;;kFAEvC,KAACqC;wEAAK5C,WAAWvB,GAAG8B,SAAS;kFAC1BK,cAAcC,OAAOE,WAAW,GAAGF,OAAOC,SAAS;;;;;wDAK3DrB,QAAQgC,GAAG,CAAC,CAACC,uBACZ,KAACxC;gEAEC4D,UAAU,IAAMhB,mBAAmBJ,OAAOhC,KAAK;0EAE/C,cAAA,MAAC2C;oEACCrC,WAAWvB,GACT,4CACA8B,SAAS;;wEAGVN,4BACC,KAACb;4EACC2D,SAASpC,eAAesB,QAAQ,CAACP,OAAOhC,KAAK;4EAC7CM,WAAWvB,GAAG8B,QAAQ,eAAe;2FAGvC,KAAClC;4EACC2B,WAAWvB,GACT,iBACA8B,QAAQ,SAAS,QACjBI,eAAesB,QAAQ,CAACP,OAAOhC,KAAK,IAAI,gBAAgB;;sFAI9D,KAACkD;4EAAK5C,WAAWvB,GAAG8B,SAAS;sFAAuBmB,OAAOlC,KAAK;;;;+DAvB7DkC,OAAOhC,KAAK;;;;;;;;;;oBAgC9BiB,eAAeF,MAAM,GAAG,mBACvB,KAACuC;wBACChD,WAAW,CAAC,eAAe,EAAEO,QAAQ,WAAW,UAAU,sGAAsG,CAAC;wBACjK0C,SAAS,CAACC;4BACRA,EAAEC,eAAe;4BACjBvB;wBACF;kCAEA,cAAA,KAACrD;4BAAEyB,WAAU;;;;;YAKlBC,eAAeU,eAAeF,MAAM,GAAG,KAAKE,eAAeF,MAAM,GAAGhB,QAAQgB,MAAM,kBACjF,KAAC4B;gBAAIrC,WAAU;0BACZW,eAAec,GAAG,CAAC,CAAC/B,OAAO0D;oBAC1B,MAAM1B,SAASjC,QAAQ4D,IAAI,CAAC,CAACC,MAAQA,IAAI5D,KAAK,KAAKA;oBACnD,qBACE,MAACL;wBAAwBoD,SAAQ;wBAAYzC,WAAU;;4BACpD0B,QAAQlC,SAASE;0CAClB,KAACsD;gCACChD,WAAU;gCACViD,SAAS,IAAMnB,mBAAmBpC;0CACnC;;;uBALSA,QAAM0D;gBAUtB;;;;AAKV"}
|