@feathery/react 2.30.0 → 2.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/cjs/Form/grid/Element/index.d.ts.map +1 -1
  2. package/cjs/Form/index.d.ts.map +1 -1
  3. package/cjs/assistant/index.d.ts +4 -8
  4. package/cjs/assistant/index.d.ts.map +1 -1
  5. package/cjs/assistant/utils.d.ts +23 -0
  6. package/cjs/assistant/utils.d.ts.map +1 -0
  7. package/cjs/elements/basic/TableElement/Actions.d.ts +3 -1
  8. package/cjs/elements/basic/TableElement/Actions.d.ts.map +1 -1
  9. package/cjs/elements/basic/TableElement/DeleteConfirm.d.ts +11 -0
  10. package/cjs/elements/basic/TableElement/DeleteConfirm.d.ts.map +1 -0
  11. package/cjs/elements/basic/TableElement/EditableCell.d.ts +10 -0
  12. package/cjs/elements/basic/TableElement/EditableCell.d.ts.map +1 -0
  13. package/cjs/elements/basic/TableElement/Search.d.ts.map +1 -1
  14. package/cjs/elements/basic/TableElement/index.d.ts +1 -1
  15. package/cjs/elements/basic/TableElement/index.d.ts.map +1 -1
  16. package/cjs/elements/basic/TableElement/styles.d.ts +221 -4
  17. package/cjs/elements/basic/TableElement/styles.d.ts.map +1 -1
  18. package/cjs/elements/basic/TableElement/useColumnWidths.d.ts +7 -0
  19. package/cjs/elements/basic/TableElement/useColumnWidths.d.ts.map +1 -0
  20. package/cjs/elements/basic/TableElement/useTableData.d.ts +6 -1
  21. package/cjs/elements/basic/TableElement/useTableData.d.ts.map +1 -1
  22. package/cjs/elements/basic/TableElement/useTableMutations.d.ts +23 -0
  23. package/cjs/elements/basic/TableElement/useTableMutations.d.ts.map +1 -0
  24. package/cjs/elements/components/icons/TrashIcon.d.ts +3 -0
  25. package/cjs/elements/components/icons/TrashIcon.d.ts.map +1 -0
  26. package/cjs/elements/components/icons/index.d.ts +2 -1
  27. package/cjs/elements/components/icons/index.d.ts.map +1 -1
  28. package/cjs/{fthry_FormControl._mBWRKs7.js → fthry_FormControl.BtNu9i-u.js} +1 -1
  29. package/cjs/{fthry_InlineTooltip.Ci88wpmH.js → fthry_InlineTooltip.DuFB8p7w.js} +2 -2
  30. package/cjs/{fthry_Overlay.EZR3dxIp.js → fthry_Overlay.DqGyzI8W.js} +1 -1
  31. package/cjs/{fthry_PaymentMethodField.D1qfT6ml.js → fthry_PaymentMethodField.D0kI1ZxS.js} +4 -4
  32. package/cjs/{fthry_Placeholder.CxuLPsF-.js → fthry_Placeholder.WRNgQX3l.js} +1 -1
  33. package/cjs/{fthry_ShowEyeIcon.B7ZyaGae.js → fthry_ShowEyeIcon.1seA7I1l.js} +1 -1
  34. package/cjs/{fthry_index.DRlPrDHk.js → fthry_index.B96nzeqy.js} +4 -4
  35. package/cjs/{fthry_index.qIj6fG9T.js → fthry_index.BEVaTA54.js} +3 -3
  36. package/cjs/{fthry_index.BS76NJIi.js → fthry_index.BI7CrYad.js} +2 -2
  37. package/cjs/{fthry_index.B29cmrSc.js → fthry_index.BM4ep-AK.js} +5 -5
  38. package/cjs/{fthry_index.Bm1hHYyX.js → fthry_index.BTKf9mxG.js} +1 -1
  39. package/cjs/{fthry_index.D1vI8h-g.js → fthry_index.B_-iRvUH.js} +4 -4
  40. package/cjs/{fthry_index.Dgwh7PEG.js → fthry_index.BccfyVDL.js} +6 -6
  41. package/cjs/{fthry_index.CatPMXS_.js → fthry_index.BhC7LkQw.js} +5 -5
  42. package/cjs/{fthry_index.sxVKbE6v.js → fthry_index.BvkC5P1Q.js} +6 -6
  43. package/cjs/{fthry_index.CA9rB_hE.js → fthry_index.C6CH7RhD.js} +8 -8
  44. package/cjs/{fthry_index.BYHaM6D3.js → fthry_index.C7hxyJ9f.js} +1 -1
  45. package/cjs/{fthry_index.BTEjXAoq.js → fthry_index.CBJimbrX.js} +5 -5
  46. package/cjs/{fthry_index.CUmRx79G.js → fthry_index.CGQA5QkX.js} +3 -3
  47. package/cjs/{fthry_index.DESk4H5E.js → fthry_index.CUO7vSY3.js} +4 -4
  48. package/cjs/{fthry_index.esjf5uCx.js → fthry_index.CiXHBkVl.js} +362 -53
  49. package/cjs/{fthry_index.B87qkPTe.js → fthry_index.D4RrBVB-.js} +1 -1
  50. package/cjs/{fthry_index.YrpKr9cF.js → fthry_index.DbijQ61t.js} +1 -1
  51. package/cjs/{fthry_index.DlbhlY21.js → fthry_index.DloMkPdT.js} +5 -5
  52. package/cjs/{fthry_index.CfL17UCN.js → fthry_index.J4GcA3vx.js} +1 -1
  53. package/cjs/{fthry_index.Cx9wY-d4.js → fthry_index.KbHjZiIM.js} +6 -6
  54. package/cjs/{fthry_index.DmfLe1_p.js → fthry_index.TK6Jx-jy.js} +1 -1
  55. package/cjs/{fthry_index.CJ_xssDe.js → fthry_index.WRjuuH9z.js} +1 -1
  56. package/cjs/{fthry_index.C2Hmw3MN.js → fthry_index.Z6a5kUfj.js} +527 -47
  57. package/cjs/{fthry_index.CZO8LB_A.js → fthry_index.oVFShAC8.js} +2 -2
  58. package/cjs/{fthry_input.DL5PaVNA.js → fthry_input.CUTC1cQr.js} +1 -1
  59. package/cjs/{fthry_script.Dx-T4xgR.js → fthry_script.DRtiXuhL.js} +1 -1
  60. package/cjs/{fthry_styles.lXVAR-s8.js → fthry_styles.MGVgRzzA.js} +1 -1
  61. package/cjs/{fthry_useElementSize.Di0_hIVc.js → fthry_useElementSize.DXcMVgAq.js} +1 -1
  62. package/cjs/{fthry_useSalesforceSync.BRclBQ5F.js → fthry_useSalesforceSync.C87PZunf.js} +1 -1
  63. package/cjs/{fthry_webfontloader.Cpo-BOVP.js → fthry_webfontloader.CVSP2Jc5.js} +1 -1
  64. package/cjs/index.d.ts +0 -1
  65. package/cjs/index.d.ts.map +1 -1
  66. package/cjs/index.js +1 -1
  67. package/dist/Form/grid/Element/index.d.ts.map +1 -1
  68. package/dist/Form/index.d.ts.map +1 -1
  69. package/dist/assistant/index.d.ts +4 -8
  70. package/dist/assistant/index.d.ts.map +1 -1
  71. package/dist/assistant/utils.d.ts +23 -0
  72. package/dist/assistant/utils.d.ts.map +1 -0
  73. package/dist/elements/basic/TableElement/Actions.d.ts +3 -1
  74. package/dist/elements/basic/TableElement/Actions.d.ts.map +1 -1
  75. package/dist/elements/basic/TableElement/DeleteConfirm.d.ts +11 -0
  76. package/dist/elements/basic/TableElement/DeleteConfirm.d.ts.map +1 -0
  77. package/dist/elements/basic/TableElement/EditableCell.d.ts +10 -0
  78. package/dist/elements/basic/TableElement/EditableCell.d.ts.map +1 -0
  79. package/dist/elements/basic/TableElement/Search.d.ts.map +1 -1
  80. package/dist/elements/basic/TableElement/index.d.ts +1 -1
  81. package/dist/elements/basic/TableElement/index.d.ts.map +1 -1
  82. package/dist/elements/basic/TableElement/styles.d.ts +221 -4
  83. package/dist/elements/basic/TableElement/styles.d.ts.map +1 -1
  84. package/dist/elements/basic/TableElement/useColumnWidths.d.ts +7 -0
  85. package/dist/elements/basic/TableElement/useColumnWidths.d.ts.map +1 -0
  86. package/dist/elements/basic/TableElement/useTableData.d.ts +6 -1
  87. package/dist/elements/basic/TableElement/useTableData.d.ts.map +1 -1
  88. package/dist/elements/basic/TableElement/useTableMutations.d.ts +23 -0
  89. package/dist/elements/basic/TableElement/useTableMutations.d.ts.map +1 -0
  90. package/dist/elements/components/icons/TrashIcon.d.ts +3 -0
  91. package/dist/elements/components/icons/TrashIcon.d.ts.map +1 -0
  92. package/dist/elements/components/icons/index.d.ts +2 -1
  93. package/dist/elements/components/icons/index.d.ts.map +1 -1
  94. package/dist/{fthry_FormControl.CGMmdVSc.js → fthry_FormControl.C9K2iuFX.js} +1 -1
  95. package/dist/{fthry_InlineTooltip.DIH2B37d.js → fthry_InlineTooltip.CQ84q5tx.js} +2 -2
  96. package/dist/{fthry_Overlay.Dms5dmjM.js → fthry_Overlay.CaTGHPrf.js} +1 -1
  97. package/dist/{fthry_PaymentMethodField.BnL3H5Wi.js → fthry_PaymentMethodField.CLy4llPE.js} +4 -4
  98. package/dist/{fthry_Placeholder.Iyh2B1Vg.js → fthry_Placeholder.C8DX1xTT.js} +1 -1
  99. package/dist/{fthry_ShowEyeIcon.fhgXiXP4.js → fthry_ShowEyeIcon.CLCEl1M3.js} +1 -1
  100. package/dist/{fthry_index.BYbi4yOb.js → fthry_index.8KDT5i8T.js} +4 -4
  101. package/dist/{fthry_index.C_xgfMIW.js → fthry_index.9-q7smC3.js} +3 -3
  102. package/dist/{fthry_index.BkMppX8l.js → fthry_index.B-oOxFi4.js} +528 -48
  103. package/dist/{fthry_index.B6oCJbWU.js → fthry_index.B260ADJ4.js} +5 -5
  104. package/dist/{fthry_index.BRU7YLIR.js → fthry_index.BZD_DEzj.js} +1 -1
  105. package/dist/{fthry_index.BOaXtIdq.js → fthry_index.BjpHx4_T.js} +5 -5
  106. package/dist/{fthry_index.C2gfdQbg.js → fthry_index.C1_uGweo.js} +1 -1
  107. package/dist/{fthry_index.DgW_Sk0D.js → fthry_index.C5zUlrOm.js} +1 -1
  108. package/dist/{fthry_index.DNgUGj0v.js → fthry_index.CLgjzDTi.js} +1 -1
  109. package/dist/{fthry_index.BB67IaKw.js → fthry_index.CYyOgKWx.js} +8 -8
  110. package/dist/{fthry_index.Cy3JGRX4.js → fthry_index.CeglQZhs.js} +1 -1
  111. package/dist/{fthry_index.DX4rqE80.js → fthry_index.CmpLevaj.js} +6 -6
  112. package/dist/{fthry_index.DOmt6TII.js → fthry_index.CqNn14xm.js} +6 -6
  113. package/dist/{fthry_index.BSFJ3j16.js → fthry_index.DKYX71gD.js} +4 -4
  114. package/dist/{fthry_index.DBZUNt6w.js → fthry_index.DQsvec3-.js} +3 -3
  115. package/dist/{fthry_index.BkscK5im.js → fthry_index.Ddf14JA6.js} +363 -54
  116. package/dist/{fthry_index.C40AmEzu.js → fthry_index.DmcD0QUi.js} +1 -1
  117. package/dist/{fthry_index.CRvWHGpG.js → fthry_index.DoGwIkbA.js} +6 -6
  118. package/dist/{fthry_index.CxmqmKxy.js → fthry_index.DqKZq0Ur.js} +4 -4
  119. package/dist/{fthry_index.B2Y9eDOP.js → fthry_index.WnliJHmX.js} +2 -2
  120. package/dist/{fthry_index.BLyrEbs8.js → fthry_index.hyYvw_PS.js} +1 -1
  121. package/dist/{fthry_index.BtNQk9j_.js → fthry_index.kP74GhA8.js} +5 -5
  122. package/dist/{fthry_index.fnKZHN9M.js → fthry_index.qJQlILVx.js} +5 -5
  123. package/dist/{fthry_index.B5mf0ZCq.js → fthry_index.ty8LJs-R.js} +2 -2
  124. package/dist/{fthry_input.BGGtX-3o.js → fthry_input.DjzutNam.js} +1 -1
  125. package/dist/{fthry_script.Dqr52s2y.js → fthry_script.DO2CsvZO.js} +1 -1
  126. package/dist/{fthry_styles.BY3ne7eH.js → fthry_styles.Ccd48IiB.js} +1 -1
  127. package/dist/{fthry_useElementSize.OjCA2DBM.js → fthry_useElementSize.C-0G4BJy.js} +1 -1
  128. package/dist/{fthry_useSalesforceSync.C09-2TZ5.js → fthry_useSalesforceSync.B6wBqJLI.js} +1 -1
  129. package/dist/{fthry_webfontloader.DIwhNN5h.js → fthry_webfontloader.MZhbLTEd.js} +1 -1
  130. package/dist/index.d.ts +0 -1
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +1 -1
  133. package/package.json +1 -1
  134. package/umd/{277.d9907ecd5dc2117c9171.js → 277.87e6ca5c1cf2a7477992.js} +1 -1
  135. package/umd/{509.a863f8749c28540476bb.js → 509.bca2ff43c66b1dba064f.js} +2 -2
  136. package/umd/{AddressField.ec97334fe233830bc05b.js → AddressField.2d777eda22a67a0ed3a3.js} +1 -1
  137. package/umd/{DateSelectorField.00f321e0b1972feb9d69.js → DateSelectorField.54afc978d2fd9d10b106.js} +1 -1
  138. package/umd/{FileUploadField.ea0067dd62b0454b7c2e.js → FileUploadField.7a5028fb6035d09b3e81.js} +1 -1
  139. package/umd/{PasswordField.1358356d6fbc6880f12a.js → PasswordField.7585ef588333cb4181f7.js} +1 -1
  140. package/umd/{PaymentMethodField.9a8e934f7450eb141217.js → PaymentMethodField.d08bcfa1efb56084572d.js} +1 -1
  141. package/umd/{PhoneField.c526085aaa5ccd25e982.js → PhoneField.19c987f04cfcb60ab07c.js} +1 -1
  142. package/umd/{SignatureField.d710930ca89642eb651c.js → SignatureField.0e7d60fa2fafcb6be554.js} +1 -1
  143. package/umd/TableElement.b9bb3cedf1a75fd2ea01.js +1 -0
  144. package/umd/{TextArea.f566845d458d4c00e0e7.js → TextArea.7cca0d69e618846660c5.js} +1 -1
  145. package/umd/{TextField.5a5296fe3ea60c4459f2.js → TextField.f5cc4a03e69d5872027b.js} +1 -1
  146. package/umd/index.js +1 -1
  147. package/umd/TableElement.ee77e0f53a9ccac846ab.js +0 -1
  148. /package/umd/{509.a863f8749c28540476bb.js.LICENSE.txt → 509.bca2ff43c66b1dba064f.js.LICENSE.txt} +0 -0
@@ -1,10 +1,15 @@
1
- import { _ as __assign, j as jsx, a as jsxs, F as Fragment, b as __read, f as featheryDoc, c as fieldValues, s as stringifyWithNull, d as __values, e as __spreadArray } from './fthry_index.BkscK5im.js';
2
- import { useState, useRef, useEffect, useMemo } from 'react';
1
+ import { _ as __rest, j as jsx, a as __assign, b as jsxs, F as Fragment, c as __read, f as featheryDoc, d as fieldValues, s as stringifyWithNull, e as __values, g as __spreadArray, h as featheryWindow } from './fthry_index.Ddf14JA6.js';
2
+ import { useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
  import 'react/jsx-runtime';
5
5
  import 'react-dom/client';
6
6
  import 'jszip';
7
7
 
8
+ function TrashIcon(_a) {
9
+ var _b = _a.width, width = _b === void 0 ? 16 : _b, _c = _a.height, height = _c === void 0 ? 16 : _c, props = __rest(_a, ["width", "height"]);
10
+ return (jsx("svg", __assign({ width: width, height: height, fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', strokeWidth: 2, xmlns: 'http://www.w3.org/2000/svg' }, props, { children: jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16' }) })));
11
+ }
12
+
8
13
  var colors = {
9
14
  white: '#ffffff',
10
15
  gray50: '#f9fafb',
@@ -16,7 +21,9 @@ var colors = {
16
21
  gray700: '#374151',
17
22
  gray900: '#111827',
18
23
  blue50: '#eff6ff',
19
- blue700: '#1d4ed8'
24
+ blue700: '#1d4ed8',
25
+ red500: '#ef4444',
26
+ red600: '#dc2626'
20
27
  };
21
28
  var searchIconStyle = {
22
29
  width: '16px',
@@ -75,12 +82,9 @@ var emptyStateTextStyle = {
75
82
  fontWeight: '500',
76
83
  margin: 0
77
84
  };
78
- var searchContainerStyle = {
79
- padding: '16px',
80
- borderBottom: "1px solid ".concat(colors.gray200)
81
- };
82
85
  var searchWrapperStyle = {
83
- position: 'relative'
86
+ position: 'relative',
87
+ flex: 1
84
88
  };
85
89
  var searchIconWrapperStyle = {
86
90
  position: 'absolute',
@@ -127,7 +131,8 @@ var theadStyle = {
127
131
  var thStyle = {
128
132
  padding: '12px 24px',
129
133
  fontWeight: '500',
130
- userSelect: 'none'
134
+ userSelect: 'none',
135
+ whiteSpace: 'nowrap'
131
136
  };
132
137
  var rowStyle = {
133
138
  backgroundColor: colors.white,
@@ -235,6 +240,14 @@ var actionMenuItemStyle = {
235
240
  borderBottomRightRadius: '4px'
236
241
  }
237
242
  };
243
+ var actionMenuSeparatorStyle = {
244
+ borderTop: "1px solid ".concat(colors.gray200),
245
+ margin: '4px 0'
246
+ };
247
+ var actionMenuDeleteItemStyle = __assign(__assign({}, actionMenuItemStyle), { color: colors.red500, '&:hover': {
248
+ backgroundColor: colors.gray100,
249
+ color: colors.red600
250
+ } });
238
251
  var actionIconButtonStyle = __assign(__assign({}, actionButtonStyle), { aspectRatio: 1, paddingLeft: 0, paddingRight: 0 });
239
252
  var actionContainerStyle = {
240
253
  display: 'flex',
@@ -259,6 +272,111 @@ var overflowSelectStyle = __assign(__assign({}, pageButtonStyle), { appearance:
259
272
  color: colors.gray900
260
273
  }, '&:focus': {
261
274
  outline: 'none'
275
+ } });
276
+ // Editing styles
277
+ var toolbarStyle = {
278
+ display: 'flex',
279
+ alignItems: 'center',
280
+ justifyContent: 'space-between',
281
+ padding: '16px',
282
+ borderBottom: "1px solid ".concat(colors.gray200),
283
+ gap: '12px'
284
+ };
285
+ var addRowButtonStyle = __assign(__assign({}, buttonStyle), { borderRadius: '8px', paddingLeft: '12px', paddingRight: '12px', whiteSpace: 'nowrap' });
286
+ var clickToEditStyle = {
287
+ color: colors.gray400,
288
+ cursor: 'pointer',
289
+ userSelect: 'none',
290
+ fontSize: '14px'
291
+ };
292
+ var cellInputStyle = {
293
+ width: '100%',
294
+ padding: '4px 8px',
295
+ border: "1px solid ".concat(colors.blue700),
296
+ borderRadius: '4px',
297
+ fontSize: '14px',
298
+ color: colors.gray900,
299
+ outline: 'none',
300
+ boxSizing: 'border-box'
301
+ };
302
+ var editableCellContentStyle = {
303
+ display: 'flex',
304
+ alignItems: 'center',
305
+ gap: '8px'
306
+ };
307
+ var overflowIconStyle = {
308
+ display: 'flex',
309
+ alignItems: 'center',
310
+ justifyContent: 'center',
311
+ width: '24px',
312
+ height: '24px',
313
+ borderRadius: '4px',
314
+ border: 'none',
315
+ backgroundColor: 'transparent',
316
+ color: colors.gray400,
317
+ cursor: 'pointer',
318
+ opacity: 0,
319
+ transition: 'opacity 0.15s',
320
+ flexShrink: 0,
321
+ padding: 0,
322
+ 'tr:hover &, &[aria-expanded="true"]': {
323
+ opacity: 1
324
+ },
325
+ '&:hover': {
326
+ backgroundColor: colors.gray100,
327
+ color: colors.gray600
328
+ }
329
+ };
330
+ var deleteColumnStyle = {
331
+ width: '40px',
332
+ padding: '0 8px'
333
+ };
334
+ var deleteIconStyle = {
335
+ display: 'flex',
336
+ alignItems: 'center',
337
+ justifyContent: 'center',
338
+ width: '28px',
339
+ height: '28px',
340
+ borderRadius: '4px',
341
+ border: 'none',
342
+ backgroundColor: 'transparent',
343
+ color: colors.gray400,
344
+ cursor: 'pointer',
345
+ opacity: 0,
346
+ transition: 'opacity 0.15s',
347
+ padding: 0,
348
+ 'tr:hover &': {
349
+ opacity: 1
350
+ },
351
+ '&:hover': {
352
+ backgroundColor: colors.gray100,
353
+ color: colors.red500
354
+ }
355
+ };
356
+ var confirmPopoverStyle = {
357
+ position: 'fixed',
358
+ backgroundColor: colors.white,
359
+ border: "1px solid ".concat(colors.gray300),
360
+ borderRadius: '8px',
361
+ boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
362
+ zIndex: 9999,
363
+ padding: '12px 16px'
364
+ };
365
+ var confirmTextStyle = {
366
+ margin: '0 0 12px 0',
367
+ fontSize: '14px',
368
+ fontWeight: '500',
369
+ color: colors.gray900
370
+ };
371
+ var confirmButtonRowStyle = {
372
+ display: 'flex',
373
+ gap: '8px',
374
+ justifyContent: 'flex-end'
375
+ };
376
+ var confirmCancelButtonStyle = __assign(__assign({}, buttonStyle), { borderRadius: '6px', paddingLeft: '12px', paddingRight: '12px', height: '32px' });
377
+ var confirmDeleteButtonStyle = __assign(__assign({}, buttonStyle), { borderRadius: '6px', paddingLeft: '12px', paddingRight: '12px', height: '32px', backgroundColor: colors.red500, color: colors.white, border: "1px solid ".concat(colors.red500), '&:hover': {
378
+ backgroundColor: colors.red600,
379
+ color: colors.white
262
380
  } });
263
381
 
264
382
  function SearchIcon() {
@@ -271,7 +389,7 @@ function Search(_a) {
271
389
  e.preventDefault();
272
390
  }
273
391
  };
274
- return (jsx("div", __assign({ css: searchContainerStyle }, { children: jsxs("div", __assign({ css: searchWrapperStyle }, { children: [jsx("div", __assign({ css: searchIconWrapperStyle }, { children: jsx(SearchIcon, {}) })), jsx("input", { type: 'text', css: searchInputStyle, placeholder: 'Search', value: searchQuery, onChange: function (e) { return onSearchChange(e.target.value); }, onKeyDown: handleKeyDown })] })) })));
392
+ return (jsxs("div", __assign({ css: searchWrapperStyle }, { children: [jsx("div", __assign({ css: searchIconWrapperStyle }, { children: jsx(SearchIcon, {}) })), jsx("input", { type: 'text', css: searchInputStyle, placeholder: 'Search', value: searchQuery, onChange: function (e) { return onSearchChange(e.target.value); }, onKeyDown: handleKeyDown })] })));
275
393
  }
276
394
 
277
395
  function SortIcon(_a) {
@@ -356,11 +474,11 @@ function MenuIcon() {
356
474
  }
357
475
  function ActionButtons(_a) {
358
476
  var _b, _c, _d;
359
- var actions = _a.actions, rowIndex = _a.rowIndex, columnData = _a.columnData, fieldValuesProp = _a.fieldValues, onClick = _a.onClick, _e = _a.forceInlineButtons, forceInlineButtons = _e === void 0 ? false : _e, _f = _a.tableId, tableId = _f === void 0 ? '' : _f, _g = _a.buttonLoaders, buttonLoaders = _g === void 0 ? {} : _g;
477
+ var actions = _a.actions, rowIndex = _a.rowIndex, columnData = _a.columnData, fieldValuesProp = _a.fieldValues, onClick = _a.onClick, _e = _a.forceInlineButtons, forceInlineButtons = _e === void 0 ? false : _e, _f = _a.tableId, tableId = _f === void 0 ? '' : _f, _g = _a.buttonLoaders, buttonLoaders = _g === void 0 ? {} : _g, _h = _a.canDeleteRows, canDeleteRows = _h === void 0 ? false : _h, onDeleteRow = _a.onDeleteRow;
360
478
  if (actions.length === 0)
361
479
  return null;
362
- var _h = __read(useState(false), 2), isMenuOpen = _h[0], setIsMenuOpen = _h[1];
363
- var _j = __read(useState({ top: 0, left: 0 }), 2), menuPosition = _j[0], setMenuPosition = _j[1];
480
+ var _j = __read(useState(false), 2), isMenuOpen = _j[0], setIsMenuOpen = _j[1];
481
+ var _k = __read(useState({ top: 0, left: 0 }), 2), menuPosition = _k[0], setMenuPosition = _k[1];
364
482
  var containerRef = useRef(null);
365
483
  var menuRef = useRef(null);
366
484
  var menuButtonRef = useRef(null);
@@ -427,13 +545,17 @@ function ActionButtons(_a) {
427
545
  alignItems: 'center',
428
546
  justifyContent: 'center'
429
547
  } }, { children: overflowLoader }))) : (jsx(MenuIcon, {})) })), isMenuOpen &&
430
- createPortal(jsx("div", __assign({ ref: menuRef, css: __assign(__assign({}, actionMenuStyle), { top: "".concat(menuPosition.top, "px"), left: "".concat(menuPosition.left, "px"), transform: 'translateX(-100%)' }) }, { children: actions.map(function (action, index) {
431
- var disabled = Object.keys(buttonLoaders).length > 0;
432
- return (jsx("button", __assign({ type: 'button', onClick: function (e) {
433
- e.stopPropagation();
434
- handleActionClick(action);
435
- }, css: actionMenuItemStyle, disabled: disabled }, { children: action.label }), index));
436
- }) })), featheryDoc().body)] })) : (actions.map(function (action, index) {
548
+ createPortal(jsxs("div", __assign({ ref: menuRef, css: __assign(__assign({}, actionMenuStyle), { top: "".concat(menuPosition.top, "px"), left: "".concat(menuPosition.left, "px"), transform: 'translateX(-100%)' }) }, { children: [actions.map(function (action, index) {
549
+ var disabled = Object.keys(buttonLoaders).length > 0;
550
+ return (jsx("button", __assign({ type: 'button', onClick: function (e) {
551
+ e.stopPropagation();
552
+ handleActionClick(action);
553
+ }, css: actionMenuItemStyle, disabled: disabled }, { children: action.label }), index));
554
+ }), canDeleteRows && onDeleteRow && (jsxs(Fragment, { children: [jsx("div", { css: actionMenuSeparatorStyle }), jsx("button", __assign({ type: 'button', onClick: function (e) {
555
+ e.stopPropagation();
556
+ setIsMenuOpen(false);
557
+ onDeleteRow(rowIndex);
558
+ }, css: actionMenuDeleteItemStyle }, { children: "Delete" }))] }))] })), featheryDoc().body)] })) : (actions.map(function (action, index) {
437
559
  var _a;
438
560
  var buttonKey = "".concat(tableId, "_").concat(rowIndex, "_").concat(action.label);
439
561
  var loader = (_a = buttonLoaders[buttonKey]) === null || _a === void 0 ? void 0 : _a.loader;
@@ -462,6 +584,153 @@ function EmptyState(_a) {
462
584
  }, fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', strokeWidth: 1.5 }, { children: jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z' }) }))), jsx("p", __assign({ css: emptyStateTextStyle }, { children: hasSearchQuery ? 'No results found' : 'No data available' })), hasSearchQuery && (jsx("p", __assign({ css: __assign(__assign({}, emptyStateTextStyle), { fontSize: '14px', marginTop: '8px' }) }, { children: "Try adjusting your search query" })))] })));
463
585
  }
464
586
 
587
+ function DeleteConfirm(_a) {
588
+ var anchorEl = _a.anchorEl, onConfirm = _a.onConfirm, onCancel = _a.onCancel, _b = _a.message, message = _b === void 0 ? 'Delete this row?' : _b, _c = _a.confirmLabel, confirmLabel = _c === void 0 ? 'Delete' : _c;
589
+ var popoverRef = useRef(null);
590
+ if (!anchorEl)
591
+ return null;
592
+ var anchorRect = anchorEl.getBoundingClientRect();
593
+ var top = anchorRect.bottom + 4;
594
+ var left = anchorRect.right;
595
+ useEffect(function () {
596
+ var handleClickOutside = function (event) {
597
+ if (popoverRef.current &&
598
+ !popoverRef.current.contains(event.target) &&
599
+ anchorEl &&
600
+ !anchorEl.contains(event.target)) {
601
+ onCancel();
602
+ }
603
+ };
604
+ var handleScroll = function () { return onCancel(); };
605
+ var handleKeyDown = function (event) {
606
+ if (event.key === 'Escape')
607
+ onCancel();
608
+ };
609
+ var doc = featheryDoc();
610
+ doc.addEventListener('mousedown', handleClickOutside);
611
+ doc.addEventListener('scroll', handleScroll, true);
612
+ doc.addEventListener('keydown', handleKeyDown);
613
+ return function () {
614
+ doc.removeEventListener('mousedown', handleClickOutside);
615
+ doc.removeEventListener('scroll', handleScroll, true);
616
+ doc.removeEventListener('keydown', handleKeyDown);
617
+ };
618
+ }, [onCancel, anchorEl]);
619
+ return createPortal(jsxs("div", __assign({ ref: popoverRef, role: 'alertdialog', "aria-label": message, css: __assign(__assign({}, confirmPopoverStyle), { top: "".concat(top, "px"), left: "".concat(left, "px"), transform: 'translateX(-100%)' }) }, { children: [jsx("p", __assign({ css: confirmTextStyle }, { children: message })), jsxs("div", __assign({ css: confirmButtonRowStyle }, { children: [jsx("button", __assign({ type: 'button', css: confirmCancelButtonStyle, onClick: function (e) {
620
+ e.stopPropagation();
621
+ onCancel();
622
+ } }, { children: "Cancel" })), jsx("button", __assign({ type: 'button', css: confirmDeleteButtonStyle, onClick: function (e) {
623
+ e.stopPropagation();
624
+ onConfirm();
625
+ } }, { children: confirmLabel }))] }))] })), featheryDoc().body);
626
+ }
627
+
628
+ function OverflowIcon() {
629
+ return (jsxs("svg", __assign({ width: '16', height: '16', fill: 'currentColor', viewBox: '0 0 24 24' }, { children: [jsx("circle", { cx: '12', cy: '5', r: '2' }), jsx("circle", { cx: '12', cy: '12', r: '2' }), jsx("circle", { cx: '12', cy: '19', r: '2' })] })));
630
+ }
631
+ function EditableCell(_a) {
632
+ var _b;
633
+ var value = _a.value, fieldKey = _a.fieldKey, rowIndex = _a.rowIndex, onEdit = _a.onEdit, onClear = _a.onClear;
634
+ var _c = __read(useState(false), 2), isEditing = _c[0], setIsEditing = _c[1];
635
+ var _d = __read(useState(''), 2), editValue = _d[0], setEditValue = _d[1];
636
+ var _e = __read(useState(false), 2), isMenuOpen = _e[0], setIsMenuOpen = _e[1];
637
+ var _f = __read(useState(false), 2), showClearConfirm = _f[0], setShowClearConfirm = _f[1];
638
+ var _g = __read(useState({ top: 0, left: 0 }), 2), menuPosition = _g[0], setMenuPosition = _g[1];
639
+ var inputRef = useRef(null);
640
+ var menuButtonRef = useRef(null);
641
+ var menuRef = useRef(null);
642
+ var shouldSaveRef = useRef(true);
643
+ var closeClearConfirm = useCallback(function () { return setShowClearConfirm(false); }, []);
644
+ var displayValue = (_b = stringifyWithNull(value)) !== null && _b !== void 0 ? _b : '';
645
+ var isEmpty = displayValue === '';
646
+ useEffect(function () {
647
+ if (isEditing && inputRef.current) {
648
+ inputRef.current.focus();
649
+ }
650
+ }, [isEditing]);
651
+ useEffect(function () {
652
+ if (!isMenuOpen)
653
+ return;
654
+ var handleClickOutside = function (event) {
655
+ if (menuRef.current &&
656
+ !menuRef.current.contains(event.target) &&
657
+ menuButtonRef.current &&
658
+ !menuButtonRef.current.contains(event.target)) {
659
+ setIsMenuOpen(false);
660
+ }
661
+ };
662
+ var handleScroll = function () { return setIsMenuOpen(false); };
663
+ var doc = featheryDoc();
664
+ doc.addEventListener('mousedown', handleClickOutside);
665
+ doc.addEventListener('scroll', handleScroll, true);
666
+ return function () {
667
+ doc.removeEventListener('mousedown', handleClickOutside);
668
+ doc.removeEventListener('scroll', handleScroll, true);
669
+ };
670
+ }, [isMenuOpen]);
671
+ var startEditing = function () {
672
+ setEditValue(displayValue);
673
+ setIsEditing(true);
674
+ setIsMenuOpen(false);
675
+ };
676
+ var saveEdit = function () {
677
+ if (editValue !== displayValue) {
678
+ onEdit(fieldKey, rowIndex, editValue);
679
+ }
680
+ setIsEditing(false);
681
+ };
682
+ var cancelEdit = function () {
683
+ shouldSaveRef.current = false;
684
+ setIsEditing(false);
685
+ };
686
+ var handleBlur = function () {
687
+ if (shouldSaveRef.current)
688
+ saveEdit();
689
+ shouldSaveRef.current = true;
690
+ };
691
+ var handleKeyDown = function (e) {
692
+ if (e.key === 'Enter') {
693
+ e.preventDefault();
694
+ shouldSaveRef.current = false;
695
+ saveEdit();
696
+ }
697
+ else if (e.key === 'Escape') {
698
+ e.preventDefault();
699
+ cancelEdit();
700
+ }
701
+ else if (e.key === 'Tab') {
702
+ shouldSaveRef.current = false;
703
+ saveEdit();
704
+ }
705
+ };
706
+ var handleMenuToggle = function (e) {
707
+ e.stopPropagation();
708
+ if (!isMenuOpen && menuButtonRef.current) {
709
+ var rect = menuButtonRef.current.getBoundingClientRect();
710
+ setMenuPosition({ top: rect.bottom + 4, left: rect.right });
711
+ }
712
+ setIsMenuOpen(!isMenuOpen);
713
+ };
714
+ if (isEditing) {
715
+ return (jsx("input", { ref: inputRef, type: 'text', value: editValue, onChange: function (e) { return setEditValue(e.target.value); }, onBlur: handleBlur, onKeyDown: handleKeyDown, css: cellInputStyle, onClick: function (e) { return e.stopPropagation(); } }));
716
+ }
717
+ if (isEmpty) {
718
+ return (jsx("span", __assign({ css: clickToEditStyle, onClick: startEditing }, { children: "Click to edit" })));
719
+ }
720
+ return (jsxs("div", __assign({ css: editableCellContentStyle }, { children: [jsx("span", __assign({ css: { flex: 1, minWidth: 0 } }, { children: displayValue })), jsx("button", __assign({ ref: menuButtonRef, type: 'button', "aria-expanded": isMenuOpen, "aria-haspopup": 'menu', css: overflowIconStyle, onClick: handleMenuToggle }, { children: jsx(OverflowIcon, {}) })), isMenuOpen &&
721
+ createPortal(jsxs("div", __assign({ ref: menuRef, role: 'menu', css: __assign(__assign({}, actionMenuStyle), { top: "".concat(menuPosition.top, "px"), left: "".concat(menuPosition.left, "px"), transform: 'translateX(-100%)' }) }, { children: [jsx("button", __assign({ type: 'button', role: 'menuitem', css: actionMenuItemStyle, onClick: function (e) {
722
+ e.stopPropagation();
723
+ startEditing();
724
+ } }, { children: "Edit Value" })), jsx("button", __assign({ type: 'button', role: 'menuitem', css: actionMenuItemStyle, onClick: function (e) {
725
+ e.stopPropagation();
726
+ setIsMenuOpen(false);
727
+ setShowClearConfirm(true);
728
+ } }, { children: "Clear Field" }))] })), featheryDoc().body), showClearConfirm && (jsx(DeleteConfirm, { anchorEl: menuButtonRef.current, message: 'Clear this field?', confirmLabel: 'Clear', onConfirm: function () {
729
+ closeClearConfirm();
730
+ onClear(fieldKey, rowIndex);
731
+ }, onCancel: closeClearConfirm }))] })));
732
+ }
733
+
465
734
  // Utility functions for sorting strings as numbers and dates
466
735
  function tryParseNumber(value) {
467
736
  if (value === null || value === undefined || value === '')
@@ -652,14 +921,16 @@ function setCachedPage(elementId, page) {
652
921
  sessionStorage.setItem(key, page.toString());
653
922
  }
654
923
  function useTableData(_a) {
655
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
656
- var element = _a.element, _m = _a.editMode, editMode = _m === void 0 ? false : _m;
924
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
925
+ var element = _a.element, _r = _a.editMode, editMode = _r === void 0 ? false : _r, _s = _a.dataVersion, dataVersion = _s === void 0 ? 0 : _s;
657
926
  var userColumns = ((_b = element.properties) === null || _b === void 0 ? void 0 : _b.columns) || [];
658
927
  var actions = (((_c = element.properties) === null || _c === void 0 ? void 0 : _c.actions) || []).filter(function (action) { return action.label && action.label.trim() !== ''; });
659
928
  var enableSearch = (_e = (_d = element.properties) === null || _d === void 0 ? void 0 : _d.search) !== null && _e !== void 0 ? _e : false;
660
929
  var enableSort = (_g = (_f = element.properties) === null || _f === void 0 ? void 0 : _f.sort) !== null && _g !== void 0 ? _g : false;
661
930
  var enableTranspose = (_j = (_h = element.properties) === null || _h === void 0 ? void 0 : _h.transpose) !== null && _j !== void 0 ? _j : false;
662
- var paginationSetting = (_l = (_k = element.properties) === null || _k === void 0 ? void 0 : _k.pagination) !== null && _l !== void 0 ? _l : 0;
931
+ var enableEditing = (_l = (_k = element.properties) === null || _k === void 0 ? void 0 : _k.enable_editing) !== null && _l !== void 0 ? _l : false;
932
+ var enableAddDeleteRows = (_o = (_m = element.properties) === null || _m === void 0 ? void 0 : _m.add_delete_rows) !== null && _o !== void 0 ? _o : false;
933
+ var paginationSetting = (_q = (_p = element.properties) === null || _p === void 0 ? void 0 : _p.pagination) !== null && _q !== void 0 ? _q : 0;
663
934
  var rowsPerPage = typeof paginationSetting === 'number' && paginationSetting > 0
664
935
  ? Math.floor(paginationSetting)
665
936
  : 0;
@@ -672,19 +943,20 @@ function useTableData(_a) {
672
943
  }
673
944
  return cols;
674
945
  }, [editMode, userColumns]);
675
- // Use example data in edit mode
946
+ // fieldValues is mutated outside React state, so we need dataVersion
947
+ // as a manual dirty flag to trigger re-snapshots
676
948
  var baseFieldValues = useMemo(function () {
677
949
  if (editMode) {
678
950
  return generateExampleData(baseColumns);
679
951
  }
680
- return fieldValues;
681
- }, [editMode, baseColumns, userColumns.length]);
682
- var _o = __read(useState(''), 2), searchQuery = _o[0], setSearchQuery = _o[1];
683
- var _p = __read(useState(null), 2), sortColumn = _p[0], setSortColumn = _p[1];
684
- var _q = __read(useState('asc'), 2), sortDirection = _q[0], setSortDirection = _q[1];
685
- var _r = __read(useState(function () {
952
+ return __assign({}, fieldValues);
953
+ }, [editMode, baseColumns, dataVersion]);
954
+ var _t = __read(useState(''), 2), searchQuery = _t[0], setSearchQuery = _t[1];
955
+ var _u = __read(useState(null), 2), sortColumn = _u[0], setSortColumn = _u[1];
956
+ var _v = __read(useState('asc'), 2), sortDirection = _v[0], setSortDirection = _v[1];
957
+ var _w = __read(useState(function () {
686
958
  return getCachedPage(element.id);
687
- }), 2), currentPage = _r[0], setCurrentPage = _r[1];
959
+ }), 2), currentPage = _w[0], setCurrentPage = _w[1];
688
960
  var baseNumRows = useMemo(function () {
689
961
  return baseColumns.reduce(function (maxRows, column) {
690
962
  var fieldValue = baseFieldValues[column.field_key];
@@ -720,7 +992,7 @@ function useTableData(_a) {
720
992
  enableSearch,
721
993
  baseFieldValues
722
994
  ]);
723
- var _s = __read(useState(null), 2), sortedColumnIndex = _s[0], setSortedColumnIndex = _s[1];
995
+ var _x = __read(useState(null), 2), sortedColumnIndex = _x[0], setSortedColumnIndex = _x[1];
724
996
  var sortedBaseRowIndices = useMemo(function () {
725
997
  if (!enableTranspose || !enableSort || sortedColumnIndex === null) {
726
998
  return filteredBaseRowIndices;
@@ -760,7 +1032,7 @@ function useTableData(_a) {
760
1032
  rowsPerPage,
761
1033
  enablePagination
762
1034
  ]);
763
- var _t = useMemo(function () {
1035
+ var _y = useMemo(function () {
764
1036
  if (!enableTranspose || baseNumRows === 0) {
765
1037
  return {
766
1038
  columns: baseColumns,
@@ -780,7 +1052,7 @@ function useTableData(_a) {
780
1052
  baseFieldValues,
781
1053
  baseNumRows,
782
1054
  paginatedBaseRowIndices
783
- ]), columns = _t.columns, activeFieldValues = _t.activeFieldValues, transposedRowIndices = _t.transposedRowIndices;
1055
+ ]), columns = _y.columns, activeFieldValues = _y.activeFieldValues, transposedRowIndices = _y.transposedRowIndices;
784
1056
  var numRows = useMemo(function () {
785
1057
  return columns.reduce(function (maxRows, column) {
786
1058
  var fieldValue = activeFieldValues[column.field_key];
@@ -961,6 +1233,8 @@ function useTableData(_a) {
961
1233
  actions: actions,
962
1234
  isTransposed: isTransposed,
963
1235
  transposedRowIndices: transposedRowIndices,
1236
+ enableEditing: enableEditing,
1237
+ enableAddDeleteRows: enableAddDeleteRows,
964
1238
  totalRows: totalRows,
965
1239
  totalPages: totalPages,
966
1240
  hasData: hasData,
@@ -970,24 +1244,209 @@ function useTableData(_a) {
970
1244
  };
971
1245
  }
972
1246
 
1247
+ function useTableMutations(_a) {
1248
+ var columns = _a.columns, updateFieldValues = _a.updateFieldValues, submitCustom = _a.submitCustom, editMode = _a.editMode, editModeFieldValues = _a.editModeFieldValues, enablePagination = _a.enablePagination, setCurrentPage = _a.setCurrentPage, setSearchQuery = _a.setSearchQuery, searchQuery = _a.searchQuery, onMutate = _a.onMutate;
1249
+ var editModeFieldValuesRef = useRef(editModeFieldValues);
1250
+ editModeFieldValuesRef.current = editModeFieldValues;
1251
+ var getFieldArray = useCallback(function (fieldKey) {
1252
+ var source = editMode ? editModeFieldValuesRef.current : fieldValues;
1253
+ var val = source[fieldKey];
1254
+ return Array.isArray(val) ? val : [];
1255
+ }, [editMode]);
1256
+ var handleAddRow = useCallback(function () {
1257
+ var updates = {};
1258
+ columns.forEach(function (col) {
1259
+ var existing = getFieldArray(col.field_key);
1260
+ updates[col.field_key] = __spreadArray([''], __read(existing), false);
1261
+ });
1262
+ // Clear search so the new row is visible
1263
+ if (searchQuery)
1264
+ setSearchQuery('');
1265
+ // No submitCustom — new rows are provisional until the user edits a cell,
1266
+ // avoiding empty-row noise in the backend
1267
+ updateFieldValues(updates);
1268
+ onMutate();
1269
+ // Navigate to first page where the new row appears
1270
+ if (enablePagination)
1271
+ setCurrentPage(0);
1272
+ }, [
1273
+ columns,
1274
+ getFieldArray,
1275
+ updateFieldValues,
1276
+ onMutate,
1277
+ enablePagination,
1278
+ setCurrentPage,
1279
+ setSearchQuery,
1280
+ searchQuery
1281
+ ]);
1282
+ var buildRowRemovalUpdates = useCallback(function (rowIndex) {
1283
+ var updates = {};
1284
+ columns.forEach(function (col) {
1285
+ var existing = getFieldArray(col.field_key);
1286
+ updates[col.field_key] = existing.filter(function (_, i) { return i !== rowIndex; });
1287
+ });
1288
+ return updates;
1289
+ }, [columns, getFieldArray]);
1290
+ var handleDeleteRow = useCallback(function (rowIndex) {
1291
+ var updates = buildRowRemovalUpdates(rowIndex);
1292
+ updateFieldValues(updates);
1293
+ if (!editMode)
1294
+ submitCustom(updates);
1295
+ onMutate();
1296
+ }, [
1297
+ buildRowRemovalUpdates,
1298
+ updateFieldValues,
1299
+ submitCustom,
1300
+ editMode,
1301
+ onMutate
1302
+ ]);
1303
+ var handleRemoveRowLocal = useCallback(function (rowIndex) {
1304
+ var updates = buildRowRemovalUpdates(rowIndex);
1305
+ updateFieldValues(updates);
1306
+ onMutate();
1307
+ }, [buildRowRemovalUpdates, updateFieldValues, onMutate]);
1308
+ var handleCellEdit = useCallback(function (fieldKey, rowIndex, newValue) {
1309
+ var _a;
1310
+ var existing = getFieldArray(fieldKey);
1311
+ var updated = __spreadArray([], __read(existing), false);
1312
+ updated[rowIndex] = newValue;
1313
+ var values = (_a = {}, _a[fieldKey] = updated, _a);
1314
+ updateFieldValues(values);
1315
+ if (!editMode)
1316
+ submitCustom(values);
1317
+ onMutate();
1318
+ }, [getFieldArray, updateFieldValues, submitCustom, editMode, onMutate]);
1319
+ var handleCellClear = useCallback(function (fieldKey, rowIndex) {
1320
+ handleCellEdit(fieldKey, rowIndex, '');
1321
+ }, [handleCellEdit]);
1322
+ return {
1323
+ handleAddRow: handleAddRow,
1324
+ handleDeleteRow: handleDeleteRow,
1325
+ handleRemoveRowLocal: handleRemoveRowLocal,
1326
+ handleCellEdit: handleCellEdit,
1327
+ handleCellClear: handleCellClear
1328
+ };
1329
+ }
1330
+
1331
+ /**
1332
+ * Measures column widths from the browser's auto layout, then locks them
1333
+ * for use with table-layout: fixed. Re-measures when columnCount changes.
1334
+ */
1335
+ function useColumnWidths(tableRef, columnCount) {
1336
+ var _a = __read(useState(null), 2), widths = _a[0], setWidths = _a[1];
1337
+ var prevColumnCount = useRef(columnCount);
1338
+ if (prevColumnCount.current !== columnCount) {
1339
+ prevColumnCount.current = columnCount;
1340
+ setWidths(null);
1341
+ }
1342
+ useLayoutEffect(function () {
1343
+ var _a;
1344
+ if (widths !== null)
1345
+ return;
1346
+ var win = featheryWindow();
1347
+ if (!win || typeof win.getComputedStyle !== 'function')
1348
+ return;
1349
+ var table = tableRef.current;
1350
+ if (!table)
1351
+ return;
1352
+ var headerRow = (_a = table.querySelector('thead tr')) !== null && _a !== void 0 ? _a : table.querySelector('tbody tr');
1353
+ if (!headerRow)
1354
+ return;
1355
+ var measured = [];
1356
+ for (var i = 0; i < headerRow.children.length; i++) {
1357
+ measured.push(headerRow.children[i].getBoundingClientRect().width);
1358
+ }
1359
+ if (measured.length > 0)
1360
+ setWidths(measured);
1361
+ }, [widths, columnCount]);
1362
+ return widths;
1363
+ }
1364
+
973
1365
  function applyTableStyles(responsiveStyles) {
974
1366
  responsiveStyles.addTargets('table', 'thead', 'tbody', 'th', 'td', 'tr');
975
1367
  return responsiveStyles;
976
1368
  }
977
1369
  function TableElement(_a) {
978
- var element = _a.element, responsiveStyles = _a.responsiveStyles, _b = _a.onClick, onClick = _b === void 0 ? function () { } : _b, _c = _a.editMode, editMode = _c === void 0 ? false : _c, _d = _a.buttonLoaders, buttonLoaders = _d === void 0 ? {} : _d;
1370
+ var element = _a.element, responsiveStyles = _a.responsiveStyles, _b = _a.onClick, onClick = _b === void 0 ? function () { } : _b, _c = _a.updateFieldValues, updateFieldValues = _c === void 0 ? function () { } : _c, _d = _a.submitCustom, submitCustom = _d === void 0 ? function () { } : _d, _e = _a.editMode, editMode = _e === void 0 ? false : _e, _f = _a.buttonLoaders, buttonLoaders = _f === void 0 ? {} : _f;
979
1371
  var styles = useMemo(function () { return applyTableStyles(responsiveStyles); }, [responsiveStyles]);
980
- var _e = useTableData({ element: element, editMode: editMode }),
1372
+ var _g = __read(useState(0), 2), dataVersion = _g[0], setDataVersion = _g[1];
1373
+ var onMutate = useCallback(function () { return setDataVersion(function (v) { return v + 1; }); }, []);
1374
+ var _h = useTableData({ element: element, editMode: editMode, dataVersion: dataVersion }),
981
1375
  // search
982
- enableSearch = _e.enableSearch, searchQuery = _e.searchQuery, setSearchQuery = _e.setSearchQuery,
1376
+ enableSearch = _h.enableSearch, searchQuery = _h.searchQuery, setSearchQuery = _h.setSearchQuery,
983
1377
  // sort
984
- enableSort = _e.enableSort, sortColumn = _e.sortColumn, sortDirection = _e.sortDirection, sortedColumnIndex = _e.sortedColumnIndex, handleSort = _e.handleSort, handleTransposedSort = _e.handleTransposedSort,
1378
+ enableSort = _h.enableSort, sortColumn = _h.sortColumn, sortDirection = _h.sortDirection, sortedColumnIndex = _h.sortedColumnIndex, handleSort = _h.handleSort, handleTransposedSort = _h.handleTransposedSort,
985
1379
  // pagination
986
- enablePagination = _e.enablePagination, currentPage = _e.currentPage, setCurrentPage = _e.setCurrentPage, paginatedRowIndices = _e.paginatedRowIndices, rowsPerPage = _e.rowsPerPage,
1380
+ enablePagination = _h.enablePagination, currentPage = _h.currentPage, setCurrentPage = _h.setCurrentPage, paginatedRowIndices = _h.paginatedRowIndices, rowsPerPage = _h.rowsPerPage,
1381
+ // editing
1382
+ enableEditing = _h.enableEditing, enableAddDeleteRows = _h.enableAddDeleteRows,
987
1383
  // data
988
- columns = _e.columns, actions = _e.actions, isTransposed = _e.isTransposed, transposedRowIndices = _e.transposedRowIndices, totalRows = _e.totalRows, totalPages = _e.totalPages, hasData = _e.hasData, hasSearchResults = _e.hasSearchResults, activeFieldValues = _e.activeFieldValues, baseColumns = _e.baseColumns, baseFieldValues = _e.baseFieldValues;
989
- var showEmptyState = !hasData || (hasData && !hasSearchResults);
990
- return (jsx("div", __assign({ css: __assign(__assign({}, containerStyle), styles.getTarget('container')) }, { children: jsxs("div", __assign({ css: { minWidth: 'fit-content' } }, { children: [enableSearch && (jsx(Search, { searchQuery: searchQuery, onSearchChange: setSearchQuery })), showEmptyState ? (jsx(EmptyState, { hasSearchQuery: searchQuery.trim().length > 0 })) : (jsxs("table", __assign({ css: __assign(__assign({}, tableStyle), styles.getTarget('table')) }, { children: [!isTransposed && (jsx("thead", __assign({ css: theadStyle }, { children: jsxs("tr", { children: [jsx(SortHeader, { columns: columns, enableSort: enableSort, sortColumn: sortColumn, sortDirection: sortDirection, onSort: handleSort, styles: styles }), actions.length > 0 && (jsx("th", { scope: 'col', css: __assign(__assign(__assign({}, thStyle), { paddingLeft: 0 }), styles.getTarget('th')) }))] }) }))), jsxs("tbody", __assign({ css: styles.getTarget('tbody') }, { children: [paginatedRowIndices.map(function (rowIndex) {
1384
+ columns = _h.columns, actions = _h.actions, isTransposed = _h.isTransposed, transposedRowIndices = _h.transposedRowIndices, totalRows = _h.totalRows, totalPages = _h.totalPages, hasData = _h.hasData, hasSearchResults = _h.hasSearchResults, activeFieldValues = _h.activeFieldValues, baseColumns = _h.baseColumns, baseFieldValues = _h.baseFieldValues;
1385
+ var _j = useTableMutations({
1386
+ columns: baseColumns,
1387
+ updateFieldValues: updateFieldValues,
1388
+ submitCustom: submitCustom,
1389
+ editMode: editMode,
1390
+ editModeFieldValues: activeFieldValues,
1391
+ enablePagination: enablePagination,
1392
+ setCurrentPage: setCurrentPage,
1393
+ setSearchQuery: setSearchQuery,
1394
+ searchQuery: searchQuery,
1395
+ onMutate: onMutate
1396
+ }), handleAddRow = _j.handleAddRow, handleDeleteRow = _j.handleDeleteRow, handleCellEdit = _j.handleCellEdit, handleCellClear = _j.handleCellClear;
1397
+ var canEdit = enableEditing && !isTransposed;
1398
+ var showAddRow = canEdit && enableAddDeleteRows;
1399
+ var canDeleteRows = canEdit && enableAddDeleteRows;
1400
+ var hasOverflowMenu = actions.length > 1;
1401
+ var showStandaloneDeleteColumn = canDeleteRows && !hasOverflowMenu;
1402
+ var _k = __read(useState(new Set()), 2), pendingAddRows = _k[0], setPendingAddRows = _k[1];
1403
+ var pendingAddRowsRef = useRef(pendingAddRows);
1404
+ pendingAddRowsRef.current = pendingAddRows;
1405
+ var wrappedHandleCellEdit = useCallback(function (fieldKey, rowIndex, newValue) {
1406
+ if (pendingAddRowsRef.current.has(rowIndex)) {
1407
+ setPendingAddRows(function (prev) {
1408
+ var next = new Set(prev);
1409
+ next.delete(rowIndex);
1410
+ return next;
1411
+ });
1412
+ }
1413
+ handleCellEdit(fieldKey, rowIndex, newValue);
1414
+ }, [handleCellEdit]);
1415
+ var _l = __read(useState(null), 2), deleteRowIndex = _l[0], setDeleteRowIndex = _l[1];
1416
+ var prevPageRef = useRef(currentPage);
1417
+ if (prevPageRef.current !== currentPage) {
1418
+ prevPageRef.current = currentPage;
1419
+ setDeleteRowIndex(null);
1420
+ }
1421
+ var handleCancelDelete = useCallback(function () { return setDeleteRowIndex(null); }, []);
1422
+ var deleteIconRefs = useRef(new Map());
1423
+ var actionCellRefs = useRef(new Map());
1424
+ var showEmptyState = !hasData || !hasSearchResults;
1425
+ var showToolbar = enableSearch || showAddRow;
1426
+ var tableRef = useRef(null);
1427
+ var visibleColumnCount = columns.length +
1428
+ (!isTransposed && actions.length > 0 ? 1 : 0) +
1429
+ (showStandaloneDeleteColumn ? 1 : 0);
1430
+ var columnWidths = useColumnWidths(tableRef, visibleColumnCount);
1431
+ return (jsxs("div", __assign({ css: __assign(__assign({}, containerStyle), styles.getTarget('container')) }, { children: [showToolbar && (jsxs("div", __assign({ css: toolbarStyle }, { children: [enableSearch ? (jsx(Search, { searchQuery: searchQuery, onSearchChange: setSearchQuery })) : (jsx("div", {})), showAddRow && (jsx("button", __assign({ type: 'button', css: addRowButtonStyle, onClick: function () {
1432
+ setDeleteRowIndex(null);
1433
+ handleAddRow();
1434
+ setPendingAddRows(function (prev) {
1435
+ var next = new Set();
1436
+ next.add(0);
1437
+ prev.forEach(function (idx) { return next.add(idx + 1); });
1438
+ return next;
1439
+ });
1440
+ } }, { children: "+ Add Row" })))] }))), showEmptyState ? (jsx(EmptyState, { hasSearchQuery: searchQuery.trim().length > 0 })) : (jsx("div", __assign({ css: { overflowX: 'auto' } }, { children: jsxs("table", __assign({ ref: tableRef, css: __assign(__assign(__assign({}, tableStyle), (columnWidths
1441
+ ? {
1442
+ tableLayout: 'fixed',
1443
+ minWidth: "".concat(columnWidths.reduce(function (a, b) { return a + b; }, 0), "px")
1444
+ }
1445
+ : {
1446
+ tableLayout: 'auto',
1447
+ width: 'max-content'
1448
+ })), styles.getTarget('table')) }, { children: [columnWidths && (jsx("colgroup", { children: columnWidths.map(function (w, i) { return (jsx("col", { style: { width: "".concat(w, "px") } }, i)); }) })), !isTransposed && (jsx("thead", __assign({ css: theadStyle }, { children: jsxs("tr", { children: [jsx(SortHeader, { columns: columns, enableSort: enableSort, sortColumn: sortColumn, sortDirection: sortDirection, onSort: handleSort, styles: styles }), actions.length > 0 && (jsx("th", { scope: 'col', css: __assign(__assign(__assign({}, thStyle), { paddingLeft: 0 }), styles.getTarget('th')) })), showStandaloneDeleteColumn && (jsx("th", { scope: 'col', css: __assign(__assign(__assign({}, thStyle), deleteColumnStyle), styles.getTarget('th')) }))] }) }))), jsxs("tbody", __assign({ css: styles.getTarget('tbody') }, { children: [paginatedRowIndices.map(function (rowIndex) {
1449
+ var _a, _b;
991
1450
  var rowData = {};
992
1451
  if (!isTransposed) {
993
1452
  columns.forEach(function (col) {
@@ -999,7 +1458,7 @@ function TableElement(_a) {
999
1458
  });
1000
1459
  }
1001
1460
  var handleRowClick = function () {
1002
- if (!isTransposed) {
1461
+ if (!isTransposed && !canEdit) {
1003
1462
  onClick({
1004
1463
  rowIndex: rowIndex,
1005
1464
  rowData: rowData
@@ -1017,7 +1476,6 @@ function TableElement(_a) {
1017
1476
  var isSorted = sortedColumnIndex === rowIndex;
1018
1477
  var isFirstColumn = colIndex === 0;
1019
1478
  var isSecondColumn = colIndex === 1;
1020
- // In transposed mode, get the original row index from the column
1021
1479
  var originalRowIndex = isTransposed && !isFirstColInTranspose
1022
1480
  ? column.originalRowIndex
1023
1481
  : undefined;
@@ -1038,7 +1496,6 @@ function TableElement(_a) {
1038
1496
  }
1039
1497
  else if (isTransposed &&
1040
1498
  originalRowIndex !== undefined) {
1041
- // In transposed mode, clicking a cell triggers with original row data
1042
1499
  e.stopPropagation();
1043
1500
  var originalRowData_1 = {};
1044
1501
  baseColumns.forEach(function (col) {
@@ -1054,9 +1511,32 @@ function TableElement(_a) {
1054
1511
  });
1055
1512
  }
1056
1513
  };
1057
- return (jsx(CellElement, __assign({ css: cellCss, onClick: handleCellClick }, (isFirstColInTranspose ? { scope: 'row' } : {}), { children: isFirstColInTranspose && isSortable ? (jsxs("div", __assign({ css: __assign(__assign({}, sortHeaderContentStyle), { justifyContent: 'space-between' }) }, { children: [jsx("span", { children: (_a = stringifyWithNull(cellValue)) !== null && _a !== void 0 ? _a : '' }), jsx("span", __assign({ css: sortIconContainerStyle }, { children: jsx(SortIcon, { isSorted: isSorted, sortDirection: sortDirection }) }))] }))) : ((_b = stringifyWithNull(cellValue)) !== null && _b !== void 0 ? _b : '') }), colIndex));
1058
- }), !isTransposed && actions.length > 0 && (jsx("td", __assign({ css: __assign(__assign(__assign({}, cellStyle), { paddingLeft: 0 }), styles.getTarget('td')) }, { children: jsx(ActionButtons, { actions: actions, rowIndex: rowIndex, columnData: baseColumns, fieldValues: baseFieldValues, onClick: onClick, tableId: element.id, buttonLoaders: buttonLoaders }) })))] }), rowIndex));
1059
- }), isTransposed && actions.length > 0 && (jsxs("tr", __assign({ css: __assign(__assign({}, rowStyle), styles.getTarget('tr')) }, { children: [jsx("th", { scope: 'row', css: __assign(__assign(__assign({}, thStyle), { backgroundColor: '#f9fafb', borderRight: '1px solid #e5e7eb', width: '1px', whiteSpace: 'nowrap' }), styles.getTarget('th')) }), transposedRowIndices.map(function (originalRowIndex, idx) { return (jsx("td", __assign({ css: __assign(__assign(__assign({}, cellStyle), (idx === 0 ? {} : { paddingLeft: 0 })), styles.getTarget('td')) }, { children: jsx("div", __assign({ css: { display: 'flex', justifyContent: 'flex-start' } }, { children: jsx(ActionButtons, { actions: actions, rowIndex: originalRowIndex, columnData: baseColumns, fieldValues: baseFieldValues, onClick: onClick, forceInlineButtons: true, tableId: element.id, buttonLoaders: buttonLoaders }) })) }), originalRowIndex)); })] })))] }))] }))), !showEmptyState && enablePagination && (jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, totalItems: totalRows, rowsPerPage: rowsPerPage, onPageChange: setCurrentPage }))] })) })));
1514
+ return (jsx(CellElement, __assign({ css: cellCss, onClick: handleCellClick }, (isFirstColInTranspose ? { scope: 'row' } : {}), { children: isFirstColInTranspose && isSortable ? (jsxs("div", __assign({ css: __assign(__assign({}, sortHeaderContentStyle), { justifyContent: 'space-between' }) }, { children: [jsx("span", { children: (_a = stringifyWithNull(cellValue)) !== null && _a !== void 0 ? _a : '' }), jsx("span", __assign({ css: sortIconContainerStyle }, { children: jsx(SortIcon, { isSorted: isSorted, sortDirection: sortDirection }) }))] }))) : canEdit ? (jsx(EditableCell, { value: cellValue, fieldKey: column.field_key, rowIndex: rowIndex, onEdit: wrappedHandleCellEdit, onClear: handleCellClear })) : ((_b = stringifyWithNull(cellValue)) !== null && _b !== void 0 ? _b : '') }), colIndex));
1515
+ }), !isTransposed && actions.length > 0 && (jsxs("td", __assign({ ref: function (el) {
1516
+ if (el)
1517
+ actionCellRefs.current.set(rowIndex, el);
1518
+ else
1519
+ actionCellRefs.current.delete(rowIndex);
1520
+ }, css: __assign(__assign(__assign({}, cellStyle), { paddingLeft: 0 }), styles.getTarget('td')) }, { children: [jsx(ActionButtons, { actions: actions, rowIndex: rowIndex, columnData: baseColumns, fieldValues: baseFieldValues, onClick: onClick, tableId: element.id, buttonLoaders: buttonLoaders, canDeleteRows: canDeleteRows && hasOverflowMenu, onDeleteRow: function (ri) { return setDeleteRowIndex(ri); } }), hasOverflowMenu &&
1521
+ canDeleteRows &&
1522
+ deleteRowIndex === rowIndex && (jsx(DeleteConfirm, { anchorEl: (_a = actionCellRefs.current.get(rowIndex)) !== null && _a !== void 0 ? _a : null, onConfirm: function () {
1523
+ handleDeleteRow(rowIndex);
1524
+ setDeleteRowIndex(null);
1525
+ }, onCancel: handleCancelDelete }))] }))), showStandaloneDeleteColumn && (jsxs("td", __assign({ css: __assign(__assign({}, deleteColumnStyle), styles.getTarget('td')) }, { children: [jsx("button", __assign({ type: 'button', ref: function (el) {
1526
+ if (el)
1527
+ deleteIconRefs.current.set(rowIndex, el);
1528
+ else
1529
+ deleteIconRefs.current.delete(rowIndex);
1530
+ }, css: __assign(__assign({}, deleteIconStyle), (deleteRowIndex === rowIndex && {
1531
+ opacity: 1
1532
+ })), onClick: function (e) {
1533
+ e.stopPropagation();
1534
+ setDeleteRowIndex(deleteRowIndex === rowIndex ? null : rowIndex);
1535
+ } }, { children: jsx(TrashIcon, {}) })), deleteRowIndex === rowIndex && (jsx(DeleteConfirm, { anchorEl: (_b = deleteIconRefs.current.get(rowIndex)) !== null && _b !== void 0 ? _b : null, onConfirm: function () {
1536
+ handleDeleteRow(rowIndex);
1537
+ setDeleteRowIndex(null);
1538
+ }, onCancel: handleCancelDelete }))] })))] }), rowIndex));
1539
+ }), isTransposed && actions.length > 0 && (jsxs("tr", __assign({ css: __assign(__assign({}, rowStyle), styles.getTarget('tr')) }, { children: [jsx("th", { scope: 'row', css: __assign(__assign(__assign({}, thStyle), { backgroundColor: '#f9fafb', borderRight: '1px solid #e5e7eb', width: '1px', whiteSpace: 'nowrap' }), styles.getTarget('th')) }), transposedRowIndices.map(function (originalRowIndex, idx) { return (jsx("td", __assign({ css: __assign(__assign(__assign({}, cellStyle), (idx === 0 ? {} : { paddingLeft: 0 })), styles.getTarget('td')) }, { children: jsx("div", __assign({ css: { display: 'flex', justifyContent: 'flex-start' } }, { children: jsx(ActionButtons, { actions: actions, rowIndex: originalRowIndex, columnData: baseColumns, fieldValues: baseFieldValues, onClick: onClick, forceInlineButtons: true, tableId: element.id, buttonLoaders: buttonLoaders }) })) }), originalRowIndex)); })] })))] }))] })) }))), !showEmptyState && enablePagination && (jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, totalItems: totalRows, rowsPerPage: rowsPerPage, onPageChange: setCurrentPage }))] })));
1060
1540
  }
1061
1541
 
1062
1542
  export { TableElement as default };