@visns-studio/visns-components 5.2.15 → 5.3.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.
package/package.json CHANGED
@@ -78,7 +78,7 @@
78
78
  "react-dom": "^17.0.0 || ^18.0.0"
79
79
  },
80
80
  "name": "@visns-studio/visns-components",
81
- "version": "5.2.15",
81
+ "version": "5.3.0",
82
82
  "description": "Various packages to assist in the development of our Custom Applications.",
83
83
  "main": "src/index.js",
84
84
  "files": [
@@ -51,6 +51,7 @@ function Field({
51
51
  inputClass,
52
52
  mapbox,
53
53
  onChange,
54
+ onChangeCanvas,
54
55
  onChangeCheckbox,
55
56
  onChangeCheckboxManual,
56
57
  onChangeColour,
@@ -196,9 +197,16 @@ function Field({
196
197
  setFormItemClass(`${styles.formItem} ${styles.qtrItem}`);
197
198
  break;
198
199
  default:
199
- setFormItemClass(`${styles.formItem}`);
200
+ setFormItemClass(`${styles.formItem} ${styles.halfItem}`);
200
201
  break;
201
202
  }
203
+
204
+ if (settings.type === 'canvas') {
205
+ const canvasType = SketchConfig.canvasTypes.find(
206
+ (a) => a.id === settings.canvasType
207
+ );
208
+ setCanvasUrl(canvasType.url);
209
+ }
202
210
  }, [settings, counter]);
203
211
 
204
212
  const fetchChildDropdownData = (s, v) => {
@@ -316,6 +324,7 @@ function Field({
316
324
  [
317
325
  'address',
318
326
  'async-dropdown-ajax',
327
+ 'canvas',
319
328
  'checkbox',
320
329
  'colour',
321
330
  'copytoclipboard',
@@ -350,32 +359,6 @@ function Field({
350
359
  {settings.label} {settings.required ? '*' : ''}
351
360
  </span>
352
361
  );
353
- } else if (['plaintext'].includes(settings.type)) {
354
- if (settings.description) {
355
- return (
356
- <span>
357
- {settings.description
358
- ? parse(settings.description)
359
- : ''}
360
- </span>
361
- );
362
- } else {
363
- return (
364
- <span
365
- className={`${styles.fi__span} ${styles.prefocus}`}
366
- >
367
- {settings.label} {settings.required ? '*' : ''}
368
- </span>
369
- );
370
- }
371
- } else if (['plaintextheading'].includes(settings.type)) {
372
- return <h2>{settings.label ? settings.label : ''}</h2>;
373
- } else if (['section'].includes(settings.type)) {
374
- return (
375
- <div className={styles.gridtxt__header}>
376
- <span>{settings.label}</span>
377
- </div>
378
- );
379
362
  } else if (['richeditor', 'textarea'].includes(settings.type)) {
380
363
  return settings.label;
381
364
  } else if (['table_radio', 'table_text'].includes(settings.type)) {
@@ -458,6 +441,19 @@ function Field({
458
441
  />
459
442
  </div>
460
443
  );
444
+ case 'canvas':
445
+ return canvasUrl ? (
446
+ <div
447
+ onClick={() => setCanvasPopupOpen(true)}
448
+ style={{ cursor: 'pointer' }}
449
+ >
450
+ <img
451
+ src={settings.imageData || canvasUrl}
452
+ width="200"
453
+ alt="Canvas Preview"
454
+ />
455
+ </div>
456
+ ) : null;
461
457
  case 'checkbox':
462
458
  return (
463
459
  <div
@@ -513,7 +509,7 @@ function Field({
513
509
  settings.options.map((option, index) => (
514
510
  <div
515
511
  key={`${settings.id}-checkbox-option-${index}`}
516
- className="fi__checkboxcontainer"
512
+ className={styles.fi__checkboxcontainer}
517
513
  >
518
514
  <input
519
515
  name={settings.id}
@@ -1186,17 +1182,17 @@ function Field({
1186
1182
  );
1187
1183
  case 'radio':
1188
1184
  return settings.options?.length > 0 ? (
1189
- <div className="fi__optionscontainer">
1185
+ <div className={styles.fi__optionscontainer}>
1190
1186
  {settings.options.map((option, index) => (
1191
1187
  <div
1192
1188
  key={`${settings.id}-checkbox-option-${index}`}
1193
- className="fi__checkboxcontainer"
1189
+ className={styles.fi__checkboxcontainer}
1194
1190
  >
1195
1191
  <input
1196
1192
  name={settings.id}
1197
1193
  data-name={settings.id}
1198
1194
  type="radio"
1199
- className="fi__customcheckbox"
1195
+ className={styles.fi__customcheckbox}
1200
1196
  value={option.id}
1201
1197
  checked={
1202
1198
  parseInt(inputValue) ===
@@ -1204,7 +1200,7 @@ function Field({
1204
1200
  }
1205
1201
  onChange={onChange}
1206
1202
  />
1207
- <label className="fi__checkboxlabel">
1203
+ <label className={styles.fi__checkboxlabel}>
1208
1204
  {option.label}
1209
1205
  </label>{' '}
1210
1206
  </div>
@@ -1213,17 +1209,17 @@ function Field({
1213
1209
  ) : null;
1214
1210
  case 'radio-ajax':
1215
1211
  return options?.length > 0 ? (
1216
- <div className="fi__optionscontainer">
1212
+ <div className={styles.fi__optionscontainer}>
1217
1213
  {options.map((option, index) => (
1218
1214
  <div
1219
1215
  key={`${settings.id}-checkbox-option-${index}`}
1220
- className="fi__checkboxcontainer"
1216
+ className={styles.fi__checkboxcontainer}
1221
1217
  >
1222
1218
  <input
1223
1219
  name={settings.id}
1224
1220
  data-name={settings.id}
1225
1221
  type="radio"
1226
- className="fi__customcheckbox"
1222
+ className={styles.fi__customcheckbox}
1227
1223
  value={option.id}
1228
1224
  checked={
1229
1225
  parseInt(inputValue) ===
@@ -1231,7 +1227,7 @@ function Field({
1231
1227
  }
1232
1228
  onChange={onChange}
1233
1229
  />
1234
- <label className="fi__checkboxlabel">
1230
+ <label className={styles.fi__checkboxlabel}>
1235
1231
  {option.label}
1236
1232
  </label>{' '}
1237
1233
  </div>
@@ -1692,6 +1688,7 @@ function Field({
1692
1688
  ![
1693
1689
  'address',
1694
1690
  'async-dropdown-ajax',
1691
+ 'canvas',
1695
1692
  'checkbox',
1696
1693
  'colour',
1697
1694
  'copytoclipboard',
@@ -1763,6 +1760,33 @@ function Field({
1763
1760
  shouldCloseOnSelect={true}
1764
1761
  />
1765
1762
  );
1763
+ case 'plaintext':
1764
+ if (settings.description) {
1765
+ return (
1766
+ <>
1767
+ {settings.description
1768
+ ? parse(settings.description)
1769
+ : ''}
1770
+ </>
1771
+ );
1772
+ } else {
1773
+ return (
1774
+ <span
1775
+ className={`${styles.fi__span} ${styles.prefocus}`}
1776
+ >
1777
+ {settings.label} {settings.required ? '*' : ''}
1778
+ </span>
1779
+ );
1780
+ }
1781
+ break;
1782
+ case 'plaintextheading':
1783
+ return <h2>{settings.label ? settings.label : ''}</h2>;
1784
+ case 'section':
1785
+ return (
1786
+ <div className={styles.gridtxt__header}>
1787
+ <span>{settings.label}</span>
1788
+ </div>
1789
+ );
1766
1790
  case 'richeditor':
1767
1791
  return (
1768
1792
  <Editor
@@ -151,6 +151,8 @@ function Form({
151
151
  }
152
152
  };
153
153
 
154
+ const handleChangeCanvas = (id, value) => {};
155
+
154
156
  const handleChangeCheckbox = (e) => {
155
157
  const { checked, name, value } = e.target;
156
158
 
@@ -1291,6 +1293,7 @@ function Form({
1291
1293
  }
1292
1294
  mapbox={mapbox}
1293
1295
  onChange={handleChange}
1296
+ onChangeCanvas={handleChangeCanvas}
1294
1297
  onChangeCheckbox={handleChangeCheckbox}
1295
1298
  onChangeCheckboxManual={
1296
1299
  handleChangeCheckboxManual
@@ -1442,6 +1445,7 @@ function Form({
1442
1445
  }
1443
1446
  mapbox={mapbox}
1444
1447
  onChange={handleChange}
1448
+ onChangeCanvas={handleChangeCanvas}
1445
1449
  onChangeCheckbox={
1446
1450
  handleChangeCheckbox
1447
1451
  }
@@ -31,6 +31,8 @@ const updateField = (fields, name, value) => {
31
31
 
32
32
  const renderValue = (field, data) => {
33
33
  switch (field.type) {
34
+ case 'canvas':
35
+ return field.value || '';
34
36
  case 'datetime':
35
37
  case 'date':
36
38
  return field.value && moment(field.value).isValid()
@@ -103,6 +105,7 @@ const GenericDynamic = ({
103
105
  }) => {
104
106
  const [activeForm, setActiveForm] = useState({});
105
107
  const [activeFormKey, setActiveFormKey] = useState(0);
108
+ const [canvasSaveCounter, setCanvasSaveCounter] = useState(0);
106
109
 
107
110
  const handleChange = (e) => {
108
111
  const {
@@ -174,6 +177,35 @@ const GenericDynamic = ({
174
177
  }
175
178
  };
176
179
 
180
+ const handleChangeCanvas = (fieldSetting, value, imageData) => {
181
+ // Check if activeForm has keys
182
+ if (activeForm && typeof activeForm === 'object') {
183
+ // Iterate over the keys in activeForm to find the matching id
184
+ for (const key in activeForm) {
185
+ if (activeForm[key].id === fieldSetting.id) {
186
+ // If a matching id is found, update the corresponding field
187
+ setActiveForm((prevState) => ({
188
+ ...prevState,
189
+ [key]: {
190
+ ...prevState[key],
191
+ value, // Update the value for the matching id
192
+ imageData,
193
+ },
194
+ }));
195
+
196
+ setCanvasSaveCounter((prevState) => prevState + 1);
197
+ return; // Exit after updating to prevent further iterations
198
+ }
199
+ }
200
+ }
201
+ };
202
+
203
+ useEffect(() => {
204
+ if (canvasSaveCounter > 0) {
205
+ handleSaveForm(false);
206
+ }
207
+ }, [canvasSaveCounter]);
208
+
177
209
  const handleChangeCheckbox = (e) => {
178
210
  const { checked, name, value } = e.target;
179
211
 
@@ -464,7 +496,7 @@ const GenericDynamic = ({
464
496
  if (showToast) {
465
497
  toast.success('Form added successfully');
466
498
  }
467
- fetchData();
499
+ fetchData(type);
468
500
  }
469
501
  }
470
502
  } catch (err) {
@@ -473,7 +505,47 @@ const GenericDynamic = ({
473
505
  }
474
506
  };
475
507
 
476
- const handleDownloadForm = async (item, label, data) => {
508
+ const handleDownloadForm = async (item, label, data, debug = false) => {
509
+ if (debug) {
510
+ // Open the form in a new tab by sending a POST request
511
+ const form = document.createElement('form');
512
+ form.method = 'POST';
513
+ form.action = setting.download;
514
+ form.target = '_blank'; // Open in new tab
515
+
516
+ // Append CSRF token if needed (for Laravel)
517
+ const csrfToken = document
518
+ .querySelector('meta[name="csrf-token"]')
519
+ ?.getAttribute('content');
520
+ if (csrfToken) {
521
+ const csrfInput = document.createElement('input');
522
+ csrfInput.type = 'hidden';
523
+ csrfInput.name = '_token';
524
+ csrfInput.value = csrfToken;
525
+ form.appendChild(csrfInput);
526
+ }
527
+
528
+ // Append the required data
529
+ const appendHiddenField = (name, value) => {
530
+ const input = document.createElement('input');
531
+ input.type = 'hidden';
532
+ input.name = name;
533
+ input.value = JSON.stringify(value);
534
+ form.appendChild(input);
535
+ };
536
+
537
+ appendHiddenField('data', item);
538
+ appendHiddenField('dynamicData', data);
539
+ appendHiddenField('label', label);
540
+ appendHiddenField('debug', true);
541
+
542
+ document.body.appendChild(form);
543
+ form.submit();
544
+ document.body.removeChild(form);
545
+
546
+ return;
547
+ }
548
+
477
549
  const toastId = toast.loading('Downloading form...');
478
550
 
479
551
  try {
@@ -538,7 +610,7 @@ const GenericDynamic = ({
538
610
 
539
611
  if (res.data.error === '') {
540
612
  toast.success('Form deleted successfully.');
541
- fetchData();
613
+ fetchData(type);
542
614
  } else {
543
615
  toast.error('Error: ' + res.data.error);
544
616
  }
@@ -597,7 +669,7 @@ const GenericDynamic = ({
597
669
 
598
670
  if (res.data.error === '') {
599
671
  toast.success('Form saved successfully.');
600
- fetchData();
672
+ fetchData(type);
601
673
  }
602
674
  } else {
603
675
  toast.error(<div>{parse(error)}</div>);
@@ -723,6 +795,9 @@ const GenericDynamic = ({
723
795
  onChange={
724
796
  handleChange
725
797
  }
798
+ onChangeCanvas={
799
+ handleChangeCanvas
800
+ }
726
801
  onChangeCheckbox={
727
802
  handleChangeCheckbox
728
803
  }
@@ -771,6 +846,9 @@ const GenericDynamic = ({
771
846
  originalData
772
847
  )}
773
848
  onChange={handleChange}
849
+ onChangeCanvas={
850
+ handleChangeCanvas
851
+ }
774
852
  onChangeCheckbox={
775
853
  handleChangeCheckbox
776
854
  }
@@ -877,7 +955,8 @@ const GenericDynamic = ({
877
955
  handleDownloadForm(
878
956
  item,
879
957
  label,
880
- originalData
958
+ originalData,
959
+ true
881
960
  )
882
961
  }
883
962
  >
@@ -347,11 +347,12 @@ input[type='file']:hover {
347
347
  display: flex;
348
348
  flex-wrap: wrap;
349
349
  gap: 10px;
350
- margin-top: 8px;
350
+ margin-top: 30px;
351
351
  }
352
352
 
353
353
  .fi__checkboxcontainer {
354
- display: flex;
354
+ display: grid;
355
+ grid-template-columns: auto 1fr;
355
356
  align-items: center;
356
357
  }
357
358
 
@@ -33,7 +33,7 @@
33
33
  form {
34
34
  width: 100%;
35
35
  display: grid;
36
- grid-template-columns: 1fr 1fr;
36
+ grid-template-columns: 1fr 1fr 1fr 1fr;
37
37
  gap: 1em;
38
38
  }
39
39
  }
@@ -110,7 +110,8 @@
110
110
  }
111
111
 
112
112
  .fi__checkboxcontainer {
113
- display: flex;
113
+ display: grid;
114
+ grid-template-columns: auto 1fr;
114
115
  align-items: center;
115
116
  }
116
117
 
@@ -125,7 +126,17 @@
125
126
 
126
127
  .fwItem,
127
128
  .fwBuilderItem {
128
- grid-column: 1 / -1;
129
+ grid-column: 1 / -1; /* Full width */
130
+ width: 100%;
131
+ }
132
+
133
+ .halfItem {
134
+ grid-column: span 2; /* Takes up 2 out of 4 columns */
135
+ width: 100%;
136
+ }
137
+
138
+ .qtrItem {
139
+ grid-column: span 1; /* Takes up 1 out of 4 columns */
129
140
  width: 100%;
130
141
  }
131
142
 
@@ -142,33 +153,33 @@ select:not(:placeholder-shown) + .fi__span {
142
153
  }
143
154
 
144
155
  .prefocus {
145
- transform: translateY(-130%) translateX(10px) scale(0.9) !important;
146
- opacity: 1 !important;
147
- padding: 0 0.25rem !important;
148
- background: var(--tertiary-color) !important;
149
- font-weight: 400 !important;
150
- transition: all 0.5s cubic-bezier(0.5, 0.5, 0, 1) !important;
151
- z-index: 1 !important;
152
- color: rgba(var(--paragraph-rgb), 0.65) !important;
156
+ position: absolute;
157
+ top: -12px; /* Adjust based on label height */
158
+ left: 10px; /* Ensures consistency across all field sizes */
159
+ font-size: 0.85em; /* Keep it proportional */
160
+ transform: scale(0.9);
161
+ opacity: 1;
162
+ background: var(--tertiary-color);
163
+ font-weight: 400;
164
+ transition: all 0.5s cubic-bezier(0.5, 0.5, 0, 1);
165
+ z-index: 1;
166
+ color: rgba(var(--paragraph-rgb), 0.65);
167
+ padding: 0 0.25rem;
153
168
  }
154
169
 
155
170
  .prefocusdate {
156
- transform: translateX(10px) scale(0.9) !important;
157
- opacity: 1 !important;
158
- padding: 0 0.25rem !important;
159
- background: var(--tertiary-color) !important;
160
- font-weight: 400 !important;
161
- transition: all 0.5s cubic-bezier(0.5, 0.5, 0, 1) !important;
162
- z-index: 1 !important;
163
- color: rgba(var(--paragraph-rgb), 0.65) !important;
164
- }
165
-
166
- .qtrItem {
167
- flex-basis: 25%;
168
- }
169
-
170
- .fwItem {
171
- flex-basis: 100%;
171
+ position: absolute;
172
+ top: -12px;
173
+ left: 10px;
174
+ font-size: 0.85em;
175
+ transform: scale(0.9);
176
+ opacity: 1;
177
+ background: var(--tertiary-color);
178
+ font-weight: 400;
179
+ transition: all 0.5s cubic-bezier(0.5, 0.5, 0, 1);
180
+ z-index: 1;
181
+ color: rgba(var(--paragraph-rgb), 0.65);
182
+ padding: 0 0.25rem;
172
183
  }
173
184
 
174
185
  .lastItem {
@@ -8,7 +8,7 @@
8
8
  form {
9
9
  width: 100%;
10
10
  display: grid;
11
- grid-template-columns: 1fr 1fr;
11
+ grid-template-columns: 1fr 1fr 1fr 1fr;
12
12
  gap: 1em;
13
13
  }
14
14
  }
@@ -73,6 +73,14 @@ p {
73
73
  }
74
74
  }
75
75
 
76
+ .Toastify__toast-body p {
77
+ font-size: revert;
78
+ color: revert;
79
+ font-weight: revert;
80
+ line-height: revert;
81
+ margin-bottom: revert;
82
+ }
83
+
76
84
  ul {
77
85
  font-size: clamp(1rem, 2vw, 1.25rem);
78
86
  color: var(--paragraph-color);