@akinon/ai-modal-table 1.0.1 → 1.0.3

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 (59) hide show
  1. package/dist/cjs/ai-modal-table/__tests__/index.test.js +36 -2
  2. package/dist/cjs/ai-modal-table/__tests__/index.test.tsx +74 -2
  3. package/dist/cjs/ai-modal-table/index.d.ts +1 -1
  4. package/dist/cjs/ai-modal-table/index.d.ts.map +1 -1
  5. package/dist/cjs/ai-modal-table/index.js +2 -2
  6. package/dist/cjs/ai-table/__tests__/index.test.js +23 -0
  7. package/dist/cjs/ai-table/__tests__/index.test.tsx +39 -0
  8. package/dist/cjs/ai-table/components/__tests__/content.test.js +61 -9
  9. package/dist/cjs/ai-table/components/__tests__/content.test.tsx +77 -9
  10. package/dist/cjs/ai-table/components/content.d.ts +2 -1
  11. package/dist/cjs/ai-table/components/content.d.ts.map +1 -1
  12. package/dist/cjs/ai-table/components/content.js +25 -15
  13. package/dist/cjs/ai-table/components/footer.js +1 -1
  14. package/dist/cjs/ai-table/components/mapper.js +1 -1
  15. package/dist/cjs/ai-table/constants/index.d.ts +4 -0
  16. package/dist/cjs/ai-table/constants/index.d.ts.map +1 -1
  17. package/dist/cjs/ai-table/constants/index.js +5 -1
  18. package/dist/cjs/ai-table/index.d.ts +1 -1
  19. package/dist/cjs/ai-table/index.d.ts.map +1 -1
  20. package/dist/cjs/ai-table/index.js +3 -3
  21. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts +2 -0
  22. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts.map +1 -0
  23. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.js +220 -0
  24. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.tsx +283 -0
  25. package/dist/cjs/ai-table/utils/render-edit-fields/index.d.ts +13 -0
  26. package/dist/cjs/ai-table/utils/render-edit-fields/index.d.ts.map +1 -0
  27. package/dist/cjs/ai-table/utils/render-edit-fields/index.js +65 -0
  28. package/dist/cjs/types/index.d.ts +24 -4
  29. package/dist/cjs/types/index.d.ts.map +1 -1
  30. package/dist/esm/ai-modal-table/__tests__/index.test.js +36 -2
  31. package/dist/esm/ai-modal-table/__tests__/index.test.tsx +74 -2
  32. package/dist/esm/ai-modal-table/index.d.ts +1 -1
  33. package/dist/esm/ai-modal-table/index.d.ts.map +1 -1
  34. package/dist/esm/ai-modal-table/index.js +2 -2
  35. package/dist/esm/ai-table/__tests__/index.test.js +23 -0
  36. package/dist/esm/ai-table/__tests__/index.test.tsx +39 -0
  37. package/dist/esm/ai-table/components/__tests__/content.test.js +61 -9
  38. package/dist/esm/ai-table/components/__tests__/content.test.tsx +77 -9
  39. package/dist/esm/ai-table/components/content.d.ts +2 -1
  40. package/dist/esm/ai-table/components/content.d.ts.map +1 -1
  41. package/dist/esm/ai-table/components/content.js +25 -15
  42. package/dist/esm/ai-table/components/footer.js +1 -1
  43. package/dist/esm/ai-table/components/mapper.js +1 -1
  44. package/dist/esm/ai-table/constants/index.d.ts +4 -0
  45. package/dist/esm/ai-table/constants/index.d.ts.map +1 -1
  46. package/dist/esm/ai-table/constants/index.js +4 -0
  47. package/dist/esm/ai-table/index.d.ts +1 -1
  48. package/dist/esm/ai-table/index.d.ts.map +1 -1
  49. package/dist/esm/ai-table/index.js +3 -3
  50. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts +2 -0
  51. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts.map +1 -0
  52. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.js +218 -0
  53. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.tsx +283 -0
  54. package/dist/esm/ai-table/utils/render-edit-fields/index.d.ts +13 -0
  55. package/dist/esm/ai-table/utils/render-edit-fields/index.d.ts.map +1 -0
  56. package/dist/esm/ai-table/utils/render-edit-fields/index.js +60 -0
  57. package/dist/esm/types/index.d.ts +24 -4
  58. package/dist/esm/types/index.d.ts.map +1 -1
  59. package/package.json +13 -13
@@ -569,4 +569,43 @@ describe('AiTable', () => {
569
569
  expect(screen.getByTestId('table-content')).toBeInTheDocument();
570
570
  });
571
571
  });
572
+
573
+ describe('Empty Text', () => {
574
+ it('should render table without emptyText prop', () => {
575
+ render(<AiTable {...defaultProps} />);
576
+
577
+ expect(screen.getByTestId('table-content')).toBeInTheDocument();
578
+ });
579
+
580
+ it('should pass emptyText prop to TableContent when provided', () => {
581
+ const customEmptyText = 'No data found';
582
+
583
+ render(<AiTable {...defaultProps} emptyText={customEmptyText} />);
584
+
585
+ expect(screen.getByTestId('table-content')).toBeInTheDocument();
586
+ });
587
+
588
+ it('should handle React nodes as emptyText', () => {
589
+ const customEmptyNode = (
590
+ <div data-testid="custom-empty-message">
591
+ <p>No results available</p>
592
+ </div>
593
+ );
594
+
595
+ render(<AiTable {...defaultProps} emptyText={customEmptyNode} />);
596
+
597
+ expect(screen.getByTestId('table-content')).toBeInTheDocument();
598
+ });
599
+
600
+ it('should work with empty data and custom emptyText', () => {
601
+ const customEmptyText = 'The table is empty';
602
+
603
+ render(
604
+ <AiTable {...defaultProps} data={[]} emptyText={customEmptyText} />
605
+ );
606
+
607
+ expect(screen.getByTestId('table-content')).toBeInTheDocument();
608
+ expect(screen.queryByTestId('row-1')).not.toBeInTheDocument();
609
+ });
610
+ });
572
611
  });
@@ -16,6 +16,7 @@ import userEvent from '@testing-library/user-event';
16
16
  import { ConfigProvider } from 'antd';
17
17
  import React from 'react';
18
18
  import { beforeEach, describe, expect, it, vi } from 'vitest';
19
+ import { EDIT_FIELD_TYPES } from '../../constants';
19
20
  import { TableContent } from '../content';
20
21
  vi.mock('@akinon/icons', () => ({
21
22
  Icon: (_a) => {
@@ -29,6 +30,12 @@ vi.mock('@akinon/ui-input', () => ({
29
30
  return (React.createElement("input", Object.assign({ onChange: onChange, value: value, className: className, "data-testid": "edit-input" }, props)));
30
31
  }
31
32
  }));
33
+ vi.mock('@akinon/ui-select', () => ({
34
+ Select: (_a) => {
35
+ var { value, onChange, rootClassName, options } = _a, props = __rest(_a, ["value", "onChange", "rootClassName", "options"]);
36
+ return (React.createElement("select", Object.assign({ "data-testid": "edit-select", value: value !== null && value !== void 0 ? value : '', onChange: e => onChange === null || onChange === void 0 ? void 0 : onChange(e.target.value), className: rootClassName }, props), options === null || options === void 0 ? void 0 : options.map((opt) => (React.createElement("option", { key: opt.value, value: String(opt.value) }, opt.label)))));
37
+ }
38
+ }));
32
39
  vi.mock('@akinon/ui-layout', () => ({
33
40
  Flex: (_a) => {
34
41
  var { children } = _a, props = __rest(_a, ["children"]);
@@ -335,12 +342,13 @@ describe('TableContent', () => {
335
342
  });
336
343
  it('should apply collapsed style when not expanded', () => {
337
344
  renderComponent({ expandedRows: [] });
345
+ // Row 2 (pk: 2) has multiple mapper items, so it has the expand button
338
346
  const expandIcons = screen.getAllByTestId('icon-chevron_down');
339
347
  expect(expandIcons[0].className).toContain('ai-modal-table__icon--collapsed');
340
348
  });
341
349
  it('should not apply collapsed style when expanded', () => {
342
- renderComponent({ expandedRows: [1] });
343
- // First icon - for row 1
350
+ renderComponent({ expandedRows: [2] });
351
+ // Icon for row 2 (which has multiple mapper items)
344
352
  const icons = screen.getAllByTestId('icon-chevron_down');
345
353
  expect(icons[0].className).not.toContain('ai-modal-table__icon--collapsed');
346
354
  });
@@ -351,9 +359,10 @@ describe('TableContent', () => {
351
359
  });
352
360
  expect(screen.queryByTestId('icon-chevron_down')).not.toBeInTheDocument();
353
361
  });
354
- it('should render multiple expand buttons for multiple rows', () => {
362
+ it('should render expand button for rows with multiple mapper items', () => {
355
363
  renderComponent();
356
- expect(screen.getAllByTestId('icon-chevron_down').length).toBe(2);
364
+ // Only row 2 has multiple mapper items (2 items), so only 1 expand button should be rendered
365
+ expect(screen.getAllByTestId('icon-chevron_down').length).toBe(1);
357
366
  });
358
367
  });
359
368
  describe('Mapper Column', () => {
@@ -550,8 +559,10 @@ describe('TableContent', () => {
550
559
  });
551
560
  it('should render expand button in first column', () => {
552
561
  renderComponent();
553
- const firstRow = screen.getAllByRole('row')[1];
554
- const firstCell = within(firstRow).getAllByRole('cell')[0];
562
+ // Row 2 (index 2) has multiple mapper items, so it has the expand button
563
+ const rows = screen.getAllByRole('row');
564
+ const rowWithExpandButton = rows[2]; // Row 2 (pk: 2) has multiple mapper items
565
+ const firstCell = within(rowWithExpandButton).getAllByRole('cell')[0];
555
566
  expect(firstCell).toContainElement(screen.getAllByTestId('icon-chevron_down')[0]);
556
567
  });
557
568
  it('should handle missing optional data gracefully', () => {
@@ -786,18 +797,20 @@ describe('TableContent', () => {
786
797
  });
787
798
  const expandButtons = screen.getAllByTestId('icon-chevron_down');
788
799
  fireEvent.click(expandButtons[0]);
789
- expect(onToggleExpand).toHaveBeenCalledWith(1);
800
+ // Row 2 (pk: 2) has multiple mapper items and is the one with expand button
801
+ expect(onToggleExpand).toHaveBeenCalledWith(2);
790
802
  });
791
803
  it('should call onToggleExpand when expand button clicked on expanded row', () => {
792
804
  const onToggleExpand = vi.fn();
793
805
  renderComponent({
794
- expandedRows: [1],
806
+ expandedRows: [2],
795
807
  onToggleExpand
796
808
  });
797
809
  const expandButtons = screen.getAllByTestId('icon-chevron_down');
798
810
  fireEvent.click(expandButtons[0]);
799
811
  // The expand button is a toggle - it should call onToggleExpand to collapse the row
800
- expect(onToggleExpand).toHaveBeenCalledWith(1);
812
+ // Row 2 (pk: 2) has multiple mapper items and is the one with expand button
813
+ expect(onToggleExpand).toHaveBeenCalledWith(2);
801
814
  });
802
815
  it('should call onAddItem with correct rowId and dataIndex when add button clicked', () => {
803
816
  const onAddItem = vi.fn();
@@ -1343,5 +1356,44 @@ describe('TableContent', () => {
1343
1356
  const inputs = screen.queryAllByTestId('edit-input');
1344
1357
  expect(inputs.length).toBeGreaterThan(0);
1345
1358
  });
1359
+ it('should render Select for editable column when editDataIndexes has SELECT config', async () => {
1360
+ const user = userEvent.setup();
1361
+ const onEdit = vi.fn();
1362
+ renderComponent({
1363
+ data: [
1364
+ {
1365
+ pk: 1,
1366
+ name: 'Item 1',
1367
+ status: 'active',
1368
+ mappings: []
1369
+ }
1370
+ ],
1371
+ columns: [
1372
+ { title: 'Name', dataIndex: 'name' },
1373
+ { title: 'Status', dataIndex: 'status' }
1374
+ ],
1375
+ mapperConfig: undefined,
1376
+ onEdit,
1377
+ editDataIndexes: [
1378
+ 'name',
1379
+ {
1380
+ key: 'status',
1381
+ type: EDIT_FIELD_TYPES.SELECT,
1382
+ attributes: {
1383
+ options: [
1384
+ { label: 'Active', value: 'active' },
1385
+ { label: 'Inactive', value: 'inactive' }
1386
+ ]
1387
+ }
1388
+ }
1389
+ ]
1390
+ });
1391
+ const editButton = screen.getByTestId('edit-button-1');
1392
+ await user.click(editButton);
1393
+ const inputs = screen.queryAllByTestId('edit-input');
1394
+ const selects = screen.queryAllByTestId('edit-select');
1395
+ expect(inputs.length).toBeGreaterThan(0);
1396
+ expect(selects.length).toBeGreaterThan(0);
1397
+ });
1346
1398
  });
1347
1399
  });
@@ -7,6 +7,7 @@ import { ConfigProvider } from 'antd';
7
7
  import React from 'react';
8
8
  import { beforeEach, describe, expect, it, vi } from 'vitest';
9
9
 
10
+ import { EDIT_FIELD_TYPES } from '../../constants';
10
11
  import { TableContent } from '../content';
11
12
 
12
13
  vi.mock('@akinon/icons', () => ({
@@ -35,6 +36,24 @@ vi.mock('@akinon/ui-input', () => ({
35
36
  )
36
37
  }));
37
38
 
39
+ vi.mock('@akinon/ui-select', () => ({
40
+ Select: ({ value, onChange, rootClassName, options, ...props }: any) => (
41
+ <select
42
+ data-testid="edit-select"
43
+ value={value ?? ''}
44
+ onChange={e => onChange?.(e.target.value)}
45
+ className={rootClassName}
46
+ {...props}
47
+ >
48
+ {options?.map((opt: { label: string; value: string | number }) => (
49
+ <option key={opt.value} value={String(opt.value)}>
50
+ {opt.label}
51
+ </option>
52
+ ))}
53
+ </select>
54
+ )
55
+ }));
56
+
38
57
  vi.mock('@akinon/ui-layout', () => ({
39
58
  Flex: ({ children, ...props }: any) => (
40
59
  <div data-testid="flex" {...props}>
@@ -434,6 +453,7 @@ describe('TableContent', () => {
434
453
 
435
454
  it('should apply collapsed style when not expanded', () => {
436
455
  renderComponent({ expandedRows: [] });
456
+ // Row 2 (pk: 2) has multiple mapper items, so it has the expand button
437
457
  const expandIcons = screen.getAllByTestId('icon-chevron_down');
438
458
  expect(expandIcons[0].className).toContain(
439
459
  'ai-modal-table__icon--collapsed'
@@ -441,8 +461,8 @@ describe('TableContent', () => {
441
461
  });
442
462
 
443
463
  it('should not apply collapsed style when expanded', () => {
444
- renderComponent({ expandedRows: [1] });
445
- // First icon - for row 1
464
+ renderComponent({ expandedRows: [2] });
465
+ // Icon for row 2 (which has multiple mapper items)
446
466
  const icons = screen.getAllByTestId('icon-chevron_down');
447
467
  expect(icons[0].className).not.toContain(
448
468
  'ai-modal-table__icon--collapsed'
@@ -457,9 +477,10 @@ describe('TableContent', () => {
457
477
  expect(screen.queryByTestId('icon-chevron_down')).not.toBeInTheDocument();
458
478
  });
459
479
 
460
- it('should render multiple expand buttons for multiple rows', () => {
480
+ it('should render expand button for rows with multiple mapper items', () => {
461
481
  renderComponent();
462
- expect(screen.getAllByTestId('icon-chevron_down').length).toBe(2);
482
+ // Only row 2 has multiple mapper items (2 items), so only 1 expand button should be rendered
483
+ expect(screen.getAllByTestId('icon-chevron_down').length).toBe(1);
463
484
  });
464
485
  });
465
486
 
@@ -691,8 +712,10 @@ describe('TableContent', () => {
691
712
 
692
713
  it('should render expand button in first column', () => {
693
714
  renderComponent();
694
- const firstRow = screen.getAllByRole('row')[1];
695
- const firstCell = within(firstRow).getAllByRole('cell')[0];
715
+ // Row 2 (index 2) has multiple mapper items, so it has the expand button
716
+ const rows = screen.getAllByRole('row');
717
+ const rowWithExpandButton = rows[2]; // Row 2 (pk: 2) has multiple mapper items
718
+ const firstCell = within(rowWithExpandButton).getAllByRole('cell')[0];
696
719
  expect(firstCell).toContainElement(
697
720
  screen.getAllByTestId('icon-chevron_down')[0]
698
721
  );
@@ -986,13 +1009,14 @@ describe('TableContent', () => {
986
1009
  const expandButtons = screen.getAllByTestId('icon-chevron_down');
987
1010
  fireEvent.click(expandButtons[0]);
988
1011
 
989
- expect(onToggleExpand).toHaveBeenCalledWith(1);
1012
+ // Row 2 (pk: 2) has multiple mapper items and is the one with expand button
1013
+ expect(onToggleExpand).toHaveBeenCalledWith(2);
990
1014
  });
991
1015
 
992
1016
  it('should call onToggleExpand when expand button clicked on expanded row', () => {
993
1017
  const onToggleExpand = vi.fn();
994
1018
  renderComponent({
995
- expandedRows: [1],
1019
+ expandedRows: [2],
996
1020
  onToggleExpand
997
1021
  });
998
1022
 
@@ -1000,7 +1024,8 @@ describe('TableContent', () => {
1000
1024
  fireEvent.click(expandButtons[0]);
1001
1025
 
1002
1026
  // The expand button is a toggle - it should call onToggleExpand to collapse the row
1003
- expect(onToggleExpand).toHaveBeenCalledWith(1);
1027
+ // Row 2 (pk: 2) has multiple mapper items and is the one with expand button
1028
+ expect(onToggleExpand).toHaveBeenCalledWith(2);
1004
1029
  });
1005
1030
 
1006
1031
  it('should call onAddItem with correct rowId and dataIndex when add button clicked', () => {
@@ -1633,5 +1658,48 @@ describe('TableContent', () => {
1633
1658
  const inputs = screen.queryAllByTestId('edit-input');
1634
1659
  expect(inputs.length).toBeGreaterThan(0);
1635
1660
  });
1661
+
1662
+ it('should render Select for editable column when editDataIndexes has SELECT config', async () => {
1663
+ const user = userEvent.setup();
1664
+ const onEdit = vi.fn();
1665
+
1666
+ renderComponent({
1667
+ data: [
1668
+ {
1669
+ pk: 1,
1670
+ name: 'Item 1',
1671
+ status: 'active',
1672
+ mappings: []
1673
+ }
1674
+ ],
1675
+ columns: [
1676
+ { title: 'Name', dataIndex: 'name' },
1677
+ { title: 'Status', dataIndex: 'status' }
1678
+ ],
1679
+ mapperConfig: undefined,
1680
+ onEdit,
1681
+ editDataIndexes: [
1682
+ 'name',
1683
+ {
1684
+ key: 'status',
1685
+ type: EDIT_FIELD_TYPES.SELECT,
1686
+ attributes: {
1687
+ options: [
1688
+ { label: 'Active', value: 'active' },
1689
+ { label: 'Inactive', value: 'inactive' }
1690
+ ]
1691
+ }
1692
+ }
1693
+ ]
1694
+ });
1695
+
1696
+ const editButton = screen.getByTestId('edit-button-1');
1697
+ await user.click(editButton);
1698
+
1699
+ const inputs = screen.queryAllByTestId('edit-input');
1700
+ const selects = screen.queryAllByTestId('edit-select');
1701
+ expect(inputs.length).toBeGreaterThan(0);
1702
+ expect(selects.length).toBeGreaterThan(0);
1703
+ });
1636
1704
  });
1637
1705
  });
@@ -5,7 +5,8 @@ interface TableContentProps extends Omit<TableBaseProps, 'onChangeSelectedRows'
5
5
  expandedRows: Array<number | string>;
6
6
  onToggleExpand: (rowId: number | string) => void;
7
7
  rowKey: string;
8
+ emptyText?: React.ReactNode;
8
9
  }
9
- export declare const TableContent: ({ columns, customActionButtons, data, editDataIndexes, expandedRows, onEdit, onToggleExpand, onToggleSelection, rowKey, selectedRows, mapperConfig }: TableContentProps) => React.JSX.Element;
10
+ export declare const TableContent: ({ columns, customActionButtons, data, editDataIndexes, expandedRows, onEdit, onToggleExpand, onToggleSelection, rowKey, selectedRows, mapperConfig, emptyText }: TableContentProps) => React.JSX.Element;
10
11
  export {};
11
12
  //# sourceMappingURL=content.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../src/ai-table/components/content.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAA8B,cAAc,EAAE,MAAM,aAAa,CAAC;AAQ9E,UAAU,iBACR,SAAQ,IAAI,CAAC,cAAc,EAAE,sBAAsB,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3E,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACrC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,GAAI,sJAY1B,iBAAiB,sBAihBnB,CAAC"}
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../src/ai-table/components/content.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAA8B,cAAc,EAAE,MAAM,aAAa,CAAC;AAY9E,UAAU,iBACR,SAAQ,IAAI,CAAC,cAAc,EAAE,sBAAsB,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3E,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACrC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,YAAY,GAAI,iKAa1B,iBAAiB,sBAuhBnB,CAAC"}
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { Icon } from '@akinon/icons';
3
- import { Input } from '@akinon/ui-input';
4
3
  import { Flex } from '@akinon/ui-layout';
5
4
  import { useToken } from '@akinon/ui-theme';
6
5
  import { useStyleRegister } from '@ant-design/cssinjs';
@@ -10,10 +9,11 @@ import { get } from 'lodash-es';
10
9
  import * as React from 'react';
11
10
  import { IS_EDITING_INITIAL_VALUE } from '../constants';
12
11
  import { i18n } from '../i18n';
12
+ import { getEditFieldConfig, renderEditField } from '../utils/render-edit-fields';
13
13
  import { TableMapper } from './mapper';
14
14
  import { ActionButtons } from './row-actions';
15
15
  const { t } = i18n;
16
- export const TableContent = ({ columns, customActionButtons, data, editDataIndexes, expandedRows, onEdit, onToggleExpand, onToggleSelection, rowKey, selectedRows, mapperConfig }) => {
16
+ export const TableContent = ({ columns, customActionButtons, data, editDataIndexes, expandedRows, onEdit, onToggleExpand, onToggleSelection, rowKey, selectedRows, mapperConfig, emptyText }) => {
17
17
  const { getPrefixCls, theme } = React.useContext(ConfigProvider.ConfigContext);
18
18
  const { token, hashId } = useToken();
19
19
  const baseCls = getPrefixCls('ai-modal-table');
@@ -110,7 +110,8 @@ export const TableContent = ({ columns, customActionButtons, data, editDataIndex
110
110
  };
111
111
  const renderMapper = ({ rowId, value, dataIndex }) => {
112
112
  const isExpanded = isRowExpanded(rowId);
113
- const displayedValues = isExpanded ? value : value.slice(0, 1);
113
+ const hasMultipleItems = value.length > 1;
114
+ const displayedValues = hasMultipleItems && !isExpanded ? value.slice(0, 1) : value;
114
115
  const handleExpand = () => {
115
116
  if (!isExpanded) {
116
117
  onToggleExpand(rowId);
@@ -146,16 +147,20 @@ export const TableContent = ({ columns, customActionButtons, data, editDataIndex
146
147
  const renderCellValue = ({ column, row, rowId }) => {
147
148
  const dataIndex = get(column, 'dataIndex', '');
148
149
  const value = get(row, dataIndex, '');
149
- if (hasEdit &&
150
- checkIsEditing(rowId) &&
151
- editDataIndexes.includes(dataIndex)) {
152
- const handleOnChangeValue = (e) => {
153
- const currentValue = e.target.value;
154
- onEdit(rowId, {
155
- [dataIndex]: currentValue
150
+ if (hasEdit && checkIsEditing(rowId)) {
151
+ const config = getEditFieldConfig(editDataIndexes, dataIndex);
152
+ if (config) {
153
+ const handleOnChangeValue = (changedValue) => {
154
+ onEdit(rowId, {
155
+ [dataIndex]: changedValue
156
+ });
157
+ };
158
+ return renderEditField({
159
+ config,
160
+ value,
161
+ onChange: handleOnChangeValue
156
162
  });
157
- };
158
- return (React.createElement(Input, { className: "w-44 h-9", onChange: handleOnChangeValue, value: value }));
163
+ }
159
164
  }
160
165
  if (hasMapper && isMapperColumn(dataIndex)) {
161
166
  return renderMapper({
@@ -182,10 +187,15 @@ export const TableContent = ({ columns, customActionButtons, data, editDataIndex
182
187
  }), onClick: handleClick }));
183
188
  };
184
189
  const renderTableCells = (row, rowId) => {
190
+ const mapperValue = hasMapper && mapperDataIndex ? row[mapperDataIndex] : null;
191
+ const hasMultipleMapperItems = Array.isArray(mapperValue) && mapperValue.length > 1;
185
192
  return columns.map((column, colIndex) => {
186
193
  const isFirstColumn = colIndex === 0;
187
194
  return (React.createElement("td", { className: "text-blue-50 font-normal text-base whitespace-nowrap py-0 px-5", key: `cell-${rowId}-${column.dataIndex || colIndex}` },
188
- isFirstColumn && hasMapper && renderExpandButton(rowId),
195
+ isFirstColumn &&
196
+ hasMapper &&
197
+ hasMultipleMapperItems &&
198
+ renderExpandButton(rowId),
189
199
  renderCellValue({
190
200
  column,
191
201
  row,
@@ -213,7 +223,7 @@ export const TableContent = ({ columns, customActionButtons, data, editDataIndex
213
223
  };
214
224
  const renderEmptyRow = () => {
215
225
  return (React.createElement("tr", null,
216
- React.createElement("td", { className: "font-normal text-center text-gray-500 text-sm py-10 px-4", colSpan: columns.length + 1 }, t('filter.no.match'))));
226
+ React.createElement("td", { className: "font-normal text-center text-gray-500 text-sm py-10 px-4", colSpan: columns.length + 1 }, emptyText !== null && emptyText !== void 0 ? emptyText : t('filter.no.match'))));
217
227
  };
218
228
  const renderGradientOverlay = () => {
219
229
  return (React.createElement(React.Fragment, null,
@@ -298,7 +308,7 @@ export const TableContent = ({ columns, customActionButtons, data, editDataIndex
298
308
  return useStyle(React.createElement("div", { className: "bg-ebonyClay-450 rounded-lg overflow-hidden" },
299
309
  React.createElement("div", { className: `${baseCls}__table-wrapper ${hashId} overflow-x-auto overflow-y-auto` },
300
310
  React.createElement("div", { className: "relative" },
301
- renderGradientOverlay(),
311
+ data.length > 0 && renderGradientOverlay(),
302
312
  React.createElement("table", { ref: tableRef, className: `${baseCls}__table-element ${hashId} w-full bg-ebonyClay-450` },
303
313
  React.createElement("thead", null, renderTableHeaders()),
304
314
  React.createElement("tbody", null, renderTableRows()))))));
@@ -12,7 +12,7 @@ export const TableFooter = ({ isSubmitting, selectedCount, submitAllLabel, submi
12
12
  onSubmitSelected();
13
13
  }
14
14
  };
15
- return (React.createElement(Flex, { justify: "end", gap: 10 },
15
+ return (React.createElement(Flex, { justify: "end", gap: 10, className: "mt-4" },
16
16
  React.createElement(Button, { className: "uppercase font-semibold", disabled: isSubmitting, loading: isSubmitting, onClick: handleSubmitAll }, submitAllLabel),
17
17
  React.createElement(Button, { className: "uppercase font-semibold", disabled: selectedCount === 0 || isSubmitting, loading: isSubmitting, onClick: handleSubmitSelected, type: "primary" },
18
18
  submitSelectedLabel,
@@ -3,7 +3,7 @@ import { Flex } from '@akinon/ui-layout';
3
3
  import * as React from 'react';
4
4
  import { renderMapperRow } from '../utils/render-mapper-fields';
5
5
  export const TableMapper = ({ values, handleAddItem, handleRemoveItem, handleItemChange }) => {
6
- return (React.createElement(Flex, { gap: 5, vertical: true, rootClassName: "py-1" }, values.map((row, index) => {
6
+ return (React.createElement(Flex, { gap: 5, vertical: true, rootClassName: "py-3" }, values.map((row, index) => {
7
7
  return (React.createElement(Flex, { gap: 12, align: "center", key: index },
8
8
  renderMapperRow({
9
9
  row,
@@ -14,4 +14,8 @@ export declare const MAPPER_ITEM_TYPES: {
14
14
  readonly SELECT: "select";
15
15
  readonly TEXT: "text";
16
16
  };
17
+ export declare const EDIT_FIELD_TYPES: {
18
+ readonly INPUT: "input";
19
+ readonly SELECT: "select";
20
+ };
17
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ai-table/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;CAExB,CAAC;AAEF,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,eAAO,MAAM,iBAAiB;;;GAG3B,CAAC;AAEJ,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,eAAO,MAAM,wBAAwB,MAAO,CAAC;AAE7C,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ai-table/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;CAExB,CAAC;AAEF,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,eAAO,MAAM,iBAAiB;;;GAG3B,CAAC;AAEJ,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,eAAO,MAAM,wBAAwB,MAAO,CAAC;AAE7C,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;CAGnB,CAAC"}
@@ -14,3 +14,7 @@ export const MAPPER_ITEM_TYPES = {
14
14
  SELECT: 'select',
15
15
  TEXT: 'text'
16
16
  };
17
+ export const EDIT_FIELD_TYPES = {
18
+ INPUT: 'input',
19
+ SELECT: 'select'
20
+ };
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
2
  import type { AiTableProps } from '../types';
3
- export declare const AiTable: ({ columns, customActionButtons, data, editDataIndexes, filters, isLoading, isSubmitting, onChangeSelectedRows, onEdit, onSubmitAllData, onSubmitSelectedData, rowKey, selectedRows, submitAllLabel, submitSelectedLabel, mapperConfig, tableClassName }: AiTableProps) => React.JSX.Element;
3
+ export declare const AiTable: ({ columns, customActionButtons, data, editDataIndexes, filters, isLoading, isSubmitting, onChangeSelectedRows, onEdit, onSubmitAllData, onSubmitSelectedData, rowKey, selectedRows, submitAllLabel, submitSelectedLabel, mapperConfig, tableClassName, emptyText }: AiTableProps) => React.JSX.Element;
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai-table/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAe7C,eAAO,MAAM,OAAO,GAAI,yPAkBrB,YAAY,sBA4Hd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai-table/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAe7C,eAAO,MAAM,OAAO,GAAI,oQAmBrB,YAAY,sBA6Hd,CAAC"}
@@ -10,7 +10,7 @@ import { DEFAULT_CURRENT_PAGE, DEFAULT_PAGE_SIZE, DEFAULT_ROW_KEY } from './cons
10
10
  import { i18n } from './i18n';
11
11
  import { filterDataByFilters, paginateData } from './utils/data-format';
12
12
  const { t } = i18n;
13
- export const AiTable = ({ columns = [], customActionButtons, data = [], editDataIndexes, filters = [], isLoading, isSubmitting, onChangeSelectedRows, onEdit, onSubmitAllData, onSubmitSelectedData, rowKey = DEFAULT_ROW_KEY, selectedRows, submitAllLabel, submitSelectedLabel, mapperConfig, tableClassName }) => {
13
+ export const AiTable = ({ columns = [], customActionButtons, data = [], editDataIndexes, filters = [], isLoading, isSubmitting, onChangeSelectedRows, onEdit, onSubmitAllData, onSubmitSelectedData, rowKey = DEFAULT_ROW_KEY, selectedRows, submitAllLabel, submitSelectedLabel, mapperConfig, tableClassName, emptyText }) => {
14
14
  const [currentPage, setCurrentPage] = React.useState(DEFAULT_CURRENT_PAGE);
15
15
  const [pageSize, setPageSize] = React.useState(DEFAULT_PAGE_SIZE);
16
16
  const [filterValues, setFilterValues] = React.useState({});
@@ -54,7 +54,7 @@ export const AiTable = ({ columns = [], customActionButtons, data = [], editData
54
54
  return (React.createElement("div", { className: "w-full h-80" },
55
55
  React.createElement(AiSpinner, null)));
56
56
  }
57
- return (React.createElement(Flex, { gap: 10, vertical: true, className: tableClassName },
57
+ return (React.createElement(Flex, { gap: 18, vertical: true, className: tableClassName },
58
58
  React.createElement(Flex, { justify: "space-between", align: "center" },
59
59
  React.createElement(Flex, { align: "center", gap: 22 },
60
60
  React.createElement(TableFilters, { filters: filters, filterValues: filterValues, onFilterChange: handleFilterChange }),
@@ -62,6 +62,6 @@ export const AiTable = ({ columns = [], customActionButtons, data = [], editData
62
62
  React.createElement(Button, { size: "small", onClick: handleExpandAll }, t('expand.all')),
63
63
  React.createElement(Button, { size: "small", onClick: handleCollapseAll }, t('collapse.all'))))),
64
64
  React.createElement(TablePagination, { currentPage: currentPage, onPageChange: handlePageChange, onPageSizeChange: handlePageSizeChange, pageSize: pageSize, total: filteredData.length })),
65
- React.createElement(TableContent, { columns: columns, customActionButtons: customActionButtons, data: paginatedData, editDataIndexes: editDataIndexes, expandedRows: expandedRows, onEdit: onEdit, onToggleExpand: handleToggleExpand, onToggleSelection: handleToggleSelection, rowKey: rowKey, selectedRows: selectedRows, mapperConfig: mapperConfig }),
65
+ React.createElement(TableContent, { columns: columns, customActionButtons: customActionButtons, data: paginatedData, editDataIndexes: editDataIndexes, emptyText: emptyText, expandedRows: expandedRows, onEdit: onEdit, onToggleExpand: handleToggleExpand, onToggleSelection: handleToggleSelection, rowKey: rowKey, selectedRows: selectedRows, mapperConfig: mapperConfig }),
66
66
  React.createElement(TableFooter, { isSubmitting: isSubmitting, selectedCount: selectedRows.length, submitAllLabel: submitAllLabel, submitSelectedLabel: submitSelectedLabel, onSubmitAll: onSubmitAllData, onSubmitSelected: onSubmitSelectedData })));
67
67
  };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../../../src/ai-table/utils/render-edit-fields/__tests__/index.test.tsx"],"names":[],"mappings":""}