@akinon/ai-modal-table 1.0.2 → 1.0.4

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 (35) hide show
  1. package/dist/cjs/ai-table/components/__tests__/content.test.js +46 -0
  2. package/dist/cjs/ai-table/components/__tests__/content.test.tsx +62 -0
  3. package/dist/cjs/ai-table/components/content.d.ts.map +1 -1
  4. package/dist/cjs/ai-table/components/content.js +14 -10
  5. package/dist/cjs/ai-table/components/mapper.js +1 -1
  6. package/dist/cjs/ai-table/constants/index.d.ts +4 -0
  7. package/dist/cjs/ai-table/constants/index.d.ts.map +1 -1
  8. package/dist/cjs/ai-table/constants/index.js +5 -1
  9. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts +2 -0
  10. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts.map +1 -0
  11. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.js +220 -0
  12. package/dist/cjs/ai-table/utils/render-edit-fields/__tests__/index.test.tsx +283 -0
  13. package/dist/cjs/ai-table/utils/render-edit-fields/index.d.ts +13 -0
  14. package/dist/cjs/ai-table/utils/render-edit-fields/index.d.ts.map +1 -0
  15. package/dist/cjs/ai-table/utils/render-edit-fields/index.js +65 -0
  16. package/dist/cjs/types/index.d.ts +20 -4
  17. package/dist/cjs/types/index.d.ts.map +1 -1
  18. package/dist/esm/ai-table/components/__tests__/content.test.js +46 -0
  19. package/dist/esm/ai-table/components/__tests__/content.test.tsx +62 -0
  20. package/dist/esm/ai-table/components/content.d.ts.map +1 -1
  21. package/dist/esm/ai-table/components/content.js +14 -10
  22. package/dist/esm/ai-table/components/mapper.js +1 -1
  23. package/dist/esm/ai-table/constants/index.d.ts +4 -0
  24. package/dist/esm/ai-table/constants/index.d.ts.map +1 -1
  25. package/dist/esm/ai-table/constants/index.js +4 -0
  26. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts +2 -0
  27. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.d.ts.map +1 -0
  28. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.js +218 -0
  29. package/dist/esm/ai-table/utils/render-edit-fields/__tests__/index.test.tsx +283 -0
  30. package/dist/esm/ai-table/utils/render-edit-fields/index.d.ts +13 -0
  31. package/dist/esm/ai-table/utils/render-edit-fields/index.d.ts.map +1 -0
  32. package/dist/esm/ai-table/utils/render-edit-fields/index.js +60 -0
  33. package/dist/esm/types/index.d.ts +20 -4
  34. package/dist/esm/types/index.d.ts.map +1 -1
  35. package/package.json +13 -13
@@ -18,6 +18,7 @@ const user_event_1 = require("@testing-library/user-event");
18
18
  const antd_1 = require("antd");
19
19
  const react_2 = require("react");
20
20
  const vitest_1 = require("vitest");
21
+ const constants_1 = require("../../constants");
21
22
  const content_1 = require("../content");
22
23
  vitest_1.vi.mock('@akinon/icons', () => ({
23
24
  Icon: (_a) => {
@@ -31,6 +32,12 @@ vitest_1.vi.mock('@akinon/ui-input', () => ({
31
32
  return (react_2.default.createElement("input", Object.assign({ onChange: onChange, value: value, className: className, "data-testid": "edit-input" }, props)));
32
33
  }
33
34
  }));
35
+ vitest_1.vi.mock('@akinon/ui-select', () => ({
36
+ Select: (_a) => {
37
+ var { value, onChange, rootClassName, options } = _a, props = __rest(_a, ["value", "onChange", "rootClassName", "options"]);
38
+ return (react_2.default.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_2.default.createElement("option", { key: opt.value, value: String(opt.value) }, opt.label)))));
39
+ }
40
+ }));
34
41
  vitest_1.vi.mock('@akinon/ui-layout', () => ({
35
42
  Flex: (_a) => {
36
43
  var { children } = _a, props = __rest(_a, ["children"]);
@@ -1351,5 +1358,44 @@ vitest_1.vi.mock('../../i18n', () => ({
1351
1358
  const inputs = react_1.screen.queryAllByTestId('edit-input');
1352
1359
  (0, vitest_1.expect)(inputs.length).toBeGreaterThan(0);
1353
1360
  });
1361
+ (0, vitest_1.it)('should render Select for editable column when editDataIndexes has SELECT config', async () => {
1362
+ const user = user_event_1.default.setup();
1363
+ const onEdit = vitest_1.vi.fn();
1364
+ renderComponent({
1365
+ data: [
1366
+ {
1367
+ pk: 1,
1368
+ name: 'Item 1',
1369
+ status: 'active',
1370
+ mappings: []
1371
+ }
1372
+ ],
1373
+ columns: [
1374
+ { title: 'Name', dataIndex: 'name' },
1375
+ { title: 'Status', dataIndex: 'status' }
1376
+ ],
1377
+ mapperConfig: undefined,
1378
+ onEdit,
1379
+ editDataIndexes: [
1380
+ 'name',
1381
+ {
1382
+ key: 'status',
1383
+ type: constants_1.EDIT_FIELD_TYPES.SELECT,
1384
+ attributes: {
1385
+ options: [
1386
+ { label: 'Active', value: 'active' },
1387
+ { label: 'Inactive', value: 'inactive' }
1388
+ ]
1389
+ }
1390
+ }
1391
+ ]
1392
+ });
1393
+ const editButton = react_1.screen.getByTestId('edit-button-1');
1394
+ await user.click(editButton);
1395
+ const inputs = react_1.screen.queryAllByTestId('edit-input');
1396
+ const selects = react_1.screen.queryAllByTestId('edit-select');
1397
+ (0, vitest_1.expect)(inputs.length).toBeGreaterThan(0);
1398
+ (0, vitest_1.expect)(selects.length).toBeGreaterThan(0);
1399
+ });
1354
1400
  });
1355
1401
  });
@@ -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}>
@@ -1639,5 +1658,48 @@ describe('TableContent', () => {
1639
1658
  const inputs = screen.queryAllByTestId('edit-input');
1640
1659
  expect(inputs.length).toBeGreaterThan(0);
1641
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
+ });
1642
1704
  });
1643
1705
  });
@@ -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;IACf,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,YAAY,GAAI,iKAa1B,iBAAiB,sBA2hBnB,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"}
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.TableContent = void 0;
5
5
  const icons_1 = require("@akinon/icons");
6
- const ui_input_1 = require("@akinon/ui-input");
7
6
  const ui_layout_1 = require("@akinon/ui-layout");
8
7
  const ui_theme_1 = require("@akinon/ui-theme");
9
8
  const cssinjs_1 = require("@ant-design/cssinjs");
@@ -13,6 +12,7 @@ const lodash_es_1 = require("lodash-es");
13
12
  const React = require("react");
14
13
  const constants_1 = require("../constants");
15
14
  const i18n_1 = require("../i18n");
15
+ const render_edit_fields_1 = require("../utils/render-edit-fields");
16
16
  const mapper_1 = require("./mapper");
17
17
  const row_actions_1 = require("./row-actions");
18
18
  const { t } = i18n_1.i18n;
@@ -150,16 +150,20 @@ const TableContent = ({ columns, customActionButtons, data, editDataIndexes, exp
150
150
  const renderCellValue = ({ column, row, rowId }) => {
151
151
  const dataIndex = (0, lodash_es_1.get)(column, 'dataIndex', '');
152
152
  const value = (0, lodash_es_1.get)(row, dataIndex, '');
153
- if (hasEdit &&
154
- checkIsEditing(rowId) &&
155
- editDataIndexes.includes(dataIndex)) {
156
- const handleOnChangeValue = (e) => {
157
- const currentValue = e.target.value;
158
- onEdit(rowId, {
159
- [dataIndex]: currentValue
153
+ if (hasEdit && checkIsEditing(rowId)) {
154
+ const config = (0, render_edit_fields_1.getEditFieldConfig)(editDataIndexes, dataIndex);
155
+ if (config) {
156
+ const handleOnChangeValue = (changedValue) => {
157
+ onEdit(rowId, {
158
+ [dataIndex]: changedValue
159
+ });
160
+ };
161
+ return (0, render_edit_fields_1.renderEditField)({
162
+ config,
163
+ value,
164
+ onChange: handleOnChangeValue
160
165
  });
161
- };
162
- return (React.createElement(ui_input_1.Input, { className: "w-44 h-9", onChange: handleOnChangeValue, value: value }));
166
+ }
163
167
  }
164
168
  if (hasMapper && isMapperColumn(dataIndex)) {
165
169
  return renderMapper({
@@ -13,7 +13,7 @@ const TableMapper = ({ values, handleAddItem, handleRemoveItem, handleItemChange
13
13
  index,
14
14
  handleItemChange
15
15
  }),
16
- React.createElement(ui_layout_1.Flex, { gap: 10 },
16
+ React.createElement(ui_layout_1.Flex, { gap: 10, className: "w-16" },
17
17
  React.createElement(icons_1.Icon, { icon: "plus", size: 20, color: "var(--color-green-500)", className: "cursor-pointer", onClick: handleAddItem }),
18
18
  React.createElement(icons_1.Icon, { icon: "minus", size: 20, color: "var(--color-red-425)", className: "cursor-pointer", onClick: handleRemoveItem(index) }))));
19
19
  })));
@@ -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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAPPER_ITEM_TYPES = exports.IS_EDITING_INITIAL_VALUE = exports.DEFAULT_ROW_KEY = exports.PAGE_SIZE_OPTIONS = exports.DEFAULT_CURRENT_PAGE = exports.DEFAULT_PAGE_SIZE = exports.DEBOUNCE_DELAY = exports.FILTER_TYPES = void 0;
3
+ exports.EDIT_FIELD_TYPES = exports.MAPPER_ITEM_TYPES = exports.IS_EDITING_INITIAL_VALUE = exports.DEFAULT_ROW_KEY = exports.PAGE_SIZE_OPTIONS = exports.DEFAULT_CURRENT_PAGE = exports.DEFAULT_PAGE_SIZE = exports.DEBOUNCE_DELAY = exports.FILTER_TYPES = void 0;
4
4
  exports.FILTER_TYPES = {
5
5
  INPUT: 'text'
6
6
  };
@@ -17,3 +17,7 @@ exports.MAPPER_ITEM_TYPES = {
17
17
  SELECT: 'select',
18
18
  TEXT: 'text'
19
19
  };
20
+ exports.EDIT_FIELD_TYPES = {
21
+ INPUT: 'input',
22
+ SELECT: 'select'
23
+ };
@@ -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":""}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ /* eslint-disable @typescript-eslint/no-explicit-any */
15
+ const react_1 = require("@testing-library/react");
16
+ const user_event_1 = require("@testing-library/user-event");
17
+ const React = require("react");
18
+ const vitest_1 = require("vitest");
19
+ const constants_1 = require("../../../constants");
20
+ const index_1 = require("../index");
21
+ vitest_1.vi.mock('@akinon/ui-input', () => ({
22
+ Input: (_a) => {
23
+ var { value, onChange, className } = _a, props = __rest(_a, ["value", "onChange", "className"]);
24
+ return (React.createElement("input", Object.assign({ "data-testid": "edit-input", value: value, onChange: onChange, className: className }, props)));
25
+ }
26
+ }));
27
+ vitest_1.vi.mock('@akinon/ui-select', () => ({
28
+ Select: (_a) => {
29
+ var { value, onChange, rootClassName, options } = _a, props = __rest(_a, ["value", "onChange", "rootClassName", "options"]);
30
+ const handleChange = (e) => {
31
+ onChange === null || onChange === void 0 ? void 0 : onChange(e.target.value);
32
+ };
33
+ return (React.createElement("select", Object.assign({ "data-testid": "edit-select", value: value !== null && value !== void 0 ? value : '', onChange: handleChange, 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)))));
34
+ }
35
+ }));
36
+ (0, vitest_1.describe)('getEditFieldConfig', () => {
37
+ (0, vitest_1.it)('returns config with INPUT type when dataIndex matches string in editDataIndexes', () => {
38
+ const editDataIndexes = ['name', 'value'];
39
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'name')).toEqual({
40
+ key: 'name',
41
+ type: constants_1.EDIT_FIELD_TYPES.INPUT
42
+ });
43
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'value')).toEqual({
44
+ key: 'value',
45
+ type: constants_1.EDIT_FIELD_TYPES.INPUT
46
+ });
47
+ });
48
+ (0, vitest_1.it)('returns undefined when dataIndex does not match any string', () => {
49
+ const editDataIndexes = ['name', 'value'];
50
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'other')).toBeUndefined();
51
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, '')).toBeUndefined();
52
+ });
53
+ (0, vitest_1.it)('returns config object when dataIndex matches object key (INPUT)', () => {
54
+ const editDataIndexes = [
55
+ { key: 'name', type: constants_1.EDIT_FIELD_TYPES.INPUT },
56
+ {
57
+ key: 'value',
58
+ type: constants_1.EDIT_FIELD_TYPES.INPUT,
59
+ attributes: { placeholder: 'Value' }
60
+ }
61
+ ];
62
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'name')).toEqual({
63
+ key: 'name',
64
+ type: constants_1.EDIT_FIELD_TYPES.INPUT
65
+ });
66
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'value')).toEqual({
67
+ key: 'value',
68
+ type: constants_1.EDIT_FIELD_TYPES.INPUT,
69
+ attributes: { placeholder: 'Value' }
70
+ });
71
+ });
72
+ (0, vitest_1.it)('returns config object when dataIndex matches object key (SELECT)', () => {
73
+ const selectConfig = {
74
+ key: 'status',
75
+ type: constants_1.EDIT_FIELD_TYPES.SELECT,
76
+ attributes: {
77
+ options: [
78
+ { label: 'Active', value: 'active' },
79
+ { label: 'Inactive', value: 'inactive' }
80
+ ]
81
+ }
82
+ };
83
+ const editDataIndexes = [selectConfig];
84
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'status')).toEqual(selectConfig);
85
+ });
86
+ (0, vitest_1.it)('returns undefined for empty editDataIndexes', () => {
87
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)([], 'name')).toBeUndefined();
88
+ });
89
+ (0, vitest_1.it)('returns first match when multiple entries could match', () => {
90
+ const editDataIndexes = [
91
+ 'name',
92
+ { key: 'name', type: constants_1.EDIT_FIELD_TYPES.INPUT }
93
+ ];
94
+ (0, vitest_1.expect)((0, index_1.getEditFieldConfig)(editDataIndexes, 'name')).toEqual({
95
+ key: 'name',
96
+ type: constants_1.EDIT_FIELD_TYPES.INPUT
97
+ });
98
+ });
99
+ });
100
+ (0, vitest_1.describe)('renderEditField', () => {
101
+ (0, vitest_1.it)('renders Input for INPUT config', () => {
102
+ const onChange = vitest_1.vi.fn();
103
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
104
+ config: { key: 'name', type: constants_1.EDIT_FIELD_TYPES.INPUT },
105
+ value: 'test',
106
+ onChange
107
+ })));
108
+ const input = react_1.screen.getByTestId('edit-input');
109
+ (0, vitest_1.expect)(input).toBeInTheDocument();
110
+ (0, vitest_1.expect)(input).toHaveValue('test');
111
+ });
112
+ (0, vitest_1.it)('calls onChange with input value when Input changes', () => {
113
+ const onChange = vitest_1.vi.fn();
114
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
115
+ config: { key: 'name', type: constants_1.EDIT_FIELD_TYPES.INPUT },
116
+ value: '',
117
+ onChange
118
+ })));
119
+ const input = react_1.screen.getByTestId('edit-input');
120
+ react_1.fireEvent.change(input, { target: { value: 'new value' } });
121
+ (0, vitest_1.expect)(onChange).toHaveBeenCalledWith('new value');
122
+ });
123
+ (0, vitest_1.it)('passes attributes to Input (className, etc.)', () => {
124
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
125
+ config: {
126
+ key: 'name',
127
+ type: constants_1.EDIT_FIELD_TYPES.INPUT,
128
+ attributes: { className: 'custom-class', placeholder: 'Name' }
129
+ },
130
+ value: '',
131
+ onChange: vitest_1.vi.fn()
132
+ })));
133
+ const input = react_1.screen.getByTestId('edit-input');
134
+ (0, vitest_1.expect)(input).toHaveClass('custom-class');
135
+ (0, vitest_1.expect)(input).toHaveAttribute('placeholder', 'Name');
136
+ });
137
+ (0, vitest_1.it)('calls attributes.onChange and then onChange when both provided', async () => {
138
+ const user = user_event_1.default.setup();
139
+ const onAttributeChange = vitest_1.vi.fn();
140
+ const onChange = vitest_1.vi.fn();
141
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
142
+ config: {
143
+ key: 'name',
144
+ type: constants_1.EDIT_FIELD_TYPES.INPUT,
145
+ attributes: { onChange: onAttributeChange }
146
+ },
147
+ value: '',
148
+ onChange
149
+ })));
150
+ const input = react_1.screen.getByTestId('edit-input');
151
+ await user.type(input, 'x');
152
+ (0, vitest_1.expect)(onAttributeChange).toHaveBeenCalled();
153
+ (0, vitest_1.expect)(onChange).toHaveBeenCalled();
154
+ });
155
+ (0, vitest_1.it)('renders Select for SELECT config', () => {
156
+ const onChange = vitest_1.vi.fn();
157
+ const options = [
158
+ { label: 'Active', value: 'active' },
159
+ { label: 'Inactive', value: 'inactive' }
160
+ ];
161
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
162
+ config: {
163
+ key: 'status',
164
+ type: constants_1.EDIT_FIELD_TYPES.SELECT,
165
+ attributes: { options }
166
+ },
167
+ value: 'active',
168
+ onChange
169
+ })));
170
+ const select = react_1.screen.getByTestId('edit-select');
171
+ (0, vitest_1.expect)(select).toBeInTheDocument();
172
+ (0, vitest_1.expect)(select).toHaveValue('active');
173
+ });
174
+ (0, vitest_1.it)('calls onChange when Select value changes', async () => {
175
+ const user = user_event_1.default.setup();
176
+ const onChange = vitest_1.vi.fn();
177
+ const options = [
178
+ { label: 'Active', value: 'active' },
179
+ { label: 'Inactive', value: 'inactive' }
180
+ ];
181
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
182
+ config: {
183
+ key: 'status',
184
+ type: constants_1.EDIT_FIELD_TYPES.SELECT,
185
+ attributes: { options }
186
+ },
187
+ value: 'active',
188
+ onChange
189
+ })));
190
+ const select = react_1.screen.getByTestId('edit-select');
191
+ await user.selectOptions(select, 'inactive');
192
+ (0, vitest_1.expect)(onChange).toHaveBeenCalledWith('inactive');
193
+ });
194
+ (0, vitest_1.it)('passes rootClassName to Select', () => {
195
+ const options = [{ label: 'A', value: 'a' }];
196
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
197
+ config: {
198
+ key: 'status',
199
+ type: constants_1.EDIT_FIELD_TYPES.SELECT,
200
+ attributes: { options, rootClassName: 'select-root' }
201
+ },
202
+ value: '',
203
+ onChange: vitest_1.vi.fn()
204
+ })));
205
+ const select = react_1.screen.getByTestId('edit-select');
206
+ (0, vitest_1.expect)(select).toHaveClass('select-root');
207
+ });
208
+ (0, vitest_1.it)('defaults to Input for unknown config type', () => {
209
+ (0, react_1.render)(React.createElement(React.Fragment, null, (0, index_1.renderEditField)({
210
+ config: {
211
+ key: 'name',
212
+ type: 'unknown'
213
+ },
214
+ value: 'fallback',
215
+ onChange: vitest_1.vi.fn()
216
+ })));
217
+ (0, vitest_1.expect)(react_1.screen.getByTestId('edit-input')).toBeInTheDocument();
218
+ (0, vitest_1.expect)(react_1.screen.getByTestId('edit-input')).toHaveValue('fallback');
219
+ });
220
+ });