@osdk/react-components 0.19.0 → 0.19.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/build/browser/action-form/FormFieldApi.js.map +1 -1
- package/build/browser/action-form/utils/getDefaultFieldDefinitions.js +1 -0
- package/build/browser/action-form/utils/getDefaultFieldDefinitions.js.map +1 -1
- package/build/browser/filter-list/FilterInput.js +7 -0
- package/build/browser/filter-list/FilterInput.js.map +1 -1
- package/build/browser/filter-list/FilterList.js +8 -2
- package/build/browser/filter-list/FilterList.js.map +1 -1
- package/build/browser/filter-list/FilterListApi.js.map +1 -1
- package/build/browser/filter-list/FilterListItemApi.js.map +1 -1
- package/build/browser/filter-list/__tests__/aggregationMocks.js +50 -0
- package/build/browser/filter-list/__tests__/aggregationMocks.js.map +1 -0
- package/build/browser/filter-list/base/BaseFilterList.js.map +1 -1
- package/build/browser/filter-list/base/BaseFilterListApi.js.map +1 -1
- package/build/browser/filter-list/base/FilterInputExcludeRow.js +12 -16
- package/build/browser/filter-list/base/FilterInputExcludeRow.js.map +1 -1
- package/build/browser/filter-list/base/FilterListContent.js +42 -40
- package/build/browser/filter-list/base/FilterListContent.js.map +1 -1
- package/build/browser/filter-list/base/FilterListItem.js +8 -36
- package/build/browser/filter-list/base/FilterListItem.js.map +1 -1
- package/build/browser/filter-list/base/SortableFilterListItem.js +3 -1
- package/build/browser/filter-list/base/SortableFilterListItem.js.map +1 -1
- package/build/browser/filter-list/base/inputs/ListogramInput.js +3 -1
- package/build/browser/filter-list/base/inputs/ListogramInput.js.map +1 -1
- package/build/browser/filter-list/base/inputs/ListogramInput.module.css +6 -0
- package/build/browser/filter-list/base/inputs/MultiDateInput.js +2 -1
- package/build/browser/filter-list/base/inputs/MultiDateInput.js.map +1 -1
- package/build/browser/filter-list/base/inputs/MultiSelectInput.js +7 -3
- package/build/browser/filter-list/base/inputs/MultiSelectInput.js.map +1 -1
- package/build/browser/filter-list/base/inputs/MultiSelectInput.module.css +6 -0
- package/build/browser/filter-list/base/inputs/MultiSelectInput.module.css.js +1 -0
- package/build/browser/filter-list/base/inputs/SingleDateInput.js +4 -2
- package/build/browser/filter-list/base/inputs/SingleDateInput.js.map +1 -1
- package/build/browser/filter-list/hooks/useDualScopeAggregation.js +70 -0
- package/build/browser/filter-list/hooks/useDualScopeAggregation.js.map +1 -0
- package/build/browser/filter-list/hooks/useFilterListState.js +35 -17
- package/build/browser/filter-list/hooks/useFilterListState.js.map +1 -1
- package/build/browser/filter-list/hooks/useFilterPropertyAggregation.js +37 -0
- package/build/browser/filter-list/hooks/useFilterPropertyAggregation.js.map +1 -0
- package/build/browser/filter-list/hooks/usePropertyAggregation.js +7 -6
- package/build/browser/filter-list/hooks/usePropertyAggregation.js.map +1 -1
- package/build/browser/filter-list/inputs/LinkedPropertyInput.js +45 -22
- package/build/browser/filter-list/inputs/LinkedPropertyInput.js.map +1 -1
- package/build/browser/filter-list/inputs/ListogramFilterInput.js +9 -7
- package/build/browser/filter-list/inputs/ListogramFilterInput.js.map +1 -1
- package/build/browser/filter-list/inputs/MultiSelectFilterInput.js +8 -6
- package/build/browser/filter-list/inputs/MultiSelectFilterInput.js.map +1 -1
- package/build/browser/filter-list/inputs/PropertyFilterInput.js +10 -1
- package/build/browser/filter-list/inputs/PropertyFilterInput.js.map +1 -1
- package/build/browser/filter-list/inputs/SingleDateFilterInput.js +4 -2
- package/build/browser/filter-list/inputs/SingleDateFilterInput.js.map +1 -1
- package/build/browser/filter-list/inputs/SingleSelectFilterInput.js +9 -6
- package/build/browser/filter-list/inputs/SingleSelectFilterInput.js.map +1 -1
- package/build/browser/filter-list/inputs/StaticValuesFilterInput.js.map +1 -1
- package/build/browser/filter-list/types/CustomRendererTypes.js.map +1 -1
- package/build/browser/filter-list/types/KeywordSearchTypes.js.map +1 -1
- package/build/browser/filter-list/types/LinkedFilterTypes.js +42 -1
- package/build/browser/filter-list/types/LinkedFilterTypes.js.map +1 -1
- package/build/browser/filter-list/types/StaticValuesTypes.js.map +1 -1
- package/build/browser/filter-list/utils/filterStateToWhereClause.js +58 -22
- package/build/browser/filter-list/utils/filterStateToWhereClause.js.map +1 -1
- package/build/browser/filter-list/utils/filterValues.js +148 -2
- package/build/browser/filter-list/utils/filterValues.js.map +1 -1
- package/build/browser/filter-list/utils/narrowObjectSet.js +48 -0
- package/build/browser/filter-list/utils/narrowObjectSet.js.map +1 -0
- package/build/browser/public/experimental/filter-list.js +1 -0
- package/build/browser/public/experimental/filter-list.js.map +1 -1
- package/build/browser/styles.css +17 -0
- package/build/browser/tokens/component-tokens/filter-list.css +5 -0
- package/build/browser/util/UserAgent.js +1 -1
- package/build/browser/util/UserAgent.js.map +1 -1
- package/build/cjs/{chunk-6XRF4IAL.cjs → chunk-2AK24MNP.cjs} +4 -4
- package/build/cjs/{chunk-6XRF4IAL.cjs.map → chunk-2AK24MNP.cjs.map} +1 -1
- package/build/cjs/chunk-3DIODTDY.cjs +11 -0
- package/build/cjs/{chunk-774FGQHO.cjs.map → chunk-3DIODTDY.cjs.map} +1 -1
- package/build/cjs/{chunk-P7R4RWMU.cjs → chunk-3RKGMRPD.cjs} +4 -4
- package/build/cjs/{chunk-P7R4RWMU.cjs.map → chunk-3RKGMRPD.cjs.map} +1 -1
- package/build/cjs/chunk-ACIIYYEL.cjs +11 -0
- package/build/cjs/{chunk-62DGPKOC.cjs.map → chunk-ACIIYYEL.cjs.map} +1 -1
- package/build/cjs/{chunk-3OUALM3K.cjs → chunk-COLGW56W.cjs} +4 -4
- package/build/cjs/{chunk-3OUALM3K.cjs.map → chunk-COLGW56W.cjs.map} +1 -1
- package/build/cjs/{chunk-DKPG7O4B.cjs → chunk-GTFPQHZL.cjs} +5 -4
- package/build/cjs/chunk-GTFPQHZL.cjs.map +1 -0
- package/build/cjs/{chunk-L6QDNMMG.cjs → chunk-K3IJA7WZ.cjs} +4 -4
- package/build/cjs/{chunk-L6QDNMMG.cjs.map → chunk-K3IJA7WZ.cjs.map} +1 -1
- package/build/cjs/chunk-MAQSZDRT.cjs +11 -0
- package/build/cjs/{chunk-S25XCKOA.cjs.map → chunk-MAQSZDRT.cjs.map} +1 -1
- package/build/cjs/chunk-MHMRIDIM.cjs +11 -0
- package/build/cjs/{chunk-SLHKSOQC.cjs.map → chunk-MHMRIDIM.cjs.map} +1 -1
- package/build/cjs/{chunk-BXCHISUQ.cjs → chunk-NOONKE5X.cjs} +3 -3
- package/build/cjs/{chunk-BXCHISUQ.cjs.map → chunk-NOONKE5X.cjs.map} +1 -1
- package/build/cjs/chunk-OEESYGT4.cjs +11 -0
- package/build/cjs/{chunk-3Y4W37E3.cjs.map → chunk-OEESYGT4.cjs.map} +1 -1
- package/build/cjs/{chunk-QOI2FQSL.cjs → chunk-PUZZZTC7.cjs} +372 -157
- package/build/cjs/chunk-PUZZZTC7.cjs.map +1 -0
- package/build/cjs/{chunk-FIAYYZHY.cjs → chunk-QWKUCBXE.cjs} +4 -4
- package/build/cjs/{chunk-FIAYYZHY.cjs.map → chunk-QWKUCBXE.cjs.map} +1 -1
- package/build/cjs/public/experimental/action-form.cjs +4 -4
- package/build/cjs/public/experimental/action-form.d.cts +1 -1
- package/build/cjs/public/experimental/document-viewer.cjs +4 -4
- package/build/cjs/public/experimental/email-viewer.cjs +3 -3
- package/build/cjs/public/experimental/excel-viewer.cjs +3 -3
- package/build/cjs/public/experimental/filter-list.cjs +17 -13
- package/build/cjs/public/experimental/filter-list.css +8 -0
- package/build/cjs/public/experimental/filter-list.css.map +1 -1
- package/build/cjs/public/experimental/filter-list.d.cts +95 -25
- package/build/cjs/public/experimental/image-viewer.cjs +3 -3
- package/build/cjs/public/experimental/markdown-renderer.cjs +3 -3
- package/build/cjs/public/experimental/object-table.cjs +8 -8
- package/build/cjs/public/experimental/pdf-viewer.cjs +7 -7
- package/build/cjs/public/experimental/tiff-renderer.cjs +3 -3
- package/build/cjs/public/experimental/video-viewer.cjs +3 -3
- package/build/cjs/public/experimental/xml-viewer.cjs +3 -3
- package/build/cjs/public/experimental.cjs +50 -46
- package/build/cjs/public/experimental.css +8 -0
- package/build/cjs/public/experimental.css.map +1 -1
- package/build/cjs/public/experimental.d.cts +1 -1
- package/build/esm/action-form/FormFieldApi.js.map +1 -1
- package/build/esm/action-form/utils/getDefaultFieldDefinitions.js +1 -0
- package/build/esm/action-form/utils/getDefaultFieldDefinitions.js.map +1 -1
- package/build/esm/filter-list/FilterInput.js +7 -0
- package/build/esm/filter-list/FilterInput.js.map +1 -1
- package/build/esm/filter-list/FilterList.js +8 -2
- package/build/esm/filter-list/FilterList.js.map +1 -1
- package/build/esm/filter-list/FilterListApi.js.map +1 -1
- package/build/esm/filter-list/FilterListItemApi.js.map +1 -1
- package/build/esm/filter-list/__tests__/aggregationMocks.js +50 -0
- package/build/esm/filter-list/__tests__/aggregationMocks.js.map +1 -0
- package/build/esm/filter-list/base/BaseFilterList.js.map +1 -1
- package/build/esm/filter-list/base/BaseFilterListApi.js.map +1 -1
- package/build/esm/filter-list/base/FilterInputExcludeRow.js +12 -16
- package/build/esm/filter-list/base/FilterInputExcludeRow.js.map +1 -1
- package/build/esm/filter-list/base/FilterListContent.js +42 -40
- package/build/esm/filter-list/base/FilterListContent.js.map +1 -1
- package/build/esm/filter-list/base/FilterListItem.js +8 -36
- package/build/esm/filter-list/base/FilterListItem.js.map +1 -1
- package/build/esm/filter-list/base/SortableFilterListItem.js +3 -1
- package/build/esm/filter-list/base/SortableFilterListItem.js.map +1 -1
- package/build/esm/filter-list/base/inputs/ListogramInput.js +3 -1
- package/build/esm/filter-list/base/inputs/ListogramInput.js.map +1 -1
- package/build/esm/filter-list/base/inputs/ListogramInput.module.css +6 -0
- package/build/esm/filter-list/base/inputs/MultiDateInput.js +2 -1
- package/build/esm/filter-list/base/inputs/MultiDateInput.js.map +1 -1
- package/build/esm/filter-list/base/inputs/MultiSelectInput.js +7 -3
- package/build/esm/filter-list/base/inputs/MultiSelectInput.js.map +1 -1
- package/build/esm/filter-list/base/inputs/MultiSelectInput.module.css +6 -0
- package/build/esm/filter-list/base/inputs/SingleDateInput.js +4 -2
- package/build/esm/filter-list/base/inputs/SingleDateInput.js.map +1 -1
- package/build/esm/filter-list/hooks/useDualScopeAggregation.js +70 -0
- package/build/esm/filter-list/hooks/useDualScopeAggregation.js.map +1 -0
- package/build/esm/filter-list/hooks/useFilterListState.js +35 -17
- package/build/esm/filter-list/hooks/useFilterListState.js.map +1 -1
- package/build/esm/filter-list/hooks/useFilterPropertyAggregation.js +37 -0
- package/build/esm/filter-list/hooks/useFilterPropertyAggregation.js.map +1 -0
- package/build/esm/filter-list/hooks/usePropertyAggregation.js +7 -6
- package/build/esm/filter-list/hooks/usePropertyAggregation.js.map +1 -1
- package/build/esm/filter-list/inputs/LinkedPropertyInput.js +45 -22
- package/build/esm/filter-list/inputs/LinkedPropertyInput.js.map +1 -1
- package/build/esm/filter-list/inputs/ListogramFilterInput.js +9 -7
- package/build/esm/filter-list/inputs/ListogramFilterInput.js.map +1 -1
- package/build/esm/filter-list/inputs/MultiSelectFilterInput.js +8 -6
- package/build/esm/filter-list/inputs/MultiSelectFilterInput.js.map +1 -1
- package/build/esm/filter-list/inputs/PropertyFilterInput.js +10 -1
- package/build/esm/filter-list/inputs/PropertyFilterInput.js.map +1 -1
- package/build/esm/filter-list/inputs/SingleDateFilterInput.js +4 -2
- package/build/esm/filter-list/inputs/SingleDateFilterInput.js.map +1 -1
- package/build/esm/filter-list/inputs/SingleSelectFilterInput.js +9 -6
- package/build/esm/filter-list/inputs/SingleSelectFilterInput.js.map +1 -1
- package/build/esm/filter-list/inputs/StaticValuesFilterInput.js.map +1 -1
- package/build/esm/filter-list/types/CustomRendererTypes.js.map +1 -1
- package/build/esm/filter-list/types/KeywordSearchTypes.js.map +1 -1
- package/build/esm/filter-list/types/LinkedFilterTypes.js +42 -1
- package/build/esm/filter-list/types/LinkedFilterTypes.js.map +1 -1
- package/build/esm/filter-list/types/StaticValuesTypes.js.map +1 -1
- package/build/esm/filter-list/utils/filterStateToWhereClause.js +58 -22
- package/build/esm/filter-list/utils/filterStateToWhereClause.js.map +1 -1
- package/build/esm/filter-list/utils/filterValues.js +148 -2
- package/build/esm/filter-list/utils/filterValues.js.map +1 -1
- package/build/esm/filter-list/utils/narrowObjectSet.js +48 -0
- package/build/esm/filter-list/utils/narrowObjectSet.js.map +1 -0
- package/build/esm/public/experimental/filter-list.js +1 -0
- package/build/esm/public/experimental/filter-list.js.map +1 -1
- package/build/esm/tokens/component-tokens/filter-list.css +5 -0
- package/build/esm/util/UserAgent.js +1 -1
- package/build/esm/util/UserAgent.js.map +1 -1
- package/build/types/action-form/FormFieldApi.d.ts +1 -1
- package/build/types/action-form/FormFieldApi.d.ts.map +1 -1
- package/build/types/filter-list/FilterInput.d.ts +6 -1
- package/build/types/filter-list/FilterInput.d.ts.map +1 -1
- package/build/types/filter-list/FilterList.d.ts.map +1 -1
- package/build/types/filter-list/FilterListApi.d.ts +30 -15
- package/build/types/filter-list/FilterListApi.d.ts.map +1 -1
- package/build/types/filter-list/FilterListItemApi.d.ts +15 -1
- package/build/types/filter-list/FilterListItemApi.d.ts.map +1 -1
- package/build/types/filter-list/__tests__/aggregationMocks.d.ts +11 -0
- package/build/types/filter-list/__tests__/aggregationMocks.d.ts.map +1 -0
- package/build/types/filter-list/base/BaseFilterList.d.ts +2 -1
- package/build/types/filter-list/base/BaseFilterList.d.ts.map +1 -1
- package/build/types/filter-list/base/BaseFilterListApi.d.ts +2 -2
- package/build/types/filter-list/base/BaseFilterListApi.d.ts.map +1 -1
- package/build/types/filter-list/base/FilterInputExcludeRow.d.ts.map +1 -1
- package/build/types/filter-list/base/FilterListContent.d.ts +3 -3
- package/build/types/filter-list/base/FilterListContent.d.ts.map +1 -1
- package/build/types/filter-list/base/FilterListItem.d.ts +2 -1
- package/build/types/filter-list/base/FilterListItem.d.ts.map +1 -1
- package/build/types/filter-list/base/SortableFilterListItem.d.ts +2 -1
- package/build/types/filter-list/base/SortableFilterListItem.d.ts.map +1 -1
- package/build/types/filter-list/base/inputs/ListogramInput.d.ts.map +1 -1
- package/build/types/filter-list/base/inputs/MultiDateInput.d.ts.map +1 -1
- package/build/types/filter-list/base/inputs/MultiSelectInput.d.ts.map +1 -1
- package/build/types/filter-list/base/inputs/SingleDateInput.d.ts +2 -0
- package/build/types/filter-list/base/inputs/SingleDateInput.d.ts.map +1 -1
- package/build/types/filter-list/hooks/useDualScopeAggregation.d.ts +32 -0
- package/build/types/filter-list/hooks/useDualScopeAggregation.d.ts.map +1 -0
- package/build/types/filter-list/hooks/useFilterListState.d.ts +7 -0
- package/build/types/filter-list/hooks/useFilterListState.d.ts.map +1 -1
- package/build/types/filter-list/hooks/useFilterPropertyAggregation.d.ts +13 -0
- package/build/types/filter-list/hooks/useFilterPropertyAggregation.d.ts.map +1 -0
- package/build/types/filter-list/inputs/LinkedPropertyInput.d.ts +6 -4
- package/build/types/filter-list/inputs/LinkedPropertyInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/ListogramFilterInput.d.ts +4 -1
- package/build/types/filter-list/inputs/ListogramFilterInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/MultiSelectFilterInput.d.ts +4 -1
- package/build/types/filter-list/inputs/MultiSelectFilterInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/PropertyFilterInput.d.ts +4 -1
- package/build/types/filter-list/inputs/PropertyFilterInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/SingleDateFilterInput.d.ts +7 -1
- package/build/types/filter-list/inputs/SingleDateFilterInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/SingleSelectFilterInput.d.ts +4 -1
- package/build/types/filter-list/inputs/SingleSelectFilterInput.d.ts.map +1 -1
- package/build/types/filter-list/inputs/StaticValuesFilterInput.d.ts +1 -1
- package/build/types/filter-list/types/CustomRendererTypes.d.ts +2 -2
- package/build/types/filter-list/types/CustomRendererTypes.d.ts.map +1 -1
- package/build/types/filter-list/types/KeywordSearchTypes.d.ts +2 -2
- package/build/types/filter-list/types/KeywordSearchTypes.d.ts.map +1 -1
- package/build/types/filter-list/types/LinkedFilterTypes.d.ts +34 -4
- package/build/types/filter-list/types/LinkedFilterTypes.d.ts.map +1 -1
- package/build/types/filter-list/types/StaticValuesTypes.d.ts +2 -2
- package/build/types/filter-list/types/StaticValuesTypes.d.ts.map +1 -1
- package/build/types/filter-list/utils/filterStateToWhereClause.d.ts +24 -1
- package/build/types/filter-list/utils/filterStateToWhereClause.d.ts.map +1 -1
- package/build/types/filter-list/utils/filterValues.d.ts +26 -0
- package/build/types/filter-list/utils/filterValues.d.ts.map +1 -1
- package/build/types/filter-list/utils/narrowObjectSet.d.ts +7 -0
- package/build/types/filter-list/utils/narrowObjectSet.d.ts.map +1 -0
- package/build/types/public/experimental/filter-list.d.ts +3 -1
- package/build/types/public/experimental/filter-list.d.ts.map +1 -1
- package/docs/CSSVariables.md +78 -17
- package/docs/FilterList.md +52 -6
- package/package.json +9 -9
- package/build/cjs/chunk-3Y4W37E3.cjs +0 -11
- package/build/cjs/chunk-62DGPKOC.cjs +0 -11
- package/build/cjs/chunk-774FGQHO.cjs +0 -11
- package/build/cjs/chunk-DKPG7O4B.cjs.map +0 -1
- package/build/cjs/chunk-QOI2FQSL.cjs.map +0 -1
- package/build/cjs/chunk-S25XCKOA.cjs +0 -11
- package/build/cjs/chunk-SLHKSOQC.cjs +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiDateInput.js","names":["Button","classnames","React","memo","useCallback","DatePicker","formatDateForDisplay","formatDateForInput","styles","sharedStyles","MultiDateInputInner","selectedDates","onChange","className","style","minDate","maxDate","showClearAll","formatDate","addDate","date","dateStr","exists","some","d","sort","a","b","getTime","removeDate","filter","clearAll","createElement","multiDate","length","tagContainer","map","DateTag","key","toISOString","onRemove","onClick","calendarContainer","value","min","max","ariaLabel","modal","MultiDateInput","handleRemove","label","tag","tagRemove"],"sources":["MultiDateInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback } from \"react\";\nimport { DatePicker } from \"../../../shared/calendar/index.js\";\nimport {\n formatDateForDisplay,\n formatDateForInput,\n} from \"../../../shared/dateUtils.js\";\nimport styles from \"./MultiDateInput.module.css\";\nimport sharedStyles from \"./shared.module.css\";\n\ninterface MultiDateInputProps {\n selectedDates: Date[];\n onChange: (dates: Date[]) => void;\n className?: string;\n style?: React.CSSProperties;\n minDate?: Date;\n maxDate?: Date;\n showClearAll?: boolean;\n /**\n * Consumer-provided display formatter for chip text. Falls back to\n * `formatDateForDisplay` (locale-aware) when omitted.\n */\n formatDate?: (date: Date) => string;\n}\n\nfunction MultiDateInputInner({\n selectedDates,\n onChange,\n className,\n style,\n minDate,\n maxDate,\n showClearAll = true,\n formatDate,\n}: MultiDateInputProps): React.ReactElement {\n const addDate = useCallback(\n (date: Date | null) => {\n if (date == null) return;\n const dateStr = formatDateForInput(date);\n const exists = selectedDates.some(\n (d) => formatDateForInput(d) === dateStr,\n );\n if (!exists) {\n onChange(\n [...selectedDates, date].sort((a, b) => a.getTime() - b.getTime()),\n );\n }\n },\n [selectedDates, onChange],\n );\n\n const removeDate = useCallback(\n (date: Date) => {\n const dateStr = formatDateForInput(date);\n onChange(\n selectedDates.filter((d) => formatDateForInput(d) !== dateStr),\n );\n },\n [selectedDates, onChange],\n );\n\n const clearAll = useCallback(() => {\n onChange([]);\n }, [onChange]);\n\n return (\n <div className={classnames(styles.multiDate, className)} style={style}>\n {selectedDates.length > 0 && (\n <div className={sharedStyles.tagContainer}>\n {selectedDates.map((date) => (\n <DateTag\n key={date.toISOString()}\n date={date}\n formatDate={formatDate}\n onRemove={removeDate}\n />\n ))}\n {showClearAll && selectedDates.length > 1 && (\n <Button\n className={styles.clearAll}\n onClick={clearAll}\n aria-label=\"Clear all dates\"\n >\n Clear all\n </Button>\n )}\n </div>\n )}\n\n <div className={styles.calendarContainer}>\n <DatePicker\n value={null}\n onChange={addDate}\n min={minDate}\n max={maxDate}\n ariaLabel=\"Add date\"\n modal={false}\n />\n </div>\n </div>\n );\n}\n\nexport const MultiDateInput: React.NamedExoticComponent<MultiDateInputProps> =\n memo(MultiDateInputInner);\n\ninterface DateTagProps {\n date: Date;\n formatDate: ((date: Date) => string) | undefined;\n onRemove: (date: Date) => void;\n}\n\nfunction DateTag(\n { date, formatDate, onRemove }: DateTagProps,\n): React.ReactElement {\n const handleRemove = useCallback(() => {\n onRemove(date);\n }, [onRemove, date]);\n const label = formatDate != null\n ? formatDate(date)\n : formatDateForDisplay(date);\n return (\n <span className={sharedStyles.tag}>\n {label}\n <Button\n className={sharedStyles.tagRemove}\n onClick={handleRemove}\n aria-label={`Remove ${label}`}\n >\n ×\n </Button>\n </span>\n );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,KAAK,IAAIC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AAChD,SAASC,UAAU,QAAQ,mCAAmC;AAC9D,SACEC,oBAAoB,EACpBC,kBAAkB,QACb,8BAA8B;AACrC,OAAOC,MAAM,MAAM,6BAA6B;AAChD,OAAOC,YAAY,MAAM,qBAAqB;AAiB9C,SAASC,mBAAmBA,CAAC;EAC3BC,aAAa;EACbC,QAAQ;EACRC,SAAS;EACTC,KAAK;EACLC,OAAO;EACPC,OAAO;EACPC,YAAY,GAAG,IAAI;EACnBC;AACmB,CAAC,EAAsB;EAC1C,MAAMC,OAAO,GAAGf,WAAW,CACxBgB,IAAiB,IAAK;IACrB,IAAIA,IAAI,IAAI,IAAI,EAAE;IAClB,MAAMC,OAAO,GAAGd,kBAAkB,CAACa,IAAI,CAAC;IACxC,MAAME,MAAM,GAAGX,aAAa,CAACY,IAAI,CAC9BC,CAAC,IAAKjB,kBAAkB,CAACiB,CAAC,CAAC,KAAKH,OACnC,CAAC;IACD,IAAI,CAACC,MAAM,EAAE;MACXV,QAAQ,CACN,CAAC,GAAGD,aAAa,EAAES,IAAI,CAAC,CAACK,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKD,CAAC,CAACE,OAAO,CAAC,CAAC,GAAGD,CAAC,CAACC,OAAO,CAAC,CAAC,CACnE,CAAC;IACH;EACF,CAAC,EACD,CAACjB,aAAa,EAAEC,QAAQ,CAC1B,CAAC;EAED,MAAMiB,UAAU,GAAGzB,WAAW,CAC3BgB,IAAU,IAAK;IACd,MAAMC,OAAO,GAAGd,kBAAkB,CAACa,IAAI,CAAC;IACxCR,QAAQ,CACND,aAAa,CAACmB,MAAM,CAAEN,CAAC,IAAKjB,kBAAkB,CAACiB,CAAC,CAAC,KAAKH,OAAO,CAC/D,CAAC;EACH,CAAC,EACD,CAACV,aAAa,EAAEC,QAAQ,CAC1B,CAAC;EAED,MAAMmB,QAAQ,GAAG3B,WAAW,CAAC,MAAM;IACjCQ,QAAQ,CAAC,EAAE,CAAC;EACd,CAAC,EAAE,CAACA,QAAQ,CAAC,CAAC;EAEd,oBACEV,KAAA,CAAA8B,aAAA;IAAKnB,SAAS,EAAEZ,UAAU,CAACO,MAAM,CAACyB,SAAS,EAAEpB,SAAS,CAAE;IAACC,KAAK,EAAEA;EAAM,GACnEH,aAAa,CAACuB,MAAM,GAAG,CAAC,iBACvBhC,KAAA,CAAA8B,aAAA;IAAKnB,SAAS,EAAEJ,YAAY,CAAC0B;EAAa,GACvCxB,aAAa,CAACyB,GAAG,CAAEhB,IAAI,iBACtBlB,KAAA,CAAA8B,aAAA,CAACK,OAAO;IACNC,GAAG,EAAElB,IAAI,CAACmB,WAAW,CAAC,CAAE;IACxBnB,IAAI,EAAEA,IAAK;IACXF,UAAU,EAAEA,UAAW;IACvBsB,QAAQ,EAAEX;EAAW,CACtB,CACF,CAAC,EACDZ,YAAY,IAAIN,aAAa,CAACuB,MAAM,GAAG,CAAC,iBACvChC,KAAA,CAAA8B,aAAA,CAAChC,MAAM;IACLa,SAAS,EAAEL,MAAM,CAACuB,QAAS;IAC3BU,OAAO,EAAEV,QAAS;IAClB,cAAW;EAAiB,GAC7B,WAEO,CAEP,CACN,eAED7B,KAAA,CAAA8B,aAAA;IAAKnB,SAAS,EAAEL,MAAM,CAACkC;EAAkB,gBACvCxC,KAAA,CAAA8B,aAAA,CAAC3B,UAAU;IACTsC,KAAK,EAAE,IAAK;IACZ/B,QAAQ,EAAEO,OAAQ;IAClByB,GAAG,EAAE7B,OAAQ;IACb8B,GAAG,EAAE7B,OAAQ;IACb8B,SAAS,EAAC,UAAU;IACpBC,KAAK,EAAE;
|
|
1
|
+
{"version":3,"file":"MultiDateInput.js","names":["Button","classnames","React","memo","useCallback","DatePicker","formatDateForDisplay","formatDateForInput","styles","sharedStyles","MultiDateInputInner","selectedDates","onChange","className","style","minDate","maxDate","showClearAll","formatDate","addDate","date","dateStr","exists","some","d","sort","a","b","getTime","removeDate","filter","clearAll","createElement","multiDate","length","tagContainer","map","DateTag","key","toISOString","onRemove","onClick","calendarContainer","value","min","max","ariaLabel","modal","MultiDateInput","handleRemove","label","tag","tagRemove"],"sources":["MultiDateInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback } from \"react\";\nimport { DatePicker } from \"../../../shared/calendar/index.js\";\nimport {\n formatDateForDisplay,\n formatDateForInput,\n} from \"../../../shared/dateUtils.js\";\nimport styles from \"./MultiDateInput.module.css\";\nimport sharedStyles from \"./shared.module.css\";\n\ninterface MultiDateInputProps {\n selectedDates: Date[];\n onChange: (dates: Date[]) => void;\n className?: string;\n style?: React.CSSProperties;\n minDate?: Date;\n maxDate?: Date;\n showClearAll?: boolean;\n /**\n * Consumer-provided display formatter for chip text. Falls back to\n * `formatDateForDisplay` (locale-aware) when omitted.\n */\n formatDate?: (date: Date) => string;\n}\n\nfunction MultiDateInputInner({\n selectedDates,\n onChange,\n className,\n style,\n minDate,\n maxDate,\n showClearAll = true,\n formatDate,\n}: MultiDateInputProps): React.ReactElement {\n const addDate = useCallback(\n (date: Date | null) => {\n if (date == null) return;\n const dateStr = formatDateForInput(date);\n const exists = selectedDates.some(\n (d) => formatDateForInput(d) === dateStr,\n );\n if (!exists) {\n onChange(\n [...selectedDates, date].sort((a, b) => a.getTime() - b.getTime()),\n );\n }\n },\n [selectedDates, onChange],\n );\n\n const removeDate = useCallback(\n (date: Date) => {\n const dateStr = formatDateForInput(date);\n onChange(\n selectedDates.filter((d) => formatDateForInput(d) !== dateStr),\n );\n },\n [selectedDates, onChange],\n );\n\n const clearAll = useCallback(() => {\n onChange([]);\n }, [onChange]);\n\n return (\n <div className={classnames(styles.multiDate, className)} style={style}>\n {selectedDates.length > 0 && (\n <div className={sharedStyles.tagContainer}>\n {selectedDates.map((date) => (\n <DateTag\n key={date.toISOString()}\n date={date}\n formatDate={formatDate}\n onRemove={removeDate}\n />\n ))}\n {showClearAll && selectedDates.length > 1 && (\n <Button\n className={styles.clearAll}\n onClick={clearAll}\n aria-label=\"Clear all dates\"\n >\n Clear all\n </Button>\n )}\n </div>\n )}\n\n <div className={styles.calendarContainer}>\n <DatePicker\n value={null}\n onChange={addDate}\n min={minDate}\n max={maxDate}\n ariaLabel=\"Add date\"\n modal={false}\n formatDate={formatDate}\n />\n </div>\n </div>\n );\n}\n\nexport const MultiDateInput: React.NamedExoticComponent<MultiDateInputProps> =\n memo(MultiDateInputInner);\n\ninterface DateTagProps {\n date: Date;\n formatDate: ((date: Date) => string) | undefined;\n onRemove: (date: Date) => void;\n}\n\nfunction DateTag(\n { date, formatDate, onRemove }: DateTagProps,\n): React.ReactElement {\n const handleRemove = useCallback(() => {\n onRemove(date);\n }, [onRemove, date]);\n const label = formatDate != null\n ? formatDate(date)\n : formatDateForDisplay(date);\n return (\n <span className={sharedStyles.tag}>\n {label}\n <Button\n className={sharedStyles.tagRemove}\n onClick={handleRemove}\n aria-label={`Remove ${label}`}\n >\n ×\n </Button>\n </span>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -63,18 +63,22 @@ function MultiSelectInputInner({
|
|
|
63
63
|
value,
|
|
64
64
|
count
|
|
65
65
|
}) => [value, count])), [stableValues]);
|
|
66
|
+
const selectedSet = useMemo(() => new Set(selectedValues), [selectedValues]);
|
|
66
67
|
const comboboxFilter = useMemo(() => renderValue ? createRenderValueFilter(renderValue) : undefined, [renderValue]);
|
|
67
68
|
const renderItem = useCallback(value => {
|
|
68
69
|
const isEmpty = isEmptyValue(value);
|
|
70
|
+
const count = countByValue.get(value) ?? 0;
|
|
71
|
+
const isFilteredOut = count === 0 && !selectedSet.has(value);
|
|
69
72
|
return /*#__PURE__*/React.createElement(Combobox.Item, {
|
|
70
73
|
key: value,
|
|
71
|
-
value: value
|
|
74
|
+
value: value,
|
|
75
|
+
className: isFilteredOut ? styles.filteredOutItem : undefined
|
|
72
76
|
}, /*#__PURE__*/React.createElement(Combobox.ItemIndicator, null), /*#__PURE__*/React.createElement("span", {
|
|
73
77
|
className: styles.itemLabel
|
|
74
78
|
}, isEmpty ? /*#__PURE__*/React.createElement(NoValueLabel, null) : renderValue ? renderValue(value) : value), showCounts && /*#__PURE__*/React.createElement("span", {
|
|
75
79
|
className: styles.itemCount
|
|
76
|
-
}, "(",
|
|
77
|
-
}, [countByValue, showCounts, renderValue]);
|
|
80
|
+
}, "(", count.toLocaleString(), ")"));
|
|
81
|
+
}, [countByValue, selectedSet, showCounts, renderValue]);
|
|
78
82
|
const renderChips = useCallback(selectedItems => /*#__PURE__*/React.createElement(React.Fragment, null, selectedItems.map(value => {
|
|
79
83
|
const isEmpty = isEmptyValue(value);
|
|
80
84
|
return /*#__PURE__*/React.createElement(Combobox.Chip, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelectInput.js","names":["classnames","React","memo","useCallback","useMemo","Combobox","isEmptyValue","useFilterListBoundary","createRenderValueFilter","MultiSelectDropdownLayout","MultiSelectInlineLayout","styles","NoValueLabel","SelectInputSkeleton","sharedStyles","useStableData","MultiSelectInputInner","values","isLoading","error","selectedValues","onChange","className","style","placeholder","showCounts","ariaLabel","renderValue","layout","collisionBoundary","handleValueChange","newValues","stableValues","items","map","value","countByValue","Map","count","comboboxFilter","undefined","renderItem","isEmpty","createElement","Item","key","ItemIndicator","itemLabel","itemCount","get","toLocaleString","renderChips","selectedItems","Fragment","Chip","ChipRemove","Input","length","isNoData","isReloading","multiSelect","srOnly","role","errorMessage","message","emptyMessage","Root","multiple","onValueChange","filter","MultiSelectInput"],"sources":["MultiSelectInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo } from \"react\";\nimport { Combobox } from \"../../../base-components/combobox/Combobox.js\";\nimport type { PropertyAggregationValue } from \"../../types/AggregationTypes.js\";\nimport { isEmptyValue } from \"../../utils/filterValues.js\";\nimport { useFilterListBoundary } from \"../FilterListBoundaryContext.js\";\nimport { createRenderValueFilter } from \"./comboboxFilter.js\";\nimport { MultiSelectDropdownLayout } from \"./MultiSelectDropdownLayout.js\";\nimport { MultiSelectInlineLayout } from \"./MultiSelectInlineLayout.js\";\nimport styles from \"./MultiSelectInput.module.css\";\nimport { NoValueLabel } from \"./NoValueLabel.js\";\nimport { SelectInputSkeleton } from \"./SelectInputSkeleton.js\";\nimport sharedStyles from \"./shared.module.css\";\nimport { useStableData } from \"./useStableData.js\";\n\n/**\n * Layout for the value list:\n * - `\"dropdown\"` (default): chips inline + portaled Combobox popup. Use when\n * the input drives its own surface (e.g. standalone in a row).\n * - `\"inline\"`: search input + always-visible value list rendered in flow.\n * Use when wrapping the input in your own popover so the values are\n * immediately visible without an extra inner trigger.\n */\nexport type MultiSelectInputLayout = \"dropdown\" | \"inline\";\n\ninterface MultiSelectInputProps {\n values: PropertyAggregationValue[];\n isLoading: boolean;\n error: Error | null;\n selectedValues: string[];\n onChange: (values: string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n showCounts?: boolean;\n ariaLabel?: string;\n renderValue?: (value: string) => React.ReactNode;\n layout?: MultiSelectInputLayout;\n}\n\nfunction MultiSelectInputInner({\n values,\n isLoading,\n error,\n selectedValues,\n onChange,\n className,\n style,\n placeholder = \"Select values...\",\n showCounts = true,\n ariaLabel = \"Search values\",\n renderValue,\n layout = \"dropdown\",\n}: MultiSelectInputProps): React.ReactElement {\n const collisionBoundary = useFilterListBoundary();\n\n const handleValueChange = useCallback(\n (newValues: string[] | null) => {\n onChange(newValues ?? []);\n },\n [onChange],\n );\n\n const stableValues = useStableData(values, isLoading);\n\n const items = useMemo(\n () => stableValues.map(({ value }) => value),\n [stableValues],\n );\n\n const countByValue = useMemo(\n () => new Map(stableValues.map(({ value, count }) => [value, count])),\n [stableValues],\n );\n\n const comboboxFilter = useMemo(\n () => renderValue ? createRenderValueFilter(renderValue) : undefined,\n [renderValue],\n );\n\n const renderItem = useCallback(\n (value: string) => {\n const isEmpty = isEmptyValue(value);\n return (\n <Combobox.Item key={value} value={value}>\n <Combobox.ItemIndicator />\n <span className={styles.itemLabel}>\n {isEmpty\n ? <NoValueLabel />\n : (renderValue ? renderValue(value) : value)}\n </span>\n {showCounts && (\n <span className={styles.itemCount}>\n ({(countByValue.get(value) ?? 0).toLocaleString()})\n </span>\n )}\n </Combobox.Item>\n );\n },\n [countByValue, showCounts, renderValue],\n );\n\n const renderChips = useCallback(\n (selectedItems: string[]) => (\n <>\n {selectedItems.map((value) => {\n const isEmpty = isEmptyValue(value);\n return (\n <Combobox.Chip\n key={value}\n aria-label={isEmpty ? \"No value\" : value}\n >\n {isEmpty\n ? <NoValueLabel />\n : (renderValue ? renderValue(value) : value)}\n <Combobox.ChipRemove />\n </Combobox.Chip>\n );\n })}\n <Combobox.Input\n placeholder={selectedItems.length > 0 ? \"\" : placeholder}\n aria-label={ariaLabel}\n />\n </>\n ),\n [placeholder, ariaLabel, renderValue],\n );\n\n const isNoData = !error && stableValues.length === 0;\n const isReloading = isLoading && stableValues.length > 0;\n\n return (\n <div\n className={classnames(styles.multiSelect, className)}\n style={style}\n data-loading={isReloading}\n >\n <span className={sharedStyles.srOnly} role=\"status\">\n {isLoading ? \"Loading options\" : \"\"}\n </span>\n\n {error && (\n <div className={sharedStyles.errorMessage}>\n Error loading options: {error.message}\n </div>\n )}\n\n {isNoData && isLoading && <SelectInputSkeleton />}\n {isNoData && !isLoading && (\n <div className={sharedStyles.emptyMessage}>\n No options available\n </div>\n )}\n\n {stableValues.length > 0 && (\n <Combobox.Root<string, true>\n multiple={true}\n value={selectedValues}\n onValueChange={handleValueChange}\n items={items}\n filter={comboboxFilter}\n >\n {layout === \"inline\"\n ? (\n <MultiSelectInlineLayout\n placeholder={placeholder}\n ariaLabel={ariaLabel}\n renderItem={renderItem}\n />\n )\n : (\n <MultiSelectDropdownLayout\n renderChips={renderChips}\n renderItem={renderItem}\n collisionBoundary={collisionBoundary}\n />\n )}\n </Combobox.Root>\n )}\n </div>\n );\n}\n\nexport const MultiSelectInput = memo(\n MultiSelectInputInner,\n) as typeof MultiSelectInputInner;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"MultiSelectInput.js","names":["classnames","React","memo","useCallback","useMemo","Combobox","isEmptyValue","useFilterListBoundary","createRenderValueFilter","MultiSelectDropdownLayout","MultiSelectInlineLayout","styles","NoValueLabel","SelectInputSkeleton","sharedStyles","useStableData","MultiSelectInputInner","values","isLoading","error","selectedValues","onChange","className","style","placeholder","showCounts","ariaLabel","renderValue","layout","collisionBoundary","handleValueChange","newValues","stableValues","items","map","value","countByValue","Map","count","selectedSet","Set","comboboxFilter","undefined","renderItem","isEmpty","get","isFilteredOut","has","createElement","Item","key","filteredOutItem","ItemIndicator","itemLabel","itemCount","toLocaleString","renderChips","selectedItems","Fragment","Chip","ChipRemove","Input","length","isNoData","isReloading","multiSelect","srOnly","role","errorMessage","message","emptyMessage","Root","multiple","onValueChange","filter","MultiSelectInput"],"sources":["MultiSelectInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo } from \"react\";\nimport { Combobox } from \"../../../base-components/combobox/Combobox.js\";\nimport type { PropertyAggregationValue } from \"../../types/AggregationTypes.js\";\nimport { isEmptyValue } from \"../../utils/filterValues.js\";\nimport { useFilterListBoundary } from \"../FilterListBoundaryContext.js\";\nimport { createRenderValueFilter } from \"./comboboxFilter.js\";\nimport { MultiSelectDropdownLayout } from \"./MultiSelectDropdownLayout.js\";\nimport { MultiSelectInlineLayout } from \"./MultiSelectInlineLayout.js\";\nimport styles from \"./MultiSelectInput.module.css\";\nimport { NoValueLabel } from \"./NoValueLabel.js\";\nimport { SelectInputSkeleton } from \"./SelectInputSkeleton.js\";\nimport sharedStyles from \"./shared.module.css\";\nimport { useStableData } from \"./useStableData.js\";\n\n/**\n * Layout for the value list:\n * - `\"dropdown\"` (default): chips inline + portaled Combobox popup. Use when\n * the input drives its own surface (e.g. standalone in a row).\n * - `\"inline\"`: search input + always-visible value list rendered in flow.\n * Use when wrapping the input in your own popover so the values are\n * immediately visible without an extra inner trigger.\n */\nexport type MultiSelectInputLayout = \"dropdown\" | \"inline\";\n\ninterface MultiSelectInputProps {\n values: PropertyAggregationValue[];\n isLoading: boolean;\n error: Error | null;\n selectedValues: string[];\n onChange: (values: string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n showCounts?: boolean;\n ariaLabel?: string;\n renderValue?: (value: string) => React.ReactNode;\n layout?: MultiSelectInputLayout;\n}\n\nfunction MultiSelectInputInner({\n values,\n isLoading,\n error,\n selectedValues,\n onChange,\n className,\n style,\n placeholder = \"Select values...\",\n showCounts = true,\n ariaLabel = \"Search values\",\n renderValue,\n layout = \"dropdown\",\n}: MultiSelectInputProps): React.ReactElement {\n const collisionBoundary = useFilterListBoundary();\n\n const handleValueChange = useCallback(\n (newValues: string[] | null) => {\n onChange(newValues ?? []);\n },\n [onChange],\n );\n\n const stableValues = useStableData(values, isLoading);\n\n const items = useMemo(\n () => stableValues.map(({ value }) => value),\n [stableValues],\n );\n\n const countByValue = useMemo(\n () => new Map(stableValues.map(({ value, count }) => [value, count])),\n [stableValues],\n );\n\n const selectedSet = useMemo(\n () => new Set(selectedValues),\n [selectedValues],\n );\n\n const comboboxFilter = useMemo(\n () => renderValue ? createRenderValueFilter(renderValue) : undefined,\n [renderValue],\n );\n\n const renderItem = useCallback(\n (value: string) => {\n const isEmpty = isEmptyValue(value);\n const count = countByValue.get(value) ?? 0;\n const isFilteredOut = count === 0 && !selectedSet.has(value);\n return (\n <Combobox.Item\n key={value}\n value={value}\n className={isFilteredOut ? styles.filteredOutItem : undefined}\n >\n <Combobox.ItemIndicator />\n <span className={styles.itemLabel}>\n {isEmpty\n ? <NoValueLabel />\n : (renderValue ? renderValue(value) : value)}\n </span>\n {showCounts && (\n <span className={styles.itemCount}>\n ({count.toLocaleString()})\n </span>\n )}\n </Combobox.Item>\n );\n },\n [countByValue, selectedSet, showCounts, renderValue],\n );\n\n const renderChips = useCallback(\n (selectedItems: string[]) => (\n <>\n {selectedItems.map((value) => {\n const isEmpty = isEmptyValue(value);\n return (\n <Combobox.Chip\n key={value}\n aria-label={isEmpty ? \"No value\" : value}\n >\n {isEmpty\n ? <NoValueLabel />\n : (renderValue ? renderValue(value) : value)}\n <Combobox.ChipRemove />\n </Combobox.Chip>\n );\n })}\n <Combobox.Input\n placeholder={selectedItems.length > 0 ? \"\" : placeholder}\n aria-label={ariaLabel}\n />\n </>\n ),\n [placeholder, ariaLabel, renderValue],\n );\n\n const isNoData = !error && stableValues.length === 0;\n const isReloading = isLoading && stableValues.length > 0;\n\n return (\n <div\n className={classnames(styles.multiSelect, className)}\n style={style}\n data-loading={isReloading}\n >\n <span className={sharedStyles.srOnly} role=\"status\">\n {isLoading ? \"Loading options\" : \"\"}\n </span>\n\n {error && (\n <div className={sharedStyles.errorMessage}>\n Error loading options: {error.message}\n </div>\n )}\n\n {isNoData && isLoading && <SelectInputSkeleton />}\n {isNoData && !isLoading && (\n <div className={sharedStyles.emptyMessage}>\n No options available\n </div>\n )}\n\n {stableValues.length > 0 && (\n <Combobox.Root<string, true>\n multiple={true}\n value={selectedValues}\n onValueChange={handleValueChange}\n items={items}\n filter={comboboxFilter}\n >\n {layout === \"inline\"\n ? (\n <MultiSelectInlineLayout\n placeholder={placeholder}\n ariaLabel={ariaLabel}\n renderItem={renderItem}\n />\n )\n : (\n <MultiSelectDropdownLayout\n renderChips={renderChips}\n renderItem={renderItem}\n collisionBoundary={collisionBoundary}\n />\n )}\n </Combobox.Root>\n )}\n </div>\n );\n}\n\nexport const MultiSelectInput = memo(\n MultiSelectInputInner,\n) as typeof MultiSelectInputInner;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -47,6 +47,12 @@
|
|
|
47
47
|
flex-shrink: 0;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/* Muted styling for filtered-out (count=0) entries. */
|
|
51
|
+
.filteredOutItem {
|
|
52
|
+
opacity: var(--osdk-filter-filtered-out-item-opacity);
|
|
53
|
+
color: var(--osdk-filter-filtered-out-item-color);
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
.inlineInput {
|
|
51
57
|
font-family: var(--osdk-filter-input-font-family);
|
|
52
58
|
font-size: var(--osdk-filter-input-font-size);
|
|
@@ -27,7 +27,8 @@ function SingleDateInputInner({
|
|
|
27
27
|
minDate,
|
|
28
28
|
maxDate,
|
|
29
29
|
placeholder,
|
|
30
|
-
showClearButton = true
|
|
30
|
+
showClearButton = true,
|
|
31
|
+
formatDate
|
|
31
32
|
}) {
|
|
32
33
|
const handleClear = useCallback(() => {
|
|
33
34
|
onChange(undefined);
|
|
@@ -47,7 +48,8 @@ function SingleDateInputInner({
|
|
|
47
48
|
max: maxDate,
|
|
48
49
|
placeholder: placeholder,
|
|
49
50
|
ariaLabel: "Select date",
|
|
50
|
-
modal: false
|
|
51
|
+
modal: false,
|
|
52
|
+
formatDate: formatDate
|
|
51
53
|
}), showClearButton && selectedDate !== undefined && /*#__PURE__*/React.createElement(Button, {
|
|
52
54
|
className: styles.clearButton,
|
|
53
55
|
onClick: handleClear,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SingleDateInput.js","names":["Button","classnames","React","memo","useCallback","DatePicker","styles","SingleDateInputInner","selectedDate","onChange","className","style","minDate","maxDate","placeholder","showClearButton","handleClear","undefined","handleChange","value","createElement","singleDate","dateContainer","min","max","ariaLabel","modal","clearButton","onClick","SingleDateInput"],"sources":["SingleDateInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback } from \"react\";\nimport { DatePicker } from \"../../../shared/calendar/index.js\";\nimport styles from \"./SingleDateInput.module.css\";\n\ninterface SingleDateInputProps {\n selectedDate: Date | undefined;\n onChange: (date: Date | undefined) => void;\n className?: string;\n style?: React.CSSProperties;\n minDate?: Date;\n maxDate?: Date;\n placeholder?: string;\n showClearButton?: boolean;\n}\n\nfunction SingleDateInputInner({\n selectedDate,\n onChange,\n className,\n style,\n minDate,\n maxDate,\n placeholder,\n showClearButton = true,\n}: SingleDateInputProps): React.ReactElement {\n const handleClear = useCallback(() => {\n onChange(undefined);\n }, [onChange]);\n\n const handleChange = useCallback(\n (value: Date | null) => {\n onChange(value ?? undefined);\n },\n [onChange],\n );\n\n return (\n <div className={classnames(styles.singleDate, className)} style={style}>\n <div className={styles.dateContainer}>\n <DatePicker\n value={selectedDate ?? null}\n onChange={handleChange}\n min={minDate}\n max={maxDate}\n placeholder={placeholder}\n ariaLabel=\"Select date\"\n modal={false}\n />\n {showClearButton && selectedDate !== undefined && (\n <Button\n className={styles.clearButton}\n onClick={handleClear}\n aria-label=\"Clear date\"\n >\n ×\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nexport const SingleDateInput: React.NamedExoticComponent<SingleDateInputProps> =\n memo(SingleDateInputInner);\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,KAAK,IAAIC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AAChD,SAASC,UAAU,QAAQ,mCAAmC;AAC9D,OAAOC,MAAM,MAAM,8BAA8B;
|
|
1
|
+
{"version":3,"file":"SingleDateInput.js","names":["Button","classnames","React","memo","useCallback","DatePicker","styles","SingleDateInputInner","selectedDate","onChange","className","style","minDate","maxDate","placeholder","showClearButton","formatDate","handleClear","undefined","handleChange","value","createElement","singleDate","dateContainer","min","max","ariaLabel","modal","clearButton","onClick","SingleDateInput"],"sources":["SingleDateInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback } from \"react\";\nimport { DatePicker } from \"../../../shared/calendar/index.js\";\nimport styles from \"./SingleDateInput.module.css\";\n\ninterface SingleDateInputProps {\n selectedDate: Date | undefined;\n onChange: (date: Date | undefined) => void;\n className?: string;\n style?: React.CSSProperties;\n minDate?: Date;\n maxDate?: Date;\n placeholder?: string;\n showClearButton?: boolean;\n /** Display formatter for picker idle text. Editing format stays ISO. */\n formatDate?: (date: Date) => string;\n}\n\nfunction SingleDateInputInner({\n selectedDate,\n onChange,\n className,\n style,\n minDate,\n maxDate,\n placeholder,\n showClearButton = true,\n formatDate,\n}: SingleDateInputProps): React.ReactElement {\n const handleClear = useCallback(() => {\n onChange(undefined);\n }, [onChange]);\n\n const handleChange = useCallback(\n (value: Date | null) => {\n onChange(value ?? undefined);\n },\n [onChange],\n );\n\n return (\n <div className={classnames(styles.singleDate, className)} style={style}>\n <div className={styles.dateContainer}>\n <DatePicker\n value={selectedDate ?? null}\n onChange={handleChange}\n min={minDate}\n max={maxDate}\n placeholder={placeholder}\n ariaLabel=\"Select date\"\n modal={false}\n formatDate={formatDate}\n />\n {showClearButton && selectedDate !== undefined && (\n <Button\n className={styles.clearButton}\n onClick={handleClear}\n aria-label=\"Clear date\"\n >\n ×\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nexport const SingleDateInput: React.NamedExoticComponent<SingleDateInputProps> =\n memo(SingleDateInputInner);\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,KAAK,IAAIC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AAChD,SAASC,UAAU,QAAQ,mCAAmC;AAC9D,OAAOC,MAAM,MAAM,8BAA8B;AAejD,SAASC,oBAAoBA,CAAC;EAC5BC,YAAY;EACZC,QAAQ;EACRC,SAAS;EACTC,KAAK;EACLC,OAAO;EACPC,OAAO;EACPC,WAAW;EACXC,eAAe,GAAG,IAAI;EACtBC;AACoB,CAAC,EAAsB;EAC3C,MAAMC,WAAW,GAAGb,WAAW,CAAC,MAAM;IACpCK,QAAQ,CAACS,SAAS,CAAC;EACrB,CAAC,EAAE,CAACT,QAAQ,CAAC,CAAC;EAEd,MAAMU,YAAY,GAAGf,WAAW,CAC7BgB,KAAkB,IAAK;IACtBX,QAAQ,CAACW,KAAK,IAAIF,SAAS,CAAC;EAC9B,CAAC,EACD,CAACT,QAAQ,CACX,CAAC;EAED,oBACEP,KAAA,CAAAmB,aAAA;IAAKX,SAAS,EAAET,UAAU,CAACK,MAAM,CAACgB,UAAU,EAAEZ,SAAS,CAAE;IAACC,KAAK,EAAEA;EAAM,gBACrET,KAAA,CAAAmB,aAAA;IAAKX,SAAS,EAAEJ,MAAM,CAACiB;EAAc,gBACnCrB,KAAA,CAAAmB,aAAA,CAAChB,UAAU;IACTe,KAAK,EAAEZ,YAAY,IAAI,IAAK;IAC5BC,QAAQ,EAAEU,YAAa;IACvBK,GAAG,EAAEZ,OAAQ;IACba,GAAG,EAAEZ,OAAQ;IACbC,WAAW,EAAEA,WAAY;IACzBY,SAAS,EAAC,aAAa;IACvBC,KAAK,EAAE,KAAM;IACbX,UAAU,EAAEA;EAAW,CACxB,CAAC,EACDD,eAAe,IAAIP,YAAY,KAAKU,SAAS,iBAC5ChB,KAAA,CAAAmB,aAAA,CAACrB,MAAM;IACLU,SAAS,EAAEJ,MAAM,CAACsB,WAAY;IAC9BC,OAAO,EAAEZ,WAAY;IACrB,cAAW;EAAY,GACxB,MAEO,CAEP,CACF,CAAC;AAEV;AAEA,OAAO,MAAMa,eAAiE,gBAC5E3B,IAAI,CAACI,oBAAoB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { useMemo } from "react";
|
|
18
|
+
import { usePropertyAggregation } from "./usePropertyAggregation.js";
|
|
19
|
+
const EMPTY_VALUES = [];
|
|
20
|
+
/**
|
|
21
|
+
* Aggregates a property over `scopedObjectSet` (the narrowed scope) and pins
|
|
22
|
+
* any values that exist in `emptySourceObjectSet` (the unfiltered base) but
|
|
23
|
+
* are absent from the narrowed result to count=0, so facets can render
|
|
24
|
+
* "filtered-out" rows alongside live counts.
|
|
25
|
+
*
|
|
26
|
+
* When `emptySourceObjectSet` is `undefined`, this falls through to a single
|
|
27
|
+
* aggregation against `scopedObjectSet` — equivalent to `usePropertyAggregation`
|
|
28
|
+
* with `selectedValues` as the only pinned values.
|
|
29
|
+
*
|
|
30
|
+
* @param objectType - Object type for the aggregation
|
|
31
|
+
* @param propertyKey - Property to aggregate on
|
|
32
|
+
* @param scopedObjectSet - Set the live counts are computed against (post-narrowing)
|
|
33
|
+
* @param emptySourceObjectSet - Unfiltered base set whose values are pinned as
|
|
34
|
+
* count=0 when absent from the scoped aggregation. Pass `undefined` to skip
|
|
35
|
+
* the dual-scope behavior.
|
|
36
|
+
* @param options.selectedValues - Values to always include in the result, even
|
|
37
|
+
* when their count is 0 (e.g. currently-selected filter values)
|
|
38
|
+
* @returns Aggregation against the scoped set, with isLoading reflecting both
|
|
39
|
+
* queries when dual-scope is active.
|
|
40
|
+
*/
|
|
41
|
+
export function useDualScopeAggregation(objectType, propertyKey, scopedObjectSet, emptySourceObjectSet, options = {}) {
|
|
42
|
+
const {
|
|
43
|
+
sortBy,
|
|
44
|
+
selectedValues = EMPTY_VALUES,
|
|
45
|
+
limit
|
|
46
|
+
} = options;
|
|
47
|
+
const isDualScope = emptySourceObjectSet !== undefined;
|
|
48
|
+
const emptySourceAggregation = usePropertyAggregation(objectType, propertyKey, emptySourceObjectSet);
|
|
49
|
+
const activeValues = useMemo(() => {
|
|
50
|
+
const merged = new Set(selectedValues);
|
|
51
|
+
if (isDualScope && emptySourceAggregation.error == null) {
|
|
52
|
+
for (const d of emptySourceAggregation.data) {
|
|
53
|
+
merged.add(d.value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return merged.size === 0 ? undefined : Array.from(merged);
|
|
57
|
+
}, [isDualScope, emptySourceAggregation.data, emptySourceAggregation.error, selectedValues]);
|
|
58
|
+
const primary = usePropertyAggregation(objectType, propertyKey, scopedObjectSet, {
|
|
59
|
+
sortBy,
|
|
60
|
+
activeValues,
|
|
61
|
+
limit
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
data: primary.data,
|
|
65
|
+
maxCount: primary.maxCount,
|
|
66
|
+
isLoading: primary.isLoading || isDualScope && emptySourceAggregation.isLoading,
|
|
67
|
+
error: primary.error
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=useDualScopeAggregation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDualScopeAggregation.js","names":["useMemo","usePropertyAggregation","EMPTY_VALUES","useDualScopeAggregation","objectType","propertyKey","scopedObjectSet","emptySourceObjectSet","options","sortBy","selectedValues","limit","isDualScope","undefined","emptySourceAggregation","activeValues","merged","Set","error","d","data","add","value","size","Array","from","primary","maxCount","isLoading"],"sources":["useDualScopeAggregation.ts"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ObjectSet, ObjectTypeDefinition, PropertyKeys } from \"@osdk/api\";\nimport { useMemo } from \"react\";\nimport {\n usePropertyAggregation,\n type UsePropertyAggregationResult,\n} from \"./usePropertyAggregation.js\";\n\nconst EMPTY_VALUES: string[] = [];\n\nexport interface UseDualScopeAggregationOptions {\n limit?: number;\n sortBy?: \"count\" | \"value\";\n selectedValues?: string[];\n}\n\n/**\n * Aggregates a property over `scopedObjectSet` (the narrowed scope) and pins\n * any values that exist in `emptySourceObjectSet` (the unfiltered base) but\n * are absent from the narrowed result to count=0, so facets can render\n * \"filtered-out\" rows alongside live counts.\n *\n * When `emptySourceObjectSet` is `undefined`, this falls through to a single\n * aggregation against `scopedObjectSet` — equivalent to `usePropertyAggregation`\n * with `selectedValues` as the only pinned values.\n *\n * @param objectType - Object type for the aggregation\n * @param propertyKey - Property to aggregate on\n * @param scopedObjectSet - Set the live counts are computed against (post-narrowing)\n * @param emptySourceObjectSet - Unfiltered base set whose values are pinned as\n * count=0 when absent from the scoped aggregation. Pass `undefined` to skip\n * the dual-scope behavior.\n * @param options.selectedValues - Values to always include in the result, even\n * when their count is 0 (e.g. currently-selected filter values)\n * @returns Aggregation against the scoped set, with isLoading reflecting both\n * queries when dual-scope is active.\n */\nexport function useDualScopeAggregation<\n Q extends ObjectTypeDefinition,\n K extends PropertyKeys<Q>,\n>(\n objectType: Q,\n propertyKey: K,\n scopedObjectSet: ObjectSet<Q> | undefined,\n emptySourceObjectSet: ObjectSet<Q> | undefined,\n options: UseDualScopeAggregationOptions = {},\n): UsePropertyAggregationResult {\n const { sortBy, selectedValues = EMPTY_VALUES, limit } = options;\n const isDualScope = emptySourceObjectSet !== undefined;\n\n const emptySourceAggregation = usePropertyAggregation(\n objectType,\n propertyKey,\n emptySourceObjectSet,\n );\n\n const activeValues = useMemo(() => {\n const merged = new Set(selectedValues);\n if (isDualScope && emptySourceAggregation.error == null) {\n for (const d of emptySourceAggregation.data) {\n merged.add(d.value);\n }\n }\n return merged.size === 0 ? undefined : Array.from(merged);\n }, [\n isDualScope,\n emptySourceAggregation.data,\n emptySourceAggregation.error,\n selectedValues,\n ]);\n\n const primary = usePropertyAggregation(\n objectType,\n propertyKey,\n scopedObjectSet,\n { sortBy, activeValues, limit },\n );\n\n return {\n data: primary.data,\n maxCount: primary.maxCount,\n isLoading: primary.isLoading\n || (isDualScope && emptySourceAggregation.isLoading),\n error: primary.error,\n };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SACEC,sBAAsB,QAEjB,6BAA6B;AAEpC,MAAMC,YAAsB,GAAG,EAAE;AAQjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,uBAAuBA,CAIrCC,UAAa,EACbC,WAAc,EACdC,eAAyC,EACzCC,oBAA8C,EAC9CC,OAAuC,GAAG,CAAC,CAAC,EACd;EAC9B,MAAM;IAAEC,MAAM;IAAEC,cAAc,GAAGR,YAAY;IAAES;EAAM,CAAC,GAAGH,OAAO;EAChE,MAAMI,WAAW,GAAGL,oBAAoB,KAAKM,SAAS;EAEtD,MAAMC,sBAAsB,GAAGb,sBAAsB,CACnDG,UAAU,EACVC,WAAW,EACXE,oBACF,CAAC;EAED,MAAMQ,YAAY,GAAGf,OAAO,CAAC,MAAM;IACjC,MAAMgB,MAAM,GAAG,IAAIC,GAAG,CAACP,cAAc,CAAC;IACtC,IAAIE,WAAW,IAAIE,sBAAsB,CAACI,KAAK,IAAI,IAAI,EAAE;MACvD,KAAK,MAAMC,CAAC,IAAIL,sBAAsB,CAACM,IAAI,EAAE;QAC3CJ,MAAM,CAACK,GAAG,CAACF,CAAC,CAACG,KAAK,CAAC;MACrB;IACF;IACA,OAAON,MAAM,CAACO,IAAI,KAAK,CAAC,GAAGV,SAAS,GAAGW,KAAK,CAACC,IAAI,CAACT,MAAM,CAAC;EAC3D,CAAC,EAAE,CACDJ,WAAW,EACXE,sBAAsB,CAACM,IAAI,EAC3BN,sBAAsB,CAACI,KAAK,EAC5BR,cAAc,CACf,CAAC;EAEF,MAAMgB,OAAO,GAAGzB,sBAAsB,CACpCG,UAAU,EACVC,WAAW,EACXC,eAAe,EACf;IAAEG,MAAM;IAAEM,YAAY;IAAEJ;EAAM,CAChC,CAAC;EAED,OAAO;IACLS,IAAI,EAAEM,OAAO,CAACN,IAAI;IAClBO,QAAQ,EAAED,OAAO,CAACC,QAAQ;IAC1BC,SAAS,EAAEF,OAAO,CAACE,SAAS,IACtBhB,WAAW,IAAIE,sBAAsB,CAACc,SAAU;IACtDV,KAAK,EAAEQ,OAAO,CAACR;EACjB,CAAC;AACH","ignoreList":[]}
|
|
@@ -17,14 +17,11 @@
|
|
|
17
17
|
import { useOsdkMetadata } from "@osdk/react";
|
|
18
18
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
19
19
|
import { assertUnreachable } from "../../shared/assertUnreachable.js";
|
|
20
|
-
import { buildWhereClause } from "../utils/filterStateToWhereClause.js";
|
|
20
|
+
import { buildWhereClause, getActiveLinkedFilters } from "../utils/filterStateToWhereClause.js";
|
|
21
21
|
import { filterHasActiveState } from "../utils/filterValues.js";
|
|
22
22
|
import { getFilterKey } from "../utils/getFilterKey.js";
|
|
23
|
+
import { narrowObjectSet } from "../utils/narrowObjectSet.js";
|
|
23
24
|
import { useStableMapEntries } from "./useStableMapEntries.js";
|
|
24
|
-
/**
|
|
25
|
-
* Build initial states from filter definitions.
|
|
26
|
-
* Uses string keys derived from getFilterKey() for stable lookups.
|
|
27
|
-
*/
|
|
28
25
|
function buildInitialStates(definitions) {
|
|
29
26
|
const states = new Map();
|
|
30
27
|
if (!definitions) {
|
|
@@ -79,9 +76,11 @@ function buildInitialStates(definitions) {
|
|
|
79
76
|
export function useFilterListState(props) {
|
|
80
77
|
const {
|
|
81
78
|
objectType,
|
|
79
|
+
objectSet,
|
|
82
80
|
filterDefinitions,
|
|
83
81
|
onFilterStateChanged,
|
|
84
82
|
onFilterClauseChanged,
|
|
83
|
+
onEffectiveObjectSet,
|
|
85
84
|
initialFilterStates
|
|
86
85
|
} = props;
|
|
87
86
|
const {
|
|
@@ -89,6 +88,10 @@ export function useFilterListState(props) {
|
|
|
89
88
|
} = useOsdkMetadata(objectType);
|
|
90
89
|
const onFilterClauseChangedRef = useRef(onFilterClauseChanged);
|
|
91
90
|
onFilterClauseChangedRef.current = onFilterClauseChanged;
|
|
91
|
+
const onEffectiveObjectSetRef = useRef(onEffectiveObjectSet);
|
|
92
|
+
onEffectiveObjectSetRef.current = onEffectiveObjectSet;
|
|
93
|
+
const filterDefinitionsRef = useRef(filterDefinitions);
|
|
94
|
+
filterDefinitionsRef.current = filterDefinitions;
|
|
92
95
|
const propertyTypes = useMemo(() => {
|
|
93
96
|
const map = new Map();
|
|
94
97
|
if (metadata?.properties) {
|
|
@@ -104,13 +107,13 @@ export function useFilterListState(props) {
|
|
|
104
107
|
return map;
|
|
105
108
|
}, [metadata?.properties]);
|
|
106
109
|
const [filterStates, setFilterStates] = useState(() => {
|
|
107
|
-
const
|
|
110
|
+
const initial = buildInitialStates(filterDefinitions);
|
|
108
111
|
if (initialFilterStates) {
|
|
109
112
|
for (const [key, state] of initialFilterStates) {
|
|
110
|
-
|
|
113
|
+
initial.set(key, state);
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
|
-
return
|
|
116
|
+
return initial;
|
|
114
117
|
});
|
|
115
118
|
const setFilterState = useCallback((filterKey, state) => {
|
|
116
119
|
setFilterStates(prev => {
|
|
@@ -118,11 +121,11 @@ export function useFilterListState(props) {
|
|
|
118
121
|
next.set(filterKey, state);
|
|
119
122
|
return next;
|
|
120
123
|
});
|
|
121
|
-
const definition =
|
|
124
|
+
const definition = filterDefinitionsRef.current?.find(d => getFilterKey(d) === filterKey);
|
|
122
125
|
if (definition) {
|
|
123
126
|
onFilterStateChanged?.(definition, state);
|
|
124
127
|
}
|
|
125
|
-
}, [
|
|
128
|
+
}, [onFilterStateChanged]);
|
|
126
129
|
const clearFilterState = useCallback(filterKey => {
|
|
127
130
|
setFilterStates(prev => {
|
|
128
131
|
const next = new Map(prev);
|
|
@@ -130,13 +133,21 @@ export function useFilterListState(props) {
|
|
|
130
133
|
return next;
|
|
131
134
|
});
|
|
132
135
|
}, []);
|
|
136
|
+
const reset = useCallback(() => {
|
|
137
|
+
setFilterStates(buildInitialStates(filterDefinitionsRef.current));
|
|
138
|
+
}, []);
|
|
133
139
|
const whereClause = useMemo(() => buildWhereClause(filterDefinitions, filterStates, propertyTypes), [filterDefinitions, filterStates, propertyTypes]);
|
|
140
|
+
const linkedFilters = useMemo(() => getActiveLinkedFilters(filterDefinitions, filterStates), [filterDefinitions, filterStates]);
|
|
141
|
+
const effectiveObjectSet = useMemo(() => objectSet == null ? undefined : narrowObjectSet(objectSet, whereClause, linkedFilters), [objectSet, whereClause, linkedFilters]);
|
|
134
142
|
useEffect(() => {
|
|
135
143
|
onFilterClauseChangedRef.current?.(whereClause);
|
|
136
144
|
}, [whereClause]);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (effectiveObjectSet == null) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
onEffectiveObjectSetRef.current?.(effectiveObjectSet);
|
|
150
|
+
}, [effectiveObjectSet]);
|
|
140
151
|
const perFilterWhereClauses = useStableMapEntries(useMemo(() => {
|
|
141
152
|
const map = new Map();
|
|
142
153
|
for (const definition of filterDefinitions ?? []) {
|
|
@@ -145,6 +156,14 @@ export function useFilterListState(props) {
|
|
|
145
156
|
}
|
|
146
157
|
return map;
|
|
147
158
|
}, [filterDefinitions, filterStates, propertyTypes]));
|
|
159
|
+
const perFilterLinkedFilters = useStableMapEntries(useMemo(() => {
|
|
160
|
+
const map = new Map();
|
|
161
|
+
for (const definition of filterDefinitions ?? []) {
|
|
162
|
+
const key = getFilterKey(definition);
|
|
163
|
+
map.set(key, getActiveLinkedFilters(filterDefinitions, filterStates, key));
|
|
164
|
+
}
|
|
165
|
+
return map;
|
|
166
|
+
}, [filterDefinitions, filterStates]));
|
|
148
167
|
const activeFilterCount = useMemo(() => {
|
|
149
168
|
let count = 0;
|
|
150
169
|
for (const state of filterStates.values()) {
|
|
@@ -154,17 +173,16 @@ export function useFilterListState(props) {
|
|
|
154
173
|
}
|
|
155
174
|
return count;
|
|
156
175
|
}, [filterStates]);
|
|
157
|
-
const reset = useCallback(() => {
|
|
158
|
-
setFilterStates(buildInitialStates(filterDefinitions));
|
|
159
|
-
}, [filterDefinitions]);
|
|
160
176
|
return useMemo(() => ({
|
|
161
177
|
filterStates,
|
|
162
178
|
setFilterState,
|
|
163
179
|
clearFilterState,
|
|
164
180
|
whereClause,
|
|
181
|
+
linkedFilters,
|
|
165
182
|
perFilterWhereClauses,
|
|
183
|
+
perFilterLinkedFilters,
|
|
166
184
|
activeFilterCount,
|
|
167
185
|
reset
|
|
168
|
-
}), [filterStates, setFilterState, clearFilterState, whereClause, perFilterWhereClauses, activeFilterCount, reset]);
|
|
186
|
+
}), [filterStates, setFilterState, clearFilterState, whereClause, linkedFilters, perFilterWhereClauses, perFilterLinkedFilters, activeFilterCount, reset]);
|
|
169
187
|
}
|
|
170
188
|
//# sourceMappingURL=useFilterListState.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFilterListState.js","names":["useOsdkMetadata","useCallback","useEffect","useMemo","useRef","useState","assertUnreachable","buildWhereClause","filterHasActiveState","getFilterKey","useStableMapEntries","buildInitialStates","definitions","states","Map","definition","key","type","state","filterState","set","defaultFilterState","innerState","defaultLinkedFilterState","linkedFilterState","useFilterListState","props","objectType","filterDefinitions","onFilterStateChanged","onFilterClauseChanged","initialFilterStates","metadata","onFilterClauseChangedRef","current","propertyTypes","map","properties","prop","Object","entries","multiplicity","filterStates","setFilterStates","setFilterState","filterKey","prev","next","find","d","clearFilterState","delete","whereClause","perFilterWhereClauses","activeFilterCount","count","values","reset"],"sources":["useFilterListState.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ObjectTypeDefinition, WhereClause } from \"@osdk/api\";\nimport { useOsdkMetadata } from \"@osdk/react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { assertUnreachable } from \"../../shared/assertUnreachable.js\";\nimport type { FilterListProps } from \"../FilterListApi.js\";\nimport type { FilterState } from \"../FilterListItemApi.js\";\nimport type { LinkedPropertyFilterState } from \"../types/LinkedFilterTypes.js\";\nimport {\n buildWhereClause,\n type PropertyTypeInfo,\n} from \"../utils/filterStateToWhereClause.js\";\nimport { filterHasActiveState } from \"../utils/filterValues.js\";\nimport { getFilterKey } from \"../utils/getFilterKey.js\";\nimport { useStableMapEntries } from \"./useStableMapEntries.js\";\n\nexport interface UseFilterListStateResult<Q extends ObjectTypeDefinition> {\n filterStates: Map<string, FilterState>;\n setFilterState: (\n filterKey: string,\n state: FilterState,\n ) => void;\n clearFilterState: (filterKey: string) => void;\n whereClause: WhereClause<Q>;\n perFilterWhereClauses: Map<string, WhereClause<Q>>;\n activeFilterCount: number;\n reset: () => void;\n}\n\n/**\n * Build initial states from filter definitions.\n * Uses string keys derived from getFilterKey() for stable lookups.\n */\nfunction buildInitialStates<Q extends ObjectTypeDefinition>(\n definitions: FilterListProps<Q>[\"filterDefinitions\"],\n): Map<string, FilterState> {\n const states = new Map<string, FilterState>();\n\n if (!definitions) {\n return states;\n }\n\n for (const definition of definitions) {\n const key = getFilterKey(definition);\n switch (definition.type) {\n case \"PROPERTY\": {\n const state = definition.filterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"HAS_LINK\":\n case \"KEYWORD_SEARCH\":\n case \"CUSTOM\": {\n const state = definition.defaultFilterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"STATIC_VALUES\": {\n const state = definition.filterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"LINKED_PROPERTY\": {\n const innerState = definition.defaultLinkedFilterState;\n if (innerState) {\n const state: LinkedPropertyFilterState = {\n type: \"linkedProperty\",\n linkedFilterState: innerState,\n };\n states.set(key, state);\n }\n break;\n }\n default:\n assertUnreachable(definition);\n }\n }\n\n return states;\n}\n\nexport function useFilterListState<Q extends ObjectTypeDefinition>(\n props: FilterListProps<Q>,\n): UseFilterListStateResult<Q> {\n const {\n objectType,\n filterDefinitions,\n onFilterStateChanged,\n onFilterClauseChanged,\n initialFilterStates,\n } = props;\n const { metadata } = useOsdkMetadata(objectType);\n const onFilterClauseChangedRef = useRef(onFilterClauseChanged);\n onFilterClauseChangedRef.current = onFilterClauseChanged;\n\n const propertyTypes = useMemo(() => {\n const map = new Map<string, PropertyTypeInfo>();\n if (metadata?.properties) {\n for (const [key, prop] of Object.entries(metadata.properties)) {\n if (typeof prop.type === \"string\") {\n map.set(key, {\n type: prop.type,\n multiplicity: prop.multiplicity === true,\n });\n }\n }\n }\n return map;\n }, [metadata?.properties]);\n\n const [filterStates, setFilterStates] = useState<\n Map<string, FilterState>\n >(() => {\n const states = buildInitialStates(filterDefinitions);\n if (initialFilterStates) {\n for (const [key, state] of initialFilterStates) {\n states.set(key, state);\n }\n }\n return states;\n });\n\n const setFilterState = useCallback(\n (filterKey: string, state: FilterState) => {\n setFilterStates((prev) => {\n const next = new Map(prev);\n next.set(filterKey, state);\n return next;\n });\n\n const definition = filterDefinitions?.find(\n (d) => getFilterKey(d) === filterKey,\n );\n if (definition) {\n onFilterStateChanged?.(definition, state);\n }\n },\n [\n filterDefinitions,\n onFilterStateChanged,\n ],\n );\n\n const clearFilterState = useCallback(\n (filterKey: string) => {\n setFilterStates((prev) => {\n const next = new Map(prev);\n next.delete(filterKey);\n return next;\n });\n },\n [],\n );\n\n const whereClause = useMemo(\n () =>\n buildWhereClause(\n filterDefinitions,\n filterStates,\n propertyTypes,\n ),\n [filterDefinitions, filterStates, propertyTypes],\n );\n\n useEffect(() => {\n onFilterClauseChangedRef.current?.(whereClause);\n }, [whereClause]);\n\n // Preserve per-key clause references when content hasn't changed so\n // FilterInput.memo can hold and aggregations don't refetch unnecessarily.\n const perFilterWhereClauses = useStableMapEntries(\n useMemo(() => {\n const map = new Map<string, WhereClause<Q>>();\n for (const definition of filterDefinitions ?? []) {\n const key = getFilterKey(definition);\n map.set(\n key,\n buildWhereClause(\n filterDefinitions,\n filterStates,\n propertyTypes,\n key,\n ),\n );\n }\n return map;\n }, [filterDefinitions, filterStates, propertyTypes]),\n );\n\n const activeFilterCount = useMemo(() => {\n let count = 0;\n for (const state of filterStates.values()) {\n if (filterHasActiveState(state)) {\n count++;\n }\n }\n return count;\n }, [filterStates]);\n\n const reset = useCallback(() => {\n setFilterStates(buildInitialStates(filterDefinitions));\n }, [filterDefinitions]);\n\n return useMemo(() => ({\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n perFilterWhereClauses,\n activeFilterCount,\n reset,\n }), [\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n perFilterWhereClauses,\n activeFilterCount,\n reset,\n ]);\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"useFilterListState.js","names":["useOsdkMetadata","useCallback","useEffect","useMemo","useRef","useState","assertUnreachable","buildWhereClause","getActiveLinkedFilters","filterHasActiveState","getFilterKey","narrowObjectSet","useStableMapEntries","buildInitialStates","definitions","states","Map","definition","key","type","state","filterState","set","defaultFilterState","innerState","defaultLinkedFilterState","linkedFilterState","useFilterListState","props","objectType","objectSet","filterDefinitions","onFilterStateChanged","onFilterClauseChanged","onEffectiveObjectSet","initialFilterStates","metadata","onFilterClauseChangedRef","current","onEffectiveObjectSetRef","filterDefinitionsRef","propertyTypes","map","properties","prop","Object","entries","multiplicity","filterStates","setFilterStates","initial","setFilterState","filterKey","prev","next","find","d","clearFilterState","delete","reset","whereClause","linkedFilters","effectiveObjectSet","undefined","perFilterWhereClauses","perFilterLinkedFilters","activeFilterCount","count","values"],"sources":["useFilterListState.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ObjectSet, ObjectTypeDefinition, WhereClause } from \"@osdk/api\";\nimport { useOsdkMetadata } from \"@osdk/react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { assertUnreachable } from \"../../shared/assertUnreachable.js\";\nimport type { FilterListProps } from \"../FilterListApi.js\";\nimport type { FilterState } from \"../FilterListItemApi.js\";\nimport type {\n LinkedFilter,\n LinkedPropertyFilterState,\n} from \"../types/LinkedFilterTypes.js\";\nimport {\n buildWhereClause,\n getActiveLinkedFilters,\n type PropertyTypeInfo,\n} from \"../utils/filterStateToWhereClause.js\";\nimport { filterHasActiveState } from \"../utils/filterValues.js\";\nimport { getFilterKey } from \"../utils/getFilterKey.js\";\nimport { narrowObjectSet } from \"../utils/narrowObjectSet.js\";\nimport { useStableMapEntries } from \"./useStableMapEntries.js\";\n\nexport interface UseFilterListStateResult<Q extends ObjectTypeDefinition> {\n filterStates: Map<string, FilterState>;\n setFilterState: (\n filterKey: string,\n state: FilterState,\n ) => void;\n clearFilterState: (filterKey: string) => void;\n /** Direct (non-link-traversing) filters combined into a `WhereClause<Q>`. */\n whereClause: WhereClause<Q>;\n /** Active linked-property records; apply via `narrowObjectSet`. */\n linkedFilters: ReadonlyArray<LinkedFilter<Q>>;\n /** Per-filter excluding-self where clauses keyed by `getFilterKey`. */\n perFilterWhereClauses: Map<string, WhereClause<Q>>;\n /** Per-filter excluding-self linked filters keyed by `getFilterKey`. */\n perFilterLinkedFilters: Map<string, ReadonlyArray<LinkedFilter<Q>>>;\n activeFilterCount: number;\n reset: () => void;\n}\n\nfunction buildInitialStates<Q extends ObjectTypeDefinition>(\n definitions: FilterListProps<Q>[\"filterDefinitions\"],\n): Map<string, FilterState> {\n const states = new Map<string, FilterState>();\n\n if (!definitions) {\n return states;\n }\n\n for (const definition of definitions) {\n const key = getFilterKey(definition);\n switch (definition.type) {\n case \"PROPERTY\": {\n const state = definition.filterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"HAS_LINK\":\n case \"KEYWORD_SEARCH\":\n case \"CUSTOM\": {\n const state = definition.defaultFilterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"STATIC_VALUES\": {\n const state = definition.filterState;\n if (state) {\n states.set(key, state);\n }\n break;\n }\n case \"LINKED_PROPERTY\": {\n const innerState = definition.defaultLinkedFilterState;\n if (innerState) {\n const state: LinkedPropertyFilterState = {\n type: \"linkedProperty\",\n linkedFilterState: innerState,\n };\n states.set(key, state);\n }\n break;\n }\n default:\n assertUnreachable(definition);\n }\n }\n\n return states;\n}\n\nexport function useFilterListState<Q extends ObjectTypeDefinition>(\n props: FilterListProps<Q>,\n): UseFilterListStateResult<Q> {\n const {\n objectType,\n objectSet,\n filterDefinitions,\n onFilterStateChanged,\n onFilterClauseChanged,\n onEffectiveObjectSet,\n initialFilterStates,\n } = props;\n const { metadata } = useOsdkMetadata(objectType);\n const onFilterClauseChangedRef = useRef(onFilterClauseChanged);\n onFilterClauseChangedRef.current = onFilterClauseChanged;\n const onEffectiveObjectSetRef = useRef(onEffectiveObjectSet);\n onEffectiveObjectSetRef.current = onEffectiveObjectSet;\n const filterDefinitionsRef = useRef(filterDefinitions);\n filterDefinitionsRef.current = filterDefinitions;\n\n const propertyTypes = useMemo(() => {\n const map = new Map<string, PropertyTypeInfo>();\n if (metadata?.properties) {\n for (const [key, prop] of Object.entries(metadata.properties)) {\n if (typeof prop.type === \"string\") {\n map.set(key, {\n type: prop.type,\n multiplicity: prop.multiplicity === true,\n });\n }\n }\n }\n return map;\n }, [metadata?.properties]);\n\n const [filterStates, setFilterStates] = useState<Map<string, FilterState>>(\n () => {\n const initial = buildInitialStates(filterDefinitions);\n if (initialFilterStates) {\n for (const [key, state] of initialFilterStates) {\n initial.set(key, state);\n }\n }\n return initial;\n },\n );\n\n const setFilterState = useCallback(\n (filterKey: string, state: FilterState) => {\n setFilterStates((prev) => {\n const next = new Map(prev);\n next.set(filterKey, state);\n return next;\n });\n\n const definition = filterDefinitionsRef.current?.find(\n (d) => getFilterKey(d) === filterKey,\n );\n if (definition) {\n onFilterStateChanged?.(definition, state);\n }\n },\n [onFilterStateChanged],\n );\n\n const clearFilterState = useCallback((filterKey: string) => {\n setFilterStates((prev) => {\n const next = new Map(prev);\n next.delete(filterKey);\n return next;\n });\n }, []);\n\n const reset = useCallback(() => {\n setFilterStates(buildInitialStates(filterDefinitionsRef.current));\n }, []);\n\n const whereClause = useMemo(\n () => buildWhereClause(filterDefinitions, filterStates, propertyTypes),\n [filterDefinitions, filterStates, propertyTypes],\n );\n\n const linkedFilters = useMemo(\n () => getActiveLinkedFilters(filterDefinitions, filterStates),\n [filterDefinitions, filterStates],\n );\n\n const effectiveObjectSet = useMemo<ObjectSet<Q> | undefined>(\n () =>\n objectSet == null\n ? undefined\n : narrowObjectSet(objectSet, whereClause, linkedFilters),\n [objectSet, whereClause, linkedFilters],\n );\n\n useEffect(() => {\n onFilterClauseChangedRef.current?.(whereClause);\n }, [whereClause]);\n\n useEffect(() => {\n if (effectiveObjectSet == null) {\n return;\n }\n onEffectiveObjectSetRef.current?.(effectiveObjectSet);\n }, [effectiveObjectSet]);\n\n const perFilterWhereClauses = useStableMapEntries(\n useMemo(() => {\n const map = new Map<string, WhereClause<Q>>();\n for (const definition of filterDefinitions ?? []) {\n const key = getFilterKey(definition);\n map.set(\n key,\n buildWhereClause(filterDefinitions, filterStates, propertyTypes, key),\n );\n }\n return map;\n }, [filterDefinitions, filterStates, propertyTypes]),\n );\n\n const perFilterLinkedFilters = useStableMapEntries(\n useMemo(() => {\n const map = new Map<string, ReadonlyArray<LinkedFilter<Q>>>();\n for (const definition of filterDefinitions ?? []) {\n const key = getFilterKey(definition);\n map.set(\n key,\n getActiveLinkedFilters(filterDefinitions, filterStates, key),\n );\n }\n return map;\n }, [filterDefinitions, filterStates]),\n );\n\n const activeFilterCount = useMemo(() => {\n let count = 0;\n for (const state of filterStates.values()) {\n if (filterHasActiveState(state)) {\n count++;\n }\n }\n return count;\n }, [filterStates]);\n\n return useMemo(() => ({\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n reset,\n }), [\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n reset,\n ]);\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { useMemo } from "react";
|
|
18
|
+
import { computeDualScopes } from "../utils/narrowObjectSet.js";
|
|
19
|
+
import { useDualScopeAggregation } from "./useDualScopeAggregation.js";
|
|
20
|
+
export function useFilterPropertyAggregation(objectType, propertyKey, objectSet, whereClause, linkedFilters, options = {}) {
|
|
21
|
+
const {
|
|
22
|
+
sortBy,
|
|
23
|
+
selectedValues,
|
|
24
|
+
limit,
|
|
25
|
+
showFilteredOutValues
|
|
26
|
+
} = options;
|
|
27
|
+
const {
|
|
28
|
+
scoped,
|
|
29
|
+
emptySource
|
|
30
|
+
} = useMemo(() => computeDualScopes(objectSet, whereClause, linkedFilters, showFilteredOutValues), [objectSet, whereClause, linkedFilters, showFilteredOutValues]);
|
|
31
|
+
return useDualScopeAggregation(objectType, propertyKey, scoped, emptySource, {
|
|
32
|
+
sortBy,
|
|
33
|
+
selectedValues,
|
|
34
|
+
limit
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=useFilterPropertyAggregation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFilterPropertyAggregation.js","names":["useMemo","computeDualScopes","useDualScopeAggregation","useFilterPropertyAggregation","objectType","propertyKey","objectSet","whereClause","linkedFilters","options","sortBy","selectedValues","limit","showFilteredOutValues","scoped","emptySource"],"sources":["useFilterPropertyAggregation.ts"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ObjectSet,\n ObjectTypeDefinition,\n PropertyKeys,\n WhereClause,\n} from \"@osdk/api\";\nimport { useMemo } from \"react\";\nimport type { LinkedFilter } from \"../types/LinkedFilterTypes.js\";\nimport { computeDualScopes } from \"../utils/narrowObjectSet.js\";\nimport { useDualScopeAggregation } from \"./useDualScopeAggregation.js\";\nimport type { UsePropertyAggregationResult } from \"./usePropertyAggregation.js\";\n\nexport interface UseFilterPropertyAggregationOptions {\n limit?: number;\n sortBy?: \"count\" | \"value\";\n selectedValues?: string[];\n showFilteredOutValues?: boolean;\n}\n\nexport function useFilterPropertyAggregation<\n Q extends ObjectTypeDefinition,\n K extends PropertyKeys<Q>,\n>(\n objectType: Q,\n propertyKey: K,\n objectSet: ObjectSet<Q> | undefined,\n whereClause: WhereClause<Q>,\n linkedFilters: ReadonlyArray<LinkedFilter<Q>>,\n options: UseFilterPropertyAggregationOptions = {},\n): UsePropertyAggregationResult {\n const { sortBy, selectedValues, limit, showFilteredOutValues } = options;\n\n const { scoped, emptySource } = useMemo(\n () =>\n computeDualScopes(\n objectSet,\n whereClause,\n linkedFilters,\n showFilteredOutValues,\n ),\n [objectSet, whereClause, linkedFilters, showFilteredOutValues],\n );\n\n return useDualScopeAggregation(\n objectType,\n propertyKey,\n scoped,\n emptySource,\n { sortBy, selectedValues, limit },\n );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA,SAASA,OAAO,QAAQ,OAAO;AAE/B,SAASC,iBAAiB,QAAQ,6BAA6B;AAC/D,SAASC,uBAAuB,QAAQ,8BAA8B;AAUtE,OAAO,SAASC,4BAA4BA,CAI1CC,UAAa,EACbC,WAAc,EACdC,SAAmC,EACnCC,WAA2B,EAC3BC,aAA6C,EAC7CC,OAA4C,GAAG,CAAC,CAAC,EACnB;EAC9B,MAAM;IAAEC,MAAM;IAAEC,cAAc;IAAEC,KAAK;IAAEC;EAAsB,CAAC,GAAGJ,OAAO;EAExE,MAAM;IAAEK,MAAM;IAAEC;EAAY,CAAC,GAAGf,OAAO,CACrC,MACEC,iBAAiB,CACfK,SAAS,EACTC,WAAW,EACXC,aAAa,EACbK,qBACF,CAAC,EACH,CAACP,SAAS,EAAEC,WAAW,EAAEC,aAAa,EAAEK,qBAAqB,CAC/D,CAAC;EAED,OAAOX,uBAAuB,CAC5BE,UAAU,EACVC,WAAW,EACXS,MAAM,EACNC,WAAW,EACX;IAAEL,MAAM;IAAEC,cAAc;IAAEC;EAAM,CAClC,CAAC;AACH","ignoreList":[]}
|
|
@@ -60,23 +60,24 @@ export function usePropertyAggregation(objectType, propertyKey, objectSet, optio
|
|
|
60
60
|
const dataArray = countData;
|
|
61
61
|
|
|
62
62
|
// Build a set of values present in the aggregation so we can identify
|
|
63
|
-
// which active selections need to be synthesized as
|
|
63
|
+
// which active selections need to be synthesized as filtered-out entries.
|
|
64
64
|
const existingValues = new Set();
|
|
65
65
|
for (const item of dataArray) {
|
|
66
66
|
const raw = item.$group[propertyKey];
|
|
67
67
|
existingValues.add(raw == null ? "" : String(raw));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// Synthesize
|
|
71
|
-
// results (e.g. saved filters with zero matching rows). They
|
|
72
|
-
// shape as real entries so the loop below handles isNull
|
|
73
|
-
|
|
70
|
+
// Synthesize filtered-out entries for active selections absent from
|
|
71
|
+
// aggregation results (e.g. saved filters with zero matching rows). They
|
|
72
|
+
// use the same shape as real entries so the loop below handles isNull
|
|
73
|
+
// uniformly.
|
|
74
|
+
const filteredOutEntries = activeValues.flatMap(v => existingValues.has(v) ? [] : [{
|
|
74
75
|
$group: {
|
|
75
76
|
[propertyKey]: v
|
|
76
77
|
},
|
|
77
78
|
$count: 0
|
|
78
79
|
}]);
|
|
79
|
-
for (const item of [...dataArray, ...
|
|
80
|
+
for (const item of [...dataArray, ...filteredOutEntries]) {
|
|
80
81
|
const rawValue = item.$group[propertyKey];
|
|
81
82
|
const count = item.$count ?? 0;
|
|
82
83
|
if (rawValue == null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePropertyAggregation.js","names":["useOsdkAggregation","useMemo","dedupeEmptyAggregationRows","EMPTY_ACTIVE_VALUES","usePropertyAggregation","objectType","propertyKey","objectSet","options","aggregateOptions","$select","$count","$groupBy","$exact","$includeNullValue","aggregationArgs","aggregate","where","data","countData","isLoading","error","activeValues","result","maxCount","values","dataArray","existingValues","Set","item","raw","$group","add","String","
|
|
1
|
+
{"version":3,"file":"usePropertyAggregation.js","names":["useOsdkAggregation","useMemo","dedupeEmptyAggregationRows","EMPTY_ACTIVE_VALUES","usePropertyAggregation","objectType","propertyKey","objectSet","options","aggregateOptions","$select","$count","$groupBy","$exact","$includeNullValue","aggregationArgs","aggregate","where","data","countData","isLoading","error","activeValues","result","maxCount","values","dataArray","existingValues","Set","item","raw","$group","add","String","filteredOutEntries","flatMap","v","has","rawValue","count","push","value","isNull","Math","max","deduped","sortBy","sort","a","b","localeCompare","limit","length","slice"],"sources":["usePropertyAggregation.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n AggregateOpts,\n ObjectSet,\n ObjectTypeDefinition,\n PropertyKeys,\n WhereClause,\n} from \"@osdk/api\";\nimport { useOsdkAggregation } from \"@osdk/react\";\nimport { useMemo } from \"react\";\nimport type { AggregationGroupResult } from \"../utils/aggregationHelpers.js\";\nimport { dedupeEmptyAggregationRows } from \"../utils/filterValues.js\";\n\nexport type { PropertyAggregationValue } from \"../types/AggregationTypes.js\";\n\nimport type { PropertyAggregationValue } from \"../types/AggregationTypes.js\";\n\nexport interface UsePropertyAggregationResult {\n data: PropertyAggregationValue[];\n maxCount: number;\n isLoading: boolean;\n error: Error | null;\n}\n\nconst EMPTY_ACTIVE_VALUES: string[] = [];\n\nexport interface UsePropertyAggregationOptions<\n Q extends ObjectTypeDefinition = ObjectTypeDefinition,\n> {\n limit?: number;\n where?: WhereClause<Q>;\n sortBy?: \"count\" | \"value\";\n /** Selected values to include in results even when they have zero matching\n * rows (e.g. saved filter selections from initialFilterStates). */\n activeValues?: string[];\n}\n\nexport function usePropertyAggregation<\n Q extends ObjectTypeDefinition,\n K extends PropertyKeys<Q>,\n>(\n objectType: Q,\n propertyKey: K,\n objectSet: ObjectSet<Q> | undefined,\n options?: UsePropertyAggregationOptions<Q>,\n): UsePropertyAggregationResult {\n // AggregateOpts requires specific property keys from Q, but we're dynamically\n // using propertyKey. The cast is unavoidable for this dynamic filter pattern.\n const aggregateOptions = useMemo(\n () =>\n ({\n $select: { $count: \"unordered\" as const },\n $groupBy: {\n [propertyKey as string]: {\n $exact: { $includeNullValue: true },\n },\n },\n }) as AggregateOpts<Q>,\n [propertyKey],\n );\n\n const aggregationArgs = useMemo(\n () => ({ aggregate: aggregateOptions, where: options?.where, objectSet }),\n [aggregateOptions, options?.where, objectSet],\n );\n\n const { data: countData, isLoading, error } = useOsdkAggregation(\n objectType,\n aggregationArgs,\n );\n\n const activeValues = options?.activeValues ?? EMPTY_ACTIVE_VALUES;\n\n const result = useMemo(\n (): { data: PropertyAggregationValue[]; maxCount: number } => {\n if (!countData) {\n return { data: [], maxCount: 0 };\n }\n\n const values: PropertyAggregationValue[] = [];\n let maxCount = 0;\n\n // The aggregation result type varies by query structure. Since we're building\n // the query dynamically based on propertyKey, we cast to a known shape that\n // matches the $groupBy + $count aggregation pattern.\n const dataArray = countData as AggregationGroupResult;\n\n // Build a set of values present in the aggregation so we can identify\n // which active selections need to be synthesized as filtered-out entries.\n const existingValues = new Set<string>();\n for (const item of dataArray) {\n const raw = item.$group[propertyKey as string];\n existingValues.add(raw == null ? \"\" : String(raw));\n }\n\n // Synthesize filtered-out entries for active selections absent from\n // aggregation results (e.g. saved filters with zero matching rows). They\n // use the same shape as real entries so the loop below handles isNull\n // uniformly.\n const filteredOutEntries = activeValues.flatMap((v) =>\n existingValues.has(v)\n ? []\n : [{ $group: { [propertyKey as string]: v }, $count: 0 }]\n );\n\n for (const item of [...dataArray, ...filteredOutEntries]) {\n const rawValue = item.$group[propertyKey as string];\n const count = item.$count ?? 0;\n\n if (rawValue == null) {\n values.push({ value: \"\", count, isNull: true });\n } else {\n values.push({ value: String(rawValue), count });\n }\n maxCount = Math.max(maxCount, count);\n }\n\n const deduped = dedupeEmptyAggregationRows(values);\n\n const sortBy = options?.sortBy ?? \"count\";\n if (sortBy === \"count\") {\n deduped.sort((a, b) =>\n b.count - a.count || a.value.localeCompare(b.value)\n );\n } else {\n deduped.sort((a, b) => a.value.localeCompare(b.value));\n }\n\n if (options?.limit && deduped.length > options.limit) {\n return { data: deduped.slice(0, options.limit), maxCount };\n }\n\n return { data: deduped, maxCount };\n },\n [countData, propertyKey, options?.limit, options?.sortBy, activeValues],\n );\n\n return {\n data: result.data,\n maxCount: result.maxCount,\n isLoading,\n error: error ?? null,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|