@osdk/react-components 0.9.0 → 0.10.0-main-b355bc3b41a4d89ec093054dc8d2845c772ef1e2

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 (102) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +23 -0
  3. package/build/browser/action-form/FormFieldApi.js +8 -0
  4. package/build/browser/action-form/FormFieldApi.js.map +1 -1
  5. package/build/browser/action-form/fields/AsyncDropdownField.js +81 -0
  6. package/build/browser/action-form/fields/AsyncDropdownField.js.map +1 -0
  7. package/build/browser/action-form/fields/AsyncDropdownField.module.css +31 -0
  8. package/build/browser/action-form/fields/AsyncDropdownField.module.css.js +8 -0
  9. package/build/browser/action-form/fields/DropdownField.js +29 -14
  10. package/build/browser/action-form/fields/DropdownField.js.map +1 -1
  11. package/build/browser/action-form/fields/FormFieldRenderer.js +17 -0
  12. package/build/browser/action-form/fields/FormFieldRenderer.js.map +1 -1
  13. package/build/browser/action-form/fields/ObjectSelectField.js +109 -0
  14. package/build/browser/action-form/fields/ObjectSelectField.js.map +1 -0
  15. package/build/browser/action-form/utils/getDefaultFieldDefinitions.js +14 -5
  16. package/build/browser/action-form/utils/getDefaultFieldDefinitions.js.map +1 -1
  17. package/build/browser/base-components/combobox/Combobox.module.css +23 -2
  18. package/build/browser/base-components/combobox/Combobox.module.css.js +3 -3
  19. package/build/browser/filter-list/base/inputs/TextTagsInput.js.map +1 -1
  20. package/build/browser/shared/hooks/useDebouncedValue.js +35 -0
  21. package/build/browser/shared/hooks/useDebouncedValue.js.map +1 -0
  22. package/build/browser/shared/hooks/useEventCallback.js +44 -0
  23. package/build/browser/shared/hooks/useEventCallback.js.map +1 -0
  24. package/build/browser/shared/hooks/useInfiniteScroll.js +81 -0
  25. package/build/browser/shared/hooks/useInfiniteScroll.js.map +1 -0
  26. package/build/browser/styles.css +73 -2
  27. package/build/browser/tokens/component-tokens/async-dropdown.css +16 -0
  28. package/build/browser/tokens.css +1 -0
  29. package/build/browser/util/UserAgent.js +1 -1
  30. package/build/browser/util/UserAgent.js.map +1 -1
  31. package/build/cjs/{chunk-EEES66LS.cjs → chunk-5DVHLBWS.cjs} +3 -3
  32. package/build/cjs/chunk-5DVHLBWS.cjs.map +1 -0
  33. package/build/cjs/{chunk-OXP3XQE4.cjs → chunk-ALZS624H.cjs} +47 -47
  34. package/build/cjs/{chunk-OXP3XQE4.cjs.map → chunk-ALZS624H.cjs.map} +1 -1
  35. package/build/cjs/{chunk-UEY63J2G.cjs → chunk-FURJRQWI.cjs} +9 -9
  36. package/build/cjs/{chunk-UEY63J2G.cjs.map → chunk-FURJRQWI.cjs.map} +1 -1
  37. package/build/cjs/{chunk-RY2GVYT2.cjs → chunk-MVNWOKH2.cjs} +49 -36
  38. package/build/cjs/chunk-MVNWOKH2.cjs.map +1 -0
  39. package/build/cjs/{chunk-O5ZAMFDU.cjs → chunk-QWFJF7IM.cjs} +468 -207
  40. package/build/cjs/chunk-QWFJF7IM.cjs.map +1 -0
  41. package/build/cjs/{chunk-2FPKTOPE.cjs → chunk-XBXC6VAS.cjs} +2 -2
  42. package/build/cjs/{chunk-2FPKTOPE.cjs.map → chunk-XBXC6VAS.cjs.map} +1 -1
  43. package/build/cjs/{chunk-SHTQGKS5.cjs → chunk-Z3CXMFCZ.cjs} +4 -4
  44. package/build/cjs/{chunk-SHTQGKS5.cjs.map → chunk-Z3CXMFCZ.cjs.map} +1 -1
  45. package/build/cjs/public/experimental/action-form.cjs +6 -6
  46. package/build/cjs/public/experimental/action-form.css +24 -1
  47. package/build/cjs/public/experimental/action-form.css.map +1 -1
  48. package/build/cjs/public/experimental/action-form.d.cts +48 -3
  49. package/build/cjs/public/experimental/filter-list.cjs +7 -7
  50. package/build/cjs/public/experimental/filter-list.css +9 -1
  51. package/build/cjs/public/experimental/filter-list.css.map +1 -1
  52. package/build/cjs/public/experimental/object-table.cjs +10 -10
  53. package/build/cjs/public/experimental/object-table.css +9 -1
  54. package/build/cjs/public/experimental/object-table.css.map +1 -1
  55. package/build/cjs/public/experimental/pdf-viewer.cjs +24 -24
  56. package/build/cjs/public/experimental.cjs +41 -41
  57. package/build/cjs/public/experimental.css +24 -1
  58. package/build/cjs/public/experimental.css.map +1 -1
  59. package/build/esm/action-form/FormFieldApi.js +8 -0
  60. package/build/esm/action-form/FormFieldApi.js.map +1 -1
  61. package/build/esm/action-form/fields/AsyncDropdownField.js +81 -0
  62. package/build/esm/action-form/fields/AsyncDropdownField.js.map +1 -0
  63. package/build/esm/action-form/fields/AsyncDropdownField.module.css +31 -0
  64. package/build/esm/action-form/fields/DropdownField.js +29 -14
  65. package/build/esm/action-form/fields/DropdownField.js.map +1 -1
  66. package/build/esm/action-form/fields/FormFieldRenderer.js +17 -0
  67. package/build/esm/action-form/fields/FormFieldRenderer.js.map +1 -1
  68. package/build/esm/action-form/fields/ObjectSelectField.js +109 -0
  69. package/build/esm/action-form/fields/ObjectSelectField.js.map +1 -0
  70. package/build/esm/action-form/utils/getDefaultFieldDefinitions.js +14 -5
  71. package/build/esm/action-form/utils/getDefaultFieldDefinitions.js.map +1 -1
  72. package/build/esm/base-components/combobox/Combobox.module.css +23 -2
  73. package/build/esm/filter-list/base/inputs/TextTagsInput.js.map +1 -1
  74. package/build/esm/shared/hooks/useDebouncedValue.js +35 -0
  75. package/build/esm/shared/hooks/useDebouncedValue.js.map +1 -0
  76. package/build/esm/shared/hooks/useEventCallback.js +44 -0
  77. package/build/esm/shared/hooks/useEventCallback.js.map +1 -0
  78. package/build/esm/shared/hooks/useInfiniteScroll.js +81 -0
  79. package/build/esm/shared/hooks/useInfiniteScroll.js.map +1 -0
  80. package/build/esm/tokens/component-tokens/async-dropdown.css +16 -0
  81. package/build/esm/tokens.css +1 -0
  82. package/build/esm/util/UserAgent.js +1 -1
  83. package/build/esm/util/UserAgent.js.map +1 -1
  84. package/build/types/action-form/FormFieldApi.d.ts +48 -3
  85. package/build/types/action-form/FormFieldApi.d.ts.map +1 -1
  86. package/build/types/action-form/fields/AsyncDropdownField.d.ts +25 -0
  87. package/build/types/action-form/fields/AsyncDropdownField.d.ts.map +1 -0
  88. package/build/types/action-form/fields/DropdownField.d.ts +2 -2
  89. package/build/types/action-form/fields/DropdownField.d.ts.map +1 -1
  90. package/build/types/action-form/fields/FormFieldRenderer.d.ts.map +1 -1
  91. package/build/types/action-form/fields/ObjectSelectField.d.ts +3 -0
  92. package/build/types/action-form/fields/ObjectSelectField.d.ts.map +1 -0
  93. package/build/types/shared/hooks/useDebouncedValue.d.ts +5 -0
  94. package/build/types/shared/hooks/useDebouncedValue.d.ts.map +1 -0
  95. package/build/types/shared/hooks/useEventCallback.d.ts +13 -0
  96. package/build/types/shared/hooks/useEventCallback.d.ts.map +1 -0
  97. package/build/types/shared/hooks/useInfiniteScroll.d.ts +19 -0
  98. package/build/types/shared/hooks/useInfiniteScroll.d.ts.map +1 -0
  99. package/package.json +9 -9
  100. package/build/cjs/chunk-EEES66LS.cjs.map +0 -1
  101. package/build/cjs/chunk-O5ZAMFDU.cjs.map +0 -1
  102. package/build/cjs/chunk-RY2GVYT2.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FormFieldRenderer.js","names":["React","memo","FormField","EMPTY_RANGE","CustomField","DateRangeInputField","DatetimePickerField","DropdownField","FilePickerField","NumberInputField","ObjectSetField","RadioButtonsField","TextAreaField","TextInputField","FormFieldRenderer","fieldDefinition","value","onFieldValueChange","onBlur","error","label","isRequired","helperText","helperTextPlacement","createElement","fieldKey","undefined","renderFieldComponent","onChange","fieldComponent","_extends","id","coerceToDateRange","placeholderStart","placeholder","fieldComponentProps","String","Date","coerceToFileValue","assertUnreachableFieldComponent","Array","isArray","length","start","end","isFileArray","every","v","File","Error"],"sources":["FormFieldRenderer.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { memo } from \"react\";\nimport { FormField } from \"../FormField.js\";\nimport {\n type DateRange,\n EMPTY_RANGE,\n type RendererFieldDefinition,\n} from \"../FormFieldApi.js\";\nimport { CustomField } from \"./CustomField.js\";\nimport { DateRangeInputField } from \"./DateRangeInputField.js\";\nimport { DatetimePickerField } from \"./DatetimePickerField.js\";\nimport { DropdownField } from \"./DropdownField.js\";\nimport { FilePickerField } from \"./FilePickerField.js\";\nimport { NumberInputField } from \"./NumberInputField.js\";\nimport { ObjectSetField } from \"./ObjectSetField.js\";\nimport { RadioButtonsField } from \"./RadioButtonsField.js\";\nimport { TextAreaField } from \"./TextAreaField.js\";\nimport { TextInputField } from \"./TextInputField.js\";\n\nexport interface FormFieldRendererProps {\n fieldDefinition: RendererFieldDefinition;\n value: unknown;\n onFieldValueChange: (value: unknown) => void;\n onBlur: (e: React.FocusEvent<HTMLDivElement>) => void;\n error: string | undefined;\n}\n\nexport const FormFieldRenderer: React.FC<FormFieldRendererProps> = memo(\n function FormFieldRendererFn({\n fieldDefinition,\n value,\n onFieldValueChange,\n onBlur,\n error,\n }: FormFieldRendererProps): React.ReactElement {\n const { label, isRequired, helperText, helperTextPlacement } =\n fieldDefinition;\n\n return (\n <FormField\n label={label}\n isRequired={isRequired}\n fieldKey={fieldDefinition.fieldKey}\n helperText={helperTextPlacement !== \"tooltip\" ? helperText : undefined}\n error={error}\n onBlur={onBlur}\n >\n {renderFieldComponent(\n fieldDefinition,\n value,\n onFieldValueChange,\n error,\n )}\n </FormField>\n );\n },\n);\n\nfunction renderFieldComponent(\n fieldDefinition: RendererFieldDefinition,\n value: unknown,\n onChange: (value: unknown) => void,\n error: string | undefined,\n): React.ReactElement {\n switch (fieldDefinition.fieldComponent) {\n case \"DATE_RANGE_INPUT\":\n return (\n <DateRangeInputField\n id={fieldDefinition.fieldKey}\n value={coerceToDateRange(value)}\n onChange={onChange}\n placeholderStart={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_INPUT\":\n return (\n <TextInputField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_AREA\":\n return (\n <TextAreaField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"DROPDOWN\": {\n return (\n <DropdownField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n }\n case \"DATETIME_PICKER\":\n return (\n <DatetimePickerField\n id={fieldDefinition.fieldKey}\n placeholder={fieldDefinition.placeholder}\n // TODO: Use coerceFieldValue\n value={value instanceof Date ? value : null}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"RADIO_BUTTONS\":\n return (\n <RadioButtonsField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"CUSTOM\":\n return (\n <CustomField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"NUMBER_INPUT\":\n // TODO: Use coerceFieldValue\n return (\n <NumberInputField\n id={fieldDefinition.fieldKey}\n value={typeof value === \"number\" ? value : null}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"FILE_PICKER\":\n return (\n <FilePickerField\n id={fieldDefinition.fieldKey}\n value={coerceToFileValue(value)}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"OBJECT_SET\":\n return (\n <ObjectSetField\n id={fieldDefinition.fieldKey}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n default:\n return assertUnreachableFieldComponent(fieldDefinition);\n }\n}\n\nfunction coerceToDateRange(value: unknown): DateRange {\n if (!Array.isArray(value) || value.length !== 2) return EMPTY_RANGE;\n const start = value[0] instanceof Date ? value[0] : null;\n const end = value[1] instanceof Date ? value[1] : null;\n if (start == null && end == null) return EMPTY_RANGE;\n return [start, end];\n}\n\n// TODO: Move and share with `coerceFieldValue`\nfunction isFileArray(value: unknown[]): value is File[] {\n return value.every((v) => v instanceof File);\n}\n\nfunction coerceToFileValue(value: unknown): File | File[] | null {\n if (value instanceof File) {\n return value;\n }\n if (Array.isArray(value) && isFileArray(value)) {\n return value;\n }\n return null;\n}\n\nfunction assertUnreachableFieldComponent(value: never): never {\n throw new Error(`Unhandled field component: ${String(value)}`);\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FormFieldRenderer.js","names":["React","memo","FormField","EMPTY_RANGE","CustomField","DateRangeInputField","DatetimePickerField","DropdownField","FilePickerField","NumberInputField","ObjectSelectField","ObjectSetField","RadioButtonsField","TextAreaField","TextInputField","FormFieldRenderer","fieldDefinition","value","onFieldValueChange","onBlur","error","label","isRequired","helperText","helperTextPlacement","createElement","fieldKey","undefined","renderFieldComponent","onChange","fieldComponent","_extends","id","coerceToDateRange","placeholderStart","placeholder","fieldComponentProps","String","Date","coerceToFileValue","narrowToOsdkObject","assertUnreachableFieldComponent","Array","isArray","length","start","end","isFileArray","every","v","File","Error"],"sources":["FormFieldRenderer.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ObjectTypeDefinition, Osdk } from \"@osdk/api\";\nimport React, { memo } from \"react\";\nimport { FormField } from \"../FormField.js\";\nimport {\n type DateRange,\n EMPTY_RANGE,\n type RendererFieldDefinition,\n} from \"../FormFieldApi.js\";\nimport { CustomField } from \"./CustomField.js\";\nimport { DateRangeInputField } from \"./DateRangeInputField.js\";\nimport { DatetimePickerField } from \"./DatetimePickerField.js\";\nimport { DropdownField } from \"./DropdownField.js\";\nimport { FilePickerField } from \"./FilePickerField.js\";\nimport { NumberInputField } from \"./NumberInputField.js\";\nimport { ObjectSelectField } from \"./ObjectSelectField.js\";\nimport { ObjectSetField } from \"./ObjectSetField.js\";\nimport { RadioButtonsField } from \"./RadioButtonsField.js\";\nimport { TextAreaField } from \"./TextAreaField.js\";\nimport { TextInputField } from \"./TextInputField.js\";\n\nexport interface FormFieldRendererProps {\n fieldDefinition: RendererFieldDefinition;\n value: unknown;\n onFieldValueChange: (value: unknown) => void;\n onBlur: (e: React.FocusEvent<HTMLDivElement>) => void;\n error: string | undefined;\n}\n\nexport const FormFieldRenderer: React.FC<FormFieldRendererProps> = memo(\n function FormFieldRendererFn({\n fieldDefinition,\n value,\n onFieldValueChange,\n onBlur,\n error,\n }: FormFieldRendererProps): React.ReactElement {\n const { label, isRequired, helperText, helperTextPlacement } =\n fieldDefinition;\n\n return (\n <FormField\n label={label}\n isRequired={isRequired}\n fieldKey={fieldDefinition.fieldKey}\n helperText={helperTextPlacement !== \"tooltip\" ? helperText : undefined}\n error={error}\n onBlur={onBlur}\n >\n {renderFieldComponent(\n fieldDefinition,\n value,\n onFieldValueChange,\n error,\n )}\n </FormField>\n );\n },\n);\n\nfunction renderFieldComponent(\n fieldDefinition: RendererFieldDefinition,\n value: unknown,\n onChange: (value: unknown) => void,\n error: string | undefined,\n): React.ReactElement {\n switch (fieldDefinition.fieldComponent) {\n case \"DATE_RANGE_INPUT\":\n return (\n <DateRangeInputField\n id={fieldDefinition.fieldKey}\n value={coerceToDateRange(value)}\n onChange={onChange}\n placeholderStart={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_INPUT\":\n return (\n <TextInputField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_AREA\":\n return (\n <TextAreaField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"DROPDOWN\": {\n return (\n <DropdownField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n }\n case \"DATETIME_PICKER\":\n return (\n <DatetimePickerField\n id={fieldDefinition.fieldKey}\n placeholder={fieldDefinition.placeholder}\n // TODO: Use coerceFieldValue\n value={value instanceof Date ? value : null}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"RADIO_BUTTONS\":\n return (\n <RadioButtonsField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"CUSTOM\":\n return (\n <CustomField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"NUMBER_INPUT\":\n // TODO: Use coerceFieldValue\n return (\n <NumberInputField\n id={fieldDefinition.fieldKey}\n value={typeof value === \"number\" ? value : null}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"FILE_PICKER\":\n return (\n <FilePickerField\n id={fieldDefinition.fieldKey}\n value={coerceToFileValue(value)}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"OBJECT_SELECT\":\n return (\n <ObjectSelectField\n id={fieldDefinition.fieldKey}\n value={narrowToOsdkObject(value)}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"OBJECT_SET\":\n return (\n <ObjectSetField\n id={fieldDefinition.fieldKey}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n default:\n return assertUnreachableFieldComponent(fieldDefinition);\n }\n}\n\nfunction coerceToDateRange(value: unknown): DateRange {\n if (!Array.isArray(value) || value.length !== 2) return EMPTY_RANGE;\n const start = value[0] instanceof Date ? value[0] : null;\n const end = value[1] instanceof Date ? value[1] : null;\n if (start == null && end == null) return EMPTY_RANGE;\n return [start, end];\n}\n\n// TODO: Move and share with `coerceFieldValue`\nfunction isFileArray(value: unknown[]): value is File[] {\n return value.every((v) => v instanceof File);\n}\n\nfunction coerceToFileValue(value: unknown): File | File[] | null {\n if (value instanceof File) {\n return value;\n }\n if (Array.isArray(value) && isFileArray(value)) {\n return value;\n }\n return null;\n}\n\n/** Narrows the untyped form value to an OsdkObject by checking for $primaryKey. */\nfunction narrowToOsdkObject(\n value: unknown,\n): Osdk.Instance<ObjectTypeDefinition> | null {\n if (value != null && typeof value === \"object\" && \"$primaryKey\" in value) {\n return value as Osdk.Instance<ObjectTypeDefinition>;\n }\n return null;\n}\n\nfunction assertUnreachableFieldComponent(value: never): never {\n throw new Error(`Unhandled field component: ${String(value)}`);\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,109 @@
1
+ /*
2
+ * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { useOsdkMetadata } from "@osdk/react";
18
+ import { useOsdkObjects } from "@osdk/react/experimental";
19
+ import React, { memo, useCallback, useMemo, useState } from "react";
20
+ import { useDebouncedValue } from "../../shared/hooks/useDebouncedValue.js";
21
+ import { AsyncDropdownField } from "./AsyncDropdownField.js";
22
+
23
+ /** Debounce search input to avoid firing a server query on every keystroke. */
24
+ const SEARCH_DEBOUNCE_MS = 300;
25
+ /** Number of objects fetched per page from the OSDK. */
26
+ const PAGE_SIZE = 50;
27
+ /** Stable empty array so the component doesn't re-render when data is undefined. */
28
+ const EMPTY_ITEMS = [];
29
+ export const ObjectSelectField = /*#__PURE__*/memo(function ({
30
+ objectType,
31
+ value,
32
+ onChange,
33
+ error,
34
+ id,
35
+ placeholder,
36
+ isMultiple,
37
+ portalRef
38
+ }) {
39
+ // Tracks the user's search text. Cleared on selection so the selected
40
+ // label (managed by base-ui) doesn't trigger a server-side search.
41
+ const [query, setQuery] = useState("");
42
+ const debouncedQuery = useDebouncedValue(query, SEARCH_DEBOUNCE_MS);
43
+ const handleChange = useCallback(newValue => {
44
+ onChange?.(newValue);
45
+ setQuery("");
46
+ }, [onChange]);
47
+ const {
48
+ metadata
49
+ } = useOsdkMetadata(objectType);
50
+ const titleProperty = typeof metadata?.titleProperty === "string" ? metadata.titleProperty : undefined;
51
+
52
+ // Search on the title property (e.g. "fullName") so the where clause
53
+ // matches the same text displayed to the user via obj.$title.
54
+ // The where clause is loosely typed because we resolve the property
55
+ // name at runtime from metadata, not from compile-time type info.
56
+ const where = useMemo(() => {
57
+ const trimmed = debouncedQuery.trim();
58
+ if (trimmed === "" || titleProperty == null) {
59
+ return undefined;
60
+ }
61
+ return {
62
+ [titleProperty]: {
63
+ $containsAllTermsInOrder: trimmed
64
+ }
65
+ };
66
+ }, [debouncedQuery, titleProperty]);
67
+ const {
68
+ data,
69
+ isLoading,
70
+ error: fetchError,
71
+ fetchMore,
72
+ hasMore
73
+ } = useOsdkObjects(objectType, {
74
+ where,
75
+ pageSize: PAGE_SIZE
76
+ });
77
+ const handleFetchMore = useCallback(() => {
78
+ void fetchMore?.();
79
+ }, [fetchMore]);
80
+ return /*#__PURE__*/React.createElement(AsyncDropdownField, {
81
+ id: id,
82
+ value: value,
83
+ onChange: handleChange,
84
+ error: error,
85
+ items: data ?? EMPTY_ITEMS,
86
+ itemToStringLabel: itemToStringLabel,
87
+ itemToKey: itemToKey,
88
+ isItemEqual: isItemEqual,
89
+ placeholder: placeholder ?? "Search…",
90
+ isMultiple: isMultiple,
91
+ portalRef: portalRef,
92
+ onQueryChange: setQuery,
93
+ isLoading: isLoading,
94
+ isSearching: debouncedQuery.trim() !== "" && isLoading,
95
+ hasMore: hasMore,
96
+ onFetchMore: handleFetchMore,
97
+ fetchError: fetchError
98
+ });
99
+ });
100
+ function itemToStringLabel(obj) {
101
+ return obj.$title ?? String(obj.$primaryKey);
102
+ }
103
+ function itemToKey(obj) {
104
+ return String(obj.$primaryKey);
105
+ }
106
+ function isItemEqual(a, b) {
107
+ return a.$primaryKey === b.$primaryKey;
108
+ }
109
+ //# sourceMappingURL=ObjectSelectField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectSelectField.js","names":["useOsdkMetadata","useOsdkObjects","React","memo","useCallback","useMemo","useState","useDebouncedValue","AsyncDropdownField","SEARCH_DEBOUNCE_MS","PAGE_SIZE","EMPTY_ITEMS","ObjectSelectField","objectType","value","onChange","error","id","placeholder","isMultiple","portalRef","query","setQuery","debouncedQuery","handleChange","newValue","metadata","titleProperty","undefined","where","trimmed","trim","$containsAllTermsInOrder","data","isLoading","fetchError","fetchMore","hasMore","pageSize","handleFetchMore","createElement","items","itemToStringLabel","itemToKey","isItemEqual","onQueryChange","isSearching","onFetchMore","obj","$title","String","$primaryKey","a","b"],"sources":["ObjectSelectField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ObjectTypeDefinition, Osdk, WhereClause } from \"@osdk/api\";\nimport { useOsdkMetadata } from \"@osdk/react\";\nimport { useOsdkObjects } from \"@osdk/react/experimental\";\nimport React, { memo, useCallback, useMemo, useState } from \"react\";\nimport { useDebouncedValue } from \"../../shared/hooks/useDebouncedValue.js\";\nimport type { ObjectSelectFieldProps } from \"../FormFieldApi.js\";\nimport { AsyncDropdownField } from \"./AsyncDropdownField.js\";\n\n/** Debounce search input to avoid firing a server query on every keystroke. */\nconst SEARCH_DEBOUNCE_MS = 300;\n/** Number of objects fetched per page from the OSDK. */\nconst PAGE_SIZE = 50;\n\ntype OsdkObject = Osdk.Instance<ObjectTypeDefinition>;\n\n/** Stable empty array so the component doesn't re-render when data is undefined. */\nconst EMPTY_ITEMS: OsdkObject[] = [];\n\nexport const ObjectSelectField: React.NamedExoticComponent<\n ObjectSelectFieldProps\n> = memo(function ObjectSelectFieldFn({\n objectType,\n value,\n onChange,\n error,\n id,\n placeholder,\n isMultiple,\n portalRef,\n}): React.ReactElement {\n // Tracks the user's search text. Cleared on selection so the selected\n // label (managed by base-ui) doesn't trigger a server-side search.\n const [query, setQuery] = useState(\"\");\n const debouncedQuery = useDebouncedValue(query, SEARCH_DEBOUNCE_MS);\n\n const handleChange = useCallback(\n (newValue: OsdkObject | null) => {\n onChange?.(newValue);\n setQuery(\"\");\n },\n [onChange],\n );\n\n const { metadata } = useOsdkMetadata(objectType);\n const titleProperty = typeof metadata?.titleProperty === \"string\"\n ? metadata.titleProperty\n : undefined;\n\n // Search on the title property (e.g. \"fullName\") so the where clause\n // matches the same text displayed to the user via obj.$title.\n // The where clause is loosely typed because we resolve the property\n // name at runtime from metadata, not from compile-time type info.\n const where: WhereClause<ObjectTypeDefinition> | undefined = useMemo(() => {\n const trimmed = debouncedQuery.trim();\n if (trimmed === \"\" || titleProperty == null) {\n return undefined;\n }\n return {\n [titleProperty]: { $containsAllTermsInOrder: trimmed },\n } as WhereClause<ObjectTypeDefinition>;\n }, [debouncedQuery, titleProperty]);\n\n const {\n data,\n isLoading,\n error: fetchError,\n fetchMore,\n hasMore,\n } = useOsdkObjects(objectType, {\n where,\n pageSize: PAGE_SIZE,\n });\n\n const items = data ?? EMPTY_ITEMS;\n\n const handleFetchMore = useCallback(() => {\n void fetchMore?.();\n }, [fetchMore]);\n\n return (\n <AsyncDropdownField\n id={id}\n value={value}\n onChange={handleChange}\n error={error}\n items={items}\n itemToStringLabel={itemToStringLabel}\n itemToKey={itemToKey}\n isItemEqual={isItemEqual}\n placeholder={placeholder ?? \"Search…\"}\n isMultiple={isMultiple}\n portalRef={portalRef}\n onQueryChange={setQuery}\n isLoading={isLoading}\n isSearching={debouncedQuery.trim() !== \"\" && isLoading}\n hasMore={hasMore}\n onFetchMore={handleFetchMore}\n fetchError={fetchError}\n />\n );\n});\n\nfunction itemToStringLabel(obj: OsdkObject): string {\n return obj.$title ?? String(obj.$primaryKey);\n}\n\nfunction itemToKey(obj: OsdkObject): string {\n return String(obj.$primaryKey);\n}\n\nfunction isItemEqual(a: OsdkObject, b: OsdkObject): boolean {\n return a.$primaryKey === b.$primaryKey;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -24,7 +24,6 @@ import { assertUnreachable } from "../../shared/assertUnreachable.js";
24
24
  export function getDefaultFieldDefinitions(metadata) {
25
25
  return Object.entries(metadata.parameters).map(([key, param]) => buildFieldDefinition(key, param));
26
26
  }
27
- const EMPTY_ITEMS = [];
28
27
 
29
28
  /**
30
29
  * Maps a single action parameter to its default RendererFieldDefinition.
@@ -51,15 +50,25 @@ function buildFieldDefinition(key, param) {
51
50
  }
52
51
  };
53
52
  case "object":
54
- case "interface":
55
- // TODO: provide correct items
56
53
  return {
57
54
  ...base,
58
- fieldComponent: "DROPDOWN",
55
+ fieldComponent: "OBJECT_SELECT",
59
56
  fieldComponentProps: {
60
- items: EMPTY_ITEMS
57
+ // Construct a minimal ObjectTypeDefinition from the action
58
+ // parameter metadata. At runtime useOsdkObjects only reads
59
+ // type + apiName from the definition.
60
+ objectType: {
61
+ type: "object",
62
+ apiName: paramType.object
63
+ }
61
64
  }
62
65
  };
66
+ case "interface":
67
+ return {
68
+ ...base,
69
+ fieldComponent: "TEXT_INPUT",
70
+ fieldComponentProps: {}
71
+ };
63
72
  case "struct":
64
73
  return {
65
74
  ...base,
@@ -1 +1 @@
1
- {"version":3,"file":"getDefaultFieldDefinitions.js","names":["assertUnreachable","getDefaultFieldDefinitions","metadata","Object","entries","parameters","map","key","param","buildFieldDefinition","EMPTY_ITEMS","base","fieldKey","label","isRequired","nullable","fieldType","type","paramType","fieldComponent","fieldComponentProps","value","items","options"],"sources":["getDefaultFieldDefinitions.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 { ActionMetadata } from \"@osdk/api\";\nimport { assertUnreachable } from \"../../shared/assertUnreachable.js\";\nimport type { RendererFieldDefinition } from \"../FormFieldApi.js\";\n\n/**\n * Derives default field definitions from ActionMetadata.\n *\n * Each parameter type maps to a concrete RendererFieldDefinition with the\n * correct fieldComponent and default fieldComponentProps.\n */\nexport function getDefaultFieldDefinitions(\n metadata: ActionMetadata,\n): ReadonlyArray<RendererFieldDefinition> {\n return Object.entries(metadata.parameters).map(\n ([key, param]) => buildFieldDefinition(key, param),\n );\n}\n\nconst EMPTY_ITEMS: unknown[] = [];\n\n/**\n * Maps a single action parameter to its default RendererFieldDefinition.\n *\n * Switches on the parameter's data type to select both the field component\n * and its required default props.\n */\nfunction buildFieldDefinition(\n key: string,\n param: ActionMetadata.Parameter,\n): RendererFieldDefinition {\n const base = {\n fieldKey: key,\n label: key,\n isRequired: !param.nullable,\n fieldType: param.type,\n };\n\n const paramType = param.type;\n\n if (typeof paramType === \"object\") {\n switch (paramType.type) {\n case \"objectSet\":\n return {\n ...base,\n fieldComponent: \"OBJECT_SET\",\n fieldComponentProps: { value: null },\n };\n case \"object\":\n case \"interface\":\n // TODO: provide correct items\n return {\n ...base,\n fieldComponent: \"DROPDOWN\",\n fieldComponentProps: { items: EMPTY_ITEMS },\n };\n case \"struct\":\n return {\n ...base,\n fieldComponent: \"TEXT_INPUT\",\n fieldComponentProps: {},\n };\n }\n }\n\n switch (paramType) {\n case \"string\":\n case \"marking\":\n case \"geohash\":\n case \"geoshape\":\n case \"objectType\":\n return {\n ...base,\n fieldComponent: \"TEXT_INPUT\",\n fieldComponentProps: {},\n };\n case \"boolean\":\n return {\n ...base,\n fieldComponent: \"RADIO_BUTTONS\",\n fieldComponentProps: {\n options: [{ label: \"True\", value: true }, {\n label: \"False\",\n value: false,\n }],\n },\n };\n case \"integer\":\n case \"double\":\n case \"long\":\n return {\n ...base,\n fieldComponent: \"NUMBER_INPUT\",\n fieldComponentProps: {},\n };\n case \"datetime\":\n case \"timestamp\":\n return {\n ...base,\n fieldComponent: \"DATETIME_PICKER\",\n fieldComponentProps: {},\n };\n case \"attachment\":\n case \"mediaReference\":\n return {\n ...base,\n fieldComponent: \"FILE_PICKER\",\n fieldComponentProps: {},\n };\n default:\n return assertUnreachable(paramType);\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,iBAAiB,QAAQ,mCAAmC;AAGrE;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,0BAA0BA,CACxCC,QAAwB,EACgB;EACxC,OAAOC,MAAM,CAACC,OAAO,CAACF,QAAQ,CAACG,UAAU,CAAC,CAACC,GAAG,CAC5C,CAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,KAAKC,oBAAoB,CAACF,GAAG,EAAEC,KAAK,CACnD,CAAC;AACH;AAEA,MAAME,WAAsB,GAAG,EAAE;;AAEjC;AACA;AACA;AACA;AACA;AACA;AACA,SAASD,oBAAoBA,CAC3BF,GAAW,EACXC,KAA+B,EACN;EACzB,MAAMG,IAAI,GAAG;IACXC,QAAQ,EAAEL,GAAG;IACbM,KAAK,EAAEN,GAAG;IACVO,UAAU,EAAE,CAACN,KAAK,CAACO,QAAQ;IAC3BC,SAAS,EAAER,KAAK,CAACS;EACnB,CAAC;EAED,MAAMC,SAAS,GAAGV,KAAK,CAACS,IAAI;EAE5B,IAAI,OAAOC,SAAS,KAAK,QAAQ,EAAE;IACjC,QAAQA,SAAS,CAACD,IAAI;MACpB,KAAK,WAAW;QACd,OAAO;UACL,GAAGN,IAAI;UACPQ,cAAc,EAAE,YAAY;UAC5BC,mBAAmB,EAAE;YAAEC,KAAK,EAAE;UAAK;QACrC,CAAC;MACH,KAAK,QAAQ;MACb,KAAK,WAAW;QACd;QACA,OAAO;UACL,GAAGV,IAAI;UACPQ,cAAc,EAAE,UAAU;UAC1BC,mBAAmB,EAAE;YAAEE,KAAK,EAAEZ;UAAY;QAC5C,CAAC;MACH,KAAK,QAAQ;QACX,OAAO;UACL,GAAGC,IAAI;UACPQ,cAAc,EAAE,YAAY;UAC5BC,mBAAmB,EAAE,CAAC;QACxB,CAAC;IACL;EACF;EAEA,QAAQF,SAAS;IACf,KAAK,QAAQ;IACb,KAAK,SAAS;IACd,KAAK,SAAS;IACd,KAAK,UAAU;IACf,KAAK,YAAY;MACf,OAAO;QACL,GAAGP,IAAI;QACPQ,cAAc,EAAE,YAAY;QAC5BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,SAAS;MACZ,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,eAAe;QAC/BC,mBAAmB,EAAE;UACnBG,OAAO,EAAE,CAAC;YAAEV,KAAK,EAAE,MAAM;YAAEQ,KAAK,EAAE;UAAK,CAAC,EAAE;YACxCR,KAAK,EAAE,OAAO;YACdQ,KAAK,EAAE;UACT,CAAC;QACH;MACF,CAAC;IACH,KAAK,SAAS;IACd,KAAK,QAAQ;IACb,KAAK,MAAM;MACT,OAAO;QACL,GAAGV,IAAI;QACPQ,cAAc,EAAE,cAAc;QAC9BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,UAAU;IACf,KAAK,WAAW;MACd,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,iBAAiB;QACjCC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,YAAY;IACjB,KAAK,gBAAgB;MACnB,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,aAAa;QAC7BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH;MACE,OAAOpB,iBAAiB,CAACkB,SAAS,CAAC;EACvC;AACF","ignoreList":[]}
1
+ {"version":3,"file":"getDefaultFieldDefinitions.js","names":["assertUnreachable","getDefaultFieldDefinitions","metadata","Object","entries","parameters","map","key","param","buildFieldDefinition","base","fieldKey","label","isRequired","nullable","fieldType","type","paramType","fieldComponent","fieldComponentProps","value","objectType","apiName","object","options"],"sources":["getDefaultFieldDefinitions.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 { ActionMetadata } from \"@osdk/api\";\nimport { assertUnreachable } from \"../../shared/assertUnreachable.js\";\nimport type { RendererFieldDefinition } from \"../FormFieldApi.js\";\n\n/**\n * Derives default field definitions from ActionMetadata.\n *\n * Each parameter type maps to a concrete RendererFieldDefinition with the\n * correct fieldComponent and default fieldComponentProps.\n */\nexport function getDefaultFieldDefinitions(\n metadata: ActionMetadata,\n): ReadonlyArray<RendererFieldDefinition> {\n return Object.entries(metadata.parameters).map(\n ([key, param]) => buildFieldDefinition(key, param),\n );\n}\n\n/**\n * Maps a single action parameter to its default RendererFieldDefinition.\n *\n * Switches on the parameter's data type to select both the field component\n * and its required default props.\n */\nfunction buildFieldDefinition(\n key: string,\n param: ActionMetadata.Parameter,\n): RendererFieldDefinition {\n const base = {\n fieldKey: key,\n label: key,\n isRequired: !param.nullable,\n fieldType: param.type,\n };\n\n const paramType = param.type;\n\n if (typeof paramType === \"object\") {\n switch (paramType.type) {\n case \"objectSet\":\n return {\n ...base,\n fieldComponent: \"OBJECT_SET\",\n fieldComponentProps: { value: null },\n };\n case \"object\":\n return {\n ...base,\n fieldComponent: \"OBJECT_SELECT\",\n fieldComponentProps: {\n // Construct a minimal ObjectTypeDefinition from the action\n // parameter metadata. At runtime useOsdkObjects only reads\n // type + apiName from the definition.\n objectType: {\n type: \"object\" as const,\n apiName: paramType.object,\n },\n },\n };\n case \"interface\":\n return {\n ...base,\n fieldComponent: \"TEXT_INPUT\",\n fieldComponentProps: {},\n };\n case \"struct\":\n return {\n ...base,\n fieldComponent: \"TEXT_INPUT\",\n fieldComponentProps: {},\n };\n }\n }\n\n switch (paramType) {\n case \"string\":\n case \"marking\":\n case \"geohash\":\n case \"geoshape\":\n case \"objectType\":\n return {\n ...base,\n fieldComponent: \"TEXT_INPUT\",\n fieldComponentProps: {},\n };\n case \"boolean\":\n return {\n ...base,\n fieldComponent: \"RADIO_BUTTONS\",\n fieldComponentProps: {\n options: [{ label: \"True\", value: true }, {\n label: \"False\",\n value: false,\n }],\n },\n };\n case \"integer\":\n case \"double\":\n case \"long\":\n return {\n ...base,\n fieldComponent: \"NUMBER_INPUT\",\n fieldComponentProps: {},\n };\n case \"datetime\":\n case \"timestamp\":\n return {\n ...base,\n fieldComponent: \"DATETIME_PICKER\",\n fieldComponentProps: {},\n };\n case \"attachment\":\n case \"mediaReference\":\n return {\n ...base,\n fieldComponent: \"FILE_PICKER\",\n fieldComponentProps: {},\n };\n default:\n return assertUnreachable(paramType);\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,iBAAiB,QAAQ,mCAAmC;AAGrE;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,0BAA0BA,CACxCC,QAAwB,EACgB;EACxC,OAAOC,MAAM,CAACC,OAAO,CAACF,QAAQ,CAACG,UAAU,CAAC,CAACC,GAAG,CAC5C,CAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,KAAKC,oBAAoB,CAACF,GAAG,EAAEC,KAAK,CACnD,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,oBAAoBA,CAC3BF,GAAW,EACXC,KAA+B,EACN;EACzB,MAAME,IAAI,GAAG;IACXC,QAAQ,EAAEJ,GAAG;IACbK,KAAK,EAAEL,GAAG;IACVM,UAAU,EAAE,CAACL,KAAK,CAACM,QAAQ;IAC3BC,SAAS,EAAEP,KAAK,CAACQ;EACnB,CAAC;EAED,MAAMC,SAAS,GAAGT,KAAK,CAACQ,IAAI;EAE5B,IAAI,OAAOC,SAAS,KAAK,QAAQ,EAAE;IACjC,QAAQA,SAAS,CAACD,IAAI;MACpB,KAAK,WAAW;QACd,OAAO;UACL,GAAGN,IAAI;UACPQ,cAAc,EAAE,YAAY;UAC5BC,mBAAmB,EAAE;YAAEC,KAAK,EAAE;UAAK;QACrC,CAAC;MACH,KAAK,QAAQ;QACX,OAAO;UACL,GAAGV,IAAI;UACPQ,cAAc,EAAE,eAAe;UAC/BC,mBAAmB,EAAE;YACnB;YACA;YACA;YACAE,UAAU,EAAE;cACVL,IAAI,EAAE,QAAiB;cACvBM,OAAO,EAAEL,SAAS,CAACM;YACrB;UACF;QACF,CAAC;MACH,KAAK,WAAW;QACd,OAAO;UACL,GAAGb,IAAI;UACPQ,cAAc,EAAE,YAAY;UAC5BC,mBAAmB,EAAE,CAAC;QACxB,CAAC;MACH,KAAK,QAAQ;QACX,OAAO;UACL,GAAGT,IAAI;UACPQ,cAAc,EAAE,YAAY;UAC5BC,mBAAmB,EAAE,CAAC;QACxB,CAAC;IACL;EACF;EAEA,QAAQF,SAAS;IACf,KAAK,QAAQ;IACb,KAAK,SAAS;IACd,KAAK,SAAS;IACd,KAAK,UAAU;IACf,KAAK,YAAY;MACf,OAAO;QACL,GAAGP,IAAI;QACPQ,cAAc,EAAE,YAAY;QAC5BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,SAAS;MACZ,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,eAAe;QAC/BC,mBAAmB,EAAE;UACnBK,OAAO,EAAE,CAAC;YAAEZ,KAAK,EAAE,MAAM;YAAEQ,KAAK,EAAE;UAAK,CAAC,EAAE;YACxCR,KAAK,EAAE,OAAO;YACdQ,KAAK,EAAE;UACT,CAAC;QACH;MACF,CAAC;IACH,KAAK,SAAS;IACd,KAAK,QAAQ;IACb,KAAK,MAAM;MACT,OAAO;QACL,GAAGV,IAAI;QACPQ,cAAc,EAAE,cAAc;QAC9BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,UAAU;IACf,KAAK,WAAW;MACd,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,iBAAiB;QACjCC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH,KAAK,YAAY;IACjB,KAAK,gBAAgB;MACnB,OAAO;QACL,GAAGT,IAAI;QACPQ,cAAc,EAAE,aAAa;QAC7BC,mBAAmB,EAAE,CAAC;MACxB,CAAC;IACH;MACE,OAAOnB,iBAAiB,CAACiB,SAAS,CAAC;EACvC;AACF","ignoreList":[]}
@@ -322,6 +322,26 @@
322
322
  box-shadow: var(--osdk-combobox-popup-shadow, var(--osdk-surface-shadow-2));
323
323
  }
324
324
 
325
+ /*
326
+ * When the popup contains a sticky search input, delegate scrolling to the
327
+ * list so the scrollbar doesn't render behind the pinned search input.
328
+ * The popup becomes a non-scrolling flex column; the list fills remaining
329
+ * space and scrolls its own content.
330
+ */
331
+ .osdkComboboxPopup:has(> .osdkComboboxPopupSearchInput) {
332
+ overflow: hidden;
333
+ }
334
+
335
+ /*
336
+ * When the popup has a search input it stops scrolling (overflow: hidden above).
337
+ * The list fills the remaining space so either its own content or the
338
+ * VirtualizedScroller inside can scroll independently.
339
+ */
340
+ .osdkComboboxPopup:has(> .osdkComboboxPopupSearchInput) > .osdkComboboxList {
341
+ flex: 1;
342
+ min-block-size: 0;
343
+ }
344
+
325
345
  .osdkComboboxItem {
326
346
  display: flex;
327
347
  align-items: center;
@@ -510,11 +530,12 @@
510
530
  .osdkComboboxList {
511
531
  display: flex;
512
532
  flex-direction: column;
533
+ overflow-y: auto;
513
534
  }
514
535
 
515
536
  .osdkComboboxEmpty {
516
- padding: calc(var(--osdk-combobox-spacing, var(--osdk-surface-spacing)) * 3)
517
- calc(var(--osdk-combobox-spacing, var(--osdk-surface-spacing)) * 2);
537
+ padding: var(--osdk-combobox-spacing, var(--osdk-surface-spacing))
538
+ var(--osdk-combobox-spacing, var(--osdk-surface-spacing));
518
539
  text-align: center;
519
540
  color: var(--osdk-combobox-empty-color, var(--osdk-typography-color-muted));
520
541
  font-family: var(
@@ -10,19 +10,19 @@ const styles = {
10
10
  "osdkComboboxInput": "Combobox-module__osdkComboboxInput___9516ISdK",
11
11
  "osdkComboboxPositioner": "Combobox-module__osdkComboboxPositioner___hKb8oXuo",
12
12
  "osdkComboboxPopup": "Combobox-module__osdkComboboxPopup___J-p7AW55",
13
+ "osdkComboboxPopupSearchInput": "Combobox-module__osdkComboboxPopupSearchInput___uTmFtNbw",
14
+ "osdkComboboxList": "Combobox-module__osdkComboboxList___q5-nhrtp",
13
15
  "osdkComboboxItem": "Combobox-module__osdkComboboxItem___aw0l3CKj",
14
16
  "osdkComboboxItemIndicator": "Combobox-module__osdkComboboxItemIndicator___ES80Zdrm",
15
17
  "osdkComboboxChips": "Combobox-module__osdkComboboxChips___LX40CFj-",
16
18
  "osdkComboboxChip": "Combobox-module__osdkComboboxChip___9O7-N50F",
17
19
  "osdkComboboxChipRemove": "Combobox-module__osdkComboboxChipRemove___QTqMJiEh",
18
20
  "osdkComboboxClear": "Combobox-module__osdkComboboxClear___ylbP7z6a",
19
- "osdkComboboxList": "Combobox-module__osdkComboboxList___q5-nhrtp",
20
21
  "osdkComboboxEmpty": "Combobox-module__osdkComboboxEmpty___rfSN-zlQ",
21
22
  "osdkComboboxItemCheckbox": "Combobox-module__osdkComboboxItemCheckbox___uK3qU1O7",
22
23
  "osdkComboboxTriggerChips": "Combobox-module__osdkComboboxTriggerChips___-kaN6nhS",
23
24
  "osdkComboboxTriggerChip": "Combobox-module__osdkComboboxTriggerChip___vAAyRpKe",
24
- "osdkComboboxTriggerChipRemove": "Combobox-module__osdkComboboxTriggerChipRemove___Hu8-bWrJ",
25
- "osdkComboboxPopupSearchInput": "Combobox-module__osdkComboboxPopupSearchInput___uTmFtNbw"
25
+ "osdkComboboxTriggerChipRemove": "Combobox-module__osdkComboboxTriggerChipRemove___Hu8-bWrJ"
26
26
  };
27
27
 
28
28
  export default styles;
@@ -1 +1 @@
1
- {"version":3,"file":"TextTagsInput.js","names":["Button","classnames","React","memo","useCallback","useMemo","useState","Combobox","sharedStyles","styles","TAG_SEPARATOR_PATTERN","TagItem","tag","onRemove","handleRemove","createElement","className","type","tagRemove","onClick","TextTagsInputInner","suggestions","isLoading","error","tags","onChange","style","placeholder","allowCustomTags","suggestionLimit","ariaLabel","inputValue","setInputValue","filteredSuggestions","lowerInput","toLowerCase","filter","s","trim","value","includes","slice","addTag","trimmedTag","removeTag","t","handleValueChange","newTags","handleInputValueChange","handleKeyDown","e","key","length","preventDefault","handlePaste","pastedText","clipboardData","getData","test","split","map","textTags","errorMessage","message","Root","multiple","onValueChange","onInputValueChange","tagContainer","SearchInput","input","onKeyDown","onPaste","Portal","Positioner","Popup","Empty","count","Item","toLocaleString","loadingMessage","TextTagsInput"],"sources":["TextTagsInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo, useState } from \"react\";\nimport { Combobox } from \"../../../base-components/combobox/Combobox.js\";\nimport type { PropertyAggregationValue } from \"../../types/AggregationTypes.js\";\nimport sharedStyles from \"./shared.module.css\";\nimport styles from \"./TextTagsInput.module.css\";\n\nconst TAG_SEPARATOR_PATTERN = /[,\\n]/;\n\ninterface TagItemProps {\n tag: string;\n onRemove: (tag: string) => void;\n}\n\nconst TagItem = memo(function TagItem({ tag, onRemove }: TagItemProps) {\n const handleRemove = useCallback(() => {\n onRemove(tag);\n }, [tag, onRemove]);\n\n return (\n <span className={sharedStyles.tag}>\n {tag}\n <Button\n type=\"button\"\n className={sharedStyles.tagRemove}\n onClick={handleRemove}\n aria-label={`Remove ${tag}`}\n >\n ×\n </Button>\n </span>\n );\n});\n\ninterface TextTagsInputProps {\n suggestions: PropertyAggregationValue[];\n isLoading: boolean;\n error: Error | null;\n tags: string[];\n onChange: (tags: string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n allowCustomTags?: boolean;\n suggestionLimit?: number;\n ariaLabel?: string;\n}\n\nfunction TextTagsInputInner({\n suggestions,\n isLoading,\n error,\n tags,\n onChange,\n className,\n style,\n placeholder = \"Add a tag...\",\n allowCustomTags = true,\n suggestionLimit = 10,\n ariaLabel = \"Add tag\",\n}: TextTagsInputProps): React.ReactElement {\n const [inputValue, setInputValue] = useState(\"\");\n\n const filteredSuggestions = useMemo(() => {\n if (!suggestionLimit) return [];\n const lowerInput = inputValue.toLowerCase();\n return suggestions\n .filter(\n (s) =>\n (!inputValue.trim()\n || s.value.toLowerCase().includes(lowerInput))\n && !tags.includes(s.value),\n )\n .slice(0, suggestionLimit);\n }, [suggestions, inputValue, tags, suggestionLimit]);\n\n const addTag = useCallback(\n (tag: string) => {\n const trimmedTag = tag.trim();\n if (trimmedTag && !tags.includes(trimmedTag)) {\n onChange([...tags, trimmedTag]);\n }\n setInputValue(\"\");\n },\n [tags, onChange],\n );\n\n const removeTag = useCallback(\n (tag: string) => {\n onChange(tags.filter((t) => t !== tag));\n },\n [tags, onChange],\n );\n\n const handleValueChange = useCallback(\n (newTags: string[] | null) => {\n onChange(newTags ?? []);\n },\n [onChange],\n );\n\n const handleInputValueChange = useCallback(\n (value: string) => {\n setInputValue(value);\n },\n [],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n if (filteredSuggestions.length > 0) {\n return;\n }\n e.preventDefault();\n if (allowCustomTags) {\n addTag(inputValue);\n }\n } else if (e.key === \"Backspace\" && !inputValue && tags.length > 0) {\n removeTag(tags[tags.length - 1]);\n }\n },\n [inputValue, tags, addTag, removeTag, allowCustomTags, filteredSuggestions],\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n const pastedText = e.clipboardData.getData(\"text\");\n if (TAG_SEPARATOR_PATTERN.test(pastedText)) {\n e.preventDefault();\n const newTags = pastedText\n .split(TAG_SEPARATOR_PATTERN)\n .map((t) => t.trim())\n .filter((t) => t && !tags.includes(t));\n if (newTags.length > 0) {\n onChange([...tags, ...newTags]);\n }\n }\n },\n [tags, onChange],\n );\n\n return (\n <div\n className={classnames(styles.textTags, className)}\n style={style}\n data-loading={isLoading}\n >\n {error && (\n <div className={sharedStyles.errorMessage}>\n Error loading suggestions: {error.message}\n </div>\n )}\n\n <Combobox.Root<string, true>\n multiple\n value={tags}\n onValueChange={handleValueChange}\n inputValue={inputValue}\n onInputValueChange={handleInputValueChange}\n >\n {tags.length > 0 && (\n <div className={sharedStyles.tagContainer}>\n {tags.map((tag) => (\n <TagItem key={tag} tag={tag} onRemove={removeTag} />\n ))}\n </div>\n )}\n\n <Combobox.SearchInput\n className={styles.input}\n placeholder={tags.length > 0 ? \"\" : placeholder}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n aria-label={ariaLabel}\n />\n\n <Combobox.Portal>\n <Combobox.Positioner>\n <Combobox.Popup>\n {filteredSuggestions.length === 0\n ? (\n allowCustomTags && inputValue.trim()\n ? (\n <Combobox.Empty>\n Press Enter to add \"{inputValue}\"\n </Combobox.Empty>\n )\n : (\n <Combobox.Empty>\n {suggestionLimit\n ? \"No suggestions\"\n : \"Type to add a tag\"}\n </Combobox.Empty>\n )\n )\n : filteredSuggestions.map(({ value, count }) => (\n <Combobox.Item key={value} value={value}>\n {value} ({count.toLocaleString()})\n </Combobox.Item>\n ))}\n </Combobox.Popup>\n </Combobox.Positioner>\n </Combobox.Portal>\n </Combobox.Root>\n\n {isLoading && !!suggestionLimit && (\n <div className={sharedStyles.loadingMessage}>\n Loading suggestions...\n </div>\n )}\n </div>\n );\n}\n\nexport const TextTagsInput = memo(\n TextTagsInputInner,\n) as typeof TextTagsInputInner;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"TextTagsInput.js","names":["Button","classnames","React","memo","useCallback","useMemo","useState","Combobox","sharedStyles","styles","TAG_SEPARATOR_PATTERN","TagItem","tag","onRemove","handleRemove","createElement","className","type","tagRemove","onClick","TextTagsInputInner","suggestions","isLoading","error","tags","onChange","style","placeholder","allowCustomTags","suggestionLimit","ariaLabel","inputValue","setInputValue","filteredSuggestions","lowerInput","toLowerCase","filter","s","trim","value","includes","slice","addTag","trimmedTag","removeTag","t","handleValueChange","newTags","handleInputValueChange","handleKeyDown","e","key","length","preventDefault","handlePaste","pastedText","clipboardData","getData","test","split","map","textTags","errorMessage","message","Root","multiple","onValueChange","onInputValueChange","tagContainer","SearchInput","input","onKeyDown","onPaste","Portal","Positioner","Popup","Empty","count","Item","toLocaleString","loadingMessage","TextTagsInput"],"sources":["TextTagsInput.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo, useState } from \"react\";\nimport { Combobox } from \"../../../base-components/combobox/Combobox.js\";\nimport type { PropertyAggregationValue } from \"../../types/AggregationTypes.js\";\nimport sharedStyles from \"./shared.module.css\";\nimport styles from \"./TextTagsInput.module.css\";\n\nconst TAG_SEPARATOR_PATTERN = /[,\\n]/;\n\ninterface TagItemProps {\n tag: string;\n onRemove: (tag: string) => void;\n}\n\nconst TagItem = memo(function TagItem({ tag, onRemove }: TagItemProps) {\n const handleRemove = useCallback(() => {\n onRemove(tag);\n }, [tag, onRemove]);\n\n return (\n <span className={sharedStyles.tag}>\n {tag}\n <Button\n type=\"button\"\n className={sharedStyles.tagRemove}\n onClick={handleRemove}\n aria-label={`Remove ${tag}`}\n >\n ×\n </Button>\n </span>\n );\n});\n\ninterface TextTagsInputProps {\n suggestions: PropertyAggregationValue[];\n isLoading: boolean;\n error: Error | null;\n tags: string[];\n onChange: (tags: string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n allowCustomTags?: boolean;\n suggestionLimit?: number;\n ariaLabel?: string;\n}\n\nfunction TextTagsInputInner({\n suggestions,\n isLoading,\n error,\n tags,\n onChange,\n className,\n style,\n placeholder = \"Add a tag...\",\n allowCustomTags = true,\n suggestionLimit = 10,\n ariaLabel = \"Add tag\",\n}: TextTagsInputProps): React.ReactElement {\n const [inputValue, setInputValue] = useState(\"\");\n\n const filteredSuggestions = useMemo(() => {\n if (!suggestionLimit) return [];\n const lowerInput = inputValue.toLowerCase();\n return suggestions\n .filter(\n (s) =>\n (!inputValue.trim()\n || s.value.toLowerCase().includes(lowerInput))\n && !tags.includes(s.value),\n )\n .slice(0, suggestionLimit);\n }, [suggestions, inputValue, tags, suggestionLimit]);\n\n const addTag = useCallback(\n (tag: string) => {\n const trimmedTag = tag.trim();\n if (trimmedTag && !tags.includes(trimmedTag)) {\n onChange([...tags, trimmedTag]);\n }\n setInputValue(\"\");\n },\n [tags, onChange],\n );\n\n const removeTag = useCallback(\n (tag: string) => {\n onChange(tags.filter((t) => t !== tag));\n },\n [tags, onChange],\n );\n\n const handleValueChange = useCallback(\n (newTags: string[] | null) => {\n onChange(newTags ?? []);\n },\n [onChange],\n );\n\n const handleInputValueChange = useCallback(\n (value: string) => {\n setInputValue(value);\n },\n [],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n if (filteredSuggestions.length > 0) {\n return;\n }\n e.preventDefault();\n if (allowCustomTags) {\n addTag(inputValue);\n }\n } else if (e.key === \"Backspace\" && !inputValue && tags.length > 0) {\n removeTag(tags[tags.length - 1]);\n }\n },\n [inputValue, tags, addTag, removeTag, allowCustomTags, filteredSuggestions],\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n const pastedText = e.clipboardData.getData(\"text\");\n if (TAG_SEPARATOR_PATTERN.test(pastedText)) {\n e.preventDefault();\n const newTags = pastedText\n .split(TAG_SEPARATOR_PATTERN)\n .map((t) => t.trim())\n .filter((t) => t && !tags.includes(t));\n if (newTags.length > 0) {\n onChange([...tags, ...newTags]);\n }\n }\n },\n [tags, onChange],\n );\n\n return (\n <div\n className={classnames(styles.textTags, className)}\n style={style}\n data-loading={isLoading}\n >\n {error && (\n <div className={sharedStyles.errorMessage}>\n Error loading suggestions: {error.message}\n </div>\n )}\n\n <Combobox.Root<string, true>\n multiple={true}\n value={tags}\n onValueChange={handleValueChange}\n inputValue={inputValue}\n onInputValueChange={handleInputValueChange}\n >\n {tags.length > 0 && (\n <div className={sharedStyles.tagContainer}>\n {tags.map((tag) => (\n <TagItem key={tag} tag={tag} onRemove={removeTag} />\n ))}\n </div>\n )}\n\n <Combobox.SearchInput\n className={styles.input}\n placeholder={tags.length > 0 ? \"\" : placeholder}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n aria-label={ariaLabel}\n />\n\n <Combobox.Portal>\n <Combobox.Positioner>\n <Combobox.Popup>\n {filteredSuggestions.length === 0\n ? (\n allowCustomTags && inputValue.trim()\n ? (\n <Combobox.Empty>\n Press Enter to add \"{inputValue}\"\n </Combobox.Empty>\n )\n : (\n <Combobox.Empty>\n {suggestionLimit\n ? \"No suggestions\"\n : \"Type to add a tag\"}\n </Combobox.Empty>\n )\n )\n : filteredSuggestions.map(({ value, count }) => (\n <Combobox.Item key={value} value={value}>\n {value} ({count.toLocaleString()})\n </Combobox.Item>\n ))}\n </Combobox.Popup>\n </Combobox.Positioner>\n </Combobox.Portal>\n </Combobox.Root>\n\n {isLoading && !!suggestionLimit && (\n <div className={sharedStyles.loadingMessage}>\n Loading suggestions...\n </div>\n )}\n </div>\n );\n}\n\nexport const TextTagsInput = memo(\n TextTagsInputInner,\n) as typeof TextTagsInputInner;\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { useEffect, useState } from "react";
18
+
19
+ /**
20
+ * Returns a debounced version of `value` that only updates after `debounceMs`
21
+ * of inactivity. Each change to `value` resets the timer.
22
+ */
23
+ export function useDebouncedValue(value, debounceMs) {
24
+ const [debouncedValue, setDebouncedValue] = useState(value);
25
+ useEffect(function () {
26
+ const timer = setTimeout(() => {
27
+ setDebouncedValue(value);
28
+ }, debounceMs);
29
+ return () => {
30
+ clearTimeout(timer);
31
+ };
32
+ }, [value, debounceMs]);
33
+ return debouncedValue;
34
+ }
35
+ //# sourceMappingURL=useDebouncedValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDebouncedValue.js","names":["useEffect","useState","useDebouncedValue","value","debounceMs","debouncedValue","setDebouncedValue","timer","setTimeout","clearTimeout"],"sources":["useDebouncedValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * Returns a debounced version of `value` that only updates after `debounceMs`\n * of inactivity. Each change to `value` resets the timer.\n */\nexport function useDebouncedValue<T>(value: T, debounceMs: number): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(function debounceValue() {\n const timer = setTimeout(() => {\n setDebouncedValue(value);\n }, debounceMs);\n return () => {\n clearTimeout(timer);\n };\n }, [value, debounceMs]);\n\n return debouncedValue;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,OAAO;;AAE3C;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAAIC,KAAQ,EAAEC,UAAkB,EAAK;EACpE,MAAM,CAACC,cAAc,EAAEC,iBAAiB,CAAC,GAAGL,QAAQ,CAAIE,KAAK,CAAC;EAE9DH,SAAS,CAAC,YAAyB;IACjC,MAAMO,KAAK,GAAGC,UAAU,CAAC,MAAM;MAC7BF,iBAAiB,CAACH,KAAK,CAAC;IAC1B,CAAC,EAAEC,UAAU,CAAC;IACd,OAAO,MAAM;MACXK,YAAY,CAACF,KAAK,CAAC;IACrB,CAAC;EACH,CAAC,EAAE,CAACJ,KAAK,EAAEC,UAAU,CAAC,CAAC;EAEvB,OAAOC,cAAc;AACvB","ignoreList":[]}
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import * as React from "react";
18
+
19
+ /**
20
+ * Creates a MutableRefObject with a constant reference. This allows us to pass around a constant reference
21
+ * to a callback, but let the consumer change the callback over time without losing that reference.
22
+ * The callback is only updated after render, so any usage of the callback during render will operate on the
23
+ * previous render's callback. Callbacks created by this hook should **only** be used for event handling.
24
+ * If the callback is called on the first render of a component, it will log an error. In the future,
25
+ * this will throw.
26
+ *
27
+ * ```
28
+ *
29
+ * @param callback
30
+ */
31
+ /* eslint-disable-next-line @typescript-eslint/no-unsafe-function-type */
32
+ export function useEventCallback(callback) {
33
+ const latestCallbackValueWrapper = React.useRef((...args) => {
34
+ if (typeof globalThis.console !== "undefined") {
35
+ globalThis.console.error("A callback created with `useEventCallback` was called during the initial render of a component. This will throw an error in the future.");
36
+ }
37
+ return callback(...args);
38
+ });
39
+ React.useEffect(() => {
40
+ latestCallbackValueWrapper.current = callback;
41
+ }, [callback]);
42
+ return React.useCallback((...args) => latestCallbackValueWrapper.current(...args), []);
43
+ }
44
+ //# sourceMappingURL=useEventCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEventCallback.js","names":["React","useEventCallback","callback","latestCallbackValueWrapper","useRef","args","globalThis","console","error","useEffect","current","useCallback"],"sources":["useEventCallback.ts"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as React from \"react\";\n\n/**\n * Creates a MutableRefObject with a constant reference. This allows us to pass around a constant reference\n * to a callback, but let the consumer change the callback over time without losing that reference.\n * The callback is only updated after render, so any usage of the callback during render will operate on the\n * previous render's callback. Callbacks created by this hook should **only** be used for event handling.\n * If the callback is called on the first render of a component, it will log an error. In the future,\n * this will throw.\n *\n * ```\n *\n * @param callback\n */\n/* eslint-disable-next-line @typescript-eslint/no-unsafe-function-type */\nexport function useEventCallback<T extends Function>(callback: T): T {\n const latestCallbackValueWrapper = React.useRef<T>(\n ((...args: unknown[]) => {\n if (typeof globalThis.console !== \"undefined\") {\n globalThis.console.error(\n \"A callback created with `useEventCallback` was called during the initial render of a component. This will throw an error in the future.\",\n );\n }\n return (callback as unknown as (...a: unknown[]) => unknown)(...args);\n }) as unknown as T,\n );\n\n React.useEffect(() => {\n latestCallbackValueWrapper.current = callback;\n }, [callback]);\n\n return React.useCallback(\n (...args: unknown[]) =>\n (\n latestCallbackValueWrapper.current as unknown as (\n ...a: unknown[]\n ) => unknown\n )(...args),\n [],\n ) as unknown as T;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,KAAKA,KAAK,MAAM,OAAO;;AAE9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAAqBC,QAAW,EAAK;EACnE,MAAMC,0BAA0B,GAAGH,KAAK,CAACI,MAAM,CAC5C,CAAC,GAAGC,IAAe,KAAK;IACvB,IAAI,OAAOC,UAAU,CAACC,OAAO,KAAK,WAAW,EAAE;MAC7CD,UAAU,CAACC,OAAO,CAACC,KAAK,CACtB,yIACF,CAAC;IACH;IACA,OAAQN,QAAQ,CAA6C,GAAGG,IAAI,CAAC;EACvE,CACF,CAAC;EAEDL,KAAK,CAACS,SAAS,CAAC,MAAM;IACpBN,0BAA0B,CAACO,OAAO,GAAGR,QAAQ;EAC/C,CAAC,EAAE,CAACA,QAAQ,CAAC,CAAC;EAEd,OAAOF,KAAK,CAACW,WAAW,CACtB,CAAC,GAAGN,IAAe,KAEfF,0BAA0B,CAACO,OAAO,CAGlC,GAAGL,IAAI,CAAC,EACZ,EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,81 @@
1
+ /*
2
+ * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { throttle } from "lodash-es";
18
+ import { useCallback, useEffect, useRef } from "react";
19
+ import { useEventCallback } from "./useEventCallback.js";
20
+ const THRESHOLD = 0.5;
21
+ const OPTIONS = {
22
+ threshold: THRESHOLD
23
+ };
24
+ /**
25
+ * This hooks handles the logic of triggering a callback when the user reaches the target element (e.g. spinner).
26
+ * It returns a callback that must be set as the ref of the target element at the bottom of the
27
+ * scroll container.
28
+ */
29
+ export function useInfiniteScroll({
30
+ callback,
31
+ loadedCount
32
+ }) {
33
+ const observer = useRef();
34
+ const targetRef = useRef();
35
+ const eventCallback = useEventCallback(callback);
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ const throttledCallback = useCallback(throttle(eventCallback), []);
38
+
39
+ /**
40
+ * If the observer updates the entry in a way that indicates that the target element is intersecting
41
+ * with the scroll container, invoke the callback.
42
+ */
43
+ const handleObserverUpdate = useCallback(entries => {
44
+ const ent = entries[0];
45
+ if (ent && ent.isIntersecting) {
46
+ throttledCallback();
47
+ }
48
+ },
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ []);
51
+
52
+ /**
53
+ * Retrigger visibility detection whenever the loaded count of items changes. This allows us to
54
+ * detect loading initial pages in a tall container that do not cause the target element to
55
+ * change visibility.
56
+ */
57
+ useEffect(() => {
58
+ const {
59
+ current: targetElement
60
+ } = targetRef;
61
+ if (observer.current == null || targetElement == null) {
62
+ return;
63
+ }
64
+ observer.current.observe(targetElement);
65
+ return () => {
66
+ observer.current?.unobserve(targetElement);
67
+ };
68
+ }, [loadedCount]);
69
+ return node => {
70
+ if (node != null) {
71
+ targetRef.current = node;
72
+ if (observer.current == null) {
73
+ observer.current = new IntersectionObserver(handleObserverUpdate, OPTIONS);
74
+ }
75
+ observer.current.observe(node);
76
+ } else if (targetRef.current != null) {
77
+ observer.current?.unobserve(targetRef.current);
78
+ }
79
+ };
80
+ }
81
+ //# sourceMappingURL=useInfiniteScroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInfiniteScroll.js","names":["throttle","useCallback","useEffect","useRef","useEventCallback","THRESHOLD","OPTIONS","threshold","useInfiniteScroll","callback","loadedCount","observer","targetRef","eventCallback","throttledCallback","handleObserverUpdate","entries","ent","isIntersecting","current","targetElement","observe","unobserve","node","IntersectionObserver"],"sources":["useInfiniteScroll.ts"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { throttle } from \"lodash-es\";\nimport type { LegacyRef } from \"react\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useEventCallback } from \"./useEventCallback.js\";\n\nconst THRESHOLD = 0.5;\nconst OPTIONS = {\n threshold: THRESHOLD,\n};\n\nexport interface UseInfiniteScrollOptions {\n /**\n * Callback to call when new items should be loaded.\n */\n callback: () => void;\n /**\n * The current count of the number of loaded items in the infinite scroll. This is used to\n * detect changes when the height of the container is large and can hold multiple initial\n * loaded pages without making the target element scroll out of the viewport.\n */\n loadedCount: number;\n}\n\n/**\n * This hooks handles the logic of triggering a callback when the user reaches the target element (e.g. spinner).\n * It returns a callback that must be set as the ref of the target element at the bottom of the\n * scroll container.\n */\nexport function useInfiniteScroll(\n { callback, loadedCount }: UseInfiniteScrollOptions,\n): LegacyRef<HTMLDivElement> {\n const observer = useRef<IntersectionObserver>();\n const targetRef = useRef<Element | undefined>();\n\n const eventCallback = useEventCallback(callback);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const throttledCallback = useCallback(throttle(eventCallback), []);\n\n /**\n * If the observer updates the entry in a way that indicates that the target element is intersecting\n * with the scroll container, invoke the callback.\n */\n const handleObserverUpdate: IntersectionObserverCallback = useCallback(\n entries => {\n const ent = entries[0];\n if (ent && ent.isIntersecting) {\n throttledCallback();\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n /**\n * Retrigger visibility detection whenever the loaded count of items changes. This allows us to\n * detect loading initial pages in a tall container that do not cause the target element to\n * change visibility.\n */\n useEffect(() => {\n const { current: targetElement } = targetRef;\n if (observer.current == null || targetElement == null) {\n return;\n }\n observer.current.observe(targetElement);\n return () => {\n observer.current?.unobserve(targetElement);\n };\n }, [loadedCount]);\n\n const setRef = (node: HTMLDivElement) => {\n if (node != null) {\n targetRef.current = node;\n if (observer.current == null) {\n observer.current = new IntersectionObserver(\n handleObserverUpdate,\n OPTIONS,\n );\n }\n observer.current.observe(node);\n } else if (targetRef.current != null) {\n observer.current?.unobserve(targetRef.current);\n }\n };\n\n return setRef;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,QAAQ,QAAQ,WAAW;AAEpC,SAASC,WAAW,EAAEC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AACtD,SAASC,gBAAgB,QAAQ,uBAAuB;AAExD,MAAMC,SAAS,GAAG,GAAG;AACrB,MAAMC,OAAO,GAAG;EACdC,SAAS,EAAEF;AACb,CAAC;AAeD;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,iBAAiBA,CAC/B;EAAEC,QAAQ;EAAEC;AAAsC,CAAC,EACxB;EAC3B,MAAMC,QAAQ,GAAGR,MAAM,CAAuB,CAAC;EAC/C,MAAMS,SAAS,GAAGT,MAAM,CAAsB,CAAC;EAE/C,MAAMU,aAAa,GAAGT,gBAAgB,CAACK,QAAQ,CAAC;EAChD;EACA,MAAMK,iBAAiB,GAAGb,WAAW,CAACD,QAAQ,CAACa,aAAa,CAAC,EAAE,EAAE,CAAC;;EAElE;AACF;AACA;AACA;EACE,MAAME,oBAAkD,GAAGd,WAAW,CACpEe,OAAO,IAAI;IACT,MAAMC,GAAG,GAAGD,OAAO,CAAC,CAAC,CAAC;IACtB,IAAIC,GAAG,IAAIA,GAAG,CAACC,cAAc,EAAE;MAC7BJ,iBAAiB,CAAC,CAAC;IACrB;EACF,CAAC;EACD;EACA,EACF,CAAC;;EAED;AACF;AACA;AACA;AACA;EACEZ,SAAS,CAAC,MAAM;IACd,MAAM;MAAEiB,OAAO,EAAEC;IAAc,CAAC,GAAGR,SAAS;IAC5C,IAAID,QAAQ,CAACQ,OAAO,IAAI,IAAI,IAAIC,aAAa,IAAI,IAAI,EAAE;MACrD;IACF;IACAT,QAAQ,CAACQ,OAAO,CAACE,OAAO,CAACD,aAAa,CAAC;IACvC,OAAO,MAAM;MACXT,QAAQ,CAACQ,OAAO,EAAEG,SAAS,CAACF,aAAa,CAAC;IAC5C,CAAC;EACH,CAAC,EAAE,CAACV,WAAW,CAAC,CAAC;EAiBjB,OAfgBa,IAAoB,IAAK;IACvC,IAAIA,IAAI,IAAI,IAAI,EAAE;MAChBX,SAAS,CAACO,OAAO,GAAGI,IAAI;MACxB,IAAIZ,QAAQ,CAACQ,OAAO,IAAI,IAAI,EAAE;QAC5BR,QAAQ,CAACQ,OAAO,GAAG,IAAIK,oBAAoB,CACzCT,oBAAoB,EACpBT,OACF,CAAC;MACH;MACAK,QAAQ,CAACQ,OAAO,CAACE,OAAO,CAACE,IAAI,CAAC;IAChC,CAAC,MAAM,IAAIX,SAAS,CAACO,OAAO,IAAI,IAAI,EAAE;MACpCR,QAAQ,CAACQ,OAAO,EAAEG,SAAS,CAACV,SAAS,CAACO,OAAO,CAAC;IAChD;EACF,CAAC;AAGH","ignoreList":[]}