@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 +1 -1
- package/src/components/crm/Field.jsx +60 -36
- package/src/components/crm/Form.jsx +4 -0
- package/src/components/crm/generic/GenericDynamic.jsx +84 -5
- package/src/components/crm/generic/styles/GenericDynamic.module.scss +3 -2
- package/src/components/crm/styles/Field.module.scss +38 -27
- package/src/components/crm/styles/Form.module.scss +1 -1
- package/src/components/styles/global.css +8 -0
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.
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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:
|
|
350
|
+
margin-top: 30px;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
.fi__checkboxcontainer {
|
|
354
|
-
display:
|
|
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:
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
.
|
|
167
|
-
|
|
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 {
|
|
@@ -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);
|