@visns-studio/visns-components 5.8.14 → 5.8.17

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.
@@ -3,13 +3,37 @@ import '../../styles/global.css';
3
3
  import React, { useEffect, useRef, useState } from 'react';
4
4
  import { useParams } from 'react-router-dom';
5
5
  import Popup from 'reactjs-popup';
6
- import { arrayMoveImmutable } from 'array-move';
6
+ import { arrayMove } from '@dnd-kit/sortable';
7
+ import {
8
+ DndContext,
9
+ closestCenter,
10
+ KeyboardSensor,
11
+ PointerSensor,
12
+ useSensor,
13
+ useSensors,
14
+ pointerWithin,
15
+ rectIntersection,
16
+ } from '@dnd-kit/core';
17
+ import {
18
+ SortableContext,
19
+ sortableKeyboardCoordinates,
20
+ rectSortingStrategy,
21
+ } from '@dnd-kit/sortable';
22
+ import { useSortable } from '@dnd-kit/sortable';
23
+ import { CSS } from '@dnd-kit/utilities';
7
24
  import parse from 'html-react-parser';
8
25
  import Toggle from 'react-toggle';
9
26
  import { toast } from 'react-toastify';
10
27
  import { v4 as uuidv4 } from 'uuid';
11
28
  import { Editor } from '@tinymce/tinymce-react';
12
- import { CirclePlus, CircleX, TrashCan } from 'akar-icons';
29
+ import { Tooltip } from 'react-tooltip';
30
+ import {
31
+ CirclePlus,
32
+ CircleX,
33
+ TrashCan,
34
+ Pencil,
35
+ ChevronVertical,
36
+ } from 'akar-icons';
13
37
  import { confirmDialog } from '../../utils/ConfirmDialog';
14
38
 
15
39
  import 'react-toggle/style.css';
@@ -17,7 +41,6 @@ import 'react-datepicker/dist/react-datepicker.css';
17
41
 
18
42
  import Breadcrumb from '../Breadcrumb';
19
43
  import CustomFetch from '../Fetch';
20
- import SortableList from '../sorting/List';
21
44
  import SketchConfig from '../sketch/json/config.json';
22
45
 
23
46
  import styles from './styles/GenericFormBuilder.module.scss'; // Import the CSS module
@@ -83,8 +106,209 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
83
106
  });
84
107
  const [modalFormShow, setModalFormShow] = useState(false);
85
108
  const [roles, setRoles] = useState([]);
109
+
86
110
  const canvasTypes = SketchConfig.canvasTypes;
87
111
 
112
+ // Generate compact field info for display in the center top
113
+ const getFieldInfo = (field) => {
114
+ const fieldTypeLabel =
115
+ fieldTypes.find((type) => type.value === field.type)?.label ||
116
+ field.type;
117
+
118
+ let info = [];
119
+
120
+ // Always show type
121
+ info.push(fieldTypeLabel);
122
+
123
+ // Show size if not default
124
+ if (field.size && field.size !== 'half') {
125
+ info.push(field.size.charAt(0).toUpperCase() + field.size.slice(1));
126
+ }
127
+
128
+ // Show required status
129
+ if (field.required === 'yes') {
130
+ info.push('Required');
131
+ }
132
+
133
+ // Show additional properties
134
+ if (field.options && field.options.length > 0) {
135
+ info.push(`${field.options.length} options`);
136
+ }
137
+
138
+ if (field.rows && field.rows.length > 0) {
139
+ info.push(`${field.rows.length} rows`);
140
+ }
141
+
142
+ if (field.conditional_field && field.conditional_value) {
143
+ info.push('Conditional');
144
+ }
145
+
146
+ return info.join(' • ');
147
+ };
148
+
149
+ // Generate tooltip content for field information
150
+ const getFieldTooltip = (field) => {
151
+ const fieldTypeLabel =
152
+ fieldTypes.find((type) => type.value === field.type)?.label ||
153
+ field.type;
154
+ let tooltip = `Type: ${fieldTypeLabel}\n`;
155
+ tooltip += `Size: ${field.size || 'Not set'}\n`;
156
+ tooltip += `Required: ${field.required === 'yes' ? 'Yes' : 'No'}\n`;
157
+
158
+ if (field.textareaHeight) {
159
+ tooltip += `Height: ${field.textareaHeight}\n`;
160
+ }
161
+
162
+ if (field.dynamicfield) {
163
+ tooltip += `Dynamic Field: ${field.dynamicfield}\n`;
164
+ }
165
+
166
+ if (field.dynamicDropdown) {
167
+ tooltip += `Dynamic Dropdown: ${field.dynamicDropdown}\n`;
168
+ }
169
+
170
+ if (field.image_qty) {
171
+ tooltip += `Image Type: ${field.image_qty}\n`;
172
+ }
173
+
174
+ if (field.canvasType) {
175
+ tooltip += `Canvas Type: ${field.canvasType}\n`;
176
+ }
177
+
178
+ if (field.options && field.options.length > 0) {
179
+ tooltip += `Options: ${field.options.length} items\n`;
180
+ }
181
+
182
+ if (field.rows && field.rows.length > 0) {
183
+ tooltip += `Rows: ${field.rows.length} items\n`;
184
+ }
185
+
186
+ // Add conditional field information
187
+ if (field.conditional_field && field.conditional_value) {
188
+ tooltip += `\nConditional Logic:\n`;
189
+ tooltip += `Show when "${field.conditional_field}" = "${field.conditional_value}"\n`;
190
+ }
191
+
192
+ // Add other conditional properties if they exist
193
+ if (field.conditionalOperator) {
194
+ tooltip += `Operator: ${field.conditionalOperator}\n`;
195
+ }
196
+
197
+ if (field.conditionalFields && field.conditionalFields.length > 0) {
198
+ tooltip += `Multiple Conditions: ${field.conditionalFields.length} rules\n`;
199
+ }
200
+
201
+ return tooltip.trim();
202
+ };
203
+
204
+ // Create sortable field item using @dnd-kit
205
+ const SortableFieldItem = ({ field, index: counter }) => {
206
+ const {
207
+ attributes,
208
+ listeners,
209
+ setNodeRef,
210
+ transform,
211
+ transition,
212
+ isDragging,
213
+ } = useSortable({
214
+ id: field.id,
215
+ data: {
216
+ type: 'field',
217
+ size: field.size,
218
+ index: counter,
219
+ },
220
+ });
221
+
222
+ const style = {
223
+ transform: CSS.Transform.toString(transform),
224
+ transition: isDragging ? 'none' : transition,
225
+ opacity: isDragging ? 0.5 : 1,
226
+ minHeight: '64.2px',
227
+ position: 'relative',
228
+ zIndex: isDragging ? 1000 : 'auto',
229
+ // Prevent stretching during drag by setting responsive dimensions
230
+ ...(isDragging && {
231
+ width:
232
+ field.size === 'full'
233
+ ? 'min(600px, 90vw)'
234
+ : 'min(300px, 45vw)',
235
+ maxWidth: field.size === 'full' ? '800px' : '400px',
236
+ flexShrink: 0,
237
+ flexGrow: 0,
238
+ display: 'block',
239
+ }),
240
+ };
241
+
242
+ const fieldClassName = renderClassName(field);
243
+
244
+ return (
245
+ <div
246
+ ref={setNodeRef}
247
+ style={style}
248
+ className={`${fieldClassName} ${styles.interactiveField} ${
249
+ styles.previewField
250
+ } ${isDragging ? styles.dragging : ''}`}
251
+ data-tooltip-id="field-tooltip"
252
+ data-tooltip-content={getFieldTooltip(field)}
253
+ data-tooltip-place="top"
254
+ data-field-size={field.size}
255
+ >
256
+ <div className={styles.fieldControls}>
257
+ <div
258
+ {...attributes}
259
+ {...listeners}
260
+ className={styles.dragHandle}
261
+ data-tooltip-id="action-tooltip"
262
+ data-tooltip-content="Drag to Reorder"
263
+ data-tooltip-place="top"
264
+ >
265
+ <ChevronVertical strokeWidth={3} size={24} />
266
+ </div>
267
+ <div className={styles.fieldInfo}>
268
+ <span className={styles.fieldInfoText}>
269
+ {getFieldInfo(field)}
270
+ </span>
271
+ </div>
272
+ <div className={styles.fieldActions}>
273
+ <Pencil
274
+ className={styles.editIcon}
275
+ strokeWidth={3}
276
+ size={20}
277
+ onClick={(e) => {
278
+ console.info(
279
+ 'Edit button clicked - field:',
280
+ field,
281
+ 'counter:',
282
+ counter
283
+ );
284
+ e.preventDefault();
285
+ e.stopPropagation();
286
+ handleEdit(counter);
287
+ }}
288
+ data-tooltip-id="action-tooltip"
289
+ data-tooltip-content="Edit Field"
290
+ data-tooltip-place="top"
291
+ />
292
+ <TrashCan
293
+ className={styles.deleteIcon}
294
+ strokeWidth={3}
295
+ size={20}
296
+ onClick={(e) => {
297
+ e.preventDefault();
298
+ e.stopPropagation();
299
+ handleDeleteField(field.id, field.label);
300
+ }}
301
+ data-tooltip-id="action-tooltip"
302
+ data-tooltip-content="Delete Field"
303
+ data-tooltip-place="top"
304
+ />
305
+ </div>
306
+ </div>
307
+ <div className={styles.fieldContent}>{renderField(field)}</div>
308
+ </div>
309
+ );
310
+ };
311
+
88
312
  /** Data Option Functionalities */
89
313
  const handleDataOption = (e) => {
90
314
  const { name, value } = e.target;
@@ -203,13 +427,55 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
203
427
  };
204
428
 
205
429
  /** Field Functionalities */
206
- const onSortEnd = ({ oldIndex, newIndex }) => {
207
- const newData = arrayMoveImmutable(data.detail, oldIndex, newIndex);
430
+ const sensors = useSensors(
431
+ useSensor(PointerSensor, {
432
+ activationConstraint: {
433
+ distance: 8, // Require 8px of movement before activating
434
+ },
435
+ }),
436
+ useSensor(KeyboardSensor, {
437
+ coordinateGetter: sortableKeyboardCoordinates,
438
+ })
439
+ );
208
440
 
209
- setData((items) => ({
210
- ...items,
211
- detail: newData,
212
- }));
441
+ // Custom collision detection that works better with mixed-size elements
442
+ const customCollisionDetection = (args) => {
443
+ // First, try pointer-based collision for more precise detection
444
+ const pointerCollisions = pointerWithin(args);
445
+ if (pointerCollisions.length > 0) {
446
+ return pointerCollisions;
447
+ }
448
+
449
+ // Fall back to rectangle intersection for better handling of different sizes
450
+ const rectCollisions = rectIntersection(args);
451
+ if (rectCollisions.length > 0) {
452
+ return rectCollisions;
453
+ }
454
+
455
+ // Finally, use closest center as last resort
456
+ return closestCenter(args);
457
+ };
458
+
459
+ const handleDragEnd = (event) => {
460
+ const { active, over } = event;
461
+
462
+ if (active.id !== over?.id && over) {
463
+ const oldIndex = data.detail.findIndex(
464
+ (item) => item.id === active.id
465
+ );
466
+ const newIndex = data.detail.findIndex(
467
+ (item) => item.id === over.id
468
+ );
469
+
470
+ if (oldIndex !== -1 && newIndex !== -1) {
471
+ const newData = arrayMove(data.detail, oldIndex, newIndex);
472
+
473
+ setData((items) => ({
474
+ ...items,
475
+ detail: newData,
476
+ }));
477
+ }
478
+ }
213
479
  };
214
480
 
215
481
  const handleCloseModal = () => {
@@ -266,16 +532,25 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
266
532
  const handleEdit = (key) => {
267
533
  const { detail } = data;
268
534
 
269
- setDataField(() => ({
270
- ...detail[key],
271
- }));
535
+ console.info('handleEdit called with key:', key);
536
+ console.info('data.detail:', detail);
537
+ console.info('detail[key]:', detail[key]);
272
538
 
273
- setModalType(() => ({
274
- type: 'update',
275
- key: key,
276
- }));
539
+ if (detail && detail[key] !== undefined) {
540
+ setDataField(() => ({
541
+ ...detail[key],
542
+ }));
277
543
 
278
- handleOpenModal();
544
+ setModalType(() => ({
545
+ type: 'update',
546
+ key: key,
547
+ }));
548
+
549
+ handleOpenModal();
550
+ } else {
551
+ console.error('Field not found at key:', key);
552
+ toast.error('Field not found. Please try again.');
553
+ }
279
554
  };
280
555
 
281
556
  const handleDeleteField = (id, label) => {
@@ -306,7 +581,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
306
581
  },
307
582
  {
308
583
  label: 'No',
309
- onClick: () => close(),
584
+ onClick: () => {
585
+ // Dialog will close automatically
586
+ },
310
587
  },
311
588
  ],
312
589
  });
@@ -869,68 +1146,57 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
869
1146
  </div>
870
1147
  </div>
871
1148
  <div className={styles.grid}>
872
- <div className={styles.grid__subrow}>
873
- <div className={styles.grid__subnav}>
874
- <div
875
- className={styles.gridtxt__header}
876
- style={{ marginBottom: '10px' }}
877
- >
878
- <span>Form Fields</span>
879
- </div>
880
- {data.detail && data.detail.length > 0 ? (
881
- <div className={styles.sortableListContainer}>
882
- <SortableList
883
- handleClick={handleEdit}
884
- handleDelete={handleDeleteField}
885
- items={data.detail}
886
- onSortEnd={onSortEnd}
887
- axis="xy"
888
- helperClass={styles.dragitem}
889
- transitionDuration={250}
890
- showImage={false}
891
- useDragHandle
892
- />
893
- </div>
894
- ) : (
895
- <div
896
- style={{
897
- padding: '10px',
898
- textAlign: 'center',
899
- color: 'rgba(var(--paragraph-color-rgb), 0.7)',
900
- fontSize: '0.9rem',
901
- }}
902
- >
903
- No fields added yet. Click "Add Field" to get
904
- started.
905
- </div>
906
- )}
907
- </div>
908
- <div className={styles.grid__subcontent}>
1149
+ <div className={styles.grid__row}>
1150
+ <div className={styles.grid__fullwidth}>
909
1151
  <div className={styles.formSplit}>
910
1152
  <div className={styles.gridtxt__header}>
911
- <span>{formTitle ? formTitle : null}</span>
1153
+ <span>
1154
+ {formTitle
1155
+ ? formTitle
1156
+ : 'Form Template Preview'}
1157
+ </span>
912
1158
  </div>
913
1159
  {data.detail && data.detail.length > 0 ? (
914
1160
  <div className={styles.modal__content}>
915
1161
  <div className={styles.formcontainer}>
916
- <form className={styles.modalForm}>
917
- {data.detail.map((a, b) => (
1162
+ <DndContext
1163
+ sensors={sensors}
1164
+ collisionDetection={
1165
+ customCollisionDetection
1166
+ }
1167
+ onDragEnd={handleDragEnd}
1168
+ >
1169
+ <SortableContext
1170
+ items={data.detail.map(
1171
+ (field) => field.id
1172
+ )}
1173
+ strategy={rectSortingStrategy}
1174
+ >
918
1175
  <div
919
- key={`form-preview-field-${b}`}
920
- className={renderClassName(
921
- a
922
- )}
923
- style={{
924
- minHeight: '64.2px',
925
- }}
1176
+ className={styles.modalForm}
926
1177
  >
927
- {renderField(a)}
1178
+ {data.detail.map(
1179
+ (field, index) => (
1180
+ <SortableFieldItem
1181
+ key={field.id}
1182
+ field={field}
1183
+ index={index}
1184
+ />
1185
+ )
1186
+ )}
928
1187
  </div>
929
- ))}
930
- </form>
1188
+ </SortableContext>
1189
+ </DndContext>
931
1190
  </div>
932
1191
  </div>
933
- ) : null}
1192
+ ) : (
1193
+ <div className={styles.emptyState}>
1194
+ <p>
1195
+ No fields added yet. Click "Add Field"
1196
+ to get started.
1197
+ </p>
1198
+ </div>
1199
+ )}
934
1200
  </div>
935
1201
  <div className={styles.polActions}>
936
1202
  <button
@@ -972,7 +1238,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
972
1238
  </div>
973
1239
  <div className={styles.modal__content}>
974
1240
  <div className={styles.formcontainer}>
975
- <form className={styles.modalForm}>
1241
+ <form className={styles.modalFieldForm}>
976
1242
  <div className={styles.formItem}>
977
1243
  <label className={styles.fi__label}>
978
1244
  <select
@@ -1271,23 +1537,13 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1271
1537
  {['checkbox', 'dropdown'].includes(
1272
1538
  dataField.type
1273
1539
  ) ? (
1274
- <div
1275
- className={`${styles.formItem} ${styles.fwItem}`}
1276
- >
1540
+ <div className={styles.formItemFull}>
1277
1541
  <table
1278
- className={styles.contentTable}
1542
+ className={styles.optionsTable}
1279
1543
  >
1280
- <thead
1281
- className={
1282
- styles.gridHeaders
1283
- }
1284
- >
1544
+ <thead>
1285
1545
  <tr>
1286
- <th
1287
- style={{
1288
- width: '790px',
1289
- }}
1290
- >
1546
+ <th>
1291
1547
  {dataField.type ===
1292
1548
  'table_text' ||
1293
1549
  dataField.type ===
@@ -1295,7 +1551,13 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1295
1551
  ? 'Column Header'
1296
1552
  : 'Label'}
1297
1553
  </th>
1298
- <th></th>
1554
+ <th
1555
+ style={{
1556
+ width: '80px',
1557
+ }}
1558
+ >
1559
+ Actions
1560
+ </th>
1299
1561
  </tr>
1300
1562
  </thead>
1301
1563
  <tbody>
@@ -1338,20 +1600,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1338
1600
  }}
1339
1601
  />
1340
1602
  </td>
1341
- <td
1342
- style={{
1343
- textAlign:
1344
- 'right',
1345
- }}
1346
- >
1603
+ <td>
1347
1604
  <button
1348
- className={
1349
- styles.btn
1350
- }
1351
- style={{
1352
- padding:
1353
- '15px 20px',
1354
- }}
1605
+ className={`${styles.tableActionBtn} ${styles.delete}`}
1355
1606
  onClick={
1356
1607
  handleDeleteOption
1357
1608
  }
@@ -1368,7 +1619,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1368
1619
  2
1369
1620
  }
1370
1621
  size={
1371
- 18
1622
+ 14
1372
1623
  }
1373
1624
  />
1374
1625
  </button>
@@ -1390,11 +1641,6 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1390
1641
  <td>
1391
1642
  <input
1392
1643
  type="text"
1393
- style={{
1394
- height: '52px',
1395
- padding:
1396
- '1rem',
1397
- }}
1398
1644
  name="label"
1399
1645
  onChange={
1400
1646
  handleDataOption
@@ -1402,23 +1648,12 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1402
1648
  value={
1403
1649
  dataOption.label
1404
1650
  }
1405
- placeholder="Column Header"
1651
+ placeholder="Enter label..."
1406
1652
  />
1407
1653
  </td>
1408
- <td
1409
- style={{
1410
- textAlign:
1411
- 'right',
1412
- }}
1413
- >
1654
+ <td>
1414
1655
  <button
1415
- className={
1416
- styles.btn
1417
- }
1418
- style={{
1419
- padding:
1420
- '15px 20px',
1421
- }}
1656
+ className={`${styles.tableActionBtn} ${styles.add}`}
1422
1657
  onClick={
1423
1658
  handleAddOption
1424
1659
  }
@@ -1431,8 +1666,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1431
1666
  strokeWidth={
1432
1667
  2
1433
1668
  }
1434
- size={18}
1669
+ size={14}
1435
1670
  />
1671
+ Add
1436
1672
  </button>
1437
1673
  </td>
1438
1674
  </tr>
@@ -1444,27 +1680,21 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1444
1680
  {['table_radio', 'table_text'].includes(
1445
1681
  dataField.type
1446
1682
  ) ? (
1447
- <div
1448
- className={`${styles.formItem} ${styles.fwItem}`}
1449
- >
1683
+ <div className={styles.formItemFull}>
1450
1684
  <table
1451
- className={styles.contentTable}
1685
+ className={styles.optionsTable}
1452
1686
  >
1453
- <thead
1454
- className={
1455
- styles.gridHeaders
1456
- }
1457
- >
1687
+ <thead>
1458
1688
  <tr>
1689
+ <th>Column Header</th>
1690
+ <th>Column Type</th>
1459
1691
  <th
1460
1692
  style={{
1461
- width: '450px',
1693
+ width: '80px',
1462
1694
  }}
1463
1695
  >
1464
- Column Header
1696
+ Actions
1465
1697
  </th>
1466
- <th>Column Type</th>
1467
- <th></th>
1468
1698
  </tr>
1469
1699
  </thead>
1470
1700
  <tbody>
@@ -1594,20 +1824,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1594
1824
  )}
1595
1825
  </select>
1596
1826
  </td>
1597
- <td
1598
- style={{
1599
- textAlign:
1600
- 'right',
1601
- }}
1602
- >
1827
+ <td>
1603
1828
  <button
1604
- className={
1605
- styles.btn
1606
- }
1607
- style={{
1608
- padding:
1609
- '15px 20px',
1610
- }}
1829
+ className={`${styles.tableActionBtn} ${styles.delete}`}
1611
1830
  onClick={
1612
1831
  handleDeleteOption
1613
1832
  }
@@ -1624,7 +1843,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1624
1843
  2
1625
1844
  }
1626
1845
  size={
1627
- 18
1846
+ 14
1628
1847
  }
1629
1848
  />
1630
1849
  </button>
@@ -1646,11 +1865,6 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1646
1865
  <td>
1647
1866
  <input
1648
1867
  type="text"
1649
- style={{
1650
- height: '52px',
1651
- padding:
1652
- '1rem',
1653
- }}
1654
1868
  name="label"
1655
1869
  onChange={
1656
1870
  handleDataOption
@@ -1658,7 +1872,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1658
1872
  value={
1659
1873
  dataOption.label
1660
1874
  }
1661
- placeholder="Column Header"
1875
+ placeholder="Enter column header..."
1662
1876
  />
1663
1877
  </td>
1664
1878
  <td>
@@ -1731,20 +1945,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1731
1945
  )}
1732
1946
  </select>
1733
1947
  </td>
1734
- <td
1735
- style={{
1736
- textAlign:
1737
- 'right',
1738
- }}
1739
- >
1948
+ <td>
1740
1949
  <button
1741
- className={
1742
- styles.btn
1743
- }
1744
- style={{
1745
- padding:
1746
- '15px 20px',
1747
- }}
1950
+ className={`${styles.tableActionBtn} ${styles.add}`}
1748
1951
  onClick={
1749
1952
  handleAddOption
1750
1953
  }
@@ -1757,8 +1960,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1757
1960
  strokeWidth={
1758
1961
  2
1759
1962
  }
1760
- size={18}
1963
+ size={14}
1761
1964
  />
1965
+ Add
1762
1966
  </button>
1763
1967
  </td>
1764
1968
  </tr>
@@ -1841,26 +2045,20 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1841
2045
  {['table_radio'].includes(
1842
2046
  dataField.type
1843
2047
  ) ? (
1844
- <div
1845
- className={`${styles.formItem} ${styles.fwItem}`}
1846
- >
2048
+ <div className={styles.formItemFull}>
1847
2049
  <table
1848
- className={styles.contentTable}
2050
+ className={styles.optionsTable}
1849
2051
  >
1850
- <thead
1851
- className={
1852
- styles.gridHeaders
1853
- }
1854
- >
2052
+ <thead>
1855
2053
  <tr>
2054
+ <th>Row Label</th>
1856
2055
  <th
1857
2056
  style={{
1858
- width: '790px',
2057
+ width: '80px',
1859
2058
  }}
1860
2059
  >
1861
- Row Label
2060
+ Actions
1862
2061
  </th>
1863
- <th></th>
1864
2062
  </tr>
1865
2063
  </thead>
1866
2064
  <tbody>
@@ -1899,20 +2097,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1899
2097
  }}
1900
2098
  />
1901
2099
  </td>
1902
- <td
1903
- style={{
1904
- textAlign:
1905
- 'right',
1906
- }}
1907
- >
2100
+ <td>
1908
2101
  <button
1909
- className={
1910
- styles.btn
1911
- }
1912
- style={{
1913
- padding:
1914
- '15px 20px',
1915
- }}
2102
+ className={`${styles.tableActionBtn} ${styles.delete}`}
1916
2103
  onClick={
1917
2104
  handleDeleteRowOption
1918
2105
  }
@@ -1921,7 +2108,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1921
2108
  }
1922
2109
  data-tooltip-id="system-tooltip"
1923
2110
  data-tooltip-content={
1924
- 'Delete Option'
2111
+ 'Delete Row'
1925
2112
  }
1926
2113
  >
1927
2114
  <TrashCan
@@ -1929,7 +2116,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1929
2116
  2
1930
2117
  }
1931
2118
  size={
1932
- 18
2119
+ 14
1933
2120
  }
1934
2121
  />
1935
2122
  </button>
@@ -1951,11 +2138,6 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1951
2138
  <td>
1952
2139
  <input
1953
2140
  type="text"
1954
- style={{
1955
- height: '52px',
1956
- padding:
1957
- '1rem',
1958
- }}
1959
2141
  name="label"
1960
2142
  onChange={
1961
2143
  handleRowOption
@@ -1963,36 +2145,27 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1963
2145
  value={
1964
2146
  rowOption.label
1965
2147
  }
2148
+ placeholder="Enter row label..."
1966
2149
  />
1967
2150
  </td>
1968
- <td
1969
- style={{
1970
- textAlign:
1971
- 'right',
1972
- }}
1973
- >
2151
+ <td>
1974
2152
  <button
1975
- className={
1976
- styles.btn
1977
- }
1978
- style={{
1979
- padding:
1980
- '15px 20px',
1981
- }}
2153
+ className={`${styles.tableActionBtn} ${styles.add}`}
1982
2154
  onClick={
1983
2155
  handleAddRowOption
1984
2156
  }
1985
2157
  data-tooltip-id="system-tooltip"
1986
2158
  data-tooltip-content={
1987
- 'Add Option'
2159
+ 'Add Row'
1988
2160
  }
1989
2161
  >
1990
2162
  <CirclePlus
1991
2163
  strokeWidth={
1992
2164
  2
1993
2165
  }
1994
- size={18}
2166
+ size={14}
1995
2167
  />
2168
+ Add
1996
2169
  </button>
1997
2170
  </td>
1998
2171
  </tr>
@@ -2095,7 +2268,9 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
2095
2268
  <div className={styles.modal__content}>
2096
2269
  <div className={styles.formcontainer}>
2097
2270
  <form className={styles.modalForm}>
2098
- <div className={styles.formItem}>
2271
+ <div
2272
+ className={`${styles.formItem} ${styles.fwItem}`}
2273
+ >
2099
2274
  <label className={styles.fi__label}>
2100
2275
  <input
2101
2276
  type="text"
@@ -2126,6 +2301,33 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
2126
2301
  </div>
2127
2302
  </div>
2128
2303
  </Popup>
2304
+
2305
+ {/* React Tooltips */}
2306
+ <Tooltip
2307
+ id="field-tooltip"
2308
+ style={{
2309
+ backgroundColor: 'rgba(0, 0, 0, 0.9)',
2310
+ color: 'white',
2311
+ borderRadius: '8px',
2312
+ padding: '12px 16px',
2313
+ fontSize: '14px',
2314
+ lineHeight: '1.4',
2315
+ maxWidth: '300px',
2316
+ whiteSpace: 'pre-line',
2317
+ zIndex: 9999,
2318
+ }}
2319
+ />
2320
+ <Tooltip
2321
+ id="action-tooltip"
2322
+ style={{
2323
+ backgroundColor: 'rgba(0, 0, 0, 0.9)',
2324
+ color: 'white',
2325
+ borderRadius: '6px',
2326
+ padding: '8px 12px',
2327
+ fontSize: '13px',
2328
+ zIndex: 9999,
2329
+ }}
2330
+ />
2129
2331
  </>
2130
2332
  );
2131
2333
  }