@osdk/react-components 0.2.0-beta.10 → 0.2.0-beta.11

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 +6 -0
  2. package/build/browser/object-table/DefaultCellRenderer.js +5 -2
  3. package/build/browser/object-table/DefaultCellRenderer.js.map +1 -1
  4. package/build/browser/object-table/EditableCell.js +16 -6
  5. package/build/browser/object-table/EditableCell.js.map +1 -1
  6. package/build/browser/object-table/EditableCell.module.css +30 -2
  7. package/build/browser/object-table/EditableCell.module.css.js +2 -1
  8. package/build/browser/object-table/ObjectTable.js +9 -22
  9. package/build/browser/object-table/ObjectTable.js.map +1 -1
  10. package/build/browser/object-table/ObjectTableApi.js.map +1 -1
  11. package/build/browser/object-table/Table.js +23 -15
  12. package/build/browser/object-table/Table.js.map +1 -1
  13. package/build/browser/object-table/Table.module.css +0 -8
  14. package/build/browser/object-table/Table.module.css.js +1 -2
  15. package/build/browser/object-table/TableBody.js +8 -2
  16. package/build/browser/object-table/TableBody.js.map +1 -1
  17. package/build/browser/object-table/TableCell.module.css +0 -8
  18. package/build/browser/object-table/TableEditContainer.js +79 -0
  19. package/build/browser/object-table/TableEditContainer.js.map +1 -0
  20. package/build/browser/object-table/TableEditContainer.module.css +44 -0
  21. package/build/browser/object-table/TableEditContainer.module.css.js +9 -0
  22. package/build/browser/object-table/TableRow.js +12 -4
  23. package/build/browser/object-table/TableRow.js.map +1 -1
  24. package/build/browser/object-table/TableRow.module.css +2 -1
  25. package/build/browser/object-table/hooks/__tests__/useEditableTable.test.js +292 -0
  26. package/build/browser/object-table/hooks/__tests__/useEditableTable.test.js.map +1 -0
  27. package/build/browser/object-table/hooks/useEditableTable.js +20 -11
  28. package/build/browser/object-table/hooks/useEditableTable.js.map +1 -1
  29. package/build/browser/object-table/hooks/useObjectTableData.js +0 -5
  30. package/build/browser/object-table/hooks/useObjectTableData.js.map +1 -1
  31. package/build/browser/object-table/utils/getCellId.js +0 -7
  32. package/build/browser/object-table/utils/getCellId.js.map +1 -1
  33. package/build/browser/object-table/utils/types.js.map +1 -1
  34. package/build/browser/public/experimental.js.map +1 -1
  35. package/build/browser/styles.css +79 -19
  36. package/build/cjs/public/experimental.cjs +179 -90
  37. package/build/cjs/public/experimental.cjs.map +1 -1
  38. package/build/cjs/public/experimental.css +96 -57
  39. package/build/cjs/public/experimental.css.map +1 -1
  40. package/build/cjs/public/experimental.d.cts +40 -18
  41. package/build/esm/object-table/DefaultCellRenderer.js +5 -2
  42. package/build/esm/object-table/DefaultCellRenderer.js.map +1 -1
  43. package/build/esm/object-table/EditableCell.js +16 -6
  44. package/build/esm/object-table/EditableCell.js.map +1 -1
  45. package/build/esm/object-table/EditableCell.module.css +30 -2
  46. package/build/esm/object-table/ObjectTable.js +9 -22
  47. package/build/esm/object-table/ObjectTable.js.map +1 -1
  48. package/build/esm/object-table/ObjectTableApi.js.map +1 -1
  49. package/build/esm/object-table/Table.js +23 -15
  50. package/build/esm/object-table/Table.js.map +1 -1
  51. package/build/esm/object-table/Table.module.css +0 -8
  52. package/build/esm/object-table/TableBody.js +8 -2
  53. package/build/esm/object-table/TableBody.js.map +1 -1
  54. package/build/esm/object-table/TableCell.module.css +0 -8
  55. package/build/esm/object-table/TableEditContainer.js +79 -0
  56. package/build/esm/object-table/TableEditContainer.js.map +1 -0
  57. package/build/esm/object-table/TableEditContainer.module.css +44 -0
  58. package/build/esm/object-table/TableRow.js +12 -4
  59. package/build/esm/object-table/TableRow.js.map +1 -1
  60. package/build/esm/object-table/TableRow.module.css +2 -1
  61. package/build/esm/object-table/hooks/__tests__/useEditableTable.test.js +292 -0
  62. package/build/esm/object-table/hooks/__tests__/useEditableTable.test.js.map +1 -0
  63. package/build/esm/object-table/hooks/useEditableTable.js +20 -11
  64. package/build/esm/object-table/hooks/useEditableTable.js.map +1 -1
  65. package/build/esm/object-table/hooks/useObjectTableData.js +0 -5
  66. package/build/esm/object-table/hooks/useObjectTableData.js.map +1 -1
  67. package/build/esm/object-table/utils/getCellId.js +0 -7
  68. package/build/esm/object-table/utils/getCellId.js.map +1 -1
  69. package/build/esm/object-table/utils/types.js.map +1 -1
  70. package/build/esm/public/experimental.js.map +1 -1
  71. package/build/types/object-table/DefaultCellRenderer.d.ts +2 -2
  72. package/build/types/object-table/DefaultCellRenderer.d.ts.map +1 -1
  73. package/build/types/object-table/EditableCell.d.ts +18 -6
  74. package/build/types/object-table/EditableCell.d.ts.map +1 -1
  75. package/build/types/object-table/ObjectTable.d.ts +1 -1
  76. package/build/types/object-table/ObjectTable.d.ts.map +1 -1
  77. package/build/types/object-table/ObjectTableApi.d.ts +16 -6
  78. package/build/types/object-table/ObjectTableApi.d.ts.map +1 -1
  79. package/build/types/object-table/Table.d.ts +5 -10
  80. package/build/types/object-table/Table.d.ts.map +1 -1
  81. package/build/types/object-table/TableBody.d.ts +4 -1
  82. package/build/types/object-table/TableBody.d.ts.map +1 -1
  83. package/build/types/object-table/TableEditContainer.d.ts +9 -0
  84. package/build/types/object-table/TableEditContainer.d.ts.map +1 -0
  85. package/build/types/object-table/TableRow.d.ts +5 -1
  86. package/build/types/object-table/TableRow.d.ts.map +1 -1
  87. package/build/types/object-table/hooks/__tests__/useEditableTable.test.d.ts.map +1 -0
  88. package/build/types/object-table/hooks/useEditableTable.d.ts +4 -9
  89. package/build/types/object-table/hooks/useEditableTable.d.ts.map +1 -1
  90. package/build/types/object-table/utils/getCellId.d.ts +0 -1
  91. package/build/types/object-table/utils/getCellId.d.ts.map +1 -1
  92. package/build/types/object-table/utils/types.d.ts +25 -3
  93. package/build/types/object-table/utils/types.d.ts.map +1 -1
  94. package/build/types/public/experimental.d.ts +1 -1
  95. package/build/types/public/experimental.d.ts.map +1 -1
  96. package/package.json +5 -5
  97. package/build/browser/object-table/__tests__/useEditableTable.test.js +0 -197
  98. package/build/browser/object-table/__tests__/useEditableTable.test.js.map +0 -1
  99. package/build/esm/object-table/__tests__/useEditableTable.test.js +0 -197
  100. package/build/esm/object-table/__tests__/useEditableTable.test.js.map +0 -1
  101. package/build/types/object-table/__tests__/useEditableTable.test.d.ts.map +0 -1
  102. /package/build/types/object-table/{__tests__ → hooks/__tests__}/useEditableTable.test.d.ts +0 -0
@@ -0,0 +1,79 @@
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 React, { useCallback, useState } from "react";
18
+ import { ActionButton } from "../base-components/action-button/ActionButton.js";
19
+ import styles from "./TableEditContainer.module.css.js";
20
+ export function TableEditContainer({
21
+ editableConfig,
22
+ focusedRowId
23
+ }) {
24
+ const {
25
+ cellEdits,
26
+ onSubmitEdits,
27
+ clearEdits,
28
+ editMode
29
+ } = editableConfig ?? {};
30
+ const hasEdits = Object.keys(cellEdits ?? {}).length > 0;
31
+ const [isSubmitting, setIsSubmitting] = useState(false);
32
+ const isInEditMode = editMode?.isActive;
33
+ const canToggleEditMode = editMode?.type === "manual";
34
+ const handleSubmitEdits = useCallback(async () => {
35
+ setIsSubmitting(true);
36
+ try {
37
+ const success = await onSubmitEdits?.();
38
+ if (success) {
39
+ clearEdits?.();
40
+ if (editMode?.type === "manual") {
41
+ editMode.setActive(false);
42
+ }
43
+ }
44
+ } finally {
45
+ setIsSubmitting(false);
46
+ }
47
+ }, [editMode, onSubmitEdits, clearEdits]);
48
+ const handleCancelEdits = useCallback(() => {
49
+ clearEdits?.();
50
+ if (editMode?.type === "manual") {
51
+ editMode.setActive(false);
52
+ }
53
+ }, [clearEdits, editMode]);
54
+ const handleEnterEditMode = useCallback(() => {
55
+ if (editMode?.type === "manual") {
56
+ editMode.setActive(true);
57
+ }
58
+ }, [editMode]);
59
+ return /*#__PURE__*/React.createElement("div", {
60
+ className: styles.tableEditContainer
61
+ }, hasEdits ? /*#__PURE__*/React.createElement("div", {
62
+ className: styles.modificationCount
63
+ }, `${cellEdits ? Object.keys(cellEdits).length : 0} modifications`) : isInEditMode && !focusedRowId && /*#__PURE__*/React.createElement("div", {
64
+ className: styles.placeholder
65
+ }, "Select a row to edit data\u2026"), /*#__PURE__*/React.createElement("div", {
66
+ className: styles.editButtons
67
+ }, !isInEditMode && canToggleEditMode && /*#__PURE__*/React.createElement(ActionButton, {
68
+ variant: "primary",
69
+ onClick: handleEnterEditMode
70
+ }, "Edit Table"), isInEditMode && canToggleEditMode && /*#__PURE__*/React.createElement(ActionButton, {
71
+ variant: "secondary",
72
+ onClick: handleCancelEdits
73
+ }, "Cancel"), isInEditMode && !!onSubmitEdits && /*#__PURE__*/React.createElement(ActionButton, {
74
+ variant: "primary",
75
+ onClick: handleSubmitEdits,
76
+ disabled: !hasEdits || isSubmitting
77
+ }, "Submit Edits")));
78
+ }
79
+ //# sourceMappingURL=TableEditContainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableEditContainer.js","names":["React","useCallback","useState","ActionButton","styles","TableEditContainer","editableConfig","focusedRowId","cellEdits","onSubmitEdits","clearEdits","editMode","hasEdits","Object","keys","length","isSubmitting","setIsSubmitting","isInEditMode","isActive","canToggleEditMode","type","handleSubmitEdits","success","setActive","handleCancelEdits","handleEnterEditMode","createElement","className","tableEditContainer","modificationCount","placeholder","editButtons","variant","onClick","disabled"],"sources":["TableEditContainer.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 { RowData } from \"@tanstack/react-table\";\nimport React, { type ReactElement, useCallback, useState } from \"react\";\nimport { ActionButton } from \"../base-components/action-button/ActionButton.js\";\nimport styles from \"./TableEditContainer.module.css\";\nimport type { EditableConfig } from \"./utils/types.js\";\n\ninterface TableEditContainerProps<\n TData extends RowData,\n> {\n editableConfig?: EditableConfig<TData, unknown>;\n focusedRowId?: string | null;\n}\n\nexport function TableEditContainer<\n TData extends RowData,\n>({\n editableConfig,\n focusedRowId,\n}: TableEditContainerProps<TData>): ReactElement {\n const {\n cellEdits,\n onSubmitEdits,\n clearEdits,\n editMode,\n } = editableConfig ?? {};\n\n const hasEdits = Object.keys(cellEdits ?? {}).length > 0;\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const isInEditMode = editMode?.isActive;\n const canToggleEditMode = editMode?.type === \"manual\";\n\n const handleSubmitEdits = useCallback(async () => {\n setIsSubmitting(true);\n try {\n const success = await onSubmitEdits?.();\n if (success) {\n clearEdits?.();\n if (editMode?.type === \"manual\") {\n editMode.setActive(false);\n }\n }\n } finally {\n setIsSubmitting(false);\n }\n }, [editMode, onSubmitEdits, clearEdits]);\n\n const handleCancelEdits = useCallback(() => {\n clearEdits?.();\n if (editMode?.type === \"manual\") {\n editMode.setActive(false);\n }\n }, [clearEdits, editMode]);\n\n const handleEnterEditMode = useCallback(() => {\n if (editMode?.type === \"manual\") {\n editMode.setActive(true);\n }\n }, [editMode]);\n\n return (\n <div className={styles.tableEditContainer}>\n {hasEdits\n ? (\n <div className={styles.modificationCount}>\n {`${cellEdits ? Object.keys(cellEdits).length : 0} modifications`}\n </div>\n )\n : (isInEditMode && !focusedRowId && (\n <div className={styles.placeholder}>\n Select a row to edit data…\n </div>\n ))}\n <div className={styles.editButtons}>\n {!isInEditMode && canToggleEditMode && (\n <ActionButton\n variant=\"primary\"\n onClick={handleEnterEditMode}\n >\n Edit Table\n </ActionButton>\n )}\n {isInEditMode && canToggleEditMode && (\n <ActionButton\n variant=\"secondary\"\n onClick={handleCancelEdits}\n >\n Cancel\n </ActionButton>\n )}\n {isInEditMode && !!onSubmitEdits && (\n <ActionButton\n variant=\"primary\"\n onClick={handleSubmitEdits}\n disabled={!hasEdits || isSubmitting}\n >\n Submit Edits\n </ActionButton>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2025 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
+ .tableEditContainer {
18
+ display: flex;
19
+ justify-content: space-between;
20
+ align-items: center;
21
+ background-color: var(--osdk-surface-background-color-default-rest);
22
+ border-top: var(--osdk-table-border);
23
+ padding: var(--osdk-table-edit-container-padding);
24
+ min-height: var(--osdk-table-edit-container-min-height);
25
+ }
26
+
27
+ .placeholder {
28
+ color: var(--osdk-typography-color-muted);
29
+ font-size: var(--osdk-typography-size-body-small);
30
+ padding: calc(var(--osdk-surface-spacing) * 2) 0;
31
+ }
32
+
33
+ .modificationCount {
34
+ color: var(--osdk-intent-primary-rest);
35
+ font-size: var(--osdk-typography-size-body-small);
36
+ padding: calc(var(--osdk-surface-spacing) * 2) 0;
37
+ }
38
+
39
+ .editButtons {
40
+ display: flex;
41
+ justify-content: flex-end;
42
+ gap: 8px;
43
+ flex: 1;
44
+ }
@@ -0,0 +1,9 @@
1
+ // CSS Module proxy for TableEditContainer.module.css
2
+ const styles = {
3
+ "tableEditContainer": "TableEditContainer-module__tableEditContainer___cIVjgtld",
4
+ "placeholder": "TableEditContainer-module__placeholder___ggxoxvTp",
5
+ "modificationCount": "TableEditContainer-module__modificationCount___sLN93v77",
6
+ "editButtons": "TableEditContainer-module__editButtons___xI-Z7kz1"
7
+ };
8
+
9
+ export default styles;
@@ -17,17 +17,24 @@
17
17
  import React, { useCallback } from "react";
18
18
  import { TableCell } from "./TableCell.js";
19
19
  import styles from "./TableRow.module.css.js";
20
- export function TableRow({
20
+ function TableRowInner({
21
21
  row,
22
22
  virtualRow,
23
23
  onRowClick,
24
- renderCellContextMenu
24
+ renderCellContextMenu,
25
+ focusedRowId,
26
+ setFocusedRowId,
27
+ isInEditMode
25
28
  }) {
26
29
  const handleClick = useCallback(() => {
27
- onRowClick?.(row.original);
28
- }, [onRowClick, row.original]);
30
+ setFocusedRowId?.(row.id);
31
+ if (!isInEditMode) {
32
+ onRowClick?.(row.original);
33
+ }
34
+ }, [isInEditMode, onRowClick, row.original, row.id, setFocusedRowId]);
29
35
  return /*#__PURE__*/React.createElement("tr", {
30
36
  "data-selected": row.getIsSelected(),
37
+ "data-focused": focusedRowId === row.id,
31
38
  className: styles.osdkTableRow,
32
39
  style: {
33
40
  height: `${virtualRow.size}px`,
@@ -40,4 +47,5 @@ export function TableRow({
40
47
  renderCellContextMenu: renderCellContextMenu
41
48
  })));
42
49
  }
50
+ export const TableRow = /*#__PURE__*/React.memo(TableRowInner);
43
51
  //# sourceMappingURL=TableRow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableRow.js","names":["React","useCallback","TableCell","styles","TableRow","row","virtualRow","onRowClick","renderCellContextMenu","handleClick","original","createElement","getIsSelected","className","osdkTableRow","style","height","size","transform","start","onClick","getVisibleCells","map","cell","key","id"],"sources":["TableRow.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 { Cell, Row, RowData } from \"@tanstack/react-table\";\nimport type { VirtualItem } from \"@tanstack/react-virtual\";\nimport React, { useCallback } from \"react\";\nimport { TableCell } from \"./TableCell.js\";\nimport styles from \"./TableRow.module.css\";\n\ninterface TableRowProps<TData extends RowData> {\n row: Row<TData>;\n virtualRow: VirtualItem;\n onRowClick?: (row: TData) => void;\n renderCellContextMenu?: (\n row: TData,\n cell: Cell<TData, unknown>,\n ) => React.ReactNode;\n}\n\nexport function TableRow<TData extends RowData>({\n row,\n virtualRow,\n onRowClick,\n renderCellContextMenu,\n}: TableRowProps<TData>): React.ReactElement {\n const handleClick = useCallback(() => {\n onRowClick?.(row.original);\n }, [onRowClick, row.original]);\n\n return (\n <tr\n data-selected={row.getIsSelected()}\n className={styles.osdkTableRow}\n style={{\n height: `${virtualRow.size}px`,\n transform: `translateY(${virtualRow.start}px)`,\n }}\n onClick={handleClick}\n >\n {row.getVisibleCells().map((cell) => (\n <TableCell\n key={cell.id}\n cell={cell}\n renderCellContextMenu={renderCellContextMenu}\n />\n ))}\n </tr>\n );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA,OAAOA,KAAK,IAAIC,WAAW,QAAQ,OAAO;AAC1C,SAASC,SAAS,QAAQ,gBAAgB;AAC1C,OAAOC,MAAM,MAAM,uBAAuB;AAY1C,OAAO,SAASC,QAAQA,CAAwB;EAC9CC,GAAG;EACHC,UAAU;EACVC,UAAU;EACVC;AACoB,CAAC,EAAsB;EAC3C,MAAMC,WAAW,GAAGR,WAAW,CAAC,MAAM;IACpCM,UAAU,GAAGF,GAAG,CAACK,QAAQ,CAAC;EAC5B,CAAC,EAAE,CAACH,UAAU,EAAEF,GAAG,CAACK,QAAQ,CAAC,CAAC;EAE9B,oBACEV,KAAA,CAAAW,aAAA;IACE,iBAAeN,GAAG,CAACO,aAAa,CAAC,CAAE;IACnCC,SAAS,EAAEV,MAAM,CAACW,YAAa;IAC/BC,KAAK,EAAE;MACLC,MAAM,EAAE,GAAGV,UAAU,CAACW,IAAI,IAAI;MAC9BC,SAAS,EAAE,cAAcZ,UAAU,CAACa,KAAK;IAC3C,CAAE;IACFC,OAAO,EAAEX;EAAY,GAEpBJ,GAAG,CAACgB,eAAe,CAAC,CAAC,CAACC,GAAG,CAAEC,IAAI,iBAC9BvB,KAAA,CAAAW,aAAA,CAACT,SAAS;IACRsB,GAAG,EAAED,IAAI,CAACE,EAAG;IACbF,IAAI,EAAEA,IAAK;IACXf,qBAAqB,EAAEA;EAAsB,CAC9C,CACF,CACC,CAAC;AAET","ignoreList":[]}
1
+ {"version":3,"file":"TableRow.js","names":["React","useCallback","TableCell","styles","TableRowInner","row","virtualRow","onRowClick","renderCellContextMenu","focusedRowId","setFocusedRowId","isInEditMode","handleClick","id","original","createElement","getIsSelected","className","osdkTableRow","style","height","size","transform","start","onClick","getVisibleCells","map","cell","key","TableRow","memo"],"sources":["TableRow.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 { Cell, Row, RowData } from \"@tanstack/react-table\";\nimport type { VirtualItem } from \"@tanstack/react-virtual\";\nimport React, { useCallback } from \"react\";\nimport { TableCell } from \"./TableCell.js\";\nimport styles from \"./TableRow.module.css\";\n\ninterface TableRowProps<TData extends RowData> {\n row: Row<TData>;\n virtualRow: VirtualItem;\n onRowClick?: (row: TData) => void;\n renderCellContextMenu?: (\n row: TData,\n cell: Cell<TData, unknown>,\n ) => React.ReactNode;\n focusedRowId?: string | null;\n setFocusedRowId?: (rowId: string | null) => void;\n isInEditMode?: boolean;\n}\n\nfunction TableRowInner<TData extends RowData>({\n row,\n virtualRow,\n onRowClick,\n renderCellContextMenu,\n focusedRowId,\n setFocusedRowId,\n isInEditMode,\n}: TableRowProps<TData>): React.ReactElement {\n const handleClick = useCallback(() => {\n setFocusedRowId?.(row.id);\n\n if (!isInEditMode) {\n onRowClick?.(row.original);\n }\n }, [isInEditMode, onRowClick, row.original, row.id, setFocusedRowId]);\n\n return (\n <tr\n data-selected={row.getIsSelected()}\n data-focused={focusedRowId === row.id}\n className={styles.osdkTableRow}\n style={{\n height: `${virtualRow.size}px`,\n transform: `translateY(${virtualRow.start}px)`,\n }}\n onClick={handleClick}\n >\n {row.getVisibleCells().map((cell) => (\n <TableCell\n key={cell.id}\n cell={cell}\n renderCellContextMenu={renderCellContextMenu}\n />\n ))}\n </tr>\n );\n}\n\nexport const TableRow = React.memo(\n TableRowInner,\n) as typeof TableRowInner;\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA,OAAOA,KAAK,IAAIC,WAAW,QAAQ,OAAO;AAC1C,SAASC,SAAS,QAAQ,gBAAgB;AAC1C,OAAOC,MAAM,MAAM,uBAAuB;AAe1C,SAASC,aAAaA,CAAwB;EAC5CC,GAAG;EACHC,UAAU;EACVC,UAAU;EACVC,qBAAqB;EACrBC,YAAY;EACZC,eAAe;EACfC;AACoB,CAAC,EAAsB;EAC3C,MAAMC,WAAW,GAAGX,WAAW,CAAC,MAAM;IACpCS,eAAe,GAAGL,GAAG,CAACQ,EAAE,CAAC;IAEzB,IAAI,CAACF,YAAY,EAAE;MACjBJ,UAAU,GAAGF,GAAG,CAACS,QAAQ,CAAC;IAC5B;EACF,CAAC,EAAE,CAACH,YAAY,EAAEJ,UAAU,EAAEF,GAAG,CAACS,QAAQ,EAAET,GAAG,CAACQ,EAAE,EAAEH,eAAe,CAAC,CAAC;EAErE,oBACEV,KAAA,CAAAe,aAAA;IACE,iBAAeV,GAAG,CAACW,aAAa,CAAC,CAAE;IACnC,gBAAcP,YAAY,KAAKJ,GAAG,CAACQ,EAAG;IACtCI,SAAS,EAAEd,MAAM,CAACe,YAAa;IAC/BC,KAAK,EAAE;MACLC,MAAM,EAAE,GAAGd,UAAU,CAACe,IAAI,IAAI;MAC9BC,SAAS,EAAE,cAAchB,UAAU,CAACiB,KAAK;IAC3C,CAAE;IACFC,OAAO,EAAEZ;EAAY,GAEpBP,GAAG,CAACoB,eAAe,CAAC,CAAC,CAACC,GAAG,CAAEC,IAAI,iBAC9B3B,KAAA,CAAAe,aAAA,CAACb,SAAS;IACR0B,GAAG,EAAED,IAAI,CAACd,EAAG;IACbc,IAAI,EAAEA,IAAK;IACXnB,qBAAqB,EAAEA;EAAsB,CAC9C,CACF,CACC,CAAC;AAET;AAEA,OAAO,MAAMqB,QAAQ,gBAAG7B,KAAK,CAAC8B,IAAI,CAChC1B,aACF,CAAyB","ignoreList":[]}
@@ -45,7 +45,8 @@
45
45
  border-bottom-color: var(--osdk-table-row-border-color-hover);
46
46
  }
47
47
 
48
- &[data-selected="true"] {
48
+ &[data-selected="true"],
49
+ &[data-focused="true"] {
49
50
  z-index: 2;
50
51
  background-color: var(--osdk-table-row-bg-active);
51
52
  border-top-color: var(--osdk-table-row-border-color-active);
@@ -0,0 +1,292 @@
1
+ /*
2
+ * Copyright 2025 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 { act, renderHook } from "@testing-library/react";
18
+ import { describe, expect, it, vi } from "vitest";
19
+ import { getCellId } from "../../utils/getCellId.js";
20
+ import { useEditableTable } from "../useEditableTable.js";
21
+ function createMockObjectInstance(id, additionalProps = {}) {
22
+ return {
23
+ $apiName: "mock-object",
24
+ $primaryKey: id,
25
+ id,
26
+ ...additionalProps
27
+ };
28
+ }
29
+ describe("useEditableTable", () => {
30
+ it("adds cell to cellEdits when edited", () => {
31
+ const onCellValueChanged = vi.fn();
32
+ const {
33
+ result
34
+ } = renderHook(() => useEditableTable({
35
+ editMode: "always",
36
+ onCellValueChanged
37
+ }));
38
+ const cellId = getCellId({
39
+ rowId: "row-1",
40
+ columnId: "col-1"
41
+ });
42
+ const mockRowData = createMockObjectInstance("row-1", {
43
+ name: "Test"
44
+ });
45
+ const editEvent = {
46
+ rowId: "row-1",
47
+ columnId: "col-1",
48
+ newValue: "new value",
49
+ oldValue: "old value",
50
+ originalRowData: mockRowData
51
+ };
52
+ act(() => {
53
+ result.current.onCellEdit(cellId, editEvent);
54
+ });
55
+ expect(result.current.cellEdits).toEqual({
56
+ [cellId]: editEvent
57
+ });
58
+ expect(onCellValueChanged).toHaveBeenCalledWith(editEvent);
59
+ });
60
+ it("removes cell from cellEdits when edited back to original value", () => {
61
+ const onCellValueChanged = vi.fn();
62
+ const {
63
+ result
64
+ } = renderHook(() => useEditableTable({
65
+ editMode: "always",
66
+ onCellValueChanged
67
+ }));
68
+ const cellId = getCellId({
69
+ rowId: "row-1",
70
+ columnId: "col-1"
71
+ });
72
+ const mockRowData = createMockObjectInstance("row-1", {
73
+ name: "Test"
74
+ });
75
+
76
+ // First edit
77
+ const firstEdit = {
78
+ rowId: "row-1",
79
+ columnId: "col-1",
80
+ newValue: "new value",
81
+ oldValue: "original",
82
+ originalRowData: mockRowData
83
+ };
84
+ act(() => {
85
+ result.current.onCellEdit(cellId, firstEdit);
86
+ });
87
+ expect(result.current.cellEdits).toEqual({
88
+ [cellId]: firstEdit
89
+ });
90
+
91
+ // Edit back to original
92
+ const revertEdit = {
93
+ rowId: "row-1",
94
+ columnId: "col-1",
95
+ newValue: "original",
96
+ oldValue: "original",
97
+ originalRowData: mockRowData
98
+ };
99
+ act(() => {
100
+ result.current.onCellEdit(cellId, revertEdit);
101
+ });
102
+
103
+ // Should remove the cell from cellEdits
104
+ expect(result.current.cellEdits).toEqual({});
105
+ });
106
+ it("handles multiple cell edits", () => {
107
+ const {
108
+ result
109
+ } = renderHook(() => useEditableTable({
110
+ editMode: "always"
111
+ }));
112
+ const cellId1 = getCellId({
113
+ rowId: "row-1",
114
+ columnId: "col-1"
115
+ });
116
+ const cellId2 = getCellId({
117
+ rowId: "row-2",
118
+ columnId: "col-2"
119
+ });
120
+ const cellId3 = getCellId({
121
+ rowId: "row-3",
122
+ columnId: "col-3"
123
+ });
124
+ const edit1 = {
125
+ rowId: "row-1",
126
+ columnId: "col-1",
127
+ newValue: "new1",
128
+ oldValue: "old1",
129
+ originalRowData: createMockObjectInstance("row-1")
130
+ };
131
+ const edit2 = {
132
+ rowId: "row-2",
133
+ columnId: "col-2",
134
+ newValue: "new2",
135
+ oldValue: "old2",
136
+ originalRowData: createMockObjectInstance("row-2")
137
+ };
138
+ const edit3 = {
139
+ rowId: "row-3",
140
+ columnId: "col-3",
141
+ newValue: "new3",
142
+ oldValue: "old3",
143
+ originalRowData: createMockObjectInstance("row-3")
144
+ };
145
+ act(() => {
146
+ result.current.onCellEdit(cellId1, edit1);
147
+ result.current.onCellEdit(cellId2, edit2);
148
+ result.current.onCellEdit(cellId3, edit3);
149
+ });
150
+ expect(Object.keys(result.current.cellEdits).length).toBe(3);
151
+
152
+ // Edit one back to original
153
+ const revertEdit2 = {
154
+ rowId: "row-2",
155
+ columnId: "col-2",
156
+ newValue: "old2",
157
+ oldValue: "old2",
158
+ originalRowData: createMockObjectInstance("row-2")
159
+ };
160
+ act(() => {
161
+ result.current.onCellEdit(cellId2, revertEdit2);
162
+ });
163
+ expect(Object.keys(result.current.cellEdits).length).toBe(2);
164
+ expect(result.current.cellEdits[cellId2]).toBeUndefined();
165
+ });
166
+ it("clears all edits", () => {
167
+ const {
168
+ result
169
+ } = renderHook(() => useEditableTable({
170
+ editMode: "always"
171
+ }));
172
+ const cellId1 = getCellId({
173
+ rowId: "row-1",
174
+ columnId: "col-1"
175
+ });
176
+ const cellId2 = getCellId({
177
+ rowId: "row-2",
178
+ columnId: "col-2"
179
+ });
180
+ const edit1 = {
181
+ rowId: "row-1",
182
+ columnId: "col-1",
183
+ newValue: "new1",
184
+ oldValue: "old1",
185
+ originalRowData: createMockObjectInstance("row-1")
186
+ };
187
+ const edit2 = {
188
+ rowId: "row-2",
189
+ columnId: "col-2",
190
+ newValue: "new2",
191
+ oldValue: "old2",
192
+ originalRowData: createMockObjectInstance("row-2")
193
+ };
194
+ act(() => {
195
+ result.current.onCellEdit(cellId1, edit1);
196
+ result.current.onCellEdit(cellId2, edit2);
197
+ });
198
+ act(() => {
199
+ result.current.clearEdits();
200
+ });
201
+ expect(result.current.cellEdits).toEqual({});
202
+ });
203
+ it("handles submit edits", async () => {
204
+ const onSubmitEdits = vi.fn();
205
+ const {
206
+ result
207
+ } = renderHook(() => useEditableTable({
208
+ editMode: "always",
209
+ onSubmitEdits
210
+ }));
211
+ const cellId1 = getCellId({
212
+ rowId: "row-1",
213
+ columnId: "col-1"
214
+ });
215
+ const cellId2 = getCellId({
216
+ rowId: "row-2",
217
+ columnId: "col-2"
218
+ });
219
+ const edit1 = {
220
+ rowId: "row-1",
221
+ columnId: "col-1",
222
+ newValue: "new1",
223
+ oldValue: "old1",
224
+ originalRowData: createMockObjectInstance("row-1")
225
+ };
226
+ const edit2 = {
227
+ rowId: "row-2",
228
+ columnId: "col-2",
229
+ newValue: "new2",
230
+ oldValue: "old2",
231
+ originalRowData: createMockObjectInstance("row-2")
232
+ };
233
+ act(() => {
234
+ result.current.onCellEdit(cellId1, edit1);
235
+ result.current.onCellEdit(cellId2, edit2);
236
+ });
237
+ await act(async () => {
238
+ await result.current.onSubmitEdits?.();
239
+ });
240
+ expect(onSubmitEdits).toHaveBeenCalledWith([edit1, edit2]);
241
+ });
242
+ it("when submit edits is undefined, onSubmitEdits is undefined", async () => {
243
+ const {
244
+ result
245
+ } = renderHook(() => useEditableTable({
246
+ editMode: "always",
247
+ onSubmitEdits: undefined
248
+ }));
249
+ expect(result.current.onSubmitEdits).toBeUndefined();
250
+ });
251
+ it("when editMode is manual, isActive is false initially", () => {
252
+ const {
253
+ result
254
+ } = renderHook(() => useEditableTable({
255
+ editMode: "manual"
256
+ }));
257
+ expect(result.current.editMode.type).toBe("manual");
258
+ if (result.current.editMode.type === "manual") {
259
+ expect(result.current.editMode.isActive).toBe(false);
260
+ expect(result.current.editMode.setActive).toBeDefined();
261
+ act(() => {
262
+ result.current.editMode.type === "manual" && result.current.editMode.setActive(true);
263
+ });
264
+ expect(result.current.editMode.type === "manual" && result.current.editMode.isActive).toBe(true);
265
+ act(() => {
266
+ result.current.editMode.type === "manual" && result.current.editMode.setActive(false);
267
+ });
268
+ expect(result.current.editMode.type === "manual" && result.current.editMode.isActive).toBe(false);
269
+ }
270
+ });
271
+ it("when editMode is always, the type is always and isActive is true", () => {
272
+ const {
273
+ result
274
+ } = renderHook(() => useEditableTable({
275
+ editMode: "always"
276
+ }));
277
+ expect(result.current.editMode.type).toBe("always");
278
+ expect(result.current.editMode.isActive).toBe(true);
279
+ });
280
+ it("when editMode is manual with default settings, it starts as inactive", () => {
281
+ const {
282
+ result
283
+ } = renderHook(() => useEditableTable({
284
+ editMode: "manual"
285
+ }));
286
+ expect(result.current.editMode.type).toBe("manual");
287
+ if (result.current.editMode.type === "manual") {
288
+ expect(result.current.editMode.isActive).toBe(false);
289
+ }
290
+ });
291
+ });
292
+ //# sourceMappingURL=useEditableTable.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEditableTable.test.js","names":["act","renderHook","describe","expect","it","vi","getCellId","useEditableTable","createMockObjectInstance","id","additionalProps","$apiName","$primaryKey","onCellValueChanged","fn","result","editMode","cellId","rowId","columnId","mockRowData","name","editEvent","newValue","oldValue","originalRowData","current","onCellEdit","cellEdits","toEqual","toHaveBeenCalledWith","firstEdit","revertEdit","cellId1","cellId2","cellId3","edit1","edit2","edit3","Object","keys","length","toBe","revertEdit2","toBeUndefined","clearEdits","onSubmitEdits","undefined","type","isActive","setActive","toBeDefined"],"sources":["useEditableTable.test.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 { ObjectOrInterfaceDefinition, Osdk } from \"@osdk/api\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { getCellId } from \"../../utils/getCellId.js\";\nimport { useEditableTable } from \"../useEditableTable.js\";\n\ntype MockObjectDef = ObjectOrInterfaceDefinition;\ntype MockInstance = Osdk.Instance<MockObjectDef, \"$allBaseProperties\", string>;\n\nfunction createMockObjectInstance(\n id: string,\n additionalProps = {},\n): MockInstance {\n return {\n $apiName: \"mock-object\" as const,\n $primaryKey: id,\n id,\n ...additionalProps,\n } as unknown as MockInstance;\n}\n\ndescribe(\"useEditableTable\", () => {\n it(\"adds cell to cellEdits when edited\", () => {\n const onCellValueChanged = vi.fn();\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\", onCellValueChanged })\n );\n const cellIdentifier = { rowId: \"row-1\", columnId: \"col-1\" };\n const cellId = getCellId(cellIdentifier);\n const mockRowData = createMockObjectInstance(\"row-1\", { name: \"Test\" });\n\n const editEvent = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"new value\",\n oldValue: \"old value\",\n originalRowData: mockRowData,\n };\n\n act(() => {\n result.current.onCellEdit(cellId, editEvent);\n });\n\n expect(result.current.cellEdits).toEqual({\n [cellId]: editEvent,\n });\n expect(onCellValueChanged).toHaveBeenCalledWith(editEvent);\n });\n\n it(\"removes cell from cellEdits when edited back to original value\", () => {\n const onCellValueChanged = vi.fn();\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\", onCellValueChanged })\n );\n const cellIdentifier = { rowId: \"row-1\", columnId: \"col-1\" };\n const cellId = getCellId(cellIdentifier);\n const mockRowData = createMockObjectInstance(\"row-1\", { name: \"Test\" });\n\n // First edit\n const firstEdit = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"new value\",\n oldValue: \"original\",\n originalRowData: mockRowData,\n };\n\n act(() => {\n result.current.onCellEdit(cellId, firstEdit);\n });\n\n expect(result.current.cellEdits).toEqual({\n [cellId]: firstEdit,\n });\n\n // Edit back to original\n const revertEdit = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"original\",\n oldValue: \"original\",\n originalRowData: mockRowData,\n };\n\n act(() => {\n result.current.onCellEdit(cellId, revertEdit);\n });\n\n // Should remove the cell from cellEdits\n expect(result.current.cellEdits).toEqual({});\n });\n\n it(\"handles multiple cell edits\", () => {\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\" })\n );\n const cellId1 = getCellId({ rowId: \"row-1\", columnId: \"col-1\" });\n const cellId2 = getCellId({ rowId: \"row-2\", columnId: \"col-2\" });\n const cellId3 = getCellId({ rowId: \"row-3\", columnId: \"col-3\" });\n\n const edit1 = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"new1\",\n oldValue: \"old1\",\n originalRowData: createMockObjectInstance(\"row-1\"),\n };\n\n const edit2 = {\n rowId: \"row-2\",\n columnId: \"col-2\",\n newValue: \"new2\",\n oldValue: \"old2\",\n originalRowData: createMockObjectInstance(\"row-2\"),\n };\n\n const edit3 = {\n rowId: \"row-3\",\n columnId: \"col-3\",\n newValue: \"new3\",\n oldValue: \"old3\",\n originalRowData: createMockObjectInstance(\"row-3\"),\n };\n\n act(() => {\n result.current.onCellEdit(cellId1, edit1);\n result.current.onCellEdit(cellId2, edit2);\n result.current.onCellEdit(cellId3, edit3);\n });\n\n expect(Object.keys(result.current.cellEdits).length).toBe(3);\n\n // Edit one back to original\n const revertEdit2 = {\n rowId: \"row-2\",\n columnId: \"col-2\",\n newValue: \"old2\",\n oldValue: \"old2\",\n originalRowData: createMockObjectInstance(\"row-2\"),\n };\n\n act(() => {\n result.current.onCellEdit(cellId2, revertEdit2);\n });\n\n expect(Object.keys(result.current.cellEdits).length).toBe(2);\n expect(result.current.cellEdits[cellId2]).toBeUndefined();\n });\n\n it(\"clears all edits\", () => {\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\" })\n );\n const cellId1 = getCellId({ rowId: \"row-1\", columnId: \"col-1\" });\n const cellId2 = getCellId({ rowId: \"row-2\", columnId: \"col-2\" });\n\n const edit1 = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"new1\",\n oldValue: \"old1\",\n originalRowData: createMockObjectInstance(\"row-1\"),\n };\n\n const edit2 = {\n rowId: \"row-2\",\n columnId: \"col-2\",\n newValue: \"new2\",\n oldValue: \"old2\",\n originalRowData: createMockObjectInstance(\"row-2\"),\n };\n\n act(() => {\n result.current.onCellEdit(cellId1, edit1);\n result.current.onCellEdit(cellId2, edit2);\n });\n\n act(() => {\n result.current.clearEdits();\n });\n\n expect(result.current.cellEdits).toEqual({});\n });\n\n it(\"handles submit edits\", async () => {\n const onSubmitEdits = vi.fn();\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\", onSubmitEdits })\n );\n const cellId1 = getCellId({ rowId: \"row-1\", columnId: \"col-1\" });\n const cellId2 = getCellId({ rowId: \"row-2\", columnId: \"col-2\" });\n\n const edit1 = {\n rowId: \"row-1\",\n columnId: \"col-1\",\n newValue: \"new1\",\n oldValue: \"old1\",\n originalRowData: createMockObjectInstance(\"row-1\"),\n };\n\n const edit2 = {\n rowId: \"row-2\",\n columnId: \"col-2\",\n newValue: \"new2\",\n oldValue: \"old2\",\n originalRowData: createMockObjectInstance(\"row-2\"),\n };\n\n act(() => {\n result.current.onCellEdit(cellId1, edit1);\n result.current.onCellEdit(cellId2, edit2);\n });\n\n await act(async () => {\n await result.current.onSubmitEdits?.();\n });\n\n expect(onSubmitEdits).toHaveBeenCalledWith([edit1, edit2]);\n });\n\n it(\"when submit edits is undefined, onSubmitEdits is undefined\", async () => {\n const { result } = renderHook(() =>\n useEditableTable({\n editMode: \"always\",\n onSubmitEdits: undefined,\n })\n );\n\n expect(result.current.onSubmitEdits).toBeUndefined();\n });\n\n it(\"when editMode is manual, isActive is false initially\", () => {\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"manual\" })\n );\n\n expect(result.current.editMode.type).toBe(\"manual\");\n if (result.current.editMode.type === \"manual\") {\n expect(result.current.editMode.isActive).toBe(false);\n expect(result.current.editMode.setActive).toBeDefined();\n\n act(() => {\n result.current.editMode.type === \"manual\"\n && result.current.editMode.setActive(true);\n });\n\n expect(\n result.current.editMode.type === \"manual\"\n && result.current.editMode.isActive,\n ).toBe(true);\n\n act(() => {\n result.current.editMode.type === \"manual\"\n && result.current.editMode.setActive(false);\n });\n\n expect(\n result.current.editMode.type === \"manual\"\n && result.current.editMode.isActive,\n ).toBe(false);\n }\n });\n\n it(\"when editMode is always, the type is always and isActive is true\", () => {\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"always\" })\n );\n\n expect(result.current.editMode.type).toBe(\"always\");\n expect(result.current.editMode.isActive).toBe(true);\n });\n\n it(\"when editMode is manual with default settings, it starts as inactive\", () => {\n const { result } = renderHook(() =>\n useEditableTable({ editMode: \"manual\" })\n );\n\n expect(result.current.editMode.type).toBe(\"manual\");\n if (result.current.editMode.type === \"manual\") {\n expect(result.current.editMode.isActive).toBe(false);\n }\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -15,17 +15,16 @@
15
15
  */
16
16
 
17
17
  import { useCallback, useState } from "react";
18
- import { getCellIdentifier } from "../utils/getCellId.js";
19
18
  export function useEditableTable({
19
+ editMode = "manual",
20
20
  onCellValueChanged,
21
21
  onSubmitEdits
22
22
  }) {
23
+ const [isActive, setActive] = useState(editMode === "always");
23
24
  const [cellEdits, setCellEdits] = useState({});
24
- const handleCellEdit = useCallback((cellId, state) => {
25
- const cellIdentifier = getCellIdentifier(cellId);
26
-
25
+ const handleCellEdit = useCallback((cellId, info) => {
27
26
  // If value is changed back to original, remove it from edits
28
- if (state.newValue === state.oldValue) {
27
+ if (info.newValue === info.oldValue) {
29
28
  setCellEdits(prev => {
30
29
  const {
31
30
  [cellId]: _,
@@ -36,22 +35,32 @@ export function useEditableTable({
36
35
  } else {
37
36
  setCellEdits(prev => ({
38
37
  ...prev,
39
- [cellId]: state
38
+ [cellId]: info
40
39
  }));
41
40
  }
42
- onCellValueChanged?.(cellIdentifier, state);
41
+ onCellValueChanged?.(info);
43
42
  }, [onCellValueChanged]);
44
43
  const clearEdits = useCallback(() => {
45
44
  setCellEdits({});
46
45
  }, []);
47
46
  const handleSubmitEdits = useCallback(async () => {
48
- await onSubmitEdits?.(cellEdits);
47
+ const edits = Object.values(cellEdits);
48
+ return onSubmitEdits ? onSubmitEdits(edits) : false;
49
49
  }, [cellEdits, onSubmitEdits]);
50
+ const editModeConfig = editMode === "always" ? {
51
+ type: "always",
52
+ isActive: true
53
+ } : {
54
+ type: "manual",
55
+ isActive,
56
+ setActive
57
+ };
50
58
  return {
51
59
  cellEdits,
52
- handleCellEdit,
53
- handleSubmitEdits,
54
- clearEdits
60
+ onCellEdit: handleCellEdit,
61
+ onSubmitEdits: onSubmitEdits ? handleSubmitEdits : undefined,
62
+ clearEdits,
63
+ editMode: editModeConfig
55
64
  };
56
65
  }
57
66
  //# sourceMappingURL=useEditableTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEditableTable.js","names":["useCallback","useState","getCellIdentifier","useEditableTable","onCellValueChanged","onSubmitEdits","cellEdits","setCellEdits","handleCellEdit","cellId","state","cellIdentifier","newValue","oldValue","prev","_","rest","clearEdits","handleSubmitEdits"],"sources":["useEditableTable.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 ObjectOrInterfaceDefinition,\n QueryDefinition,\n SimplePropertyDef,\n} from \"@osdk/api\";\nimport { useCallback, useState } from \"react\";\nimport type { ObjectTableProps } from \"../ObjectTableApi.js\";\nimport { getCellIdentifier } from \"../utils/getCellId.js\";\nimport type { CellValueState } from \"../utils/types.js\";\n\nexport interface UseEditableTableProps<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = Record<\n string,\n never\n >,\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n onCellValueChanged?: ObjectTableProps<\n Q,\n RDPs,\n FunctionColumns\n >[\"onCellValueChanged\"];\n\n onSubmitEdits?: ObjectTableProps<\n Q,\n RDPs,\n FunctionColumns\n >[\"onSubmitEdits\"];\n}\n\nexport interface UseEditableTableResult {\n cellEdits: Record<string, CellValueState>;\n handleCellEdit: (\n cellId: string,\n state: CellValueState,\n ) => void;\n handleSubmitEdits: () => Promise<void>;\n clearEdits: () => void;\n}\n\nexport function useEditableTable<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = Record<\n string,\n never\n >,\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>({\n onCellValueChanged,\n onSubmitEdits,\n}: UseEditableTableProps<Q, RDPs, FunctionColumns>): UseEditableTableResult {\n const [cellEdits, setCellEdits] = useState<Record<string, CellValueState>>(\n {},\n );\n\n const handleCellEdit = useCallback(\n (cellId: string, state: CellValueState) => {\n const cellIdentifier = getCellIdentifier(cellId);\n\n // If value is changed back to original, remove it from edits\n if (state.newValue === state.oldValue) {\n setCellEdits(prev => {\n const { [cellId]: _, ...rest } = prev;\n return rest;\n });\n } else {\n setCellEdits(prev => ({\n ...prev,\n [cellId]: state,\n }));\n }\n\n onCellValueChanged?.(cellIdentifier, state);\n },\n [onCellValueChanged],\n );\n\n const clearEdits = useCallback(() => {\n setCellEdits({});\n }, []);\n\n const handleSubmitEdits = useCallback(async () => {\n await onSubmitEdits?.(cellEdits);\n }, [cellEdits, onSubmitEdits]);\n\n return {\n cellEdits,\n handleCellEdit,\n handleSubmitEdits,\n clearEdits,\n };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA,SAASA,WAAW,EAAEC,QAAQ,QAAQ,OAAO;AAE7C,SAASC,iBAAiB,QAAQ,uBAAuB;AAqCzD,OAAO,SAASC,gBAAgBA,CAU9B;EACAC,kBAAkB;EAClBC;AAC+C,CAAC,EAA0B;EAC1E,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAGN,QAAQ,CACxC,CAAC,CACH,CAAC;EAED,MAAMO,cAAc,GAAGR,WAAW,CAChC,CAACS,MAAc,EAAEC,KAAqB,KAAK;IACzC,MAAMC,cAAc,GAAGT,iBAAiB,CAACO,MAAM,CAAC;;IAEhD;IACA,IAAIC,KAAK,CAACE,QAAQ,KAAKF,KAAK,CAACG,QAAQ,EAAE;MACrCN,YAAY,CAACO,IAAI,IAAI;QACnB,MAAM;UAAE,CAACL,MAAM,GAAGM,CAAC;UAAE,GAAGC;QAAK,CAAC,GAAGF,IAAI;QACrC,OAAOE,IAAI;MACb,CAAC,CAAC;IACJ,CAAC,MAAM;MACLT,YAAY,CAACO,IAAI,KAAK;QACpB,GAAGA,IAAI;QACP,CAACL,MAAM,GAAGC;MACZ,CAAC,CAAC,CAAC;IACL;IAEAN,kBAAkB,GAAGO,cAAc,EAAED,KAAK,CAAC;EAC7C,CAAC,EACD,CAACN,kBAAkB,CACrB,CAAC;EAED,MAAMa,UAAU,GAAGjB,WAAW,CAAC,MAAM;IACnCO,YAAY,CAAC,CAAC,CAAC,CAAC;EAClB,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMW,iBAAiB,GAAGlB,WAAW,CAAC,YAAY;IAChD,MAAMK,aAAa,GAAGC,SAAS,CAAC;EAClC,CAAC,EAAE,CAACA,SAAS,EAAED,aAAa,CAAC,CAAC;EAE9B,OAAO;IACLC,SAAS;IACTE,cAAc;IACdU,iBAAiB;IACjBD;EACF,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"file":"useEditableTable.js","names":["useCallback","useState","useEditableTable","editMode","onCellValueChanged","onSubmitEdits","isActive","setActive","cellEdits","setCellEdits","handleCellEdit","cellId","info","newValue","oldValue","prev","_","rest","clearEdits","handleSubmitEdits","edits","Object","values","editModeConfig","type","onCellEdit","undefined"],"sources":["useEditableTable.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 ObjectOrInterfaceDefinition,\n Osdk,\n PropertyKeys,\n QueryDefinition,\n SimplePropertyDef,\n} from \"@osdk/api\";\nimport { useCallback, useState } from \"react\";\nimport type { ObjectTableProps } from \"../ObjectTableApi.js\";\nimport type { CellEditInfo, EditableConfig, EditMode } from \"../utils/types.js\";\n\nexport interface UseEditableTableProps<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = Record<\n string,\n never\n >,\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n> {\n editMode?: \"always\" | \"manual\";\n\n onCellValueChanged?: ObjectTableProps<\n Q,\n RDPs,\n FunctionColumns\n >[\"onCellValueChanged\"];\n\n onSubmitEdits?: ObjectTableProps<\n Q,\n RDPs,\n FunctionColumns\n >[\"onSubmitEdits\"];\n}\n\nexport function useEditableTable<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = Record<\n string,\n never\n >,\n FunctionColumns extends Record<string, QueryDefinition<{}>> = Record<\n string,\n never\n >,\n>({\n editMode = \"manual\",\n onCellValueChanged,\n onSubmitEdits,\n}: UseEditableTableProps<Q, RDPs, FunctionColumns>): EditableConfig<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n> {\n const [isActive, setActive] = useState(editMode === \"always\");\n const [cellEdits, setCellEdits] = useState<\n Record<\n string,\n CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >\n >\n >(\n {},\n );\n\n const handleCellEdit = useCallback(\n (\n cellId: string,\n info: CellEditInfo<\n Osdk.Instance<Q, \"$allBaseProperties\", PropertyKeys<Q>, RDPs>,\n unknown\n >,\n ) => {\n // If value is changed back to original, remove it from edits\n if (info.newValue === info.oldValue) {\n setCellEdits(prev => {\n const { [cellId]: _, ...rest } = prev;\n return rest;\n });\n } else {\n setCellEdits(prev => ({\n ...prev,\n [cellId]: info,\n }));\n }\n\n onCellValueChanged?.(info);\n },\n [onCellValueChanged],\n );\n\n const clearEdits = useCallback(() => {\n setCellEdits({});\n }, []);\n\n const handleSubmitEdits = useCallback(async () => {\n const edits = Object.values(cellEdits);\n return onSubmitEdits ? onSubmitEdits(edits) : false;\n }, [cellEdits, onSubmitEdits]);\n\n const editModeConfig: EditMode = editMode === \"always\"\n ? { type: \"always\", isActive: true }\n : { type: \"manual\", isActive, setActive };\n\n return {\n cellEdits,\n onCellEdit: handleCellEdit,\n onSubmitEdits: onSubmitEdits ? handleSubmitEdits : undefined,\n clearEdits,\n editMode: editModeConfig,\n };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA,SAASA,WAAW,EAAEC,QAAQ,QAAQ,OAAO;AA8B7C,OAAO,SAASC,gBAAgBA,CAU9B;EACAC,QAAQ,GAAG,QAAQ;EACnBC,kBAAkB;EAClBC;AAC+C,CAAC,EAGhD;EACA,MAAM,CAACC,QAAQ,EAAEC,SAAS,CAAC,GAAGN,QAAQ,CAACE,QAAQ,KAAK,QAAQ,CAAC;EAC7D,MAAM,CAACK,SAAS,EAAEC,YAAY,CAAC,GAAGR,QAAQ,CASxC,CAAC,CACH,CAAC;EAED,MAAMS,cAAc,GAAGV,WAAW,CAChC,CACEW,MAAc,EACdC,IAGC,KACE;IACH;IACA,IAAIA,IAAI,CAACC,QAAQ,KAAKD,IAAI,CAACE,QAAQ,EAAE;MACnCL,YAAY,CAACM,IAAI,IAAI;QACnB,MAAM;UAAE,CAACJ,MAAM,GAAGK,CAAC;UAAE,GAAGC;QAAK,CAAC,GAAGF,IAAI;QACrC,OAAOE,IAAI;MACb,CAAC,CAAC;IACJ,CAAC,MAAM;MACLR,YAAY,CAACM,IAAI,KAAK;QACpB,GAAGA,IAAI;QACP,CAACJ,MAAM,GAAGC;MACZ,CAAC,CAAC,CAAC;IACL;IAEAR,kBAAkB,GAAGQ,IAAI,CAAC;EAC5B,CAAC,EACD,CAACR,kBAAkB,CACrB,CAAC;EAED,MAAMc,UAAU,GAAGlB,WAAW,CAAC,MAAM;IACnCS,YAAY,CAAC,CAAC,CAAC,CAAC;EAClB,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMU,iBAAiB,GAAGnB,WAAW,CAAC,YAAY;IAChD,MAAMoB,KAAK,GAAGC,MAAM,CAACC,MAAM,CAACd,SAAS,CAAC;IACtC,OAAOH,aAAa,GAAGA,aAAa,CAACe,KAAK,CAAC,GAAG,KAAK;EACrD,CAAC,EAAE,CAACZ,SAAS,EAAEH,aAAa,CAAC,CAAC;EAE9B,MAAMkB,cAAwB,GAAGpB,QAAQ,KAAK,QAAQ,GAClD;IAAEqB,IAAI,EAAE,QAAQ;IAAElB,QAAQ,EAAE;EAAK,CAAC,GAClC;IAAEkB,IAAI,EAAE,QAAQ;IAAElB,QAAQ;IAAEC;EAAU,CAAC;EAE3C,OAAO;IACLC,SAAS;IACTiB,UAAU,EAAEf,cAAc;IAC1BL,aAAa,EAAEA,aAAa,GAAGc,iBAAiB,GAAGO,SAAS;IAC5DR,UAAU;IACVf,QAAQ,EAAEoB;EACZ,CAAC;AACH","ignoreList":[]}