blixify-ui-web 1.2.180 → 1.2.182

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 (54) hide show
  1. package/lib/components/data/dataTemplate/activityChanges.d.ts.map +1 -1
  2. package/lib/components/data/dataTemplate/activityChanges.js +1 -0
  3. package/lib/components/data/dataTemplate/activityChanges.js.map +1 -1
  4. package/lib/components/data/dataTemplate/index.d.ts +1 -0
  5. package/lib/components/data/dataTemplate/index.d.ts.map +1 -1
  6. package/lib/components/data/dataTemplate/index.js +502 -246
  7. package/lib/components/data/dataTemplate/index.js.map +1 -1
  8. package/lib/components/data/dataTemplate/model.d.ts +11 -2
  9. package/lib/components/data/dataTemplate/model.d.ts.map +1 -1
  10. package/lib/components/data/flexFilter/index.d.ts.map +1 -1
  11. package/lib/components/data/flexFilter/index.js +41 -14
  12. package/lib/components/data/flexFilter/index.js.map +1 -1
  13. package/lib/components/data/formula/builder.d.ts +19 -0
  14. package/lib/components/data/formula/builder.d.ts.map +1 -0
  15. package/lib/components/data/formula/builder.js +189 -0
  16. package/lib/components/data/formula/builder.js.map +1 -0
  17. package/lib/components/data/formula/functions.d.ts +22 -0
  18. package/lib/components/data/formula/functions.d.ts.map +1 -0
  19. package/lib/components/data/formula/functions.js +773 -0
  20. package/lib/components/data/formula/functions.js.map +1 -0
  21. package/lib/components/data/formula/index.d.ts +75 -0
  22. package/lib/components/data/formula/index.d.ts.map +1 -0
  23. package/lib/components/data/formula/index.js +801 -0
  24. package/lib/components/data/formula/index.js.map +1 -0
  25. package/lib/components/data/listModule.d.ts.map +1 -1
  26. package/lib/components/data/listModule.js +7 -1
  27. package/lib/components/data/listModule.js.map +1 -1
  28. package/lib/components/data/readModule.d.ts.map +1 -1
  29. package/lib/components/data/readModule.js +25 -2
  30. package/lib/components/data/readModule.js.map +1 -1
  31. package/lib/components/data/utils.d.ts.map +1 -1
  32. package/lib/components/data/utils.js +4 -0
  33. package/lib/components/data/utils.js.map +1 -1
  34. package/lib/components/display/newTable/index.d.ts +1 -0
  35. package/lib/components/display/newTable/index.d.ts.map +1 -1
  36. package/lib/components/display/newTable/index.js +129 -42
  37. package/lib/components/display/newTable/index.js.map +1 -1
  38. package/lib/components/input/markdown/index.d.ts.map +1 -1
  39. package/lib/components/input/markdown/index.js +65 -40
  40. package/lib/components/input/markdown/index.js.map +1 -1
  41. package/lib/components/input/markdown/tableControls.d.ts +24 -0
  42. package/lib/components/input/markdown/tableControls.d.ts.map +1 -0
  43. package/lib/components/input/markdown/tableControls.js +471 -0
  44. package/lib/components/input/markdown/tableControls.js.map +1 -0
  45. package/lib/components/input/markdown/tableMarkdown.d.ts +34 -0
  46. package/lib/components/input/markdown/tableMarkdown.d.ts.map +1 -0
  47. package/lib/components/input/markdown/tableMarkdown.js +182 -0
  48. package/lib/components/input/markdown/tableMarkdown.js.map +1 -0
  49. package/lib/components/input/markdown/textColor.d.ts +40 -0
  50. package/lib/components/input/markdown/textColor.d.ts.map +1 -0
  51. package/lib/components/input/markdown/textColor.js +285 -0
  52. package/lib/components/input/markdown/textColor.js.map +1 -0
  53. package/lib/tail.css +2 -2
  54. package/package.json +1 -1
@@ -94,6 +94,8 @@ var iconButton_1 = require("../../action/iconButton");
94
94
  var textButton_1 = require("../../action/textButton");
95
95
  var collapse_1 = require("../../advanced/collapse");
96
96
  var popUp_1 = require("../../advanced/popUp");
97
+ var formula_1 = require("../../data/formula");
98
+ var builder_1 = require("../../data/formula/builder");
97
99
  var readModule_1 = require("../../data/readModule");
98
100
  var updateModule_1 = require("../../data/updateModule");
99
101
  var utils_1 = require("../../data/utils");
@@ -177,6 +179,8 @@ var ADD_COLUMN_TYPES = [
177
179
  { key: "textArea", label: "Long text" },
178
180
  { key: "markdown", label: "Markdown" },
179
181
  { key: "number", label: "Number" },
182
+ // INFO: a monday-style formula, built in the formula builder
183
+ { key: "formula", label: "Formula" },
180
184
  { key: "boolean", label: "Yes / No" },
181
185
  { key: "date", label: "Date" },
182
186
  { key: "list", label: "Single select" },
@@ -320,6 +324,9 @@ var NewTable = function (props) {
320
324
  // INFO: compute sticky left/right offsets for pinned columns.
321
325
  var DEFAULT_PIN_WIDTH = 150;
322
326
  var CHECKBOX_WIDTH = 66;
327
+ // INFO: room for the add row's confirm and cancel buttons plus cell padding.
328
+ // Only enforced when right-pinned columns need to know where to start.
329
+ var ACTION_COLUMN_WIDTH = 136;
323
330
  // INFO: keys that belong to grouped columns — these cannot be pinned.
324
331
  var groupedKeys = new Set();
325
332
  columns.forEach(function (col) {
@@ -362,19 +369,22 @@ var NewTable = function (props) {
362
369
  var _10 = (0, react_2.useState)(""), newColumnOptions = _10[0], setNewColumnOptions = _10[1];
363
370
  var _11 = (0, react_2.useState)(false), newColumnRequired = _11[0], setNewColumnRequired = _11[1];
364
371
  var _12 = (0, react_2.useState)(false), addingColumn = _12[0], setAddingColumn = _12[1];
372
+ // INFO: the formula as shown in the builder — column names, not ids
373
+ var _13 = (0, react_2.useState)(""), newColumnFormula = _13[0], setNewColumnFormula = _13[1];
374
+ var addColumnPopUpRef = (0, react_2.useRef)(null);
365
375
  // INFO: the column being changed — empty while the panel adds a new one
366
- var _13 = (0, react_2.useState)(null), editingColumn = _13[0], setEditingColumn = _13[1];
376
+ var _14 = (0, react_2.useState)(null), editingColumn = _14[0], setEditingColumn = _14[1];
367
377
  //=====================================================================================
368
378
  // SECTION: Editable & Addable cells
369
379
  //=====================================================================================
370
- var _14 = (0, react_2.useState)(""), editDataRowId = _14[0], setEditDataRowId = _14[1];
371
- var _15 = (0, react_2.useState)(""), editDataHeaderKey = _15[0], setEditDataHeaderKey = _15[1];
380
+ var _15 = (0, react_2.useState)(""), editDataRowId = _15[0], setEditDataRowId = _15[1];
381
+ var _16 = (0, react_2.useState)(""), editDataHeaderKey = _16[0], setEditDataHeaderKey = _16[1];
372
382
  // INFO: an editable table used to mount an input in every cell — it read as a
373
383
  // form, and a row click always landed on a child input. Only the hovered cell
374
384
  // becomes its input now.
375
- var _16 = (0, react_2.useState)(null), hoveredCell = _16[0], setHoveredCell = _16[1];
376
- var _17 = (0, react_2.useState)(false), modalEditVisible = _17[0], setModalEditVisible = _17[1];
377
- var _18 = (0, react_2.useState)([]), collapsedGroupIds = _18[0], setCollapsedGroupIds = _18[1];
385
+ var _17 = (0, react_2.useState)(null), hoveredCell = _17[0], setHoveredCell = _17[1];
386
+ var _18 = (0, react_2.useState)(false), modalEditVisible = _18[0], setModalEditVisible = _18[1];
387
+ var _19 = (0, react_2.useState)([]), collapsedGroupIds = _19[0], setCollapsedGroupIds = _19[1];
378
388
  // INFO: per-group scroll pagination. One sentinel element per band, observed
379
389
  // by a single IntersectionObserver that fires props.onGroupLoadMore when a
380
390
  // band's sentinel scrolls into view. The debounce guard stops repeat fires
@@ -390,25 +400,25 @@ var NewTable = function (props) {
390
400
  var lastSelectedRowRef = (0, react_2.useRef)(null);
391
401
  var dragSelectRef = (0, react_2.useRef)(null);
392
402
  var suppressNextClickRef = (0, react_2.useRef)(false);
393
- var _19 = (0, react_2.useState)(false), isDragSelecting = _19[0], setIsDragSelecting = _19[1];
394
- var _20 = (0, react_2.useState)(0), copiedCount = _20[0], setCopiedCount = _20[1];
395
- var _21 = (0, react_2.useState)({}), editDataValue = _21[0], setEditDataValue = _21[1];
396
- var _22 = (0, react_2.useState)(false), editDataIsLoading = _22[0], setEditDataIsLoading = _22[1];
403
+ var _20 = (0, react_2.useState)(false), isDragSelecting = _20[0], setIsDragSelecting = _20[1];
404
+ var _21 = (0, react_2.useState)(0), copiedCount = _21[0], setCopiedCount = _21[1];
405
+ var _22 = (0, react_2.useState)({}), editDataValue = _22[0], setEditDataValue = _22[1];
406
+ var _23 = (0, react_2.useState)(false), editDataIsLoading = _23[0], setEditDataIsLoading = _23[1];
397
407
  // INFO: true while the empty bottom row is being filled in; the row itself is
398
408
  // always there in an addable table
399
- var _23 = (0, react_2.useState)(false), addData = _23[0], setAddData = _23[1];
400
- var _24 = (0, react_2.useState)({}), addDataValue = _24[0], setAddDataValue = _24[1];
409
+ var _24 = (0, react_2.useState)(false), addData = _24[0], setAddData = _24[1];
410
+ var _25 = (0, react_2.useState)({}), addDataValue = _25[0], setAddDataValue = _25[1];
401
411
  // INFO: bumped after each saved row, so the next one starts with fresh
402
412
  // inputs and its first cell takes the focus
403
- var _25 = (0, react_2.useState)(0), addRowKey = _25[0], setAddRowKey = _25[1];
404
- var _26 = (0, react_2.useState)({}), referencesOptions = _26[0], setReferencesOptions = _26[1];
413
+ var _26 = (0, react_2.useState)(0), addRowKey = _26[0], setAddRowKey = _26[1];
414
+ var _27 = (0, react_2.useState)({}), referencesOptions = _27[0], setReferencesOptions = _27[1];
405
415
  // INFO: seeded options sit under the local map so a cell's own search
406
416
  // results still win per key
407
417
  var mergedReferencesOptions = __assign(__assign({}, ((_l = props.referencesOptions) !== null && _l !== void 0 ? _l : {})), referencesOptions);
408
- var _27 = (0, react_2.useState)({}), referencesDetails = _27[0], setReferencesDetails = _27[1];
409
- var _28 = (0, react_2.useState)(false), referenceLoading = _28[0], setReferenceLoading = _28[1];
418
+ var _28 = (0, react_2.useState)({}), referencesDetails = _28[0], setReferencesDetails = _28[1];
419
+ var _29 = (0, react_2.useState)(false), referenceLoading = _29[0], setReferenceLoading = _29[1];
410
420
  // INFO: measured pixel widths for pinned columns without an explicit width.
411
- var _29 = (0, react_2.useState)({}), measuredPinWidths = _29[0], setMeasuredPinWidths = _29[1];
421
+ var _30 = (0, react_2.useState)({}), measuredPinWidths = _30[0], setMeasuredPinWidths = _30[1];
412
422
  var editDataValueRef = (0, react_2.useRef)({});
413
423
  var editDataRowIdRef = (0, react_2.useRef)("");
414
424
  var editDataHeaderKeyRef = (0, react_2.useRef)("");
@@ -1033,7 +1043,7 @@ var NewTable = function (props) {
1033
1043
  // resize is a per-viewer preference and there is no storage for it yet.
1034
1044
  // Tailwind cannot emit a runtime w-[Npx], so this drives an inline style and
1035
1045
  // wins over the col.width class.
1036
- var _30 = (0, react_2.useState)({}), columnWidths = _30[0], setColumnWidths = _30[1];
1046
+ var _31 = (0, react_2.useState)({}), columnWidths = _31[0], setColumnWidths = _31[1];
1037
1047
  var resizeRef = (0, react_2.useRef)(null);
1038
1048
  // INFO: a consumer may deliberately set a column narrower than the default
1039
1049
  // floor (a 40px icon column, say) — never force it wider than it was asked to
@@ -1099,7 +1109,7 @@ var NewTable = function (props) {
1099
1109
  });
1100
1110
  };
1101
1111
  var renderAddColumnPanel = function () {
1102
- var _a, _b, _c, _d, _e, _f, _g, _h;
1112
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1103
1113
  // INFO: a caller that renders its own form keeps full control; the
1104
1114
  // built-in one only appears when it hands over onAddColumn instead
1105
1115
  if ((_a = props.advSettings) === null || _a === void 0 ? void 0 : _a.renderAddColumnElements)
@@ -1114,8 +1124,9 @@ var NewTable = function (props) {
1114
1124
  react_2.default.createElement(textInput_1.TextInput, { id: "newColumnName", type: "text", label: "Column name", placeholder: "Order Date", value: newColumnName, darkMode: props.darkMode, onChange: function (event) { var _a, _b; return setNewColumnName((_b = (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ""); } }),
1115
1125
  !editingColumn && (react_2.default.createElement("div", { className: "-mt-2" },
1116
1126
  react_2.default.createElement("p", { className: "text-xs text-gray-500" }, derivedId ? (react_2.default.createElement(react_2.default.Fragment, null,
1117
- "Saved on each record as",
1118
- " ",
1127
+ newColumnType === "formula"
1128
+ ? "Column id "
1129
+ : "Saved on each record as ",
1119
1130
  react_2.default.createElement("span", { className: "font-mono font-medium" }, derivedId),
1120
1131
  taken ? " — already used by another column" : "")) : ("The field id is generated from the name")))),
1121
1132
  react_2.default.createElement(select_1.Select, { id: "newColumnType", label: "Type", value: newColumnType, darkMode: props.darkMode, options: editingColumn
@@ -1123,7 +1134,16 @@ var NewTable = function (props) {
1123
1134
  return (0, exports.handleGetEditableColumnTypes)(editingColumn.type).includes(eachType.key);
1124
1135
  })
1125
1136
  : ADD_COLUMN_TYPES, disabled: !!editingColumn &&
1126
- (0, exports.handleGetEditableColumnTypes)(editingColumn.type).length < 2, portalDropdown: true, onChange: function (value) { return setNewColumnType(value); } }),
1137
+ (0, exports.handleGetEditableColumnTypes)(editingColumn.type).length < 2, portalDropdown: true, onChange: function (value) {
1138
+ var _a;
1139
+ setNewColumnType(value);
1140
+ // INFO: the formula builder needs a modal's room, as monday opens
1141
+ // its builder — the popup hands over what was typed and closes
1142
+ if (value === "formula" && !addColumnModal) {
1143
+ (_a = addColumnPopUpRef.current) === null || _a === void 0 ? void 0 : _a.handleOnClose();
1144
+ setAddColumnModal("new");
1145
+ }
1146
+ } }),
1127
1147
  REFERENCE_TYPES.includes(newColumnType) &&
1128
1148
  ((_c = props.advSettings) === null || _c === void 0 ? void 0 : _c.renderReferenceSpaceOptions) && (react_2.default.createElement(react_2.default.Fragment, null,
1129
1149
  react_2.default.createElement(select_1.Select, { id: "newColumnRefSpace", label: "Reference endpoint", value: newColumnRefSpace, darkMode: props.darkMode, portalDropdown: true, options: (_d = props.advSettings.renderReferenceSpaceOptions()) !== null && _d !== void 0 ? _d : [], onChange: function (value) {
@@ -1141,13 +1161,14 @@ var NewTable = function (props) {
1141
1161
  return eachOption.includes(",");
1142
1162
  }), onChange: function (event) { var _a, _b; return setNewColumnOptions((_b = (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ""); } })),
1143
1163
  ASSET_TYPES.includes(newColumnType) && (react_2.default.createElement("p", { className: "-mt-2 text-xs text-gray-500" }, "Uploads are stored against this space automatically.")),
1144
- react_2.default.createElement(checkbox_1.Checkbox, { id: "newColumnRequired",
1164
+ newColumnType === "formula" && (react_2.default.createElement(builder_1.FormulaBuilder, { value: newColumnFormula, schema: handleGetFormulaSchema(), columnId: editingColumn === null || editingColumn === void 0 ? void 0 : editingColumn.id, previewRow: (_j = props.data) === null || _j === void 0 ? void 0 : _j[0], previewDisplayRow: (_k = props.spaceData) === null || _k === void 0 ? void 0 : _k[0], darkMode: props.darkMode, onChange: setNewColumnFormula })),
1165
+ newColumnType !== "formula" && (react_2.default.createElement(checkbox_1.Checkbox, { id: "newColumnRequired",
1145
1166
  // INFO: the checkbox itself is not a required field — without this it
1146
1167
  // renders "Required *", which reads as a validation error on a toggle
1147
1168
  optional: true, darkMode: props.darkMode, itemList: [{ key: "required", label: "Required" }], selectItemList: newColumnRequired ? ["required"] : [], onChange: function (items) {
1148
1169
  return setNewColumnRequired(items.includes("required"));
1149
- } }),
1150
- newColumnRequired && !editingColumn && (react_2.default.createElement("p", { className: "-mt-3 text-xs text-gray-500" }, "Rows already in this table have no value for it yet.")),
1170
+ } })),
1171
+ newColumnType !== "formula" && newColumnRequired && !editingColumn && (react_2.default.createElement("p", { className: "-mt-3 text-xs text-gray-500" }, "Rows already in this table have no value for it yet.")),
1151
1172
  react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-2" },
1152
1173
  react_2.default.createElement(button_1.Button, { type: "light", text: "Cancel", onClick: function () { return handleAddColumnModal(""); } }),
1153
1174
  react_2.default.createElement(button_1.Button, { type: "normal", text: editingColumn
@@ -1174,6 +1195,9 @@ var NewTable = function (props) {
1174
1195
  setNewColumnRefLabel((_f = schema.referenceLabel) !== null && _f !== void 0 ? _f : "");
1175
1196
  setNewColumnOptions(handleJoinOptions((_g = schema.listSelection) !== null && _g !== void 0 ? _g : []));
1176
1197
  setNewColumnRequired(!schema.optional);
1198
+ setNewColumnFormula(schema.type === "formula"
1199
+ ? (0, formula_1.handleGetFormulaDisplay)(schema, handleGetFormulaSchema())
1200
+ : "");
1177
1201
  setAddColumnModal(columnId);
1178
1202
  };
1179
1203
  var handleAddColumnModal = function (id) {
@@ -1186,6 +1210,7 @@ var NewTable = function (props) {
1186
1210
  setNewColumnRefLabel("");
1187
1211
  setNewColumnOptions("");
1188
1212
  setNewColumnRequired(false);
1213
+ setNewColumnFormula("");
1189
1214
  }
1190
1215
  };
1191
1216
  // INFO: the stored field id is derived from what the user types rather than
@@ -1205,11 +1230,36 @@ var NewTable = function (props) {
1205
1230
  var handleColumnIdTaken = function (id) {
1206
1231
  return flatColumns.some(function (eachColumn) { return eachColumn.key === id; });
1207
1232
  };
1233
+ // INFO: every column a formula may read. The full model when the caller
1234
+ // gives it — hidden columns are still on the row — else the shown columns.
1235
+ var handleGetFormulaSchema = function () {
1236
+ var _a, _b;
1237
+ var schema = (_b = (_a = props.advSettings) === null || _a === void 0 ? void 0 : _a.getSchema) === null || _b === void 0 ? void 0 : _b.call(_a);
1238
+ if (schema)
1239
+ return schema;
1240
+ return flatColumns
1241
+ .filter(function (eachColumn) { return eachColumn.key !== "update"; })
1242
+ .map(function (eachColumn) {
1243
+ var _a, _b, _c, _d;
1244
+ return (_c = (_b = (_a = props.advSettings) === null || _a === void 0 ? void 0 : _a.getColumnSchema) === null || _b === void 0 ? void 0 : _b.call(_a, eachColumn.key)) !== null && _c !== void 0 ? _c : {
1245
+ id: eachColumn.key,
1246
+ name: eachColumn.title,
1247
+ type: (_d = eachColumn.type) !== null && _d !== void 0 ? _d : "string",
1248
+ };
1249
+ });
1250
+ };
1208
1251
  // INFO: a reference with no target resolves nothing, so it cannot be saved
1209
1252
  // half-built. Everything else is complete with a name and a type.
1210
1253
  var handleIsNewColumnReady = function () {
1211
1254
  if (REFERENCE_TYPES.includes(newColumnType))
1212
1255
  return !!newColumnRefSpace && !!newColumnRefLabel;
1256
+ // INFO: an illegal formula would show "Error" in every row
1257
+ if (newColumnType === "formula") {
1258
+ if (!newColumnFormula.trim())
1259
+ return false;
1260
+ var schema = handleGetFormulaSchema();
1261
+ return !(0, formula_1.handleValidateFormula)((0, formula_1.handleFormulaToStorage)(newColumnFormula, schema), schema);
1262
+ }
1213
1263
  return true;
1214
1264
  };
1215
1265
  var handleSubmitNewColumn = function () { return __awaiter(void 0, void 0, void 0, function () {
@@ -1249,6 +1299,10 @@ var NewTable = function (props) {
1249
1299
  .split(",")
1250
1300
  .map(function (eachOption) { return eachOption.trim(); })
1251
1301
  .filter(Boolean);
1302
+ if (newColumnType === "formula") {
1303
+ column.formulaExpression = (0, formula_1.handleFormulaToStorage)(newColumnFormula.trim(), handleGetFormulaSchema());
1304
+ column.optional = true;
1305
+ }
1252
1306
  return [4 /*yield*/, ((_b = (_a = props.advSettings) === null || _a === void 0 ? void 0 : _a.onAddColumn) === null || _b === void 0 ? void 0 : _b.call(_a, column))];
1253
1307
  case 4:
1254
1308
  _c.sent();
@@ -1316,6 +1370,10 @@ var NewTable = function (props) {
1316
1370
  delete column_1.listSelectionColour;
1317
1371
  delete column_1.listSelectionLabel;
1318
1372
  }
1373
+ if (newColumnType === "formula") {
1374
+ column_1.formulaExpression = (0, formula_1.handleFormulaToStorage)(newColumnFormula.trim(), handleGetFormulaSchema());
1375
+ column_1.optional = true;
1376
+ }
1319
1377
  return [4 /*yield*/, ((_d = (_c = props.advSettings) === null || _c === void 0 ? void 0 : _c.onEditColumn) === null || _d === void 0 ? void 0 : _d.call(_c, column_1))];
1320
1378
  case 2:
1321
1379
  _e.sent();
@@ -1603,10 +1661,11 @@ var NewTable = function (props) {
1603
1661
  borderClass = "".concat(pinBase, " ").concat(afterBase, " after:right-0 ").concat(afterColor);
1604
1662
  }
1605
1663
  else if (rightIdx >= 0) {
1606
- // INFO: offset = sum of widths of all right-pinned columns after this one
1664
+ // INFO: offset = sum of widths of all right-pinned columns after this one,
1665
+ // starting past the Actions column, which is pinned at the very edge
1607
1666
  var right = rightPinned
1608
1667
  .slice(rightIdx + 1)
1609
- .reduce(function (sum, key) { return sum + parsePinWidth(key); }, 0);
1668
+ .reduce(function (sum, key) { return sum + parsePinWidth(key); }, handleShowsActionColumn() ? ACTION_COLUMN_WIDTH : 0);
1610
1669
  var colWidth = parsePinWidth(colKey);
1611
1670
  var col = flatColumns.find(function (c) { return c.key === colKey; });
1612
1671
  var hasFixedWidth = !!(col === null || col === void 0 ? void 0 : col.width) || !!measuredPinWidths[colKey];
@@ -1743,9 +1802,36 @@ var NewTable = function (props) {
1743
1802
  react_2.default.createElement(outline_1.ChatBubbleOvalLeftEllipsisIcon, { className: "h-5 w-5", "aria-hidden": "true" }))) : null;
1744
1803
  };
1745
1804
  var handleShowsActionColumn = function () { var _a; return !!((_a = props.deleteable) === null || _a === void 0 ? void 0 : _a.active) || (addData && handleValidateAddColumns()); };
1805
+ /**
1806
+ * INFO: the table is max-content wide inside a horizontal scroller, so a
1807
+ * last column in normal flow sits off screen on any wide table — the add
1808
+ * row's tick and cross were only reachable by scrolling to the far right,
1809
+ * under the scroll shadow. Pinned to the right edge, every cell of the
1810
+ * column carries a background so the scrolling cells pass beneath it.
1811
+ */
1812
+ var handleGetActionCellPin = function (isHeader, rowBg, isHoverable) {
1813
+ var bg = isHeader ? tableHeaderBgColor : (rowBg !== null && rowBg !== void 0 ? rowBg : bgColor);
1814
+ var hoverClass = !isHeader && isHoverable
1815
+ ? props.darkMode
1816
+ ? "group-hover:bg-gray-700"
1817
+ : "group-hover:bg-gray-100"
1818
+ : "";
1819
+ var divider = props.darkMode
1820
+ ? "before:bg-gray-700"
1821
+ : "before:bg-gray-200";
1822
+ return {
1823
+ className: "sticky right-0 z-[3] ".concat(bg, " ").concat(hoverClass, " before:absolute before:inset-y-0 before:left-0 before:w-px before:pointer-events-none ").concat(divider),
1824
+ // INFO: right-pinned data columns offset by this width, so it has to be
1825
+ // exact while they exist
1826
+ style: rightPinned.length > 0
1827
+ ? { width: ACTION_COLUMN_WIDTH, minWidth: ACTION_COLUMN_WIDTH }
1828
+ : undefined,
1829
+ };
1830
+ };
1746
1831
  var renderActionColumnHeader = function () {
1747
1832
  if (handleShowsActionColumn()) {
1748
- return (react_2.default.createElement("th", { key: "actions", className: "".concat(cellPadding, " text-left text-xs font-semibold uppercase tracking-wide") }, "Actions"));
1833
+ var pin = handleGetActionCellPin(true);
1834
+ return (react_2.default.createElement("th", { key: "actions", className: "".concat(cellPadding, " text-left text-xs font-semibold uppercase tracking-wide ").concat(pin.className), style: pin.style }, "Actions"));
1749
1835
  }
1750
1836
  return null;
1751
1837
  };
@@ -1777,14 +1863,15 @@ var NewTable = function (props) {
1777
1863
  // — or the body loses a column exactly while the add row is on screen and the
1778
1864
  // confirm buttons appear under the wrong heading. Mirrors
1779
1865
  // renderActionColumnHeader's condition rather than restating it loosely.
1780
- var renderActionColumnCell = function (rowId) {
1866
+ var renderActionColumnCell = function (rowId, rowBg, isHoverable) {
1781
1867
  var _a;
1782
1868
  if (!handleShowsActionColumn())
1783
1869
  return null;
1870
+ var pin = handleGetActionCellPin(false, rowBg, isHoverable);
1784
1871
  if (((_a = props.deleteable) === null || _a === void 0 ? void 0 : _a.active) && !addData) {
1785
- return (react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm") }, renderDeleteButton(rowId)));
1872
+ return (react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm ").concat(pin.className), style: pin.style }, renderDeleteButton(rowId)));
1786
1873
  }
1787
- return react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm") });
1874
+ return (react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm ").concat(pin.className), style: pin.style }));
1788
1875
  };
1789
1876
  var renderAddDataRow = function () {
1790
1877
  var filteredCols = handleGetAddColumns();
@@ -1799,10 +1886,10 @@ var NewTable = function (props) {
1799
1886
  return react_2.default.createElement("td", { key: ds.id + String(index), "data-add-cell": ds.id });
1800
1887
  }),
1801
1888
  renderAddColumnCell(),
1802
- react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm") },
1889
+ react_2.default.createElement("td", { className: "".concat(cellPadding, " text-sm ").concat(handleGetActionCellPin(false).className), style: handleGetActionCellPin(false).style },
1803
1890
  react_2.default.createElement("div", { className: "flex flex-row gap-2" },
1804
- react_2.default.createElement(iconButton_1.IconButton, { icon: react_2.default.createElement(solid_2.CheckIcon, { className: "w-5 h-5 text-green-500" }), onClick: function () { return handleCommitAdd(false); } }),
1805
- react_2.default.createElement(iconButton_1.IconButton, { icon: react_2.default.createElement(solid_2.XMarkIcon, { className: "h-5 w-5 text-red-500" }), onClick: handleCancelAdd })))));
1891
+ react_2.default.createElement(iconButton_1.IconButton, { testId: "table-add-row-confirm", icon: react_2.default.createElement(solid_2.CheckIcon, { className: "w-5 h-5 text-green-500" }), onClick: function () { return handleCommitAdd(false); } }),
1892
+ react_2.default.createElement(iconButton_1.IconButton, { testId: "table-add-row-cancel", icon: react_2.default.createElement(solid_2.XMarkIcon, { className: "h-5 w-5 text-red-500" }), onClick: handleCancelAdd })))));
1806
1893
  };
1807
1894
  // INFO: the empty row at the bottom of an addable table — clicking any of
1808
1895
  // its cells starts a new record there, as the next empty row of a
@@ -1813,11 +1900,11 @@ var NewTable = function (props) {
1813
1900
  return null;
1814
1901
  if (((_c = (_b = props.selectedIds) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 0 || props.selectAll)
1815
1902
  return null;
1816
- return (react_2.default.createElement("tr", { "data-testid": "table-add-row", className: "cursor-text ".concat(props.darkMode ? "hover:bg-gray-800" : "hover:bg-gray-50") },
1903
+ return (react_2.default.createElement("tr", { "data-testid": "table-add-row", className: "group cursor-text ".concat(props.darkMode ? "hover:bg-gray-800" : "hover:bg-gray-50") },
1817
1904
  props.checkbox && react_2.default.createElement("td", { className: "w-10 ".concat(cellPadding) }),
1818
1905
  handleGetAddColumns().map(function (col, index) { return (react_2.default.createElement("td", { key: col.key, "data-add-cell": col.key, className: "".concat(cellPadding, " h-10"), onClick: function () { return handleStartAdd(col.key); } }, index === 0 && (react_2.default.createElement(solid_1.PlusIcon, { className: "h-4 w-4 ".concat(props.darkMode ? "text-gray-500" : "text-gray-400"), "aria-hidden": "true" })))); }),
1819
1906
  renderAddColumnCell(),
1820
- handleShowsActionColumn() && react_2.default.createElement("td", { className: cellPadding })));
1907
+ handleShowsActionColumn() && (react_2.default.createElement("td", { className: "".concat(cellPadding, " ").concat(handleGetActionCellPin(false).className, " ").concat(props.darkMode ? "group-hover:bg-gray-800" : "group-hover:bg-gray-50"), style: handleGetActionCellPin(false).style }))));
1821
1908
  };
1822
1909
  var renderSelectAll = function () {
1823
1910
  var _a, _b;
@@ -2038,7 +2125,7 @@ var NewTable = function (props) {
2038
2125
  }, cell.props.children, renderActivityButton(row.id, true));
2039
2126
  }),
2040
2127
  renderAddColumnCell(),
2041
- renderActionColumnCell(row.id)));
2128
+ renderActionColumnCell(row.id, rowBgClass, isRowHoverable)));
2042
2129
  };
2043
2130
  // INFO: with groups, each group is a tinted band row (chevron, title, count)
2044
2131
  // followed by its member rows; collapsing a band hides them. Without groups,
@@ -2225,14 +2312,14 @@ var NewTable = function (props) {
2225
2312
  var filterColumnEnabled = utils_1.supportedAQList.includes((_b = col.type) !== null && _b !== void 0 ? _b : "");
2226
2313
  if (sortColumnEnabled && (advSettings === null || advSettings === void 0 ? void 0 : advSettings.sortEnabled)) {
2227
2314
  if (col.key !== ((_c = advSettings.sortId) === null || _c === void 0 ? void 0 : _c.sortId)) {
2228
- sortIcon = (react_2.default.createElement(solid_2.ArrowsUpDownIcon, { className: sortClassname, onClick: function () { return handleSort(col.key, "new"); } }));
2315
+ sortIcon = (react_2.default.createElement(solid_2.ArrowsUpDownIcon, { "data-testid": "table-column-sort-".concat(col.key), className: sortClassname, onClick: function () { return handleSort(col.key, "new"); } }));
2229
2316
  }
2230
2317
  else if (col.key === advSettings.sortId.sortId) {
2231
2318
  if (advSettings.sortId.type === "desc") {
2232
- sortIcon = (react_2.default.createElement(solid_2.BarsArrowDownIcon, { className: sortClassname, onClick: function () { return handleSort(col.key, "asc"); } }));
2319
+ sortIcon = (react_2.default.createElement(solid_2.BarsArrowDownIcon, { "data-testid": "table-column-sort-".concat(col.key), className: sortClassname, onClick: function () { return handleSort(col.key, "asc"); } }));
2233
2320
  }
2234
2321
  else if (advSettings.sortId.type === "asc") {
2235
- sortIcon = (react_2.default.createElement(solid_2.BarsArrowUpIcon, { className: sortClassname, onClick: function () { return handleSort(col.key, "desc"); } }));
2322
+ sortIcon = (react_2.default.createElement(solid_2.BarsArrowUpIcon, { "data-testid": "table-column-sort-".concat(col.key), className: sortClassname, onClick: function () { return handleSort(col.key, "desc"); } }));
2236
2323
  }
2237
2324
  }
2238
2325
  }
@@ -2259,7 +2346,7 @@ var NewTable = function (props) {
2259
2346
  // this reason.
2260
2347
  className: "".concat(cellPadding, " w-px whitespace-nowrap text-left text-xs font-semibold uppercase tracking-wide ").concat(cursorClassname) },
2261
2348
  react_2.default.createElement("div", { className: "hidden flex-row items-center md:flex" },
2262
- react_2.default.createElement(popUp_1.PopUp, { darkMode: props.darkMode, darkModeBg: props.darkModeBg, anchor: "right", portal: true, lib: { Transition: react_1.Transition }, excludePortalIds: ["select-portal"], ctaComp: react_2.default.createElement(iconButton_1.IconButton, { testId: "table-add-column-btn", icon: react_2.default.createElement(solid_1.PlusIcon, { className: "h-5 w-5 text-gray" }) }), renderComp: react_2.default.createElement("div", { className: "w-80 p-4 normal-case tracking-normal" }, renderAddColumnPanel()) })),
2349
+ react_2.default.createElement(popUp_1.PopUp, { ref: addColumnPopUpRef, darkMode: props.darkMode, darkModeBg: props.darkModeBg, anchor: "right", portal: true, lib: { Transition: react_1.Transition }, excludePortalIds: ["select-portal"], ctaComp: react_2.default.createElement(iconButton_1.IconButton, { testId: "table-add-column-btn", icon: react_2.default.createElement(solid_1.PlusIcon, { className: "h-5 w-5 text-gray" }) }), renderComp: react_2.default.createElement("div", { className: "w-80 p-4 normal-case tracking-normal" }, renderAddColumnPanel()) })),
2263
2350
  react_2.default.createElement("div", { className: "flex flex-row items-center md:hidden" },
2264
2351
  react_2.default.createElement(iconButton_1.IconButton, { testId: "table-add-column-btn-mobile", icon: react_2.default.createElement(solid_1.PlusIcon, { className: "h-5 w-5 text-gray" }), onClick: function () { return handleAddColumnModal("new"); } }))));
2265
2352
  };
@@ -2545,7 +2632,7 @@ var NewTable = function (props) {
2545
2632
  react_2.default.createElement(button_1.Button, { text: "Cancel", type: "light", onClick: handleModalEditClose }),
2546
2633
  react_2.default.createElement(button_1.Button, { text: editDataIsLoading ? "Saving" : "Save", type: "normal", disable: editDataIsLoading, onClick: handleModalEditSave }))));
2547
2634
  } }),
2548
- react_2.default.createElement(modal_1.Modal, { open: addColumnModal ? true : false, title: editingColumn ? "Edit Column" : "Add Column", renderContent: renderAddColumnPanel, onClose: function () { return handleAddColumnModal(""); } }),
2635
+ react_2.default.createElement(modal_1.Modal, { open: addColumnModal ? true : false, maxWidth: newColumnType === "formula" ? "2xl" : undefined, title: editingColumn ? "Edit Column" : "Add Column", renderContent: renderAddColumnPanel, onClose: function () { return handleAddColumnModal(""); } }),
2549
2636
  react_2.default.createElement(scrollShadow_1.ScrollShadow, { className: "w-full overflow-x-auto ".concat(isFlat
2550
2637
  ? ""
2551
2638
  : "".concat(borderRadius, " border ").concat(borderColor, " ").concat(bgColor, " shadow-sm")), darkMode: props.darkMode },