@osdk/react-components 0.54.0 → 0.55.0-main-caff0c0ea39b54fba6782b0f2a1514f491afa4c1

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/browser/filter-list/FilterList.js.map +1 -1
  3. package/build/browser/filter-list/FilterListApi.js.map +1 -1
  4. package/build/browser/filter-list/hooks/useFilterListState.js +92 -16
  5. package/build/browser/filter-list/hooks/useFilterListState.js.map +1 -1
  6. package/build/browser/filter-list/types/LinkedFilterTypes.js.map +1 -1
  7. package/build/browser/object-table/ObjectTableApi.js.map +1 -1
  8. package/build/browser/public/experimental/filter-list.js.map +1 -1
  9. package/build/browser/util/UserAgent.js +1 -1
  10. package/build/browser/util/UserAgent.js.map +1 -1
  11. package/build/cjs/chunk-4OB3E6KJ.cjs +11 -0
  12. package/build/cjs/{chunk-D2XXXPH6.cjs.map → chunk-4OB3E6KJ.cjs.map} +1 -1
  13. package/build/cjs/chunk-C4M2S3UN.cjs +11 -0
  14. package/build/cjs/{chunk-EYGD2H45.cjs.map → chunk-C4M2S3UN.cjs.map} +1 -1
  15. package/build/cjs/chunk-DRCXFM73.cjs +11 -0
  16. package/build/cjs/{chunk-LJLLTHYK.cjs.map → chunk-DRCXFM73.cjs.map} +1 -1
  17. package/build/cjs/{chunk-HWY2YSBD.cjs → chunk-GL2UPD5Q.cjs} +4 -4
  18. package/build/cjs/{chunk-HWY2YSBD.cjs.map → chunk-GL2UPD5Q.cjs.map} +1 -1
  19. package/build/cjs/{chunk-4QUYZCMR.cjs → chunk-HG2XX6LZ.cjs} +4 -4
  20. package/build/cjs/{chunk-4QUYZCMR.cjs.map → chunk-HG2XX6LZ.cjs.map} +1 -1
  21. package/build/cjs/{chunk-EANEZ7DS.cjs → chunk-K6OEAX2T.cjs} +4 -4
  22. package/build/cjs/{chunk-EANEZ7DS.cjs.map → chunk-K6OEAX2T.cjs.map} +1 -1
  23. package/build/cjs/{chunk-B2VLYFEO.cjs → chunk-L57CLKED.cjs} +4 -4
  24. package/build/cjs/{chunk-B2VLYFEO.cjs.map → chunk-L57CLKED.cjs.map} +1 -1
  25. package/build/cjs/{chunk-JJTZZ4AO.cjs → chunk-LUHPM2MY.cjs} +91 -20
  26. package/build/cjs/chunk-LUHPM2MY.cjs.map +1 -0
  27. package/build/cjs/{chunk-RCPPRRRK.cjs → chunk-R3KKO3FP.cjs} +4 -4
  28. package/build/cjs/{chunk-RCPPRRRK.cjs.map → chunk-R3KKO3FP.cjs.map} +1 -1
  29. package/build/cjs/{chunk-G7M3NOUP.cjs → chunk-WATCUA6R.cjs} +3 -3
  30. package/build/cjs/chunk-WATCUA6R.cjs.map +1 -0
  31. package/build/cjs/chunk-WTIDFE4H.cjs +11 -0
  32. package/build/cjs/{chunk-NX3YZIHN.cjs.map → chunk-WTIDFE4H.cjs.map} +1 -1
  33. package/build/cjs/{chunk-R6TVZR37.cjs → chunk-YCBXWCQB.cjs} +4 -4
  34. package/build/cjs/{chunk-R6TVZR37.cjs.map → chunk-YCBXWCQB.cjs.map} +1 -1
  35. package/build/cjs/{chunk-LCSQHTQ2.cjs → chunk-YU4NMPPG.cjs} +4 -4
  36. package/build/cjs/{chunk-LCSQHTQ2.cjs.map → chunk-YU4NMPPG.cjs.map} +1 -1
  37. package/build/cjs/{chunk-USKT6B3H.cjs → chunk-Z3LAOM6L.cjs} +4 -4
  38. package/build/cjs/{chunk-USKT6B3H.cjs.map → chunk-Z3LAOM6L.cjs.map} +1 -1
  39. package/build/cjs/public/experimental/action-form.cjs +4 -4
  40. package/build/cjs/public/experimental/cbac-picker.cjs +11 -11
  41. package/build/cjs/public/experimental/document-viewer.cjs +4 -4
  42. package/build/cjs/public/experimental/email-viewer.cjs +3 -3
  43. package/build/cjs/public/experimental/filter-list.cjs +15 -15
  44. package/build/cjs/public/experimental/filter-list.d.cts +66 -12
  45. package/build/cjs/public/experimental/image-viewer.cjs +3 -3
  46. package/build/cjs/public/experimental/markdown-renderer.cjs +5 -5
  47. package/build/cjs/public/experimental/object-table.cjs +22 -22
  48. package/build/cjs/public/experimental/object-table.d.cts +0 -1
  49. package/build/cjs/public/experimental/pdf-viewer.cjs +7 -7
  50. package/build/cjs/public/experimental/spreadsheet-viewer.cjs +3 -3
  51. package/build/cjs/public/experimental/tiff-renderer.cjs +5 -5
  52. package/build/cjs/public/experimental/video-viewer.cjs +3 -3
  53. package/build/cjs/public/experimental/xml-viewer.cjs +3 -3
  54. package/build/cjs/public/experimental.cjs +76 -76
  55. package/build/cjs/public/experimental.d.cts +1 -1
  56. package/build/esm/filter-list/FilterList.js.map +1 -1
  57. package/build/esm/filter-list/FilterListApi.js.map +1 -1
  58. package/build/esm/filter-list/hooks/useFilterListState.js +92 -16
  59. package/build/esm/filter-list/hooks/useFilterListState.js.map +1 -1
  60. package/build/esm/filter-list/types/LinkedFilterTypes.js.map +1 -1
  61. package/build/esm/object-table/ObjectTableApi.js.map +1 -1
  62. package/build/esm/public/experimental/filter-list.js.map +1 -1
  63. package/build/esm/util/UserAgent.js +1 -1
  64. package/build/esm/util/UserAgent.js.map +1 -1
  65. package/build/types/filter-list/FilterList.d.ts.map +1 -1
  66. package/build/types/filter-list/FilterListApi.d.ts +56 -10
  67. package/build/types/filter-list/FilterListApi.d.ts.map +1 -1
  68. package/build/types/filter-list/hooks/useFilterListState.d.ts.map +1 -1
  69. package/build/types/filter-list/types/LinkedFilterTypes.d.ts +1 -1
  70. package/build/types/object-table/ObjectTableApi.d.ts +0 -1
  71. package/build/types/object-table/ObjectTableApi.d.ts.map +1 -1
  72. package/build/types/public/experimental/filter-list.d.ts +1 -1
  73. package/build/types/public/experimental/filter-list.d.ts.map +1 -1
  74. package/docs/FilterList.md +93 -27
  75. package/docs/ObjectTable.md +1 -1
  76. package/docs/ObjectTableOverview.md +1 -1
  77. package/package.json +4 -4
  78. package/build/cjs/chunk-D2XXXPH6.cjs +0 -11
  79. package/build/cjs/chunk-EYGD2H45.cjs +0 -11
  80. package/build/cjs/chunk-G7M3NOUP.cjs.map +0 -1
  81. package/build/cjs/chunk-JJTZZ4AO.cjs.map +0 -1
  82. package/build/cjs/chunk-LJLLTHYK.cjs +0 -11
  83. package/build/cjs/chunk-NX3YZIHN.cjs +0 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @osdk/react-components
2
2
 
3
+ ## 0.55.0-main-caff0c0ea39b54fba6782b0f2a1514f491afa4c1
4
+
5
+ ### Minor Changes
6
+
7
+ - caff0c0: FilterList: add `onFilterListChanged`, a single callback that fires on mount and on every filter-state change — set, remove or reset. The event has a `snapshot` with the resulting `filterClause` and filtered `ObjectSet`, plus a `reason` tagged union (`FILTER_STATE_CHANGED`, `FILTER_REMOVED`, `FILTER_LIST_RESET`, `FILTER_LIST_INITIALIZED`) describing what changed — replacing the need to wire up `onFilterStateChanged`, `onFilterClauseChanged` and `onEffectiveObjectSet` separately.
8
+
9
+ `filterKey` on `onFilterAdded`, `onFilterRemoved` and `onFilterVisibilityChange` is now typed `string` rather than a union of the declared filter keys.
10
+
3
11
  ## 0.54.0
4
12
 
5
13
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"FilterList.js","names":["React","useCallback","useMemo","AddFilterPopover","BaseFilterList","FilterInput","useFilterListState","useFilterVisibility","EMPTY_LINKED_FILTERS","getEmptyDisplayState","getFilterKey","getFilterLabel","EMPTY_WHERE","EMPTY_DEFINITIONS","FilterList","props","objectType","objectSet","title","titleIcon","enableCollapse","defaultCollapsed","collapsed","onCollapsedChange","filterDefinitions","addFilterMode","showResetButton","onReset","showActiveFilterCount","showFilteredOutValues","className","enableSorting","onFilterAdded","onFilterRemoved","onFilterVisibilityChange","renderAddFilterButton","filterStates","setFilterState","clearFilterState","perFilterWhereClauses","perFilterLinkedFilters","activeFilterCount","hasChangesFromInitial","reset","uncontrolledAddFilterMode","handleVisibilityChange","visibleKeys","hiddenKeys","states","map","key","filterKey","isVisible","visibleDefinitions","managedVisibleDefinitions","hiddenDefinitions","managedHiddenDefinitions","showFilter","hideFilter","reorderVisible","hasVisibilityChanges","resetVisibility","handleReset","simpleVisibleDefinitions","undefined","filter","def","effectiveVisibleDefinitions","handleFilterRemoved","handleFilterShown","handleOrderChange","orderedKeys","hiddenFilterItems","label","effectiveRenderAddFilterButton","length","createElement","onShowFilter","renderTrigger","effectiveOnFilterRemoved","renderInput","definition","filterState","onFilterStateChanged","searchQuery","excludeRowOpen","whereClause","get","linkedFilters","canReset","onOrderChange"],"sources":["FilterList.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 type { ObjectTypeDefinition } from \"@osdk/api\";\nimport React, { useCallback, useMemo } from \"react\";\n\nimport { AddFilterPopover } from \"./base/AddFilterPopover.js\";\nimport { BaseFilterList } from \"./base/BaseFilterList.js\";\nimport type { RenderFilterInput } from \"./base/BaseFilterListApi.js\";\nimport { FilterInput } from \"./FilterInput.js\";\nimport type {\n FilterDefinitionUnion,\n FilterKey,\n FilterListProps,\n} from \"./FilterListApi.js\";\nimport { useFilterListState } from \"./hooks/useFilterListState.js\";\nimport { useFilterVisibility } from \"./hooks/useFilterVisibility.js\";\nimport { EMPTY_LINKED_FILTERS } from \"./types/LinkedFilterTypes.js\";\nimport { getEmptyDisplayState } from \"./utils/emptyFilterDisplayState.js\";\nimport { getFilterKey } from \"./utils/getFilterKey.js\";\nimport { getFilterLabel } from \"./utils/getFilterLabel.js\";\n\nconst EMPTY_WHERE = {};\nconst EMPTY_DEFINITIONS: Array<never> = [];\n\nexport function FilterList<Q extends ObjectTypeDefinition>(\n props: FilterListProps<Q>,\n): React.ReactElement {\n const {\n objectType,\n objectSet,\n title,\n titleIcon,\n enableCollapse,\n defaultCollapsed,\n collapsed,\n onCollapsedChange,\n filterDefinitions,\n addFilterMode = \"uncontrolled\",\n showResetButton = false,\n onReset,\n showActiveFilterCount = false,\n showFilteredOutValues = false,\n className,\n enableSorting,\n onFilterAdded,\n onFilterRemoved,\n onFilterVisibilityChange,\n renderAddFilterButton,\n } = props;\n\n const {\n filterStates,\n setFilterState,\n clearFilterState,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n } = useFilterListState(props);\n\n const uncontrolledAddFilterMode = addFilterMode === \"uncontrolled\";\n\n const handleVisibilityChange = useCallback(\n (visibleKeys: string[], hiddenKeys: string[]) => {\n if (!onFilterVisibilityChange) {\n return;\n }\n const states: Array<{ filterKey: FilterKey<Q>; isVisible: boolean }> = [\n ...visibleKeys.map((key) => ({\n filterKey: key as FilterKey<Q>,\n isVisible: true,\n })),\n ...hiddenKeys.map((key) => ({\n filterKey: key as FilterKey<Q>,\n isVisible: false,\n })),\n ];\n onFilterVisibilityChange(states);\n },\n [onFilterVisibilityChange],\n );\n\n const {\n visibleDefinitions: managedVisibleDefinitions,\n hiddenDefinitions: managedHiddenDefinitions,\n showFilter,\n hideFilter,\n reorderVisible,\n hasVisibilityChanges,\n resetVisibility,\n } = useFilterVisibility(filterDefinitions, handleVisibilityChange);\n\n const canReset = hasChangesFromInitial || hasVisibilityChanges;\n\n const handleReset = useCallback(() => {\n reset();\n resetVisibility();\n onReset?.();\n }, [reset, resetVisibility, onReset]);\n\n const simpleVisibleDefinitions = useMemo(() => {\n if (filterDefinitions == null) {\n return undefined;\n }\n return filterDefinitions.filter(\n (def: FilterDefinitionUnion<Q>) => def.isVisible !== false,\n );\n }, [filterDefinitions]);\n\n const effectiveVisibleDefinitions = uncontrolledAddFilterMode\n ? managedVisibleDefinitions\n : simpleVisibleDefinitions;\n\n const handleFilterRemoved = useCallback(\n (filterKey: string) => {\n clearFilterState(filterKey);\n if (uncontrolledAddFilterMode) {\n hideFilter(filterKey);\n }\n onFilterRemoved?.(filterKey);\n },\n [clearFilterState, uncontrolledAddFilterMode, hideFilter, onFilterRemoved],\n );\n\n const handleFilterShown = useCallback(\n (filterKey: string) => {\n showFilter(filterKey);\n onFilterAdded?.(filterKey, filterDefinitions ?? EMPTY_DEFINITIONS);\n },\n [showFilter, onFilterAdded, filterDefinitions],\n );\n\n const handleOrderChange = useCallback(\n (orderedKeys: string[]) => {\n reorderVisible(orderedKeys);\n },\n [reorderVisible],\n );\n\n const hiddenFilterItems = useMemo(\n () =>\n managedHiddenDefinitions.map((def) => ({\n key: getFilterKey(def),\n label: getFilterLabel(def),\n })),\n [managedHiddenDefinitions],\n );\n\n const effectiveRenderAddFilterButton = useMemo(() => {\n if (uncontrolledAddFilterMode) {\n if (managedHiddenDefinitions.length === 0) {\n return undefined;\n }\n return () => (\n <AddFilterPopover\n hiddenDefinitions={hiddenFilterItems}\n onShowFilter={handleFilterShown}\n renderTrigger={renderAddFilterButton}\n />\n );\n }\n return renderAddFilterButton;\n }, [\n uncontrolledAddFilterMode,\n managedHiddenDefinitions.length,\n hiddenFilterItems,\n handleFilterShown,\n renderAddFilterButton,\n ]);\n\n const effectiveOnFilterRemoved = uncontrolledAddFilterMode\n ? handleFilterRemoved\n : onFilterRemoved;\n\n const renderInput = useCallback<RenderFilterInput<FilterDefinitionUnion<Q>>>(\n ({\n definition,\n filterKey,\n filterState,\n onFilterStateChanged,\n searchQuery,\n excludeRowOpen,\n }) => (\n <FilterInput\n objectType={objectType}\n objectSet={objectSet}\n definition={definition}\n filterState={filterState}\n onFilterStateChanged={onFilterStateChanged}\n whereClause={perFilterWhereClauses.get(filterKey) ?? EMPTY_WHERE}\n linkedFilters={\n perFilterLinkedFilters.get(filterKey) ?? EMPTY_LINKED_FILTERS\n }\n showFilteredOutValues={showFilteredOutValues}\n searchQuery={searchQuery}\n excludeRowOpen={excludeRowOpen}\n />\n ),\n [\n objectType,\n objectSet,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n showFilteredOutValues,\n ],\n );\n\n return (\n <BaseFilterList\n title={title}\n titleIcon={titleIcon}\n enableCollapse={enableCollapse}\n defaultCollapsed={defaultCollapsed}\n collapsed={collapsed}\n onCollapsedChange={onCollapsedChange}\n filterDefinitions={effectiveVisibleDefinitions}\n filterStates={filterStates}\n onFilterStateChanged={setFilterState}\n renderInput={renderInput}\n getFilterKey={getFilterKey}\n getFilterLabel={getFilterLabel}\n getEmptyDisplayState={getEmptyDisplayState}\n activeFilterCount={activeFilterCount}\n onReset={handleReset}\n showResetButton={showResetButton}\n showActiveFilterCount={showActiveFilterCount}\n canReset={canReset}\n enableSorting={enableSorting}\n onFilterRemoved={effectiveOnFilterRemoved}\n onOrderChange={handleOrderChange}\n className={className}\n renderAddFilterButton={effectiveRenderAddFilterButton}\n />\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FilterList.js","names":["React","useCallback","useMemo","AddFilterPopover","BaseFilterList","FilterInput","useFilterListState","useFilterVisibility","EMPTY_LINKED_FILTERS","getEmptyDisplayState","getFilterKey","getFilterLabel","EMPTY_WHERE","EMPTY_DEFINITIONS","FilterList","props","objectType","objectSet","title","titleIcon","enableCollapse","defaultCollapsed","collapsed","onCollapsedChange","filterDefinitions","addFilterMode","showResetButton","onReset","showActiveFilterCount","showFilteredOutValues","className","enableSorting","onFilterAdded","onFilterRemoved","onFilterVisibilityChange","renderAddFilterButton","filterStates","setFilterState","clearFilterState","perFilterWhereClauses","perFilterLinkedFilters","activeFilterCount","hasChangesFromInitial","reset","uncontrolledAddFilterMode","handleVisibilityChange","visibleKeys","hiddenKeys","states","map","key","filterKey","isVisible","visibleDefinitions","managedVisibleDefinitions","hiddenDefinitions","managedHiddenDefinitions","showFilter","hideFilter","reorderVisible","hasVisibilityChanges","resetVisibility","handleReset","simpleVisibleDefinitions","undefined","filter","def","effectiveVisibleDefinitions","handleFilterRemoved","handleFilterShown","handleOrderChange","orderedKeys","hiddenFilterItems","label","effectiveRenderAddFilterButton","length","createElement","onShowFilter","renderTrigger","effectiveOnFilterRemoved","renderInput","definition","filterState","onFilterStateChanged","searchQuery","excludeRowOpen","whereClause","get","linkedFilters","canReset","onOrderChange"],"sources":["FilterList.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 type { ObjectTypeDefinition } from \"@osdk/api\";\nimport React, { useCallback, useMemo } from \"react\";\n\nimport { AddFilterPopover } from \"./base/AddFilterPopover.js\";\nimport { BaseFilterList } from \"./base/BaseFilterList.js\";\nimport type { RenderFilterInput } from \"./base/BaseFilterListApi.js\";\nimport { FilterInput } from \"./FilterInput.js\";\nimport type {\n FilterDefinitionUnion,\n FilterListProps,\n} from \"./FilterListApi.js\";\nimport { useFilterListState } from \"./hooks/useFilterListState.js\";\nimport { useFilterVisibility } from \"./hooks/useFilterVisibility.js\";\nimport { EMPTY_LINKED_FILTERS } from \"./types/LinkedFilterTypes.js\";\nimport { getEmptyDisplayState } from \"./utils/emptyFilterDisplayState.js\";\nimport { getFilterKey } from \"./utils/getFilterKey.js\";\nimport { getFilterLabel } from \"./utils/getFilterLabel.js\";\n\nconst EMPTY_WHERE = {};\nconst EMPTY_DEFINITIONS: Array<never> = [];\n\nexport function FilterList<Q extends ObjectTypeDefinition>(\n props: FilterListProps<Q>,\n): React.ReactElement {\n const {\n objectType,\n objectSet,\n title,\n titleIcon,\n enableCollapse,\n defaultCollapsed,\n collapsed,\n onCollapsedChange,\n filterDefinitions,\n addFilterMode = \"uncontrolled\",\n showResetButton = false,\n onReset,\n showActiveFilterCount = false,\n showFilteredOutValues = false,\n className,\n enableSorting,\n onFilterAdded,\n onFilterRemoved,\n onFilterVisibilityChange,\n renderAddFilterButton,\n } = props;\n\n const {\n filterStates,\n setFilterState,\n clearFilterState,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n } = useFilterListState(props);\n\n const uncontrolledAddFilterMode = addFilterMode === \"uncontrolled\";\n\n const handleVisibilityChange = useCallback(\n (visibleKeys: string[], hiddenKeys: string[]) => {\n if (!onFilterVisibilityChange) {\n return;\n }\n const states: Array<{ filterKey: string; isVisible: boolean }> = [\n ...visibleKeys.map((key) => ({ filterKey: key, isVisible: true })),\n ...hiddenKeys.map((key) => ({ filterKey: key, isVisible: false })),\n ];\n onFilterVisibilityChange(states);\n },\n [onFilterVisibilityChange],\n );\n\n const {\n visibleDefinitions: managedVisibleDefinitions,\n hiddenDefinitions: managedHiddenDefinitions,\n showFilter,\n hideFilter,\n reorderVisible,\n hasVisibilityChanges,\n resetVisibility,\n } = useFilterVisibility(filterDefinitions, handleVisibilityChange);\n\n const canReset = hasChangesFromInitial || hasVisibilityChanges;\n\n const handleReset = useCallback(() => {\n reset();\n resetVisibility();\n onReset?.();\n }, [reset, resetVisibility, onReset]);\n\n const simpleVisibleDefinitions = useMemo(() => {\n if (filterDefinitions == null) {\n return undefined;\n }\n return filterDefinitions.filter(\n (def: FilterDefinitionUnion<Q>) => def.isVisible !== false,\n );\n }, [filterDefinitions]);\n\n const effectiveVisibleDefinitions = uncontrolledAddFilterMode\n ? managedVisibleDefinitions\n : simpleVisibleDefinitions;\n\n const handleFilterRemoved = useCallback(\n (filterKey: string) => {\n clearFilterState(filterKey);\n if (uncontrolledAddFilterMode) {\n hideFilter(filterKey);\n }\n onFilterRemoved?.(filterKey);\n },\n [clearFilterState, uncontrolledAddFilterMode, hideFilter, onFilterRemoved],\n );\n\n const handleFilterShown = useCallback(\n (filterKey: string) => {\n showFilter(filterKey);\n onFilterAdded?.(filterKey, filterDefinitions ?? EMPTY_DEFINITIONS);\n },\n [showFilter, onFilterAdded, filterDefinitions],\n );\n\n const handleOrderChange = useCallback(\n (orderedKeys: string[]) => {\n reorderVisible(orderedKeys);\n },\n [reorderVisible],\n );\n\n const hiddenFilterItems = useMemo(\n () =>\n managedHiddenDefinitions.map((def) => ({\n key: getFilterKey(def),\n label: getFilterLabel(def),\n })),\n [managedHiddenDefinitions],\n );\n\n const effectiveRenderAddFilterButton = useMemo(() => {\n if (uncontrolledAddFilterMode) {\n if (managedHiddenDefinitions.length === 0) {\n return undefined;\n }\n return () => (\n <AddFilterPopover\n hiddenDefinitions={hiddenFilterItems}\n onShowFilter={handleFilterShown}\n renderTrigger={renderAddFilterButton}\n />\n );\n }\n return renderAddFilterButton;\n }, [\n uncontrolledAddFilterMode,\n managedHiddenDefinitions.length,\n hiddenFilterItems,\n handleFilterShown,\n renderAddFilterButton,\n ]);\n\n const effectiveOnFilterRemoved = uncontrolledAddFilterMode\n ? handleFilterRemoved\n : onFilterRemoved;\n\n const renderInput = useCallback<RenderFilterInput<FilterDefinitionUnion<Q>>>(\n ({\n definition,\n filterKey,\n filterState,\n onFilterStateChanged,\n searchQuery,\n excludeRowOpen,\n }) => (\n <FilterInput\n objectType={objectType}\n objectSet={objectSet}\n definition={definition}\n filterState={filterState}\n onFilterStateChanged={onFilterStateChanged}\n whereClause={perFilterWhereClauses.get(filterKey) ?? EMPTY_WHERE}\n linkedFilters={\n perFilterLinkedFilters.get(filterKey) ?? EMPTY_LINKED_FILTERS\n }\n showFilteredOutValues={showFilteredOutValues}\n searchQuery={searchQuery}\n excludeRowOpen={excludeRowOpen}\n />\n ),\n [\n objectType,\n objectSet,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n showFilteredOutValues,\n ],\n );\n\n return (\n <BaseFilterList\n title={title}\n titleIcon={titleIcon}\n enableCollapse={enableCollapse}\n defaultCollapsed={defaultCollapsed}\n collapsed={collapsed}\n onCollapsedChange={onCollapsedChange}\n filterDefinitions={effectiveVisibleDefinitions}\n filterStates={filterStates}\n onFilterStateChanged={setFilterState}\n renderInput={renderInput}\n getFilterKey={getFilterKey}\n getFilterLabel={getFilterLabel}\n getEmptyDisplayState={getEmptyDisplayState}\n activeFilterCount={activeFilterCount}\n onReset={handleReset}\n showResetButton={showResetButton}\n showActiveFilterCount={showActiveFilterCount}\n canReset={canReset}\n enableSorting={enableSorting}\n onFilterRemoved={effectiveOnFilterRemoved}\n onOrderChange={handleOrderChange}\n className={className}\n renderAddFilterButton={effectiveRenderAddFilterButton}\n />\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterListApi.js","names":[],"sources":["FilterListApi.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 LinkNames,\n ObjectSet,\n ObjectTypeDefinition,\n WhereClause,\n} from \"@osdk/api\";\nimport type React from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type {\n FilterState,\n PropertyFilterDefinition,\n} from \"./FilterListItemApi.js\";\nimport type { CustomFilterDefinition } from \"./types/CustomRendererTypes.js\";\nimport type { KeywordSearchFilterDefinition } from \"./types/KeywordSearchTypes.js\";\nimport type {\n HasLinkFilterDefinition,\n LinkedPropertyFilterDefinition,\n} from \"./types/LinkedFilterTypes.js\";\nimport type { StaticValuesFilterDefinition } from \"./types/StaticValuesTypes.js\";\n\n/**\n * Distributes LinkedPropertyFilterDefinition over each link name individually,\n * so that LinkedQ/LinkedK/LinkedC defaults resolve correctly per link.\n */\ntype DistributeLinkedProperty<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q>,\n> = L extends LinkNames<Q> ? LinkedPropertyFilterDefinition<Q, L> : never;\n\n/**\n * Union type of all filter definition types\n */\nexport type FilterDefinitionUnion<Q extends ObjectTypeDefinition> =\n | PropertyFilterDefinition<Q>\n | HasLinkFilterDefinition<Q>\n | DistributeLinkedProperty<Q, LinkNames<Q>>\n | KeywordSearchFilterDefinition<Q>\n | CustomFilterDefinition<Q>\n | StaticValuesFilterDefinition<Q>;\n\n/**\n * Extract the key from a filter definition union\n */\ntype ExtractFilterKey<D> = D extends { key: infer K }\n ? K\n : D extends { linkName: infer L }\n ? L\n : never;\n\nexport type FilterKey<Q extends ObjectTypeDefinition> = ExtractFilterKey<\n FilterDefinitionUnion<Q>\n>;\n\nexport interface FilterListProps<Q extends ObjectTypeDefinition> {\n /**\n * The object type definition for the objects being filtered.\n * Used for metadata resolution (property types, display names).\n */\n objectType: Q;\n\n /**\n * Optional object set to scope aggregation queries. When omitted,\n * aggregations run against the full object type.\n *\n * Required for `HAS_LINK` and `LINKED_PROPERTY` filters to work.\n */\n objectSet?: ObjectSet<Q>;\n\n /**\n * Called whenever the filter clause changes. FilterList owns filter state;\n * this is how you read it out, e.g. to feed an `ObjectTable`'s `filter`.\n *\n * `HAS_LINK` and `LINKED_PROPERTY` filters are not represented in the clause\n * — use `onEffectiveObjectSet` for those.\n *\n * @param newClause The updated filter clause\n */\n onFilterClauseChanged?: (newClause: WhereClause<Q>) => void;\n\n /**\n * Optional title to display in the filter list header\n */\n title?: ReactNode;\n\n /**\n * Optional icon to display next to the title\n */\n titleIcon?: React.ReactNode;\n\n /**\n * The definition for all supported filter items in the list\n * If not supplied, all filterable properties will be available\n */\n filterDefinitions?: Array<FilterDefinitionUnion<Q>>;\n\n /**\n * Called when filter state changes\n *\n * @param definition The filter definition whose state changed\n * @param newState The updated filter state\n */\n onFilterStateChanged?: (\n definition: FilterDefinitionUnion<Q>,\n newState: FilterState,\n ) => void;\n\n /**\n * Called with the narrowed `ObjectSet` whenever filters change. Requires\n * `objectSet` to be set. `HAS_LINK` and `LINKED_PROPERTY` filters narrow only\n * here, never through the filter clause.\n */\n onEffectiveObjectSet?: (objectSet: ObjectSet<Q>) => void;\n\n /**\n * When `true`, facets render greyed-out count=0 rows for values present in\n * the unfiltered data but excluded by other active filters.\n * @default false\n */\n showFilteredOutValues?: boolean;\n\n /**\n * Controls how filter visibility (add/remove) is managed.\n *\n * - `\"uncontrolled\"` (default): FilterList manages visibility internally.\n * An \"Add filter\" popover is rendered for filters with `isVisible: false`,\n * and each visible filter shows a remove button.\n * - `\"controlled\"`: The consumer manages which filters are visible via\n * `filterDefinitions`. Filters with `isVisible: false` are excluded from\n * the rendered list.\n *\n * @default \"uncontrolled\"\n * @deprecated Going away; visibility will always be managed internally.\n * Seed it with `isVisible` on each `filterDefinitions` entry and observe\n * changes with `onFilterVisibilityChange`.\n */\n addFilterMode?: \"controlled\" | \"uncontrolled\";\n\n /**\n * Called after a filter is shown from the built-in \"Add filter\" popover.\n *\n * @param filterKey The key of the added filter\n * @param newDefinitions Deprecated. The `filterDefinitions` you passed in,\n * unchanged — not the post-add state. Use `onFilterVisibilityChange`.\n */\n onFilterAdded?: (\n filterKey: FilterKey<Q>,\n /** @deprecated Use `onFilterVisibilityChange`. */\n /* eslint-disable-next-line @typescript-eslint/no-deprecated */\n newDefinitions: Array<FilterDefinitionUnion<Q>>,\n ) => void;\n\n /**\n * Called after a filter's remove button is clicked, once the filter is\n * hidden and its state cleared.\n *\n * @param filterKey The key of the removed filter\n */\n onFilterRemoved?: (filterKey: FilterKey<Q>) => void;\n\n /**\n * Called when filter visibility or ordering changes, i.e. when filters are\n * reordered, added or removed via the built-in show/remove controls, or\n * reset.\n *\n * Visible filters come first, in display order, followed by the hidden ones.\n * Persist this array and feed it back as the order and `isVisible` of\n * `filterDefinitions` to make reordering survive a remount.\n *\n * @param newStates The filters in current display order with their visibility state\n */\n onFilterVisibilityChange?: (\n newStates: Array<{\n filterKey: FilterKey<Q>;\n isVisible: boolean;\n }>,\n ) => void;\n\n /**\n * Enable drag-and-drop reordering of filters. When `true`, drag handles are\n * rendered and filters can be reordered.\n *\n * Reorder state is managed internally; persist `onFilterVisibilityChange` to\n * track order across remounts.\n *\n * @default false\n */\n enableSorting?: boolean;\n\n /**\n * Whether the collapse/expand control is available. When `false` the panel is\n * always expanded, no collapse control is rendered, and `collapsed` /\n * `defaultCollapsed` are ignored.\n * @default true\n */\n enableCollapse?: boolean;\n\n /**\n * Controlled mode. When supplied, this prop is the source of truth for\n * whether the panel is collapsed and the component keeps no internal state;\n * re-render with a new value in response to `onCollapsedChange`.\n *\n * If both `collapsed` and `defaultCollapsed` are provided, `collapsed` takes\n * precedence. Ignored when `enableCollapse` is `false`.\n */\n collapsed?: boolean;\n\n /**\n * Uncontrolled mode. Seeds the panel's internal collapsed state; the\n * component continues to own the state after mount, so later changes to this\n * prop are ignored.\n *\n * If both `collapsed` and `defaultCollapsed` are provided, `collapsed` takes\n * precedence. Ignored when `enableCollapse` is `false`.\n * @default false\n */\n defaultCollapsed?: boolean;\n\n /**\n * Called whenever the collapsed state changes.\n *\n * @param collapsed The new collapsed state\n */\n onCollapsedChange?: (collapsed: boolean) => void;\n\n /**\n * Seeds filter states from external storage, keyed by `getFilterKey`.\n * Applied over the per-definition `defaultFilterState` seeds on mount, and\n * FilterList owns the states from then on. Also the state the reset button\n * restores to.\n * Use `onFilterStateChanged` to persist changes back out.\n *\n * @default undefined (filters seed from their definitions alone)\n */\n defaultFilterStates?: Map<string, FilterState>;\n\n /**\n * @deprecated Rename to `defaultFilterStates`.\n */\n initialFilterStates?: Map<string, FilterState>;\n\n /**\n * Show reset filters button in header\n */\n showResetButton?: boolean;\n\n /**\n * Called when reset button is clicked\n */\n onReset?: () => void;\n\n /**\n * Show count of active filters in header\n */\n showActiveFilterCount?: boolean;\n\n /**\n * Additional CSS class name\n */\n className?: string;\n\n /**\n * Custom render function for the \"Add filter\" button. Customizes the trigger\n * element for the built-in add-filter popover; the popover behavior is\n * handled automatically.\n */\n renderAddFilterButton?: () => React.ReactNode;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"FilterListApi.js","names":[],"sources":["FilterListApi.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 LinkNames,\n ObjectSet,\n ObjectTypeDefinition,\n WhereClause,\n} from \"@osdk/api\";\nimport type React from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type {\n FilterState,\n PropertyFilterDefinition,\n} from \"./FilterListItemApi.js\";\nimport type { CustomFilterDefinition } from \"./types/CustomRendererTypes.js\";\nimport type { KeywordSearchFilterDefinition } from \"./types/KeywordSearchTypes.js\";\nimport type {\n HasLinkFilterDefinition,\n LinkedPropertyFilterDefinition,\n} from \"./types/LinkedFilterTypes.js\";\nimport type { StaticValuesFilterDefinition } from \"./types/StaticValuesTypes.js\";\n\n/**\n * Distributes LinkedPropertyFilterDefinition over each link name individually,\n * so that LinkedQ/LinkedK/LinkedC defaults resolve correctly per link.\n */\ntype DistributeLinkedProperty<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q>,\n> = L extends LinkNames<Q> ? LinkedPropertyFilterDefinition<Q, L> : never;\n\n/**\n * Union type of all filter definition types\n */\nexport type FilterDefinitionUnion<Q extends ObjectTypeDefinition> =\n | PropertyFilterDefinition<Q>\n | HasLinkFilterDefinition<Q>\n | DistributeLinkedProperty<Q, LinkNames<Q>>\n | KeywordSearchFilterDefinition<Q>\n | CustomFilterDefinition<Q>\n | StaticValuesFilterDefinition<Q>;\n\n/**\n * The filter state after a change, in one payload.\n */\nexport interface FilterChangeSnapshot<Q extends ObjectTypeDefinition> {\n /**\n * The combined clause for all active filters.\n *\n * `HAS_LINK` and `LINKED_PROPERTY` filters are not represented in the clause —\n * read `filteredObjectSet` for those.\n */\n filterClause: WhereClause<Q>;\n\n /**\n * The `objectSet` prop filtered by all active filters, including `HAS_LINK`\n * and `LINKED_PROPERTY`, or `undefined` when no `objectSet` was supplied.\n */\n filteredObjectSet: ObjectSet<Q> | undefined;\n}\n\n/**\n * What the user did to the filter state.\n */\nexport type FilterChangeReason =\n /** A filter's state was set — selected values changed, include/exclude mode toggled, or filter cleared. */\n | { type: \"FILTER_STATE_CHANGED\"; filterKey: string; newState: FilterState }\n /** A filter was removed from the list. */\n | { type: \"FILTER_REMOVED\"; filterKey: string }\n /** Every filter was restored to the state it mounted with. */\n | { type: \"FILTER_LIST_RESET\" }\n /** The list mounted, reporting the state it started with. */\n | { type: \"FILTER_LIST_INITIALIZED\" };\n\n/**\n * The payload delivered to `onFilterListChanged`.\n */\nexport interface FilterChangeEvent<Q extends ObjectTypeDefinition> {\n /** The filter state the change produced. */\n snapshot: FilterChangeSnapshot<Q>;\n /** What changed. */\n reason: FilterChangeReason;\n}\n\nexport interface FilterListProps<Q extends ObjectTypeDefinition> {\n /**\n * The object type definition for the objects being filtered.\n * Used for metadata resolution (property types, display names).\n */\n objectType: Q;\n\n /**\n * Optional object set to scope aggregation queries. When omitted,\n * aggregations run against the full object type.\n *\n * Required for `HAS_LINK` and `LINKED_PROPERTY` filters to work.\n */\n objectSet?: ObjectSet<Q>;\n\n /**\n * Called whenever the filter clause changes. FilterList owns filter state;\n * this is how you read it out, e.g. to feed an `ObjectTable`'s `filter`.\n *\n * `HAS_LINK` and `LINKED_PROPERTY` filters are not represented in the clause\n * — use `onEffectiveObjectSet` for those.\n *\n * @param newClause The updated filter clause\n * @deprecated Use `onFilterListChanged`, whose `snapshot` reports the clause\n * alongside the filtered `ObjectSet`.\n */\n onFilterClauseChanged?: (newClause: WhereClause<Q>) => void;\n\n /**\n * Optional title to display in the filter list header\n */\n title?: ReactNode;\n\n /**\n * Optional icon to display next to the title\n */\n titleIcon?: React.ReactNode;\n\n /**\n * The definition for all supported filter items in the list\n * If not supplied, all filterable properties will be available\n */\n filterDefinitions?: Array<FilterDefinitionUnion<Q>>;\n\n /**\n * Called when filter state changes\n *\n * @param definition The filter definition whose state changed\n * @param newState The updated filter state\n * @deprecated Use `onFilterListChanged`, which reports every set / clear / reset\n * with an `event` describing what changed.\n */\n onFilterStateChanged?: (\n definition: FilterDefinitionUnion<Q>,\n newState: FilterState,\n ) => void;\n\n /**\n * Called on filter init and when filter state changes.\n *\n * @param event `snapshot` carries the filter state the change produced;\n * `reason` carries what changed.\n */\n onFilterListChanged?: (event: FilterChangeEvent<Q>) => void;\n\n /**\n * Called with the narrowed `ObjectSet` whenever filters change. Requires\n * `objectSet` to be set. `HAS_LINK` and `LINKED_PROPERTY` filters narrow only\n * here, never through the filter clause.\n *\n * @deprecated Use `onFilterListChanged`, whose `snapshot.filteredObjectSet`\n * reports the same narrowed set alongside the clause.\n */\n onEffectiveObjectSet?: (objectSet: ObjectSet<Q>) => void;\n\n /**\n * When `true`, facets render greyed-out count=0 rows for values present in\n * the unfiltered data but excluded by other active filters.\n * @default false\n */\n showFilteredOutValues?: boolean;\n\n /**\n * Controls how filter visibility (add/remove) is managed.\n *\n * - `\"uncontrolled\"` (default): FilterList manages visibility internally.\n * An \"Add filter\" popover is rendered for filters with `isVisible: false`,\n * and each visible filter shows a remove button.\n * - `\"controlled\"`: The consumer manages which filters are visible via\n * `filterDefinitions`. Filters with `isVisible: false` are excluded from\n * the rendered list.\n *\n * @default \"uncontrolled\"\n * @deprecated Going away; visibility will always be managed internally.\n * Seed it with `isVisible` on each `filterDefinitions` entry and observe\n * changes with `onFilterVisibilityChange`.\n */\n addFilterMode?: \"controlled\" | \"uncontrolled\";\n\n /**\n * Called after a filter is shown from the built-in \"Add filter\" popover.\n *\n * @param filterKey The key of the added filter\n * @param newDefinitions Deprecated. The `filterDefinitions` you passed in,\n * unchanged — not the post-add state. Use `onFilterVisibilityChange`.\n */\n onFilterAdded?: (\n filterKey: string,\n /** @deprecated Use `onFilterVisibilityChange`. */\n /* eslint-disable-next-line @typescript-eslint/no-deprecated */\n newDefinitions: Array<FilterDefinitionUnion<Q>>,\n ) => void;\n\n /**\n * Called after a filter's remove button is clicked, once the filter is\n * hidden and its state cleared.\n *\n * @param filterKey The key of the removed filter\n */\n onFilterRemoved?: (filterKey: string) => void;\n\n /**\n * Called when filter visibility or ordering changes, i.e. when filters are\n * reordered, added or removed via the built-in show/remove controls, or\n * reset.\n *\n * Visible filters come first, in display order, followed by the hidden ones.\n * Persist this array and feed it back as the order and `isVisible` of\n * `filterDefinitions` to make reordering survive a remount.\n *\n * @param newStates The filters in current display order with their visibility state\n */\n onFilterVisibilityChange?: (\n newStates: Array<{\n filterKey: string;\n isVisible: boolean;\n }>,\n ) => void;\n\n /**\n * Enable drag-and-drop reordering of filters. When `true`, drag handles are\n * rendered and filters can be reordered.\n *\n * Reorder state is managed internally; persist `onFilterVisibilityChange` to\n * track order across remounts.\n *\n * @default false\n */\n enableSorting?: boolean;\n\n /**\n * Whether the collapse/expand control is available. When `false` the panel is\n * always expanded, no collapse control is rendered, and `collapsed` /\n * `defaultCollapsed` are ignored.\n * @default true\n */\n enableCollapse?: boolean;\n\n /**\n * Controlled mode. When supplied, this prop is the source of truth for\n * whether the panel is collapsed and the component keeps no internal state;\n * re-render with a new value in response to `onCollapsedChange`.\n *\n * If both `collapsed` and `defaultCollapsed` are provided, `collapsed` takes\n * precedence. Ignored when `enableCollapse` is `false`.\n */\n collapsed?: boolean;\n\n /**\n * Uncontrolled mode. Seeds the panel's internal collapsed state; the\n * component continues to own the state after mount, so later changes to this\n * prop are ignored.\n *\n * If both `collapsed` and `defaultCollapsed` are provided, `collapsed` takes\n * precedence. Ignored when `enableCollapse` is `false`.\n * @default false\n */\n defaultCollapsed?: boolean;\n\n /**\n * Called whenever the collapsed state changes.\n *\n * @param collapsed The new collapsed state\n */\n onCollapsedChange?: (collapsed: boolean) => void;\n\n /**\n * Seeds filter states from external storage, keyed by `getFilterKey`.\n * Applied over the per-definition `defaultFilterState` seeds on mount, and\n * FilterList owns the states from then on. Also the state the reset button\n * restores to.\n * Use `onFilterStateChanged` to persist changes back out.\n *\n * @default undefined (filters seed from their definitions alone)\n */\n defaultFilterStates?: Map<string, FilterState>;\n\n /**\n * @deprecated Rename to `defaultFilterStates`.\n */\n initialFilterStates?: Map<string, FilterState>;\n\n /**\n * Show reset filters button in header\n */\n showResetButton?: boolean;\n\n /**\n * Called when reset button is clicked\n */\n onReset?: () => void;\n\n /**\n * Show count of active filters in header\n */\n showActiveFilterCount?: boolean;\n\n /**\n * Additional CSS class name\n */\n className?: string;\n\n /**\n * Custom render function for the \"Add filter\" button. Customizes the trigger\n * element for the built-in add-filter popover; the popover behavior is\n * handled automatically.\n */\n renderAddFilterButton?: () => React.ReactNode;\n}\n"],"mappings":"","ignoreList":[]}
@@ -36,13 +36,26 @@ function buildInitialStates(definitions) {
36
36
  }
37
37
  return states;
38
38
  }
39
+ function deriveSnapshot(definitions, filterStates, propertyTypes, objectSet) {
40
+ const whereClause = buildWhereClause(definitions, filterStates, propertyTypes);
41
+ const linkedFilters = getActiveLinkedFilters(definitions, filterStates);
42
+ return {
43
+ whereClause,
44
+ linkedFilters,
45
+ effectiveObjectSet: objectSet == null ? undefined : narrowObjectSet(objectSet, whereClause, linkedFilters)
46
+ };
47
+ }
39
48
  export function useFilterListState(props) {
40
49
  const {
41
50
  objectType,
42
51
  objectSet,
43
52
  filterDefinitions,
53
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported
44
54
  onFilterStateChanged,
55
+ onFilterListChanged,
56
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported
45
57
  onFilterClauseChanged,
58
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported
46
59
  onEffectiveObjectSet,
47
60
  defaultFilterStates,
48
61
  // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat fallback for the pre-rename prop
@@ -50,14 +63,21 @@ export function useFilterListState(props) {
50
63
  } = props;
51
64
  const seededFilterStates = defaultFilterStates ?? initialFilterStates;
52
65
  const {
53
- metadata
66
+ metadata,
67
+ loading: metadataLoading
54
68
  } = useOsdkMetadata(objectType);
69
+ const onFilterStateChangedRef = useRef(onFilterStateChanged);
70
+ onFilterStateChangedRef.current = onFilterStateChanged;
55
71
  const onFilterClauseChangedRef = useRef(onFilterClauseChanged);
56
72
  onFilterClauseChangedRef.current = onFilterClauseChanged;
57
73
  const onEffectiveObjectSetRef = useRef(onEffectiveObjectSet);
58
74
  onEffectiveObjectSetRef.current = onEffectiveObjectSet;
75
+ const onFilterListChangedRef = useRef(onFilterListChanged);
76
+ onFilterListChangedRef.current = onFilterListChanged;
59
77
  const filterDefinitionsRef = useRef(filterDefinitions);
60
78
  filterDefinitionsRef.current = filterDefinitions;
79
+ const objectSetRef = useRef(objectSet);
80
+ objectSetRef.current = objectSet;
61
81
  const propertyTypes = useMemo(() => {
62
82
  const map = new Map();
63
83
  if (metadata?.properties) {
@@ -72,6 +92,22 @@ export function useFilterListState(props) {
72
92
  }
73
93
  return map;
74
94
  }, [metadata?.properties]);
95
+ const propertyTypesRef = useRef(propertyTypes);
96
+ propertyTypesRef.current = propertyTypes;
97
+ const emitFilterListChanged = useCallback((states, reason) => {
98
+ const onChange = onFilterListChangedRef.current;
99
+ if (onChange == null) {
100
+ return;
101
+ }
102
+ const snapshot = deriveSnapshot(filterDefinitionsRef.current, states, propertyTypesRef.current, objectSetRef.current);
103
+ onChange({
104
+ snapshot: {
105
+ filterClause: snapshot.whereClause,
106
+ filteredObjectSet: snapshot.effectiveObjectSet
107
+ },
108
+ reason
109
+ });
110
+ }, []);
75
111
 
76
112
  // Captured once on first render to provide a stable baseline for the reset
77
113
  // button's enabled state. `useState`'s lazy initializer pins the value for
@@ -86,30 +122,70 @@ export function useFilterListState(props) {
86
122
  return snapshot;
87
123
  });
88
124
  const [filterStates, setFilterStates] = useState(() => new Map(initialFilterStatesSnapshot));
125
+
126
+ // Back-to-back writes can occur before React commits, so each transition must
127
+ // build on the latest eagerly computed state rather than the render snapshot.
128
+ const filterStatesRef = useRef(filterStates);
129
+ filterStatesRef.current = filterStates;
130
+ const applyChange = useCallback((transition, reason) => {
131
+ const next = transition(filterStatesRef.current);
132
+ if (next === undefined) {
133
+ return;
134
+ }
135
+ filterStatesRef.current = next;
136
+ setFilterStates(next);
137
+ emitFilterListChanged(next, reason);
138
+ }, [emitFilterListChanged]);
89
139
  const setFilterState = useCallback((filterKey, state) => {
90
- setFilterStates(prev => {
91
- const next = new Map(prev);
140
+ const definition = filterDefinitionsRef.current?.find(candidate => getFilterKey(candidate) === filterKey);
141
+ if (definition) {
142
+ onFilterStateChangedRef.current?.(definition, state);
143
+ }
144
+ applyChange(previous => {
145
+ const next = new Map(previous);
92
146
  next.set(filterKey, state);
93
147
  return next;
148
+ }, {
149
+ type: "FILTER_STATE_CHANGED",
150
+ filterKey,
151
+ newState: state
94
152
  });
95
- const definition = filterDefinitionsRef.current?.find(d => getFilterKey(d) === filterKey);
96
- if (definition) {
97
- onFilterStateChanged?.(definition, state);
98
- }
99
- }, [onFilterStateChanged]);
153
+ }, [applyChange]);
100
154
  const clearFilterState = useCallback(filterKey => {
101
- setFilterStates(prev => {
102
- const next = new Map(prev);
155
+ applyChange(previous => {
156
+ if (!previous.has(filterKey)) {
157
+ return;
158
+ }
159
+ const next = new Map(previous);
103
160
  next.delete(filterKey);
104
161
  return next;
162
+ }, {
163
+ type: "FILTER_REMOVED",
164
+ filterKey
105
165
  });
106
- }, []);
166
+ }, [applyChange]);
107
167
  const reset = useCallback(() => {
108
- setFilterStates(new Map(initialFilterStatesSnapshot));
109
- }, [initialFilterStatesSnapshot]);
110
- const whereClause = useMemo(() => buildWhereClause(filterDefinitions, filterStates, propertyTypes), [filterDefinitions, filterStates, propertyTypes]);
111
- const linkedFilters = useMemo(() => getActiveLinkedFilters(filterDefinitions, filterStates), [filterDefinitions, filterStates]);
112
- const effectiveObjectSet = useMemo(() => objectSet == null ? undefined : narrowObjectSet(objectSet, whereClause, linkedFilters), [objectSet, whereClause, linkedFilters]);
168
+ applyChange(() => new Map(initialFilterStatesSnapshot), {
169
+ type: "FILTER_LIST_RESET"
170
+ });
171
+ }, [applyChange, initialFilterStatesSnapshot]);
172
+ const {
173
+ whereClause,
174
+ linkedFilters,
175
+ effectiveObjectSet
176
+ } = useMemo(() => deriveSnapshot(filterDefinitions, filterStates, propertyTypes, objectSet), [filterDefinitions, filterStates, propertyTypes, objectSet]);
177
+ const hasEmittedInit = useRef(false);
178
+ useEffect(() => {
179
+ // We need to wait until metadata is loaded because we need
180
+ // metadata to construct the filter clause
181
+ if (hasEmittedInit.current || metadataLoading) {
182
+ return;
183
+ }
184
+ hasEmittedInit.current = true;
185
+ emitFilterListChanged(filterStatesRef.current, {
186
+ type: "FILTER_LIST_INITIALIZED"
187
+ });
188
+ }, [metadataLoading, emitFilterListChanged]);
113
189
  useEffect(() => {
114
190
  onFilterClauseChangedRef.current?.(whereClause);
115
191
  }, [whereClause]);
@@ -1 +1 @@
1
- {"version":3,"file":"useFilterListState.js","names":["useOsdkMetadata","isEqual","useCallback","useEffect","useMemo","useRef","useState","buildWhereClause","getActiveLinkedFilters","filterHasActiveState","getFilterKey","getSeedFilterState","narrowObjectSet","useStableMapEntries","buildInitialStates","definitions","states","Map","definition","state","set","useFilterListState","props","objectType","objectSet","filterDefinitions","onFilterStateChanged","onFilterClauseChanged","onEffectiveObjectSet","defaultFilterStates","initialFilterStates","seededFilterStates","metadata","onFilterClauseChangedRef","current","onEffectiveObjectSetRef","filterDefinitionsRef","propertyTypes","map","properties","key","prop","Object","entries","type","multiplicity","initialFilterStatesSnapshot","snapshot","filterStates","setFilterStates","setFilterState","filterKey","prev","next","find","d","clearFilterState","delete","reset","whereClause","linkedFilters","effectiveObjectSet","undefined","perFilterWhereClauses","perFilterLinkedFilters","activeFilterCount","count","get","clause","toWhereClause","keys","length","hasChangesFromInitial"],"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 { isEqual } from \"lodash-es\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { FilterListProps } from \"../FilterListApi.js\";\nimport type { FilterState } from \"../FilterListItemApi.js\";\nimport type { LinkedFilter } 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 { getSeedFilterState } from \"../utils/getSeedFilterState.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: (filterKey: string, state: FilterState) => void;\n clearFilterState: (filterKey: string) => void;\n /** Direct (non-link-traversing) filters combined into a `WhereClause<Q>`. */\n whereClause: WhereClause<Q>;\n /** Active HAS_LINK and LINKED_PROPERTY records */\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 hasChangesFromInitial: boolean;\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 state = getSeedFilterState(definition);\n if (state) {\n states.set(getFilterKey(definition), state);\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 defaultFilterStates,\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat fallback for the pre-rename prop\n initialFilterStates,\n } = props;\n const seededFilterStates = defaultFilterStates ?? initialFilterStates;\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 // Captured once on first render to provide a stable baseline for the reset\n // button's enabled state. `useState`'s lazy initializer pins the value for\n // the lifetime of the component (unlike `useMemo`, which React may discard).\n const [initialFilterStatesSnapshot] = useState<Map<string, FilterState>>(\n () => {\n const snapshot = buildInitialStates(filterDefinitions);\n if (seededFilterStates) {\n for (const [key, state] of seededFilterStates) {\n snapshot.set(key, state);\n }\n }\n return snapshot;\n },\n );\n\n const [filterStates, setFilterStates] = useState<Map<string, FilterState>>(\n () => new Map(initialFilterStatesSnapshot),\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(new Map(initialFilterStatesSnapshot));\n }, [initialFilterStatesSnapshot]);\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 definition of filterDefinitions ?? []) {\n const state = filterStates.get(getFilterKey(definition));\n if (state == null) {\n continue;\n }\n // A custom filter's state is opaque, so `filterHasActiveState` can only\n // say \"some state exists\". Only its own `toWhereClause` knows whether\n // that state filters anything, so match what `buildWhereClause` keeps.\n if (definition.type === \"CUSTOM\") {\n if (state.type === \"custom\") {\n const clause = definition.toWhereClause(state);\n if (clause != null && Object.keys(clause).length > 0) {\n count++;\n }\n }\n continue;\n }\n if (filterHasActiveState(state)) {\n count++;\n }\n }\n return count;\n }, [filterDefinitions, filterStates]);\n\n const hasChangesFromInitial = useMemo(\n () => !isEqual(filterStates, initialFilterStatesSnapshot),\n [filterStates, initialFilterStatesSnapshot],\n );\n\n return useMemo(\n () => ({\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n }),\n [\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n ],\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"useFilterListState.js","names":["useOsdkMetadata","isEqual","useCallback","useEffect","useMemo","useRef","useState","buildWhereClause","getActiveLinkedFilters","filterHasActiveState","getFilterKey","getSeedFilterState","narrowObjectSet","useStableMapEntries","buildInitialStates","definitions","states","Map","definition","state","set","deriveSnapshot","filterStates","propertyTypes","objectSet","whereClause","linkedFilters","effectiveObjectSet","undefined","useFilterListState","props","objectType","filterDefinitions","onFilterStateChanged","onFilterListChanged","onFilterClauseChanged","onEffectiveObjectSet","defaultFilterStates","initialFilterStates","seededFilterStates","metadata","loading","metadataLoading","onFilterStateChangedRef","current","onFilterClauseChangedRef","onEffectiveObjectSetRef","onFilterListChangedRef","filterDefinitionsRef","objectSetRef","map","properties","key","prop","Object","entries","type","multiplicity","propertyTypesRef","emitFilterListChanged","reason","onChange","snapshot","filterClause","filteredObjectSet","initialFilterStatesSnapshot","setFilterStates","filterStatesRef","applyChange","transition","next","setFilterState","filterKey","find","candidate","previous","newState","clearFilterState","has","delete","reset","hasEmittedInit","perFilterWhereClauses","perFilterLinkedFilters","activeFilterCount","count","get","clause","toWhereClause","keys","length","hasChangesFromInitial"],"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 { isEqual } from \"lodash-es\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type {\n FilterChangeReason,\n FilterDefinitionUnion,\n FilterListProps,\n} from \"../FilterListApi.js\";\nimport type { FilterState } from \"../FilterListItemApi.js\";\nimport type { LinkedFilter } 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 { getSeedFilterState } from \"../utils/getSeedFilterState.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: (filterKey: string, state: FilterState) => void;\n clearFilterState: (filterKey: string) => void;\n /** Direct (non-link-traversing) filters combined into a `WhereClause<Q>`. */\n whereClause: WhereClause<Q>;\n /** Active HAS_LINK and LINKED_PROPERTY records */\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 hasChangesFromInitial: boolean;\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 state = getSeedFilterState(definition);\n if (state) {\n states.set(getFilterKey(definition), state);\n }\n }\n\n return states;\n}\n\ninterface FilterSnapshot<Q extends ObjectTypeDefinition> {\n whereClause: WhereClause<Q>;\n linkedFilters: ReadonlyArray<LinkedFilter<Q>>;\n effectiveObjectSet: ObjectSet<Q> | undefined;\n}\n\nfunction deriveSnapshot<Q extends ObjectTypeDefinition>(\n definitions: Array<FilterDefinitionUnion<Q>> | undefined,\n filterStates: Map<string, FilterState>,\n propertyTypes: Map<string, PropertyTypeInfo>,\n objectSet: ObjectSet<Q> | undefined,\n): FilterSnapshot<Q> {\n const whereClause = buildWhereClause(\n definitions,\n filterStates,\n propertyTypes,\n );\n const linkedFilters = getActiveLinkedFilters(definitions, filterStates);\n return {\n whereClause,\n linkedFilters,\n effectiveObjectSet:\n objectSet == null\n ? undefined\n : narrowObjectSet(objectSet, whereClause, linkedFilters),\n };\n}\n\nexport function useFilterListState<Q extends ObjectTypeDefinition>(\n props: FilterListProps<Q>,\n): UseFilterListStateResult<Q> {\n const {\n objectType,\n objectSet,\n filterDefinitions,\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported\n onFilterStateChanged,\n onFilterListChanged,\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported\n onFilterClauseChanged,\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat callback still supported\n onEffectiveObjectSet,\n defaultFilterStates,\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- back-compat fallback for the pre-rename prop\n initialFilterStates,\n } = props;\n const seededFilterStates = defaultFilterStates ?? initialFilterStates;\n const { metadata, loading: metadataLoading } = useOsdkMetadata(objectType);\n\n const onFilterStateChangedRef = useRef(onFilterStateChanged);\n onFilterStateChangedRef.current = onFilterStateChanged;\n const onFilterClauseChangedRef = useRef(onFilterClauseChanged);\n onFilterClauseChangedRef.current = onFilterClauseChanged;\n const onEffectiveObjectSetRef = useRef(onEffectiveObjectSet);\n onEffectiveObjectSetRef.current = onEffectiveObjectSet;\n const onFilterListChangedRef = useRef(onFilterListChanged);\n onFilterListChangedRef.current = onFilterListChanged;\n const filterDefinitionsRef = useRef(filterDefinitions);\n filterDefinitionsRef.current = filterDefinitions;\n const objectSetRef = useRef(objectSet);\n objectSetRef.current = objectSet;\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 const propertyTypesRef = useRef(propertyTypes);\n propertyTypesRef.current = propertyTypes;\n\n const emitFilterListChanged = useCallback(\n (states: Map<string, FilterState>, reason: FilterChangeReason) => {\n const onChange = onFilterListChangedRef.current;\n if (onChange == null) {\n return;\n }\n const snapshot = deriveSnapshot(\n filterDefinitionsRef.current,\n states,\n propertyTypesRef.current,\n objectSetRef.current,\n );\n onChange({\n snapshot: {\n filterClause: snapshot.whereClause,\n filteredObjectSet: snapshot.effectiveObjectSet,\n },\n reason,\n });\n },\n [],\n );\n\n // Captured once on first render to provide a stable baseline for the reset\n // button's enabled state. `useState`'s lazy initializer pins the value for\n // the lifetime of the component (unlike `useMemo`, which React may discard).\n const [initialFilterStatesSnapshot] = useState<Map<string, FilterState>>(\n () => {\n const snapshot = buildInitialStates(filterDefinitions);\n if (seededFilterStates) {\n for (const [key, state] of seededFilterStates) {\n snapshot.set(key, state);\n }\n }\n return snapshot;\n },\n );\n\n const [filterStates, setFilterStates] = useState<Map<string, FilterState>>(\n () => new Map(initialFilterStatesSnapshot),\n );\n\n // Back-to-back writes can occur before React commits, so each transition must\n // build on the latest eagerly computed state rather than the render snapshot.\n const filterStatesRef = useRef(filterStates);\n filterStatesRef.current = filterStates;\n\n const applyChange = useCallback(\n (\n transition: (\n previous: Map<string, FilterState>,\n ) => Map<string, FilterState> | undefined,\n reason: FilterChangeReason,\n ) => {\n const next = transition(filterStatesRef.current);\n if (next === undefined) {\n return;\n }\n filterStatesRef.current = next;\n setFilterStates(next);\n emitFilterListChanged(next, reason);\n },\n [emitFilterListChanged],\n );\n\n const setFilterState = useCallback(\n (filterKey: string, state: FilterState) => {\n const definition = filterDefinitionsRef.current?.find(\n (candidate) => getFilterKey(candidate) === filterKey,\n );\n if (definition) {\n onFilterStateChangedRef.current?.(definition, state);\n }\n applyChange(\n (previous) => {\n const next = new Map(previous);\n next.set(filterKey, state);\n return next;\n },\n { type: \"FILTER_STATE_CHANGED\", filterKey, newState: state },\n );\n },\n [applyChange],\n );\n\n const clearFilterState = useCallback(\n (filterKey: string) => {\n applyChange(\n (previous) => {\n if (!previous.has(filterKey)) {\n return;\n }\n const next = new Map(previous);\n next.delete(filterKey);\n return next;\n },\n { type: \"FILTER_REMOVED\", filterKey },\n );\n },\n [applyChange],\n );\n\n const reset = useCallback(() => {\n applyChange(() => new Map(initialFilterStatesSnapshot), {\n type: \"FILTER_LIST_RESET\",\n });\n }, [applyChange, initialFilterStatesSnapshot]);\n\n const { whereClause, linkedFilters, effectiveObjectSet } = useMemo(\n () =>\n deriveSnapshot(filterDefinitions, filterStates, propertyTypes, objectSet),\n [filterDefinitions, filterStates, propertyTypes, objectSet],\n );\n\n const hasEmittedInit = useRef(false);\n useEffect(() => {\n // We need to wait until metadata is loaded because we need\n // metadata to construct the filter clause\n if (hasEmittedInit.current || metadataLoading) {\n return;\n }\n hasEmittedInit.current = true;\n emitFilterListChanged(filterStatesRef.current, {\n type: \"FILTER_LIST_INITIALIZED\",\n });\n }, [metadataLoading, emitFilterListChanged]);\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 definition of filterDefinitions ?? []) {\n const state = filterStates.get(getFilterKey(definition));\n if (state == null) {\n continue;\n }\n // A custom filter's state is opaque, so `filterHasActiveState` can only\n // say \"some state exists\". Only its own `toWhereClause` knows whether\n // that state filters anything, so match what `buildWhereClause` keeps.\n if (definition.type === \"CUSTOM\") {\n if (state.type === \"custom\") {\n const clause = definition.toWhereClause(state);\n if (clause != null && Object.keys(clause).length > 0) {\n count++;\n }\n }\n continue;\n }\n if (filterHasActiveState(state)) {\n count++;\n }\n }\n return count;\n }, [filterDefinitions, filterStates]);\n\n const hasChangesFromInitial = useMemo(\n () => !isEqual(filterStates, initialFilterStatesSnapshot),\n [filterStates, initialFilterStatesSnapshot],\n );\n\n return useMemo(\n () => ({\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n }),\n [\n filterStates,\n setFilterState,\n clearFilterState,\n whereClause,\n linkedFilters,\n perFilterWhereClauses,\n perFilterLinkedFilters,\n activeFilterCount,\n hasChangesFromInitial,\n reset,\n ],\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"LinkedFilterTypes.js","names":["EMPTY_LINKED_FILTERS"],"sources":["LinkedFilterTypes.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 LinkedType,\n LinkNames,\n ObjectTypeDefinition,\n PropertyKeys,\n WhereClause,\n} from \"@osdk/api\";\nimport type { ReactNode } from \"react\";\n\nimport type {\n BaseFilterState,\n FilterDefinitionControls,\n FilterState,\n FilterStateByComponentType,\n PropertyTypeFromKey,\n ValidComponentsForPropertyType,\n} from \"../FilterListItemApi.js\";\n\n/**\n * Runtime representation of an active link-traversing filter\n */\nexport type LinkedFilter<Q extends ObjectTypeDefinition> = {\n [L in LinkNames<Q>]: {\n /** Stable identity for the filter */\n id: string;\n\n linkName: L;\n /**\n * Predicate the linked objects must match to be counted.\n */\n innerWhere?: WhereClause<LinkedType<Q, L>>;\n /**\n * When true, keep source rows whose match-count is zero.\n */\n isExcluding?: boolean;\n };\n}[LinkNames<Q>];\n\n/** Shared empty default for `LinkedFilter` arrays — avoids new-array-per-render. */\nexport const EMPTY_LINKED_FILTERS: readonly never[] = [];\n\n/**\n * State for \"has link\" filter\n */\nexport interface HasLinkFilterState extends BaseFilterState {\n type: \"hasLink\";\n hasLink: boolean;\n}\n\n/**\n * State for linked property filter\n * Wraps the filter state of the linked property\n */\nexport interface LinkedPropertyFilterState<\n S extends FilterState = FilterState,\n> extends BaseFilterState {\n type: \"linkedProperty\";\n linkedFilterState: S;\n}\n\n/**\n * Filter definition for \"Has Link\" filter\n * Filters objects based on whether they have any linked objects of the specified\n * type. Narrows `objectSet` and is emitted via `onEffectiveObjectSet`; link\n * presence has no filter-clause form, so it never appears in\n * `onFilterClauseChanged`.\n */\nexport interface HasLinkFilterDefinition<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q> = LinkNames<Q>,\n> extends FilterDefinitionControls {\n type: \"HAS_LINK\";\n linkName: L;\n label?: string;\n\n /**\n * Seeds the filter's state on mount, FilterList owns the state from then on\n *\n * @default undefined (filter starts empty)\n */\n defaultFilterState?: HasLinkFilterState;\n\n /**\n * @deprecated Has no effect, remove it.\n */\n filterState?: HasLinkFilterState;\n}\n\n/**\n * Filter definition for filtering on a property of linked objects\n */\nexport interface LinkedPropertyFilterDefinition<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q>,\n LinkedQ extends ObjectTypeDefinition = LinkedType<Q, L>,\n LinkedK extends PropertyKeys<LinkedQ> = PropertyKeys<LinkedQ>,\n LinkedC extends ValidComponentsForPropertyType<\n PropertyTypeFromKey<LinkedQ, LinkedK>\n > = ValidComponentsForPropertyType<PropertyTypeFromKey<LinkedQ, LinkedK>>,\n> extends FilterDefinitionControls {\n type: \"LINKED_PROPERTY\";\n linkName: L;\n /**\n * @deprecated Has no effect, remove it.\n */\n reverseLinkName?: LinkNames<LinkedQ>;\n linkedPropertyKey: LinkedK;\n\n /**\n * The filter component to render for the linked property. Must be\n * compatible with the linked property's type, see\n * ValidComponentsForPropertyType.\n *\n * Required in practice — a definition that sets neither this nor\n * `linkedFilterComponent` renders as unsupported.\n */\n // TODO: make this required, and drop the note above, when\n // `linkedFilterComponent` is removed.\n filterComponent?: LinkedC;\n\n /**\n * @deprecated Rename to `filterComponent`.\n */\n linkedFilterComponent?: LinkedC;\n\n /**\n * Seeds the state of the filter on the *linked* property. FilterList owns the\n * state from then on. `onFilterStateChanged` fires with the wrapper.\n *\n * @default undefined (filter starts empty)\n */\n defaultFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Rename to `defaultFilterState`.\n */\n defaultLinkedFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Has no effect, remove it.\n */\n linkedFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Has no effect, remove it.\n */\n filterState?: LinkedPropertyFilterState<FilterStateByComponentType[LinkedC]>;\n\n label?: string;\n\n /**\n * Show aggregation counts next to filter option values.\n * Applies to LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT linked components.\n * @default true for LISTOGRAM and MULTI_SELECT, false for SINGLE_SELECT\n */\n showCount?: boolean;\n\n /**\n * Custom display function for filter values.\n * Replaces the default string display in dropdown items, chips, and listogram rows.\n * When the function returns a string, that string is also used for search matching\n * within filter dropdowns. When it returns a non-string `ReactNode`, search falls\n * back to the raw value.\n */\n renderValue?: (value: string) => ReactNode;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAoBA;AACA;AACA;;AAkBA;AACA,OAAO,MAAMA,oBAAsC,GAAG,EAAE;;AAExD;AACA;AACA;;AAMA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;AAsBA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"file":"LinkedFilterTypes.js","names":["EMPTY_LINKED_FILTERS"],"sources":["LinkedFilterTypes.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 LinkedType,\n LinkNames,\n ObjectTypeDefinition,\n PropertyKeys,\n WhereClause,\n} from \"@osdk/api\";\nimport type { ReactNode } from \"react\";\n\nimport type {\n BaseFilterState,\n FilterDefinitionControls,\n FilterState,\n FilterStateByComponentType,\n PropertyTypeFromKey,\n ValidComponentsForPropertyType,\n} from \"../FilterListItemApi.js\";\n\n/**\n * Runtime representation of an active link-traversing filter\n */\nexport type LinkedFilter<Q extends ObjectTypeDefinition> = {\n [L in LinkNames<Q>]: {\n /** The filter definition's `getFilterKey` value. */\n id: string;\n\n linkName: L;\n /**\n * Predicate the linked objects must match to be counted.\n */\n innerWhere?: WhereClause<LinkedType<Q, L>>;\n /**\n * When true, keep source rows whose match-count is zero.\n */\n isExcluding?: boolean;\n };\n}[LinkNames<Q>];\n\n/** Shared empty default for `LinkedFilter` arrays — avoids new-array-per-render. */\nexport const EMPTY_LINKED_FILTERS: readonly never[] = [];\n\n/**\n * State for \"has link\" filter\n */\nexport interface HasLinkFilterState extends BaseFilterState {\n type: \"hasLink\";\n hasLink: boolean;\n}\n\n/**\n * State for linked property filter\n * Wraps the filter state of the linked property\n */\nexport interface LinkedPropertyFilterState<\n S extends FilterState = FilterState,\n> extends BaseFilterState {\n type: \"linkedProperty\";\n linkedFilterState: S;\n}\n\n/**\n * Filter definition for \"Has Link\" filter\n * Filters objects based on whether they have any linked objects of the specified\n * type. Narrows `objectSet` and is emitted via `onEffectiveObjectSet`; link\n * presence has no filter-clause form, so it never appears in\n * `onFilterClauseChanged`.\n */\nexport interface HasLinkFilterDefinition<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q> = LinkNames<Q>,\n> extends FilterDefinitionControls {\n type: \"HAS_LINK\";\n linkName: L;\n label?: string;\n\n /**\n * Seeds the filter's state on mount, FilterList owns the state from then on\n *\n * @default undefined (filter starts empty)\n */\n defaultFilterState?: HasLinkFilterState;\n\n /**\n * @deprecated Has no effect, remove it.\n */\n filterState?: HasLinkFilterState;\n}\n\n/**\n * Filter definition for filtering on a property of linked objects\n */\nexport interface LinkedPropertyFilterDefinition<\n Q extends ObjectTypeDefinition,\n L extends LinkNames<Q>,\n LinkedQ extends ObjectTypeDefinition = LinkedType<Q, L>,\n LinkedK extends PropertyKeys<LinkedQ> = PropertyKeys<LinkedQ>,\n LinkedC extends ValidComponentsForPropertyType<\n PropertyTypeFromKey<LinkedQ, LinkedK>\n > = ValidComponentsForPropertyType<PropertyTypeFromKey<LinkedQ, LinkedK>>,\n> extends FilterDefinitionControls {\n type: \"LINKED_PROPERTY\";\n linkName: L;\n /**\n * @deprecated Has no effect, remove it.\n */\n reverseLinkName?: LinkNames<LinkedQ>;\n linkedPropertyKey: LinkedK;\n\n /**\n * The filter component to render for the linked property. Must be\n * compatible with the linked property's type, see\n * ValidComponentsForPropertyType.\n *\n * Required in practice — a definition that sets neither this nor\n * `linkedFilterComponent` renders as unsupported.\n */\n // TODO: make this required, and drop the note above, when\n // `linkedFilterComponent` is removed.\n filterComponent?: LinkedC;\n\n /**\n * @deprecated Rename to `filterComponent`.\n */\n linkedFilterComponent?: LinkedC;\n\n /**\n * Seeds the state of the filter on the *linked* property. FilterList owns the\n * state from then on. `onFilterStateChanged` fires with the wrapper.\n *\n * @default undefined (filter starts empty)\n */\n defaultFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Rename to `defaultFilterState`.\n */\n defaultLinkedFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Has no effect, remove it.\n */\n linkedFilterState?: FilterStateByComponentType[LinkedC];\n\n /**\n * @deprecated Has no effect, remove it.\n */\n filterState?: LinkedPropertyFilterState<FilterStateByComponentType[LinkedC]>;\n\n label?: string;\n\n /**\n * Show aggregation counts next to filter option values.\n * Applies to LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT linked components.\n * @default true for LISTOGRAM and MULTI_SELECT, false for SINGLE_SELECT\n */\n showCount?: boolean;\n\n /**\n * Custom display function for filter values.\n * Replaces the default string display in dropdown items, chips, and listogram rows.\n * When the function returns a string, that string is also used for search matching\n * within filter dropdowns. When it returns a non-string `ReactNode`, search falls\n * back to the raw value.\n */\n renderValue?: (value: string) => ReactNode;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAoBA;AACA;AACA;;AAkBA;AACA,OAAO,MAAMA,oBAAsC,GAAG,EAAE;;AAExD;AACA;AACA;;AAMA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;;AAsBA;AACA;AACA","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectTableApi.js","names":[],"sources":["ObjectTableApi.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 BaseWirePropertyTypes,\n CompileTimeMetadata,\n DerivedProperty,\n ObjectOrInterfaceDefinition,\n ObjectSet,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\n PropertyValueWireToClient,\n QueryDefinition,\n SimplePropertyDef,\n WhereClause,\n} from \"@osdk/api\";\nimport type { QueryParameterType } from \"@osdk/client/observable\";\nimport type * as React from \"react\";\n\nimport type { CellEditInfo, EditFieldConfig } from \"./utils/types.js\";\n\nexport type { EditFieldConfig } from \"./utils/types.js\";\n\nexport type ColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n | EditableColumnDefinition<Q, RDPs, FunctionColumns>\n | EditableFunctionColumnDefinition<Q, RDPs, FunctionColumns>\n | ReadonlyColumnDefinition<Q, RDPs, FunctionColumns>\n | ReadonlyFunctionColumnDefinition<Q, RDPs, FunctionColumns>;\n\n/** A column whose value comes from the row's object. */\ntype DerivableValueColumn<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = {\n /**\n * What the column shows — a property, a linked object property (derived\n * property), or a custom column — and that locator's configuration.\n */\n locator:\n | PropertyColumnLocator<Q>\n | RdpColumnLocator<Q, RDPs>\n | CustomColumnLocator;\n} & CellValueOverride<Q, RDPs, FunctionColumns>;\n\n/**\n * The cell's value and the type it's declared to have.\n *\n * `cellValueType` is required whenever `getCellValue` is provided — declaring\n * the type constrains what `getCellValue` may return, so a column can't\n * advertise one type and hand the cell a value of another. `cellValueType` may\n * also be declared on its own to pick the editor without transforming the\n * value.\n */\ntype CellValueOverride<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n // Use cellValueType + typed getCellValue together\n | {\n [T in BaseWirePropertyTypes]: {\n /**\n * The cell value's data type. Constrains what `getCellValue` may\n * return, and selects the editor for an `editable` column.\n */\n cellValueType: T;\n\n /**\n * Derives the cell's value from the row's object. Without it the column\n * reads the property named by `locator.id`.\n *\n * Use this to change what the cell's value *is* — what it returns is\n * the value the table renders, edits, and passes on to `renderCell`.\n * Use `renderCell` to change only how that value is displayed. The two\n * can be combined.\n */\n getCellValue: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n locator: ColumnDefinitionLocator<Q, RDPs, FunctionColumns>,\n ) => PropertyValueWireToClient[T] | null | undefined;\n };\n }[BaseWirePropertyTypes]\n // Using cellValueType alone.\n | {\n [T in BaseWirePropertyTypes]: {\n cellValueType: T;\n getCellValue?: never;\n };\n }[BaseWirePropertyTypes]\n // Neither\n | {\n cellValueType?: undefined;\n getCellValue?: never;\n };\n\n/** A column whose value comes from a function query rather than the row. */\ninterface FunctionValueColumn<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /** What the column shows, and that locator's configuration. */\n locator: FunctionColumnLocator<Q, RDPs, FunctionColumns>;\n\n /** The cell value's data type. */\n cellValueType?: BaseWirePropertyTypes;\n\n /**\n * Use {@link FunctionColumnLocator}'s own `getValue` instead.\n */\n getCellValue?: never;\n}\n\ninterface SharedColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /**\n * @default true\n */\n isVisible?: boolean;\n\n /**\n * @default none\n */\n pinned?: \"left\" | \"right\" | \"none\";\n width?: number;\n minWidth?: number;\n maxWidth?: number;\n resizable?: boolean;\n orderable?: boolean;\n\n /**\n * Custom renderer for the cell value.\n *\n * This changes only how the cell's value is displayed; the value itself is\n * unchanged. To change the value, use `getCellValue` (and declare its\n * `cellValueType`) — `renderCell` then receives that value as its third\n * argument. The two can be combined.\n *\n * `renderCell` is used only when the cell is read-only.\n * When cells are actually editable, the in-built edit component takes over.\n *\n * @param object - The row's object instance.\n * @param locator - The column locator of this cell.\n * @param value - The cell's value computed by the given `getCellValue` or the default property lookup.\n * @returns custom cell renderer component\n */\n renderCell?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n locator: ColumnDefinitionLocator<Q, RDPs, FunctionColumns>,\n value: unknown,\n ) => React.ReactNode;\n\n /**\n * If provided, this will be used in the column header.\n * If both columnName and renderHeader are provided, renderHeader will take precedence in the table header.\n * columnName will still be used in other parts where the column name is displayed.\n *\n * If not provided,\n * for a property column, the property displayName will be used\n * for other columns, the id will be used.\n */\n columnName?: string;\n\n /**\n * If provided, this will be used to render the header component.\n * When both columnName and renderHeader are provided, renderHeader will take precedence in the table header.\n */\n renderHeader?: () => React.ReactNode;\n}\n\ninterface EditableColumnOptions<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * `editable` can be a boolean or a predicate that receives the row's object\n * and returns whether the cell is editable\n */\n editable:\n | true\n | ((\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => boolean);\n\n /**\n * Configuration for the cell editor component.\n *\n * When provided, the column uses the specified field component\n * (e.g. dropdown) instead of the default auto-detected text/number input.\n *\n * `getFieldComponentProps` receives the row's object and a map of any\n * pending edits for that row (keyed by column id), and returns the props to\n * pass to the field component. Editor configuration can depend on the\n * current row or on other in-progress edits within the row.\n */\n editFieldConfig?: EditFieldConfig<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>\n >;\n\n /**\n * Additional function to validate the cell value during edit.\n *\n * @param value the current cell value\n * @returns a promise that resolves to an error message string if validation fails, or undefined if validation succeeds\n */\n validateEdit?: (value: unknown) => Promise<string | undefined>;\n}\n\ntype EditableColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = SharedColumnDefinition<Q, RDPs, FunctionColumns> &\n EditableColumnOptions<Q, RDPs> &\n DerivableValueColumn<Q, RDPs, FunctionColumns>;\n\n/** Editable column backed by a function query. */\ninterface EditableFunctionColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>\n extends\n SharedColumnDefinition<Q, RDPs, FunctionColumns>,\n EditableColumnOptions<Q, RDPs>,\n FunctionValueColumn<Q, RDPs, FunctionColumns> {}\n\n/**\n * Column definition for a read-only column (default).\n * `editFieldConfig` and `validateEdit` are not available.\n */\ntype ReadonlyColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = SharedColumnDefinition<Q, RDPs, FunctionColumns> &\n DerivableValueColumn<Q, RDPs, FunctionColumns> & { editable?: false };\n\n/** Read-only column backed by a function query. */\ninterface ReadonlyFunctionColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>\n extends\n SharedColumnDefinition<Q, RDPs, FunctionColumns>,\n FunctionValueColumn<Q, RDPs, FunctionColumns> {\n editable?: false;\n}\n\nexport type ExtractQueryParameters<Q extends QueryDefinition> =\n CompileTimeMetadata<Q>[\"parameters\"] extends Record<string, never>\n ? undefined\n : QueryParameterType<CompileTimeMetadata<Q>[\"parameters\"]>;\n\nexport interface PropertyColumnLocator<Q extends ObjectOrInterfaceDefinition> {\n type: \"property\";\n id: PropertyKeys<Q>;\n}\n\n/**\n * Concrete function column locator for a single key K.\n * Correlates the id, queryDefinition, and getFunctionParams types.\n */\ninterface FunctionColumnLocatorForKey<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef>,\n FunctionColumns extends Record<string, QueryDefinition<{}>>,\n K extends keyof FunctionColumns,\n> {\n /**\n * This is equivalent to workshop's function-backed columns.\n * The function needs to meet the specifications stated in https://www.palantir.com/docs/foundry/workshop/widgets-object-table/#function-backed-columns\n */\n type: \"function\";\n id: K;\n queryDefinition: FunctionColumns[K];\n\n /**\n * The function will be called with the current object set to get the input parameters for the function query.\n * @param objectSet - The current object set.\n * @returns - The function's input parameters including the object set.\n */\n getFunctionParams: (\n objectSet: ObjectSet<Q, RDPs>,\n ) => ExtractQueryParameters<FunctionColumns[K]>;\n\n /**\n * Function to generate keys for looking up results in the FunctionsMap.\n * @param object - The object instance\n * @returns - The key to use for looking up this object's result in the FunctionsMap\n */\n getKey: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => string;\n\n /**\n * Function to extract the cell value from the raw cell data returned by the function.\n * This is useful when functions return custom types with multiple properties.\n * @param cellData - The raw data returned by the function for this object\n * @returns - The value to display in the cell\n */\n getValue?: (cellData?: unknown) => unknown;\n\n /**\n * Minimum time between re-fetches of the same function with the same parameters, in milliseconds.\n * Defaults to 5 minutes as it is expensive to fetch function columns for a large object set\n * and they are expected to be relatively static in the context of an object table\n *\n * @default 300_000 (5 minutes)\n */\n dedupeIntervalMs?: number;\n\n /**\n * Object type apiNames the function reads but doesn't take as a parameter (e.g.\n * linked object types the function traverses internally). The column auto-revalidates\n * when an action edits an object of any of these types. Param-derived types are\n * tracked automatically and don't need to be listed here.\n */\n dependsOn?: string[];\n}\n\n/**\n * Distributes over each key in FunctionColumns so that id, queryDefinition,\n * and getFunctionParams are correlated per key.\n */\nexport type FunctionColumnLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = keyof FunctionColumns extends infer K\n ? K extends keyof FunctionColumns\n ? FunctionColumnLocatorForKey<Q, RDPs, FunctionColumns, K>\n : never\n : never;\n\nexport interface RdpColumnLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n type: \"rdp\";\n id: keyof RDPs;\n creator: DerivedProperty.Creator<Q, RDPs[keyof RDPs]>;\n}\n\nexport interface CustomColumnLocator {\n type: \"custom\";\n id: string;\n}\n\nexport type ColumnDefinitionLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n | PropertyColumnLocator<Q>\n | FunctionColumnLocator<Q, RDPs, FunctionColumns>\n | RdpColumnLocator<Q, RDPs>\n | CustomColumnLocator;\n\nexport interface ObjectTableProps<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /**\n * The object or interface type of the object\n * If objectSet is not provided, objects will be fetched based on this type.\n */\n objectType: Q;\n\n /**\n * The set of objects to show in the table.\n * If provided, the table fetches through this object set instead of fetching based on\n * objectType. Supported for both object and interface types.\n *\n * For an interface object set, rows expose the interface's declared properties;\n * the underlying concrete object's non-interface properties are not loaded.\n * Use objectType-based fetching if you need those.\n */\n objectSet?: ObjectSet<Q>;\n\n /**\n * Ordered list of column definitions to show in the table\n *\n * If not provided, all of the properties of the object type will be shown in default order.\n */\n columnDefinitions?: Array<ColumnDefinition<Q, RDPs, FunctionColumns>>;\n\n objectSetOptions?: ObjectSetOptions<Q>;\n\n /**\n * Minimum time between fetch requests in milliseconds.\n * Increasing this value reduces redundant network calls when the same data\n * is requested multiple times in quick succession.\n *\n * @default 60_000 1 minute\n */\n dedupeIntervalMs?: number;\n\n /**\n * Enable streaming updates via websocket subscription.\n * When true, the table will automatically update when matching\n * objects are added, updated, or removed in Foundry.\n *\n * Limitations: `streamUpdates` cannot be used together with `pivotTo` or\n * `withProperties`. The server does not support websocket subscriptions\n * for link-traversal or derived-property queries. Those queries still\n * fetch data normally but won't receive real-time updates.\n *\n * @default false\n */\n streamUpdates?: boolean;\n\n /**\n * Number of objects to fetch per page.\n *\n * @default 50\n */\n pageSize?: number;\n\n /**\n * The current where clause to filter the objects in the table.\n * If provided, the filter is controlled.\n */\n filter?: WhereClause<Q, RDPs>;\n\n /**\n * Whether the column configuration dialog for column visibility and ordering is available to the user.\n *\n * @default true\n */\n enableColumnConfig?: boolean;\n\n /**\n * Whether columns can be pinned by the user.\n *\n * @default true\n */\n enableColumnPinning?: boolean;\n\n /**\n * Whether columns can be resized by the user.\n *\n * @default true\n */\n enableColumnResizing?: boolean;\n\n /**\n * Called when the column visibility or ordering changed.\n *\n * If provided, the table will allow the user to show/hide columns.\n *\n * @param newStates The columns sorted in their display order in the table and their visibility state.\n */\n onColumnVisibilityChanged?: (\n newStates: Array<{\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns;\n isVisible: boolean;\n }>,\n ) => void;\n\n /**\n * Called when the pinned columns change.\n *\n * If provided, the table will allow the user to pin/unpin columns.\n *\n * @param newStates The new list of column pin states\n */\n onColumnsPinnedChanged?: (\n newStates: Array<{\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns;\n pinned: \"left\" | \"right\" | \"none\";\n }>,\n ) => void;\n\n /**\n * Called when a column is resized.\n *\n * @param columnId The ID of the resized column\n * @param newWidth The new width of the column. When newWidth = null, the column size is reset.\n */\n onColumnResize?: (\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns,\n newWidth: number | null,\n ) => void;\n\n /**\n * Called when a column header is clicked.\n *\n * The columnId matches the `locator.id` configured on the column definition.\n * The dropdown menu trigger is excluded — clicking the chevron opens the\n * header menu instead of firing this callback.\n *\n * @param columnId The id of the clicked column\n */\n onColumnHeaderClick?: (\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns,\n ) => void;\n\n /**\n * Whether the table is sortable by the user.\n *\n * @default true\n */\n enableOrdering?: boolean;\n\n /**\n * The default order by clause to sort the objects in the table.\n * If provided without orderBy prop, the sorting is uncontrolled.\n * If both orderBy and defaultOrderBy are provided, orderBy takes precedence.\n */\n defaultOrderBy?: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>;\n\n /**\n * The current order by clause to sort the objects in the table.\n * If provided, the sorting is controlled.\n * If both orderBy and defaultOrderBy are provided, orderBy takes precedence.\n */\n orderBy?: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>;\n\n /**\n * Called when the order by clause is changed.\n * Required when sorting is controlled.\n *\n * @param newOrderBy The new order by clause\n */\n onOrderByChanged?: (\n newOrderBy: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>,\n ) => void;\n\n /**\n * Selection mode for the table rows.\n *\n * If multiple, a checkbox will be shown for each row to allow selecting multiple rows\n * as well as a top-level checkbox in the header to select all rows.\n *\n * @default \"none\"\n */\n selectionMode?: \"single\" | \"multiple\" | \"none\";\n\n /**\n * The currently selected rows in the table.\n * If provided, the row selection is controlled.\n */\n selectedRows?: PrimaryKeyType<Q>[];\n\n /**\n * Indicates whether all rows are selected in controlled mode.\n * When true, the table will show all rows as selected regardless of the selectedRows array.\n */\n isAllSelected?: boolean;\n\n /**\n * Called when the row selection changes, with a {@link RowSelectionChange}\n * payload describing the new state.\n *\n * @param change The new selection state. See {@link RowSelectionChange}.\n */\n onRowSelectionChanged?: (change: RowSelectionChange<Q, RDPs>) => void;\n\n /**\n * Called when the set of loaded rows changes — as pages are fetched, when\n * streamed updates arrive, and after a refetch — with a\n * {@link LoadedObjectsChange} payload.\n *\n * @param change The loaded rows and the total count. See\n * {@link LoadedObjectsChange}.\n */\n onLoadedObjectsChanged?: (change: LoadedObjectsChange<Q, RDPs>) => void;\n\n /**\n * The primary key of the row to render as visually focused (the\n * \"last interacted\" row). When provided, focus state is controlled by\n * the caller.\n *\n * Stored as a primary key rather than a full object so the focus does\n * not go stale when the underlying row data changes.\n *\n * Pass `null` to render no row as focused.\n */\n focusedRow?: PrimaryKeyType<Q> | null;\n\n /**\n * Called when the focused row changes — fires in both controlled and\n * uncontrolled modes so callers can observe focus without taking it\n * over.\n *\n * @param row The newly-focused row object, or `null` if focus was\n * cleared\n */\n onFocusedRowChanged?: (\n row: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs> | null,\n ) => void;\n\n /**\n * Controls the edit mode behavior of the table.\n * - \"always\": Editable cells are immediately in edit mode on row clicked.\n * - \"manual\": User can toggle edit mode on/off via the Edit Table button.\n *\n * @default \"manual\"\n */\n editMode?: \"always\" | \"manual\";\n\n /**\n * Whether to render the bottom edit footer that hosts the\n * \"Edit Table\" / \"Cancel\" / \"Submit Edits\" buttons and the edit-state\n * indicators (modification count, validation errors).\n *\n * @default true whenever the table has at least one column declared\n * editable (i.e. any column with `editable: true` or `editable: (object) => boolean`).\n * When `false`, the \"Edit Table\" and \"Submit Edits\" buttons will not be shown.\n */\n showEditFooter?: boolean;\n\n /**\n * Called after the value of a cell is edited and committed by the user.\n *\n * @param info An object containing details about the cell that was edited,\n * including the rowId, columnId, new and old values, and the row data before the edit\n */\n onCellValueChanged?: (\n info: CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >,\n ) => void;\n\n /**\n * If provided, the \"Submit Edits\" button will be shown in the edit footer.\n *\n * @param edits an array of edit info containing details about the edited cells\n * including the rowId, columnId, new and old values, and the row data before the edit\n * @return a promise that resolves to true if the edits were successfully submitted\n */\n onSubmitEdits?: (\n edits: CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >[],\n ) => Promise<boolean>;\n\n /**\n * Called when a row is clicked.\n *\n * @param object The object representing the clicked row\n */\n onRowClick?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => void;\n\n /**\n * If provided, will render this context menu when right clicking on a cell\n */\n renderCellContextMenu?: (\n row: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n cellValue: unknown,\n ) => React.ReactNode;\n\n /**\n * The height of each row in pixels.\n *\n * @default 40\n */\n rowHeight?: number;\n\n /**\n * Render override for the empty state. Called when the table has no\n * rows and no error. When omitted, a default \"No Data\" indicator is\n * rendered.\n */\n renderEmptyState?: () => React.ReactNode;\n\n /**\n * Returns extra HTML attributes (typically `data-*`) to apply to each\n * row element. Use this to drive conditional row styling\n */\n getRowAttributes?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => Record<string, string | undefined>;\n\n /**\n * Imperative handle for programmatic table actions. Pass a ref\n * (`useRef<ObjectTableHandle<Q, RDPs>>(null)`) to call\n * {@link ObjectTableHandle} methods such as\n * {@link ObjectTableHandle.getSnapshot}.\n */\n tableRef?: React.Ref<ObjectTableHandle<Q, RDPs>>;\n\n className?: string;\n}\n\n/**\n * Imperative handle exposing programmatic actions on an {@link ObjectTable}.\n * Obtain it by passing {@link ObjectTableProps.tableRef}.\n */\nexport interface ObjectTableHandle<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * Loads every row matching the object set and returns a format-agnostic\n * snapshot of the table's columns, row values, and total count. The caller\n * is responsible for turning the snapshot into a downloadable artifact\n * (CSV, Spreadsheet, JSON, clipboard, …).\n *\n * Property, derived-property, and function-backed columns are included.\n * Function-backed cells are fetched per page during snapshot collection;\n * when a page's fetch fails, `row.getValue(columnId)` returns the thrown\n * `Error` instance for the affected cells while the rest of the snapshot\n * resolves normally.\n * Columns defined with `locator.type === \"custom\"` are omitted because\n * they have no underlying value to export.\n *\n * The returned promise rejects up front when the object set's `totalCount`\n * exceeds `rowLimit`. When `totalCount` is unavailable, it instead rejects\n * mid-load once more than `rowLimit` rows have been pulled, so an unknown\n * count can't drain an unbounded set into the client. Otherwise every\n * matching row is loaded.\n *\n * @param options See {@link ObjectTableSnapshotOptions}.\n */\n getSnapshot: (\n options?: ObjectTableSnapshotOptions,\n ) => Promise<ObjectTableSnapshot<Q, RDPs>>;\n}\n\n/**\n * Options for {@link ObjectTableHandle[\"getSnapshot\"]}.\n */\nexport interface ObjectTableSnapshotOptions {\n /**\n * Upper bound on how many rows the snapshot may contain. When the object\n * set's total row count exceeds this value, `getSnapshot` rejects;\n * otherwise every matching row is loaded.\n *\n * @default 10_000\n */\n rowLimit?: number;\n}\n\n/**\n * A point-in-time capture of an {@link ObjectTable}'s columns and row values,\n * returned by {@link ObjectTableHandle.getSnapshot}.\n */\nexport interface ObjectTableSnapshot<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n columns: ObjectTableDataColumn[];\n rows: ObjectTableDataRow<Q, RDPs>[];\n /**\n * Total number of objects matching the underlying object set, as reported\n * by the API. `undefined` when the API did not provide a count. Encoded as\n * a string to match the underlying list-payload representation.\n */\n totalCount: string | undefined;\n}\n\n/**\n * A single column in an {@link ObjectTableSnapshot}.\n */\nexport interface ObjectTableDataColumn {\n /** Column id, matching the `locator.id` of the column definition. */\n id: string;\n /** Display name shown in the table header. */\n name: string;\n}\n\n/**\n * A single row in an {@link ObjectTableSnapshot}.\n */\nexport interface ObjectTableDataRow<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /** Row id (the underlying object's `$primaryKey` rendered as a string). */\n id: string;\n /** The underlying loaded object. */\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>;\n /**\n * Returns the cell value for a given column id, or `undefined` when the\n * column is not part of the snapshot. Function-backed cells whose query\n * failed surface the thrown `Error` instance as their value.\n */\n getValue: (columnId: string) => unknown;\n}\n\n/**\n * Payload for {@link ObjectTableProps.onLoadedObjectsChanged}.\n */\nexport interface LoadedObjectsChange<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * The rows loaded into the table so far, in display order. Rows on pages\n * the user hasn't scrolled to yet are absent — compare `loadedObjects.length`\n * against `totalCount` to tell whether more remain.\n *\n * Each row carries the values of its function-backed columns alongside its\n * properties, so those cells are readable from the payload.\n */\n loadedObjects: Osdk.Instance<\n Q,\n \"$allBaseProperties\",\n PropertyKeys<Q>,\n RDPs\n >[];\n\n /**\n * Total number of objects matching the underlying object set, as reported\n * by the API. `undefined` when the API did not provide a count. Encoded as\n * a string to match the underlying list-payload representation.\n */\n totalCount: string | undefined;\n}\n\n/**\n * Payload for {@link ObjectTableProps.onRowSelectionChanged}. Consolidates\n * the loaded row instances, the `isSelectAll` semantic intent, and an\n * `ObjectSet` covering the selection.\n */\nexport interface RowSelectionChange<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * Loaded row instances currently selected. When `isSelectAll` is true,\n * this reflects only the rows currently in the table — pages not yet\n * fetched are absent. Use `objectSet` for the cross-page view, and\n * `selectedRows.map(r => r.$primaryKey)` if you need the primary keys.\n */\n selectedRows: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>[];\n\n /**\n * True when the user invoked \"select all\" (header checkbox) or when\n * controlled mode supplies `isAllSelected={true}`. Distinct from \"every\n * loaded row happens to be selected\" — that condition is reflected by\n * `selectedRows.length` matching the visible row count but does not set\n * this flag.\n */\n isSelectAll: boolean;\n\n /**\n * An `ObjectSet` representing the selection.\n *\n * - \"Select all\" → the underlying `ObjectSet` (`objectSet` prop if\n * provided, otherwise derived from `objectType` via `client(...)`).\n * This includes rows not yet loaded into the table.\n * - Partial selection → the underlying `ObjectSet` narrowed to\n * `{ $primaryKey: { $in: selectedRows.map(r => r.$primaryKey) } }`.\n * - \"Deselect all\" → an empty `ObjectSet` (`$in: []`).\n *\n * Works for both object and interface types, since the `$primaryKey`\n * special property does not require resolving the underlying primary key\n * property name. `undefined` only when there is no underlying `ObjectSet`\n * to derive from.\n */\n objectSet: ObjectSet<Q, RDPs> | undefined;\n}\n\nexport interface ObjectSetOptions<Q extends ObjectOrInterfaceDefinition> {\n /**\n * Object sets to union with\n */\n union?: ObjectSet<Q>[];\n\n /**\n * Object sets to intersect with\n */\n intersect?: ObjectSet<Q>[];\n\n /**\n * Object sets to subtract from\n */\n subtract?: ObjectSet<Q>[];\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"ObjectTableApi.js","names":[],"sources":["ObjectTableApi.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 BaseWirePropertyTypes,\n CompileTimeMetadata,\n DerivedProperty,\n ObjectOrInterfaceDefinition,\n ObjectSet,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\n PropertyValueWireToClient,\n QueryDefinition,\n SimplePropertyDef,\n WhereClause,\n} from \"@osdk/api\";\nimport type { QueryParameterType } from \"@osdk/client/observable\";\nimport type * as React from \"react\";\n\nimport type { CellEditInfo, EditFieldConfig } from \"./utils/types.js\";\n\nexport type { EditFieldConfig } from \"./utils/types.js\";\n\nexport type ColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n | EditableColumnDefinition<Q, RDPs, FunctionColumns>\n | EditableFunctionColumnDefinition<Q, RDPs, FunctionColumns>\n | ReadonlyColumnDefinition<Q, RDPs, FunctionColumns>\n | ReadonlyFunctionColumnDefinition<Q, RDPs, FunctionColumns>;\n\n/** A column whose value comes from the row's object. */\ntype DerivableValueColumn<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = {\n /**\n * What the column shows — a property, a linked object property (derived\n * property), or a custom column — and that locator's configuration.\n */\n locator:\n | PropertyColumnLocator<Q>\n | RdpColumnLocator<Q, RDPs>\n | CustomColumnLocator;\n} & CellValueOverride<Q, RDPs, FunctionColumns>;\n\n/**\n * The cell's value and the type it's declared to have.\n *\n * `cellValueType` is required whenever `getCellValue` is provided — declaring\n * the type constrains what `getCellValue` may return, so a column can't\n * advertise one type and hand the cell a value of another. `cellValueType` may\n * also be declared on its own to pick the editor without transforming the\n * value.\n */\ntype CellValueOverride<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n // Use cellValueType + typed getCellValue together\n | {\n [T in BaseWirePropertyTypes]: {\n /**\n * The cell value's data type. Constrains what `getCellValue` may\n * return, and selects the editor for an `editable` column.\n */\n cellValueType: T;\n\n /**\n * Derives the cell's value from the row's object. Without it the column\n * reads the property named by `locator.id`.\n *\n * Use this to change what the cell's value *is* — what it returns is\n * the value the table renders, edits, and passes on to `renderCell`.\n * Use `renderCell` to change only how that value is displayed. The two\n * can be combined.\n */\n getCellValue: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n locator: ColumnDefinitionLocator<Q, RDPs, FunctionColumns>,\n ) => PropertyValueWireToClient[T] | null | undefined;\n };\n }[BaseWirePropertyTypes]\n // Using cellValueType alone.\n | {\n [T in BaseWirePropertyTypes]: {\n cellValueType: T;\n getCellValue?: never;\n };\n }[BaseWirePropertyTypes]\n // Neither\n | {\n cellValueType?: undefined;\n getCellValue?: never;\n };\n\n/** A column whose value comes from a function query rather than the row. */\ninterface FunctionValueColumn<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /** What the column shows, and that locator's configuration. */\n locator: FunctionColumnLocator<Q, RDPs, FunctionColumns>;\n\n /** The cell value's data type. */\n cellValueType?: BaseWirePropertyTypes;\n\n /**\n * Use {@link FunctionColumnLocator}'s own `getValue` instead.\n */\n getCellValue?: never;\n}\n\ninterface SharedColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /**\n * @default true\n */\n isVisible?: boolean;\n\n /**\n * @default none\n */\n pinned?: \"left\" | \"right\" | \"none\";\n width?: number;\n minWidth?: number;\n maxWidth?: number;\n resizable?: boolean;\n orderable?: boolean;\n\n /**\n * Custom renderer for the cell value.\n *\n * This changes only how the cell's value is displayed; the value itself is\n * unchanged. To change the value, use `getCellValue` (and declare its\n * `cellValueType`) — `renderCell` then receives that value as its third\n * argument. The two can be combined.\n *\n * `renderCell` is used only when the cell is read-only.\n * When cells are actually editable, the in-built edit component takes over.\n *\n * @param object - The row's object instance.\n * @param locator - The column locator of this cell.\n * @param value - The cell's value computed by the given `getCellValue` or the default property lookup.\n * @returns custom cell renderer component\n */\n renderCell?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n locator: ColumnDefinitionLocator<Q, RDPs, FunctionColumns>,\n value: unknown,\n ) => React.ReactNode;\n\n /**\n * If provided, this will be used in the column header.\n * If both columnName and renderHeader are provided, renderHeader will take precedence in the table header.\n * columnName will still be used in other parts where the column name is displayed.\n *\n * If not provided,\n * for a property column, the property displayName will be used\n * for other columns, the id will be used.\n */\n columnName?: string;\n\n /**\n * If provided, this will be used to render the header component.\n * When both columnName and renderHeader are provided, renderHeader will take precedence in the table header.\n */\n renderHeader?: () => React.ReactNode;\n}\n\ninterface EditableColumnOptions<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * `editable` can be a boolean or a predicate that receives the row's object\n * and returns whether the cell is editable\n */\n editable:\n | true\n | ((\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => boolean);\n\n /**\n * Configuration for the cell editor component.\n *\n * When provided, the column uses the specified field component\n * (e.g. dropdown) instead of the default auto-detected text/number input.\n *\n * `getFieldComponentProps` receives the row's object and a map of any\n * pending edits for that row (keyed by column id), and returns the props to\n * pass to the field component. Editor configuration can depend on the\n * current row or on other in-progress edits within the row.\n */\n editFieldConfig?: EditFieldConfig<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>\n >;\n\n /**\n * Additional function to validate the cell value during edit.\n *\n * @param value the current cell value\n * @returns a promise that resolves to an error message string if validation fails, or undefined if validation succeeds\n */\n validateEdit?: (value: unknown) => Promise<string | undefined>;\n}\n\ntype EditableColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = SharedColumnDefinition<Q, RDPs, FunctionColumns> &\n EditableColumnOptions<Q, RDPs> &\n DerivableValueColumn<Q, RDPs, FunctionColumns>;\n\n/** Editable column backed by a function query. */\ninterface EditableFunctionColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>\n extends\n SharedColumnDefinition<Q, RDPs, FunctionColumns>,\n EditableColumnOptions<Q, RDPs>,\n FunctionValueColumn<Q, RDPs, FunctionColumns> {}\n\n/**\n * Column definition for a read-only column (default).\n * `editFieldConfig` and `validateEdit` are not available.\n */\ntype ReadonlyColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = SharedColumnDefinition<Q, RDPs, FunctionColumns> &\n DerivableValueColumn<Q, RDPs, FunctionColumns> & { editable?: false };\n\n/** Read-only column backed by a function query. */\ninterface ReadonlyFunctionColumnDefinition<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>\n extends\n SharedColumnDefinition<Q, RDPs, FunctionColumns>,\n FunctionValueColumn<Q, RDPs, FunctionColumns> {\n editable?: false;\n}\n\nexport type ExtractQueryParameters<Q extends QueryDefinition> =\n CompileTimeMetadata<Q>[\"parameters\"] extends Record<string, never>\n ? undefined\n : QueryParameterType<CompileTimeMetadata<Q>[\"parameters\"]>;\n\nexport interface PropertyColumnLocator<Q extends ObjectOrInterfaceDefinition> {\n type: \"property\";\n id: PropertyKeys<Q>;\n}\n\n/**\n * Concrete function column locator for a single key K.\n * Correlates the id, queryDefinition, and getFunctionParams types.\n */\ninterface FunctionColumnLocatorForKey<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef>,\n FunctionColumns extends Record<string, QueryDefinition<{}>>,\n K extends keyof FunctionColumns,\n> {\n /**\n * This is equivalent to workshop's function-backed columns.\n * The function needs to meet the specifications stated in https://www.palantir.com/docs/foundry/workshop/widgets-object-table/#function-backed-columns\n */\n type: \"function\";\n id: K;\n queryDefinition: FunctionColumns[K];\n\n /**\n * The function will be called with the current object set to get the input parameters for the function query.\n * @param objectSet - The current object set.\n * @returns - The function's input parameters including the object set.\n */\n getFunctionParams: (\n objectSet: ObjectSet<Q, RDPs>,\n ) => ExtractQueryParameters<FunctionColumns[K]>;\n\n /**\n * Function to generate keys for looking up results in the FunctionsMap.\n * @param object - The object instance\n * @returns - The key to use for looking up this object's result in the FunctionsMap\n */\n getKey: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => string;\n\n /**\n * Function to extract the cell value from the raw cell data returned by the function.\n * This is useful when functions return custom types with multiple properties.\n * @param cellData - The raw data returned by the function for this object\n * @returns - The value to display in the cell\n */\n getValue?: (cellData?: unknown) => unknown;\n\n /**\n * Minimum time between re-fetches of the same function with the same parameters, in milliseconds.\n * Defaults to 5 minutes as it is expensive to fetch function columns for a large object set\n * and they are expected to be relatively static in the context of an object table\n *\n * @default 300_000 (5 minutes)\n */\n dedupeIntervalMs?: number;\n\n /**\n * Object type apiNames the function reads but doesn't take as a parameter (e.g.\n * linked object types the function traverses internally). The column auto-revalidates\n * when an action edits an object of any of these types. Param-derived types are\n * tracked automatically and don't need to be listed here.\n */\n dependsOn?: string[];\n}\n\n/**\n * Distributes over each key in FunctionColumns so that id, queryDefinition,\n * and getFunctionParams are correlated per key.\n */\nexport type FunctionColumnLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> = keyof FunctionColumns extends infer K\n ? K extends keyof FunctionColumns\n ? FunctionColumnLocatorForKey<Q, RDPs, FunctionColumns, K>\n : never\n : never;\n\nexport interface RdpColumnLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n type: \"rdp\";\n id: keyof RDPs;\n creator: DerivedProperty.Creator<Q, RDPs[keyof RDPs]>;\n}\n\nexport interface CustomColumnLocator {\n type: \"custom\";\n id: string;\n}\n\nexport type ColumnDefinitionLocator<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> =\n | PropertyColumnLocator<Q>\n | FunctionColumnLocator<Q, RDPs, FunctionColumns>\n | RdpColumnLocator<Q, RDPs>\n | CustomColumnLocator;\n\nexport interface ObjectTableProps<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n /**\n * The object or interface type of the object\n * If objectSet is not provided, objects will be fetched based on this type.\n */\n objectType: Q;\n\n /**\n * The set of objects to show in the table.\n * If provided, the table fetches through this object set instead of fetching based on\n * objectType. Supported for both object and interface types.\n *\n * For an interface object set, rows expose the interface's declared properties;\n * the underlying concrete object's non-interface properties are not loaded.\n * Use objectType-based fetching if you need those.\n */\n objectSet?: ObjectSet<Q>;\n\n /**\n * Ordered list of column definitions to show in the table\n *\n * If not provided, all of the properties of the object type will be shown in default order.\n */\n columnDefinitions?: Array<ColumnDefinition<Q, RDPs, FunctionColumns>>;\n\n objectSetOptions?: ObjectSetOptions<Q>;\n\n /**\n * Minimum time between fetch requests in milliseconds.\n * Increasing this value reduces redundant network calls when the same data\n * is requested multiple times in quick succession.\n *\n * @default 60_000 1 minute\n */\n dedupeIntervalMs?: number;\n\n /**\n * Enable streaming updates via websocket subscription.\n * When true, the table will automatically update when matching\n * objects are added, updated, or removed in Foundry.\n *\n * Limitations: `streamUpdates` cannot be used together with `pivotTo` or\n * `withProperties`. The server does not support websocket subscriptions\n * for link-traversal or derived-property queries. Those queries still\n * fetch data normally but won't receive real-time updates.\n *\n * @default false\n */\n streamUpdates?: boolean;\n\n /**\n * Number of objects to fetch per page.\n *\n * @default 50\n */\n pageSize?: number;\n\n /**\n * The current where clause to filter the objects in the table.\n */\n filter?: WhereClause<Q, RDPs>;\n\n /**\n * Whether the column configuration dialog for column visibility and ordering is available to the user.\n *\n * @default true\n */\n enableColumnConfig?: boolean;\n\n /**\n * Whether columns can be pinned by the user.\n *\n * @default true\n */\n enableColumnPinning?: boolean;\n\n /**\n * Whether columns can be resized by the user.\n *\n * @default true\n */\n enableColumnResizing?: boolean;\n\n /**\n * Called when the column visibility or ordering changed.\n *\n * If provided, the table will allow the user to show/hide columns.\n *\n * @param newStates The columns sorted in their display order in the table and their visibility state.\n */\n onColumnVisibilityChanged?: (\n newStates: Array<{\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns;\n isVisible: boolean;\n }>,\n ) => void;\n\n /**\n * Called when the pinned columns change.\n *\n * If provided, the table will allow the user to pin/unpin columns.\n *\n * @param newStates The new list of column pin states\n */\n onColumnsPinnedChanged?: (\n newStates: Array<{\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns;\n pinned: \"left\" | \"right\" | \"none\";\n }>,\n ) => void;\n\n /**\n * Called when a column is resized.\n *\n * @param columnId The ID of the resized column\n * @param newWidth The new width of the column. When newWidth = null, the column size is reset.\n */\n onColumnResize?: (\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns,\n newWidth: number | null,\n ) => void;\n\n /**\n * Called when a column header is clicked.\n *\n * The columnId matches the `locator.id` configured on the column definition.\n * The dropdown menu trigger is excluded — clicking the chevron opens the\n * header menu instead of firing this callback.\n *\n * @param columnId The id of the clicked column\n */\n onColumnHeaderClick?: (\n columnId: PropertyKeys<Q> | keyof RDPs | keyof FunctionColumns,\n ) => void;\n\n /**\n * Whether the table is sortable by the user.\n *\n * @default true\n */\n enableOrdering?: boolean;\n\n /**\n * The default order by clause to sort the objects in the table.\n * If provided without orderBy prop, the sorting is uncontrolled.\n * If both orderBy and defaultOrderBy are provided, orderBy takes precedence.\n */\n defaultOrderBy?: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>;\n\n /**\n * The current order by clause to sort the objects in the table.\n * If provided, the sorting is controlled.\n * If both orderBy and defaultOrderBy are provided, orderBy takes precedence.\n */\n orderBy?: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>;\n\n /**\n * Called when the order by clause is changed.\n * Required when sorting is controlled.\n *\n * @param newOrderBy The new order by clause\n */\n onOrderByChanged?: (\n newOrderBy: Array<{\n property: PropertyKeys<Q> | keyof RDPs;\n direction: \"asc\" | \"desc\";\n }>,\n ) => void;\n\n /**\n * Selection mode for the table rows.\n *\n * If multiple, a checkbox will be shown for each row to allow selecting multiple rows\n * as well as a top-level checkbox in the header to select all rows.\n *\n * @default \"none\"\n */\n selectionMode?: \"single\" | \"multiple\" | \"none\";\n\n /**\n * The currently selected rows in the table.\n * If provided, the row selection is controlled.\n */\n selectedRows?: PrimaryKeyType<Q>[];\n\n /**\n * Indicates whether all rows are selected in controlled mode.\n * When true, the table will show all rows as selected regardless of the selectedRows array.\n */\n isAllSelected?: boolean;\n\n /**\n * Called when the row selection changes, with a {@link RowSelectionChange}\n * payload describing the new state.\n *\n * @param change The new selection state. See {@link RowSelectionChange}.\n */\n onRowSelectionChanged?: (change: RowSelectionChange<Q, RDPs>) => void;\n\n /**\n * Called when the set of loaded rows changes — as pages are fetched, when\n * streamed updates arrive, and after a refetch — with a\n * {@link LoadedObjectsChange} payload.\n *\n * @param change The loaded rows and the total count. See\n * {@link LoadedObjectsChange}.\n */\n onLoadedObjectsChanged?: (change: LoadedObjectsChange<Q, RDPs>) => void;\n\n /**\n * The primary key of the row to render as visually focused (the\n * \"last interacted\" row). When provided, focus state is controlled by\n * the caller.\n *\n * Stored as a primary key rather than a full object so the focus does\n * not go stale when the underlying row data changes.\n *\n * Pass `null` to render no row as focused.\n */\n focusedRow?: PrimaryKeyType<Q> | null;\n\n /**\n * Called when the focused row changes — fires in both controlled and\n * uncontrolled modes so callers can observe focus without taking it\n * over.\n *\n * @param row The newly-focused row object, or `null` if focus was\n * cleared\n */\n onFocusedRowChanged?: (\n row: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs> | null,\n ) => void;\n\n /**\n * Controls the edit mode behavior of the table.\n * - \"always\": Editable cells are immediately in edit mode on row clicked.\n * - \"manual\": User can toggle edit mode on/off via the Edit Table button.\n *\n * @default \"manual\"\n */\n editMode?: \"always\" | \"manual\";\n\n /**\n * Whether to render the bottom edit footer that hosts the\n * \"Edit Table\" / \"Cancel\" / \"Submit Edits\" buttons and the edit-state\n * indicators (modification count, validation errors).\n *\n * @default true whenever the table has at least one column declared\n * editable (i.e. any column with `editable: true` or `editable: (object) => boolean`).\n * When `false`, the \"Edit Table\" and \"Submit Edits\" buttons will not be shown.\n */\n showEditFooter?: boolean;\n\n /**\n * Called after the value of a cell is edited and committed by the user.\n *\n * @param info An object containing details about the cell that was edited,\n * including the rowId, columnId, new and old values, and the row data before the edit\n */\n onCellValueChanged?: (\n info: CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >,\n ) => void;\n\n /**\n * If provided, the \"Submit Edits\" button will be shown in the edit footer.\n *\n * @param edits an array of edit info containing details about the edited cells\n * including the rowId, columnId, new and old values, and the row data before the edit\n * @return a promise that resolves to true if the edits were successfully submitted\n */\n onSubmitEdits?: (\n edits: CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >[],\n ) => Promise<boolean>;\n\n /**\n * Called when a row is clicked.\n *\n * @param object The object representing the clicked row\n */\n onRowClick?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => void;\n\n /**\n * If provided, will render this context menu when right clicking on a cell\n */\n renderCellContextMenu?: (\n row: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n cellValue: unknown,\n ) => React.ReactNode;\n\n /**\n * The height of each row in pixels.\n *\n * @default 40\n */\n rowHeight?: number;\n\n /**\n * Render override for the empty state. Called when the table has no\n * rows and no error. When omitted, a default \"No Data\" indicator is\n * rendered.\n */\n renderEmptyState?: () => React.ReactNode;\n\n /**\n * Returns extra HTML attributes (typically `data-*`) to apply to each\n * row element. Use this to drive conditional row styling\n */\n getRowAttributes?: (\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n ) => Record<string, string | undefined>;\n\n /**\n * Imperative handle for programmatic table actions. Pass a ref\n * (`useRef<ObjectTableHandle<Q, RDPs>>(null)`) to call\n * {@link ObjectTableHandle} methods such as\n * {@link ObjectTableHandle.getSnapshot}.\n */\n tableRef?: React.Ref<ObjectTableHandle<Q, RDPs>>;\n\n className?: string;\n}\n\n/**\n * Imperative handle exposing programmatic actions on an {@link ObjectTable}.\n * Obtain it by passing {@link ObjectTableProps.tableRef}.\n */\nexport interface ObjectTableHandle<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * Loads every row matching the object set and returns a format-agnostic\n * snapshot of the table's columns, row values, and total count. The caller\n * is responsible for turning the snapshot into a downloadable artifact\n * (CSV, Spreadsheet, JSON, clipboard, …).\n *\n * Property, derived-property, and function-backed columns are included.\n * Function-backed cells are fetched per page during snapshot collection;\n * when a page's fetch fails, `row.getValue(columnId)` returns the thrown\n * `Error` instance for the affected cells while the rest of the snapshot\n * resolves normally.\n * Columns defined with `locator.type === \"custom\"` are omitted because\n * they have no underlying value to export.\n *\n * The returned promise rejects up front when the object set's `totalCount`\n * exceeds `rowLimit`. When `totalCount` is unavailable, it instead rejects\n * mid-load once more than `rowLimit` rows have been pulled, so an unknown\n * count can't drain an unbounded set into the client. Otherwise every\n * matching row is loaded.\n *\n * @param options See {@link ObjectTableSnapshotOptions}.\n */\n getSnapshot: (\n options?: ObjectTableSnapshotOptions,\n ) => Promise<ObjectTableSnapshot<Q, RDPs>>;\n}\n\n/**\n * Options for {@link ObjectTableHandle[\"getSnapshot\"]}.\n */\nexport interface ObjectTableSnapshotOptions {\n /**\n * Upper bound on how many rows the snapshot may contain. When the object\n * set's total row count exceeds this value, `getSnapshot` rejects;\n * otherwise every matching row is loaded.\n *\n * @default 10_000\n */\n rowLimit?: number;\n}\n\n/**\n * A point-in-time capture of an {@link ObjectTable}'s columns and row values,\n * returned by {@link ObjectTableHandle.getSnapshot}.\n */\nexport interface ObjectTableSnapshot<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n columns: ObjectTableDataColumn[];\n rows: ObjectTableDataRow<Q, RDPs>[];\n /**\n * Total number of objects matching the underlying object set, as reported\n * by the API. `undefined` when the API did not provide a count. Encoded as\n * a string to match the underlying list-payload representation.\n */\n totalCount: string | undefined;\n}\n\n/**\n * A single column in an {@link ObjectTableSnapshot}.\n */\nexport interface ObjectTableDataColumn {\n /** Column id, matching the `locator.id` of the column definition. */\n id: string;\n /** Display name shown in the table header. */\n name: string;\n}\n\n/**\n * A single row in an {@link ObjectTableSnapshot}.\n */\nexport interface ObjectTableDataRow<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /** Row id (the underlying object's `$primaryKey` rendered as a string). */\n id: string;\n /** The underlying loaded object. */\n object: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>;\n /**\n * Returns the cell value for a given column id, or `undefined` when the\n * column is not part of the snapshot. Function-backed cells whose query\n * failed surface the thrown `Error` instance as their value.\n */\n getValue: (columnId: string) => unknown;\n}\n\n/**\n * Payload for {@link ObjectTableProps.onLoadedObjectsChanged}.\n */\nexport interface LoadedObjectsChange<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * The rows loaded into the table so far, in display order. Rows on pages\n * the user hasn't scrolled to yet are absent — compare `loadedObjects.length`\n * against `totalCount` to tell whether more remain.\n *\n * Each row carries the values of its function-backed columns alongside its\n * properties, so those cells are readable from the payload.\n */\n loadedObjects: Osdk.Instance<\n Q,\n \"$allBaseProperties\",\n PropertyKeys<Q>,\n RDPs\n >[];\n\n /**\n * Total number of objects matching the underlying object set, as reported\n * by the API. `undefined` when the API did not provide a count. Encoded as\n * a string to match the underlying list-payload representation.\n */\n totalCount: string | undefined;\n}\n\n/**\n * Payload for {@link ObjectTableProps.onRowSelectionChanged}. Consolidates\n * the loaded row instances, the `isSelectAll` semantic intent, and an\n * `ObjectSet` covering the selection.\n */\nexport interface RowSelectionChange<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> {\n /**\n * Loaded row instances currently selected. When `isSelectAll` is true,\n * this reflects only the rows currently in the table — pages not yet\n * fetched are absent. Use `objectSet` for the cross-page view, and\n * `selectedRows.map(r => r.$primaryKey)` if you need the primary keys.\n */\n selectedRows: Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>[];\n\n /**\n * True when the user invoked \"select all\" (header checkbox) or when\n * controlled mode supplies `isAllSelected={true}`. Distinct from \"every\n * loaded row happens to be selected\" — that condition is reflected by\n * `selectedRows.length` matching the visible row count but does not set\n * this flag.\n */\n isSelectAll: boolean;\n\n /**\n * An `ObjectSet` representing the selection.\n *\n * - \"Select all\" → the underlying `ObjectSet` (`objectSet` prop if\n * provided, otherwise derived from `objectType` via `client(...)`).\n * This includes rows not yet loaded into the table.\n * - Partial selection → the underlying `ObjectSet` narrowed to\n * `{ $primaryKey: { $in: selectedRows.map(r => r.$primaryKey) } }`.\n * - \"Deselect all\" → an empty `ObjectSet` (`$in: []`).\n *\n * Works for both object and interface types, since the `$primaryKey`\n * special property does not require resolving the underlying primary key\n * property name. `undefined` only when there is no underlying `ObjectSet`\n * to derive from.\n */\n objectSet: ObjectSet<Q, RDPs> | undefined;\n}\n\nexport interface ObjectSetOptions<Q extends ObjectOrInterfaceDefinition> {\n /**\n * Object sets to union with\n */\n union?: ObjectSet<Q>[];\n\n /**\n * Object sets to intersect with\n */\n intersect?: ObjectSet<Q>[];\n\n /**\n * Object sets to subtract from\n */\n subtract?: ObjectSet<Q>[];\n}\n"],"mappings":"","ignoreList":[]}