@visns-studio/visns-components 5.15.2 → 5.15.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.
- package/README.md +35 -1
- package/package.json +1 -1
- package/src/components/Call.jsx +6 -4
- package/src/components/DropZone.jsx +5 -4
- package/src/components/Field.jsx +9 -11
- package/src/components/QuickAction.jsx +5 -14
- package/src/components/generic/GenericFormBuilder.jsx +9 -9
- package/src/components/generic/GenericQuote.jsx +43 -46
- package/src/components/generic/StandardModal.jsx +103 -55
- package/src/components/modals/GalleryModal.jsx +9 -16
- package/src/components/styles/GenericQuote.module.scss +44 -5
package/README.md
CHANGED
|
@@ -9,10 +9,14 @@ A comprehensive React component library used by the VISNS Studio team for CRM an
|
|
|
9
9
|
|
|
10
10
|
VISNS Components is a React-based UI component library that provides a set of reusable, consistent, and customizable components for building web applications. It includes components for authentication, data grids, forms, navigation, and more, designed to work seamlessly together.
|
|
11
11
|
|
|
12
|
-
## Recent Updates (v5.15.
|
|
12
|
+
## Recent Updates (v5.15.3)
|
|
13
13
|
|
|
14
14
|
### Latest Enhancements
|
|
15
15
|
|
|
16
|
+
- **Complete StandardModal Migration**: All components now use StandardModal instead of reactjs-popup for consistent modal behavior across the entire library
|
|
17
|
+
- **HTML Content Support**: Terms and conditions now properly parse HTML content from TinyMCE editors with clean rendering
|
|
18
|
+
- **Improved Typography**: Refined font sizing in Terms and Conditions to match page typography hierarchy
|
|
19
|
+
- **Modal Component Refactoring**: StandardModal converted to pure React implementation with enhanced accessibility and mobile support
|
|
16
20
|
- **Enhanced JSON Table Field**: Improved json-table field type with better styling, user experience, and data editing capabilities
|
|
17
21
|
- **Dynamic Action Labels**: GenericDetail component now supports dynamic action labels and custom action buttons for better user interaction
|
|
18
22
|
- **Dependency Updates**: Updated lucide-react to version 0.536.0 for improved icon consistency and performance
|
|
@@ -3379,6 +3383,29 @@ npm run build
|
|
|
3379
3383
|
yarn build
|
|
3380
3384
|
```
|
|
3381
3385
|
|
|
3386
|
+
## Migration Notes
|
|
3387
|
+
|
|
3388
|
+
### StandardModal Migration (v5.15.3) - COMPLETED
|
|
3389
|
+
|
|
3390
|
+
We have successfully migrated all components from `reactjs-popup` to our standardized `StandardModal` component for improved consistency and better user experience.
|
|
3391
|
+
|
|
3392
|
+
**All Migrations Completed ✅:**
|
|
3393
|
+
- ✅ **GenericQuote**: Updated to use StandardModal for form modals
|
|
3394
|
+
- ✅ **StandardModal**: Refactored to pure React implementation with enhanced accessibility
|
|
3395
|
+
- ✅ **Field.jsx**: Migrated 2 Popup instances (childFormShow and canvasPopupOpen)
|
|
3396
|
+
- ✅ **GenericFormBuilder.jsx**: Migrated 2 Popup instances (modalShow and modalFormShow)
|
|
3397
|
+
- ✅ **DropZone.jsx**: Migrated 1 Popup instance (modalShow)
|
|
3398
|
+
- ✅ **modals/GalleryModal.jsx**: Migrated 1 Popup instance (modalGalleryShow) with custom overlay styling
|
|
3399
|
+
- ✅ **QuickAction.jsx**: Migrated 1 Popup instance (modalShow)
|
|
3400
|
+
- ✅ **Call.jsx**: Migrated 1 Popup instance (modalShow)
|
|
3401
|
+
|
|
3402
|
+
**Benefits of StandardModal:**
|
|
3403
|
+
- Consistent modal behavior across all components
|
|
3404
|
+
- Better keyboard navigation and accessibility
|
|
3405
|
+
- Unified styling and responsive design
|
|
3406
|
+
- No external dependency on reactjs-popup
|
|
3407
|
+
- Enhanced mobile support with virtual keyboard accommodation
|
|
3408
|
+
|
|
3382
3409
|
## Contributing
|
|
3383
3410
|
|
|
3384
3411
|
We welcome contributions! Please follow these steps:
|
|
@@ -3633,6 +3660,13 @@ All existing GenericQuote functionality remains unchanged:
|
|
|
3633
3660
|
|
|
3634
3661
|
Proposal features are **opt-in** and activated only when `proposalConfig.enabled: true` is set.
|
|
3635
3662
|
|
|
3663
|
+
**Recent Improvements (v5.15.3):**
|
|
3664
|
+
- **StandardModal Integration**: Replaced reactjs-popup with StandardModal for consistent modal behavior and better maintainability
|
|
3665
|
+
- **HTML Content Rendering**: Terms and conditions now support rich HTML content from TinyMCE editors with proper parsing via `html-react-parser`
|
|
3666
|
+
- **Typography Optimization**: Refined font sizing (14px desktop, 12px mobile) for better visual hierarchy and page consistency
|
|
3667
|
+
- **Enhanced Styling**: Improved CSS for HTML elements including lists, paragraphs, and formatted text in terms sections
|
|
3668
|
+
- **Complete Modal Consistency**: All modals throughout the library now use the same StandardModal component
|
|
3669
|
+
|
|
3636
3670
|
**Advanced Usage Example:**
|
|
3637
3671
|
|
|
3638
3672
|
```jsx
|
package/package.json
CHANGED
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
91
91
|
},
|
|
92
92
|
"name": "@visns-studio/visns-components",
|
|
93
|
-
"version": "5.15.
|
|
93
|
+
"version": "5.15.3",
|
|
94
94
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
95
95
|
"main": "src/index.js",
|
|
96
96
|
"files": [
|
package/src/components/Call.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
|
-
import
|
|
2
|
+
import StandardModal from "./generic/StandardModal";
|
|
3
3
|
import moment from "moment";
|
|
4
4
|
|
|
5
5
|
import CustomFetch from "./Fetch";
|
|
@@ -124,12 +124,14 @@ function CallPop(props) {
|
|
|
124
124
|
</button>
|
|
125
125
|
</div>
|
|
126
126
|
</div>
|
|
127
|
-
<
|
|
128
|
-
|
|
127
|
+
<StandardModal
|
|
128
|
+
isOpen={modalShow}
|
|
129
129
|
onClose={() => {
|
|
130
130
|
setCallShow(false);
|
|
131
131
|
setModalShow(false);
|
|
132
132
|
}}
|
|
133
|
+
size="medium"
|
|
134
|
+
closeOnDocumentClick={false}
|
|
133
135
|
>
|
|
134
136
|
<div className="modalwrap">
|
|
135
137
|
<div className="grid">
|
|
@@ -210,7 +212,7 @@ function CallPop(props) {
|
|
|
210
212
|
</div>
|
|
211
213
|
</div>
|
|
212
214
|
</div>
|
|
213
|
-
</
|
|
215
|
+
</StandardModal>
|
|
214
216
|
</>
|
|
215
217
|
) : null}
|
|
216
218
|
</>
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from 'lucide-react';
|
|
16
16
|
import { toast } from 'react-toastify';
|
|
17
17
|
import { arrayMoveImmutable } from 'array-move';
|
|
18
|
-
import
|
|
18
|
+
import StandardModal from './generic/StandardModal';
|
|
19
19
|
import imageCompression from 'browser-image-compression';
|
|
20
20
|
|
|
21
21
|
import { confirmDialog } from './utils/ConfirmDialog';
|
|
@@ -637,9 +637,10 @@ function VisnsDropZone({ fetchData, files, settings, url, urlKey, deleteUrl, ent
|
|
|
637
637
|
</div>
|
|
638
638
|
) : null}
|
|
639
639
|
</div>
|
|
640
|
-
<
|
|
641
|
-
|
|
640
|
+
<StandardModal
|
|
641
|
+
isOpen={modalShow}
|
|
642
642
|
onClose={modalClose}
|
|
643
|
+
size="large"
|
|
643
644
|
closeOnDocumentClick={false}
|
|
644
645
|
>
|
|
645
646
|
<div className={`${styles.modalwrap} top--modal`}>
|
|
@@ -704,7 +705,7 @@ function VisnsDropZone({ fetchData, files, settings, url, urlKey, deleteUrl, ent
|
|
|
704
705
|
</div>
|
|
705
706
|
</div>
|
|
706
707
|
</div>
|
|
707
|
-
</
|
|
708
|
+
</StandardModal>
|
|
708
709
|
</>
|
|
709
710
|
);
|
|
710
711
|
}
|
package/src/components/Field.jsx
CHANGED
|
@@ -6,7 +6,7 @@ import _ from 'lodash';
|
|
|
6
6
|
import Toggle from 'react-toggle';
|
|
7
7
|
import moment from 'moment';
|
|
8
8
|
import parse from 'html-react-parser';
|
|
9
|
-
import
|
|
9
|
+
import StandardModal from './generic/StandardModal';
|
|
10
10
|
import { Sketch } from '@uiw/react-color';
|
|
11
11
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|
12
12
|
import { NumericFormat, PatternFormat } from 'react-number-format';
|
|
@@ -3095,12 +3095,11 @@ function Field({
|
|
|
3095
3095
|
{renderFieldLabel()}
|
|
3096
3096
|
</label>
|
|
3097
3097
|
{renderAdditionalContainer()}
|
|
3098
|
-
<
|
|
3099
|
-
|
|
3098
|
+
<StandardModal
|
|
3099
|
+
isOpen={childFormShow}
|
|
3100
3100
|
onClose={childFormClose}
|
|
3101
|
+
size="large"
|
|
3101
3102
|
closeOnDocumentClick={false}
|
|
3102
|
-
overlayStyle={{ zIndex: 10001 }}
|
|
3103
|
-
contentStyle={{ zIndex: 10002 }}
|
|
3104
3103
|
>
|
|
3105
3104
|
<Form
|
|
3106
3105
|
ajaxSetting={childForm.ajaxSetting}
|
|
@@ -3118,13 +3117,12 @@ function Field({
|
|
|
3118
3117
|
updateForm={setChildForm}
|
|
3119
3118
|
userProfile={userProfile}
|
|
3120
3119
|
/>
|
|
3121
|
-
</
|
|
3122
|
-
<
|
|
3123
|
-
|
|
3120
|
+
</StandardModal>
|
|
3121
|
+
<StandardModal
|
|
3122
|
+
isOpen={canvasPopupOpen}
|
|
3124
3123
|
onClose={() => setCanvasPopupOpen(false)}
|
|
3124
|
+
size="large"
|
|
3125
3125
|
closeOnDocumentClick={false}
|
|
3126
|
-
overlayStyle={{ zIndex: 10001 }}
|
|
3127
|
-
contentStyle={{ zIndex: 10002 }}
|
|
3128
3126
|
>
|
|
3129
3127
|
<div className={`${styles.modalwrap} ${styles['top--modal']}`}>
|
|
3130
3128
|
<div className={styles.modal}>
|
|
@@ -3240,7 +3238,7 @@ function Field({
|
|
|
3240
3238
|
</div>
|
|
3241
3239
|
</div>
|
|
3242
3240
|
</div>
|
|
3243
|
-
</
|
|
3241
|
+
</StandardModal>
|
|
3244
3242
|
</div>
|
|
3245
3243
|
);
|
|
3246
3244
|
}
|
|
@@ -6,7 +6,7 @@ import React, {
|
|
|
6
6
|
useMemo,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import { useNavigate } from 'react-router-dom';
|
|
9
|
-
import
|
|
9
|
+
import StandardModal from './generic/StandardModal';
|
|
10
10
|
import { Search, X, Zap } from 'lucide-react';
|
|
11
11
|
|
|
12
12
|
import CustomFetch from './Fetch';
|
|
@@ -408,20 +408,11 @@ const QuickAction = ({ setting }) => {
|
|
|
408
408
|
</div>
|
|
409
409
|
</div>
|
|
410
410
|
|
|
411
|
-
<
|
|
412
|
-
|
|
411
|
+
<StandardModal
|
|
412
|
+
isOpen={modalShow}
|
|
413
413
|
onClose={modalClose}
|
|
414
|
+
size="large"
|
|
414
415
|
closeOnDocumentClick={false}
|
|
415
|
-
contentStyle={{
|
|
416
|
-
width: '80vw',
|
|
417
|
-
maxWidth: '1200px',
|
|
418
|
-
minWidth: '600px',
|
|
419
|
-
padding: 0,
|
|
420
|
-
border: 'none',
|
|
421
|
-
borderRadius: '8px',
|
|
422
|
-
overflow: 'hidden',
|
|
423
|
-
maxHeight: '90vh',
|
|
424
|
-
}}
|
|
425
416
|
>
|
|
426
417
|
<Form
|
|
427
418
|
closeModal={modalClose}
|
|
@@ -431,7 +422,7 @@ const QuickAction = ({ setting }) => {
|
|
|
431
422
|
columnId={formId}
|
|
432
423
|
childDropdownCallback={childDropdownCallback}
|
|
433
424
|
/>
|
|
434
|
-
</
|
|
425
|
+
</StandardModal>
|
|
435
426
|
</>
|
|
436
427
|
);
|
|
437
428
|
};
|
|
@@ -2,7 +2,7 @@ import '../styles/global.css';
|
|
|
2
2
|
|
|
3
3
|
import React, { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { useParams } from 'react-router-dom';
|
|
5
|
-
import
|
|
5
|
+
import StandardModal from './StandardModal';
|
|
6
6
|
import { arrayMove } from '@dnd-kit/sortable';
|
|
7
7
|
import {
|
|
8
8
|
DndContext,
|
|
@@ -1222,12 +1222,12 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
1222
1222
|
</div>
|
|
1223
1223
|
</div>
|
|
1224
1224
|
|
|
1225
|
-
<
|
|
1226
|
-
|
|
1225
|
+
<StandardModal
|
|
1226
|
+
isOpen={modalShow}
|
|
1227
1227
|
onClose={handleCloseModal}
|
|
1228
|
+
size="medium"
|
|
1228
1229
|
closeOnDocumentClick={false}
|
|
1229
1230
|
>
|
|
1230
|
-
{modalShow && <div className={styles.modalBackdrop} />}
|
|
1231
1231
|
<div className={styles.modalwrap}>
|
|
1232
1232
|
<div className={styles.modal}>
|
|
1233
1233
|
<div className={styles.modal__header}>
|
|
@@ -2254,14 +2254,14 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
2254
2254
|
</div>
|
|
2255
2255
|
</div>
|
|
2256
2256
|
</div>
|
|
2257
|
-
</
|
|
2257
|
+
</StandardModal>
|
|
2258
2258
|
|
|
2259
|
-
<
|
|
2260
|
-
|
|
2259
|
+
<StandardModal
|
|
2260
|
+
isOpen={modalFormShow}
|
|
2261
2261
|
onClose={handleCloseModalForm}
|
|
2262
|
+
size="medium"
|
|
2262
2263
|
closeOnDocumentClick={false}
|
|
2263
2264
|
>
|
|
2264
|
-
{modalFormShow && <div className={styles.modalBackdrop} />}
|
|
2265
2265
|
<div className={styles.modalwrap}>
|
|
2266
2266
|
<div className={styles.modal}>
|
|
2267
2267
|
<div className={styles.modal__header}>
|
|
@@ -2308,7 +2308,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
|
|
|
2308
2308
|
</div>
|
|
2309
2309
|
</div>
|
|
2310
2310
|
</div>
|
|
2311
|
-
</
|
|
2311
|
+
</StandardModal>
|
|
2312
2312
|
|
|
2313
2313
|
{/* React Tooltips */}
|
|
2314
2314
|
<Tooltip
|
|
@@ -2,11 +2,12 @@ import '../styles/global.css';
|
|
|
2
2
|
|
|
3
3
|
import React, { useState, useEffect } from 'react';
|
|
4
4
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
5
|
-
import
|
|
5
|
+
import StandardModal from './StandardModal';
|
|
6
6
|
import moment from 'moment';
|
|
7
7
|
import get from 'lodash/get';
|
|
8
8
|
import { saveAs } from 'file-saver';
|
|
9
9
|
import { toast } from 'react-toastify';
|
|
10
|
+
import parse from 'html-react-parser';
|
|
10
11
|
import { arrayMoveImmutable } from 'array-move';
|
|
11
12
|
import { showConfirmDialog } from './ConfirmationDialog';
|
|
12
13
|
import { FileText, DollarSign, Clock, Eye, X, Edit3, FileEdit, Save, Settings } from 'lucide-react';
|
|
@@ -1988,61 +1989,57 @@ function GenericQuote({ logo, setting, urlParam, proposalConfig = null }) {
|
|
|
1988
1989
|
Terms and Conditions
|
|
1989
1990
|
</h3>
|
|
1990
1991
|
<div className={styles.termsContent}>
|
|
1991
|
-
{data.terms_and_condition}
|
|
1992
|
+
{parse(data.terms_and_condition || '')}
|
|
1992
1993
|
</div>
|
|
1993
1994
|
</div>
|
|
1994
1995
|
)}
|
|
1995
1996
|
</div>
|
|
1996
1997
|
|
|
1997
1998
|
{/* Form Modal */}
|
|
1998
|
-
<
|
|
1999
|
-
|
|
1999
|
+
<StandardModal
|
|
2000
|
+
isOpen={modalShow}
|
|
2000
2001
|
onClose={modalClose}
|
|
2002
|
+
size="large"
|
|
2001
2003
|
closeOnDocumentClick={false}
|
|
2002
|
-
contentStyle={{ width: '80vw', maxWidth: '1200px' }}
|
|
2003
2004
|
>
|
|
2004
|
-
<
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
);
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
};
|
|
2031
|
-
fetchData();
|
|
2032
|
-
}}
|
|
2033
|
-
formSettings={formData}
|
|
2034
|
-
formType={formType}
|
|
2035
|
-
style={form.style || {}}
|
|
2036
|
-
updateForm={setFormData}
|
|
2037
|
-
paramValue={
|
|
2038
|
-
routeParams[urlParam]
|
|
2039
|
-
? routeParams[urlParam]
|
|
2040
|
-
: 0
|
|
2005
|
+
<Form
|
|
2006
|
+
closeModal={modalClose}
|
|
2007
|
+
columnId={formId}
|
|
2008
|
+
fetchTable={() => {
|
|
2009
|
+
// Reload the quote data after form submission
|
|
2010
|
+
const fetchData = async () => {
|
|
2011
|
+
if (
|
|
2012
|
+
routeParams[urlParam] &&
|
|
2013
|
+
routeParams[urlParam] > 0
|
|
2014
|
+
) {
|
|
2015
|
+
try {
|
|
2016
|
+
const res = await CustomFetch(
|
|
2017
|
+
`${page.fetchUrl}/${routeParams[urlParam]}`,
|
|
2018
|
+
'GET',
|
|
2019
|
+
{}
|
|
2020
|
+
);
|
|
2021
|
+
setData(res.data);
|
|
2022
|
+
} catch (error) {
|
|
2023
|
+
console.error(
|
|
2024
|
+
'Error fetching data:',
|
|
2025
|
+
error
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2041
2028
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2029
|
+
};
|
|
2030
|
+
fetchData();
|
|
2031
|
+
}}
|
|
2032
|
+
formSettings={formData}
|
|
2033
|
+
formType={formType}
|
|
2034
|
+
style={form.style || {}}
|
|
2035
|
+
updateForm={setFormData}
|
|
2036
|
+
paramValue={
|
|
2037
|
+
routeParams[urlParam]
|
|
2038
|
+
? routeParams[urlParam]
|
|
2039
|
+
: 0
|
|
2040
|
+
}
|
|
2041
|
+
/>
|
|
2042
|
+
</StandardModal>
|
|
2046
2043
|
</div>
|
|
2047
2044
|
);
|
|
2048
2045
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import Popup from 'reactjs-popup';
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
3
2
|
import { X } from 'lucide-react';
|
|
4
3
|
import formStyles from '../styles/Form.module.scss';
|
|
5
4
|
|
|
@@ -67,6 +66,37 @@ const StandardModal = ({
|
|
|
67
66
|
window.addEventListener('resize', handleResize);
|
|
68
67
|
return () => window.removeEventListener('resize', handleResize);
|
|
69
68
|
}, []);
|
|
69
|
+
|
|
70
|
+
// Handle keyboard events
|
|
71
|
+
const handleKeyDown = useCallback((e) => {
|
|
72
|
+
if (!isOpen) return;
|
|
73
|
+
|
|
74
|
+
if (e.key === 'Escape' && closeOnEscape) {
|
|
75
|
+
onClose();
|
|
76
|
+
}
|
|
77
|
+
}, [isOpen, closeOnEscape, onClose]);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (isOpen) {
|
|
81
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
82
|
+
document.body.style.overflow = 'hidden';
|
|
83
|
+
} else {
|
|
84
|
+
document.body.style.overflow = 'unset';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return () => {
|
|
88
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
89
|
+
document.body.style.overflow = 'unset';
|
|
90
|
+
};
|
|
91
|
+
}, [isOpen, handleKeyDown]);
|
|
92
|
+
|
|
93
|
+
// Handle backdrop click
|
|
94
|
+
const handleBackdropClick = (e) => {
|
|
95
|
+
if (closeOnDocumentClick && e.target === e.currentTarget) {
|
|
96
|
+
onClose();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
70
100
|
// Apply vertical alignment class if needed
|
|
71
101
|
const getModalClasses = () => {
|
|
72
102
|
let classes = formStyles.modal;
|
|
@@ -76,32 +106,47 @@ const StandardModal = ({
|
|
|
76
106
|
return classes;
|
|
77
107
|
};
|
|
78
108
|
|
|
79
|
-
// Get
|
|
80
|
-
const
|
|
109
|
+
// Get overlay styles
|
|
110
|
+
const getOverlayStyle = () => {
|
|
81
111
|
const baseStyle = {
|
|
82
|
-
|
|
112
|
+
position: 'fixed',
|
|
113
|
+
top: 0,
|
|
114
|
+
left: 0,
|
|
115
|
+
right: 0,
|
|
116
|
+
bottom: 0,
|
|
117
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
118
|
+
display: 'flex',
|
|
119
|
+
alignItems: verticalAlign === 'top' ? 'flex-start' : 'center',
|
|
120
|
+
justifyContent: 'center',
|
|
121
|
+
zIndex: 1000,
|
|
122
|
+
padding: '20px',
|
|
123
|
+
...customStyles.overlay
|
|
83
124
|
};
|
|
84
125
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (isMobile || isTablet) {
|
|
88
|
-
// Position modal higher on mobile/tablet to accommodate virtual keyboard
|
|
89
|
-
positioningStyle = {
|
|
90
|
-
top: '5%', // Position higher (5% from top)
|
|
91
|
-
left: '50%', // Center horizontally
|
|
92
|
-
transform: 'translateX(-50%)', // Only center horizontally, no vertical transform
|
|
93
|
-
maxHeight: '85vh', // Limit height to prevent overflow
|
|
94
|
-
overflowY: 'auto', // Allow scrolling within modal if needed
|
|
95
|
-
position: 'fixed' // Ensure fixed positioning for proper centering
|
|
96
|
-
};
|
|
126
|
+
if (verticalAlign === 'top') {
|
|
127
|
+
baseStyle.paddingTop = '5%';
|
|
97
128
|
}
|
|
98
129
|
|
|
130
|
+
return baseStyle;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Get size-based styles for the modal content with device-aware positioning
|
|
134
|
+
const getContentStyle = () => {
|
|
135
|
+
const baseStyle = {
|
|
136
|
+
position: 'relative',
|
|
137
|
+
backgroundColor: 'white',
|
|
138
|
+
borderRadius: '8px',
|
|
139
|
+
boxShadow: '0 10px 30px rgba(0, 0, 0, 0.3)',
|
|
140
|
+
maxHeight: isMobile || isTablet ? '85vh' : '90vh',
|
|
141
|
+
overflowY: 'auto',
|
|
142
|
+
...customStyles.modal
|
|
143
|
+
};
|
|
144
|
+
|
|
99
145
|
// Apply size-based styles with device considerations
|
|
100
146
|
switch (size) {
|
|
101
147
|
case 'small':
|
|
102
148
|
return {
|
|
103
149
|
...baseStyle,
|
|
104
|
-
...positioningStyle,
|
|
105
150
|
width: isMobile ? '95vw' : '400px',
|
|
106
151
|
minWidth: isMobile ? '300px' : '400px',
|
|
107
152
|
maxWidth: isMobile ? '95vw' : '600px'
|
|
@@ -109,7 +154,6 @@ const StandardModal = ({
|
|
|
109
154
|
case 'large':
|
|
110
155
|
return {
|
|
111
156
|
...baseStyle,
|
|
112
|
-
...positioningStyle,
|
|
113
157
|
width: '95vw',
|
|
114
158
|
minWidth: isMobile ? '300px' : '800px',
|
|
115
159
|
maxWidth: isMobile ? '95vw' : '1600px'
|
|
@@ -118,51 +162,55 @@ const StandardModal = ({
|
|
|
118
162
|
default:
|
|
119
163
|
return {
|
|
120
164
|
...baseStyle,
|
|
121
|
-
|
|
122
|
-
width: isMobile ? '95vw' : '90vw',
|
|
165
|
+
width: isMobile ? '95vw' : '80vw',
|
|
123
166
|
minWidth: isMobile ? '300px' : '600px',
|
|
124
|
-
maxWidth: isMobile ? '95vw' : '
|
|
167
|
+
maxWidth: isMobile ? '95vw' : '1200px'
|
|
125
168
|
};
|
|
126
169
|
}
|
|
127
170
|
};
|
|
128
171
|
|
|
172
|
+
if (!isOpen) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
129
176
|
return (
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
modal
|
|
134
|
-
closeOnDocumentClick={closeOnDocumentClick}
|
|
135
|
-
closeOnEscape={closeOnEscape}
|
|
136
|
-
contentStyle={getContentStyle()}
|
|
177
|
+
<div
|
|
178
|
+
style={getOverlayStyle()}
|
|
179
|
+
onClick={handleBackdropClick}
|
|
137
180
|
>
|
|
138
|
-
<div
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
style={customStyles.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
181
|
+
<div
|
|
182
|
+
style={getContentStyle()}
|
|
183
|
+
onClick={(e) => e.stopPropagation()}
|
|
184
|
+
>
|
|
185
|
+
<div className={formStyles.modalwrap}>
|
|
186
|
+
<div
|
|
187
|
+
className={getModalClasses()}
|
|
188
|
+
>
|
|
189
|
+
{showHeader && (
|
|
190
|
+
<div className={formStyles.modal__header} style={customStyles.header}>
|
|
191
|
+
<h1 style={customStyles.title}>{title}</h1>
|
|
192
|
+
<button
|
|
193
|
+
className={formStyles.modal__close}
|
|
194
|
+
onClick={onClose}
|
|
195
|
+
style={customStyles.closeButton}
|
|
196
|
+
type="button"
|
|
197
|
+
aria-label="Close modal"
|
|
198
|
+
>
|
|
199
|
+
<X strokeWidth={1} size={24} />
|
|
200
|
+
</button>
|
|
201
|
+
</div>
|
|
202
|
+
)}
|
|
203
|
+
{showHeader ? (
|
|
204
|
+
<div className={formStyles.modal__content} style={customStyles.content}>
|
|
205
|
+
{children}
|
|
206
|
+
</div>
|
|
207
|
+
) : (
|
|
208
|
+
children
|
|
209
|
+
)}
|
|
210
|
+
</div>
|
|
163
211
|
</div>
|
|
164
212
|
</div>
|
|
165
|
-
</
|
|
213
|
+
</div>
|
|
166
214
|
);
|
|
167
215
|
};
|
|
168
216
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import StandardModal from '../generic/StandardModal';
|
|
3
3
|
import { toast } from 'react-toastify';
|
|
4
4
|
import imageCompression from 'browser-image-compression';
|
|
5
5
|
// import Vapor from 'laravel-vapor'; // Commented out to avoid build issues
|
|
@@ -169,22 +169,15 @@ const GalleryModal = ({
|
|
|
169
169
|
|
|
170
170
|
return (
|
|
171
171
|
<>
|
|
172
|
-
<
|
|
173
|
-
|
|
172
|
+
<StandardModal
|
|
173
|
+
isOpen={modalGalleryShow}
|
|
174
174
|
onClose={modalGalleryClose}
|
|
175
|
+
size="large"
|
|
175
176
|
closeOnDocumentClick={false}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
padding: 0,
|
|
181
|
-
border: 'none',
|
|
182
|
-
borderRadius: '8px',
|
|
183
|
-
overflow: 'hidden',
|
|
184
|
-
maxHeight: '90vh',
|
|
185
|
-
}}
|
|
186
|
-
overlayStyle={{
|
|
187
|
-
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
177
|
+
customStyles={{
|
|
178
|
+
overlay: {
|
|
179
|
+
backgroundColor: 'rgba(0, 0, 0, 0.7)'
|
|
180
|
+
}
|
|
188
181
|
}}
|
|
189
182
|
>
|
|
190
183
|
<div className={styles.modalwrap}>
|
|
@@ -390,7 +383,7 @@ const GalleryModal = ({
|
|
|
390
383
|
</div>
|
|
391
384
|
</div>
|
|
392
385
|
</div>
|
|
393
|
-
</
|
|
386
|
+
</StandardModal>
|
|
394
387
|
|
|
395
388
|
{/* Lightbox for full-size image viewing */}
|
|
396
389
|
<Lightbox
|
|
@@ -1061,10 +1061,49 @@
|
|
|
1061
1061
|
}
|
|
1062
1062
|
|
|
1063
1063
|
.termsContent {
|
|
1064
|
-
font-size:
|
|
1065
|
-
line-height: 1.
|
|
1064
|
+
font-size: 14px;
|
|
1065
|
+
line-height: 1.4;
|
|
1066
1066
|
color: var(--paragraph-color);
|
|
1067
|
-
|
|
1067
|
+
|
|
1068
|
+
/* Reset styles to avoid conflicts with TinyMCE HTML content */
|
|
1069
|
+
white-space: normal;
|
|
1070
|
+
|
|
1071
|
+
/* Basic styling for TinyMCE HTML elements */
|
|
1072
|
+
ul, ol {
|
|
1073
|
+
margin: 8px 0;
|
|
1074
|
+
padding-left: 20px;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
li {
|
|
1078
|
+
margin: 4px 0;
|
|
1079
|
+
padding: 0;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
p {
|
|
1083
|
+
margin: 8px 0;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
strong, b {
|
|
1087
|
+
font-weight: 600;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
em, i {
|
|
1091
|
+
font-style: italic;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/* Remove excessive spacing from nested elements */
|
|
1095
|
+
ul ul, ol ol, ul ol, ol ul {
|
|
1096
|
+
margin: 2px 0;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/* Ensure proper spacing for the first and last elements */
|
|
1100
|
+
> *:first-child {
|
|
1101
|
+
margin-top: 0;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
> *:last-child {
|
|
1105
|
+
margin-bottom: 0;
|
|
1106
|
+
}
|
|
1068
1107
|
}
|
|
1069
1108
|
|
|
1070
1109
|
.quoteTableSection {
|
|
@@ -1387,7 +1426,7 @@
|
|
|
1387
1426
|
}
|
|
1388
1427
|
|
|
1389
1428
|
.termsContent {
|
|
1390
|
-
font-size:
|
|
1391
|
-
line-height: 1.
|
|
1429
|
+
font-size: 12px;
|
|
1430
|
+
line-height: 1.3;
|
|
1392
1431
|
}
|
|
1393
1432
|
}
|