pixel-react 1.0.6 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- package/.yarn/install-state.gz +0 -0
- package/lib/StyleGuide/ColorPalette/types.d.ts +2 -0
- package/lib/components/DragAndDrop/DragAndDrop.d.ts +9 -0
- package/lib/components/DragAndDrop/DragAndDrop.stories.d.ts +6 -0
- package/lib/components/DragAndDrop/DragAndDropList.d.ts +20 -0
- package/lib/components/DragAndDrop/index.d.ts +1 -0
- package/lib/components/Drawer/Drawer.d.ts +2 -1
- package/lib/components/GridLayout/types.d.ts +17 -0
- package/lib/components/Modal/Modal.d.ts +5 -0
- package/lib/components/Modal/Modal.stories.d.ts +7 -0
- package/lib/components/Modal/index.d.ts +1 -0
- package/lib/components/Modal/types.d.ts +26 -0
- package/lib/components/TableTree/TableTree.d.ts +1 -1
- package/lib/index.d.ts +29 -3
- package/lib/index.esm.js +4725 -80
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +4723 -77
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +26 -23
- package/src/StyleGuide/ColorPalette/ColorPalette.scss +5 -0
- package/src/StyleGuide/ColorPalette/ColorPalette.tsx +10 -1
- package/src/StyleGuide/ColorPalette/colorPaletteList.ts +2 -2
- package/src/StyleGuide/ColorPalette/types.ts +2 -0
- package/src/assets/Themes/BaseTheme.scss +9 -8
- package/src/assets/Themes/DarkTheme.scss +1 -0
- package/src/assets/icons/collapse-icon.svg +6 -0
- package/src/assets/icons/copy-icon.svg +3 -0
- package/src/assets/icons/download-icon.svg +3 -0
- package/src/assets/icons/expand-icon.svg +6 -0
- package/src/assets/icons/license_info.svg +28 -0
- package/src/assets/icons/license_warning.svg +10 -0
- package/src/assets/icons/refresh-icon.svg +4 -0
- package/src/components/DatePicker/DatePicker.scss +3 -3
- package/src/components/DragAndDrop/DragAndDrop.d.ts +5 -0
- package/src/components/DragAndDrop/DragAndDrop.stories.tsx +25 -0
- package/src/components/DragAndDrop/DragAndDrop.ts +7 -0
- package/src/components/DragAndDrop/DragAndDropList.scss +69 -0
- package/src/components/DragAndDrop/DragAndDropList.tsx +150 -0
- package/src/components/DragAndDrop/index.ts +1 -0
- package/src/components/Drawer/Drawer.tsx +3 -7
- package/src/components/GridLayout/GridLayout.stories.tsx +13 -51
- package/src/components/GridLayout/GridLayout.tsx +9 -7
- package/src/components/GridLayout/types.ts +20 -0
- package/src/components/Icon/iconList.ts +14 -0
- package/src/components/Modal/Modal.stories.tsx +63 -0
- package/src/components/Modal/Modal.tsx +71 -0
- package/src/components/Modal/index.tsx +1 -0
- package/src/components/Modal/modal.scss +37 -0
- package/src/components/Modal/types.ts +37 -0
- package/src/components/TableTree/TableTree.tsx +1 -1
- package/src/components/ThemeProvider/ThemeProvider.tsx +11 -8
- package/src/index.ts +2 -5
@@ -0,0 +1,150 @@
|
|
1
|
+
import { useState } from 'react';
|
2
|
+
import DragAndDrop from './DragAndDrop';
|
3
|
+
const {
|
4
|
+
DNDCore: {
|
5
|
+
DndContext,
|
6
|
+
KeyboardSensor,
|
7
|
+
PointerSensor,
|
8
|
+
useSensor,
|
9
|
+
useSensors,
|
10
|
+
closestCorners,
|
11
|
+
},
|
12
|
+
DNDSortable: {
|
13
|
+
useSortable,
|
14
|
+
arrayMove,
|
15
|
+
sortableKeyboardCoordinates,
|
16
|
+
SortableContext,
|
17
|
+
verticalListSortingStrategy,
|
18
|
+
},
|
19
|
+
DNDUtilities: { CSS },
|
20
|
+
} = DragAndDrop;
|
21
|
+
import Typography from '../Typography';
|
22
|
+
|
23
|
+
import './DragAndDropList.scss';
|
24
|
+
|
25
|
+
interface TaskProps {
|
26
|
+
id: number;
|
27
|
+
title: string;
|
28
|
+
}
|
29
|
+
|
30
|
+
export const Task = ({ id, title }: TaskProps) => {
|
31
|
+
const { attributes, listeners, setNodeRef, transform, transition } =
|
32
|
+
useSortable({ id });
|
33
|
+
|
34
|
+
const style = {
|
35
|
+
transition,
|
36
|
+
transform: CSS.Transform.toString(transform),
|
37
|
+
};
|
38
|
+
|
39
|
+
return (
|
40
|
+
<div
|
41
|
+
ref={setNodeRef}
|
42
|
+
style={style}
|
43
|
+
{...attributes}
|
44
|
+
{...listeners}
|
45
|
+
className="task"
|
46
|
+
>
|
47
|
+
<Typography as='h1' fontSize={16} className='task-title'>{title}</Typography>
|
48
|
+
</div>
|
49
|
+
);
|
50
|
+
};
|
51
|
+
|
52
|
+
interface ColumnProps {
|
53
|
+
id: string;
|
54
|
+
tasks: { id: number; title: string }[];
|
55
|
+
}
|
56
|
+
|
57
|
+
export const Column: React.FC<ColumnProps> = ({ tasks }) => {
|
58
|
+
return (
|
59
|
+
<div className="column">
|
60
|
+
<SortableContext items={tasks} strategy={verticalListSortingStrategy}>
|
61
|
+
{tasks.map((task) => (
|
62
|
+
<Task key={task.id} id={task.id} title={task.title} />
|
63
|
+
))}
|
64
|
+
</SortableContext>
|
65
|
+
</div>
|
66
|
+
);
|
67
|
+
};
|
68
|
+
|
69
|
+
interface InputProps {
|
70
|
+
onSubmit: (input: string) => void;
|
71
|
+
}
|
72
|
+
|
73
|
+
export const Input: React.FC<InputProps> = ({ onSubmit }) => {
|
74
|
+
const [input, setInput] = useState('');
|
75
|
+
|
76
|
+
const handleSubmit = () => {
|
77
|
+
if (!input) return;
|
78
|
+
|
79
|
+
onSubmit(input);
|
80
|
+
|
81
|
+
setInput('');
|
82
|
+
};
|
83
|
+
|
84
|
+
return (
|
85
|
+
<div className="container">
|
86
|
+
<input
|
87
|
+
className="input"
|
88
|
+
type="text"
|
89
|
+
value={input}
|
90
|
+
onChange={(e) => setInput(e.target.value)}
|
91
|
+
/>
|
92
|
+
<button onClick={handleSubmit} className="button">
|
93
|
+
<Typography fontSize={14}>Add</Typography>
|
94
|
+
</button>
|
95
|
+
</div>
|
96
|
+
);
|
97
|
+
};
|
98
|
+
|
99
|
+
const DragAndDropList = () => {
|
100
|
+
const [tasks, setTasks] = useState([
|
101
|
+
{ id: 1, title: 'Add tests to homepage' },
|
102
|
+
{ id: 2, title: 'Fix styling in about section' },
|
103
|
+
{ id: 3, title: 'Learn how to center a div' },
|
104
|
+
]);
|
105
|
+
|
106
|
+
const addTask = (title: any) => {
|
107
|
+
setTasks((tasks) => [...tasks, { id: tasks.length + 1, title }]);
|
108
|
+
};
|
109
|
+
|
110
|
+
const sensors = useSensors(
|
111
|
+
useSensor(PointerSensor),
|
112
|
+
useSensor(KeyboardSensor, {
|
113
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
114
|
+
})
|
115
|
+
);
|
116
|
+
|
117
|
+
const getTaskPos = (id: number): number =>
|
118
|
+
tasks.findIndex((task) => task.id === id);
|
119
|
+
|
120
|
+
const handleDragEnd = (event: any) => {
|
121
|
+
const { active, over } = event;
|
122
|
+
|
123
|
+
if (active.id === over.id) return;
|
124
|
+
|
125
|
+
setTasks((tasks) => {
|
126
|
+
const originalPos = getTaskPos(active.id);
|
127
|
+
const newPos = getTaskPos(over.id);
|
128
|
+
|
129
|
+
return arrayMove(tasks, originalPos, newPos);
|
130
|
+
});
|
131
|
+
};
|
132
|
+
|
133
|
+
return (
|
134
|
+
<div className="drag-and-drop-list">
|
135
|
+
<Typography fontSize={32} fontWeight="semi-bold">
|
136
|
+
Drag and Drop test ✅
|
137
|
+
</Typography>
|
138
|
+
<Input onSubmit={addTask} />
|
139
|
+
<DndContext
|
140
|
+
sensors={sensors}
|
141
|
+
collisionDetection={closestCorners}
|
142
|
+
onDragEnd={handleDragEnd}
|
143
|
+
>
|
144
|
+
<Column id="toDo" tasks={tasks} />
|
145
|
+
</DndContext>
|
146
|
+
</div>
|
147
|
+
);
|
148
|
+
};
|
149
|
+
|
150
|
+
export default DragAndDropList;
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './DragAndDrop';
|
@@ -3,11 +3,11 @@ import { DrawerProps } from './Types.js';
|
|
3
3
|
import Button from '../Button/Button.js';
|
4
4
|
import classNames from 'classnames';
|
5
5
|
import './Drawer.scss';
|
6
|
-
import { useContext, useEffect, useState } from 'react';
|
6
|
+
import { FC, useContext, useEffect, useState } from 'react';
|
7
7
|
import Icon from '../Icon';
|
8
8
|
import useEscapeKey from '../../hooks/keyboardevents/useEscKeyEvent.js';
|
9
9
|
import { ThemeContext } from '../ThemeProvider/ThemeProvider.js';
|
10
|
-
const Drawer = ({
|
10
|
+
const Drawer: FC<DrawerProps> = ({
|
11
11
|
isOpen = true,
|
12
12
|
children = 'Drawer content area',
|
13
13
|
onClose = () => {},
|
@@ -103,11 +103,7 @@ const Drawer = ({
|
|
103
103
|
<div className="ff-drawer-title">{title}</div>
|
104
104
|
</div>
|
105
105
|
{_isCloseModalButtonVisible && (
|
106
|
-
<Icon
|
107
|
-
name="close"
|
108
|
-
hoverEffect={false}
|
109
|
-
onClick={onClose}
|
110
|
-
/>
|
106
|
+
<Icon name="close" hoverEffect={false} onClick={onClose} />
|
111
107
|
)}
|
112
108
|
</div>
|
113
109
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
2
2
|
import { Container, Row, Col } from './GridLayout';
|
3
|
-
import './GridLayoutStory.scss'
|
3
|
+
import './GridLayoutStory.scss';
|
4
4
|
|
5
5
|
const meta: Meta<typeof Container> = {
|
6
6
|
title: 'Components/GridLayout',
|
@@ -27,31 +27,21 @@ export const Grid: ContainerStory = {
|
|
27
27
|
<Container {...args}>
|
28
28
|
<Row>
|
29
29
|
<Col size={4}>
|
30
|
-
<div className=
|
31
|
-
Column 1
|
32
|
-
</div>
|
30
|
+
<div className="one">Column 1</div>
|
33
31
|
</Col>
|
34
32
|
<Col size={4}>
|
35
|
-
<div className=
|
36
|
-
Column 2
|
37
|
-
</div>
|
33
|
+
<div className="two">Column 2</div>
|
38
34
|
</Col>
|
39
35
|
<Col size={4}>
|
40
|
-
<div className=
|
41
|
-
Column 3
|
42
|
-
</div>
|
36
|
+
<div className="three">Column 3</div>
|
43
37
|
</Col>
|
44
38
|
</Row>
|
45
39
|
<Row>
|
46
40
|
<Col size={6}>
|
47
|
-
<div className=
|
48
|
-
Column 4
|
49
|
-
</div>
|
41
|
+
<div className="four">Column 4</div>
|
50
42
|
</Col>
|
51
43
|
<Col size={6}>
|
52
|
-
<div className=
|
53
|
-
Column 5
|
54
|
-
</div>
|
44
|
+
<div className="five">Column 5</div>
|
55
45
|
</Col>
|
56
46
|
</Row>
|
57
47
|
</Container>
|
@@ -67,57 +57,29 @@ export const Grid2: ContainerStory = {
|
|
67
57
|
<Container {...args}>
|
68
58
|
<Row gap="20px">
|
69
59
|
<Col size={3}>
|
70
|
-
<div
|
71
|
-
className='one'
|
72
|
-
>
|
73
|
-
Column 1 (size 3)
|
74
|
-
</div>
|
60
|
+
<div className="one">Column 1 (size 3)</div>
|
75
61
|
</Col>
|
76
62
|
<Col size={6}>
|
77
|
-
<div
|
78
|
-
className='two'
|
79
|
-
>
|
80
|
-
Column 2 (size 6)
|
81
|
-
</div>
|
63
|
+
<div className="two">Column 2 (size 6)</div>
|
82
64
|
</Col>
|
83
65
|
<Col size={3}>
|
84
|
-
<div
|
85
|
-
className='three'
|
86
|
-
>
|
87
|
-
Column 3 (size 3)
|
88
|
-
</div>
|
66
|
+
<div className="three">Column 3 (size 3)</div>
|
89
67
|
</Col>
|
90
68
|
</Row>
|
91
69
|
<Row gap="10px">
|
92
70
|
<Col size={4}>
|
93
|
-
<div
|
94
|
-
className='four'
|
95
|
-
>
|
96
|
-
Column 4 (size 4)
|
97
|
-
</div>
|
71
|
+
<div className="four">Column 4 (size 4)</div>
|
98
72
|
</Col>
|
99
73
|
<Col size={4}>
|
100
|
-
<div
|
101
|
-
className='five'
|
102
|
-
>
|
103
|
-
Column 5 (size 4)
|
104
|
-
</div>
|
74
|
+
<div className="five">Column 5 (size 4)</div>
|
105
75
|
</Col>
|
106
76
|
<Col size={4}>
|
107
|
-
<div
|
108
|
-
className='one'
|
109
|
-
>
|
110
|
-
Column 6 (size 4)
|
111
|
-
</div>
|
77
|
+
<div className="one">Column 6 (size 4)</div>
|
112
78
|
</Col>
|
113
79
|
</Row>
|
114
80
|
<Row gap="15px">
|
115
81
|
<Col size={12}>
|
116
|
-
<div
|
117
|
-
className='two'
|
118
|
-
>
|
119
|
-
Full-width column (size 12)
|
120
|
-
</div>
|
82
|
+
<div className="two">Full-width column (size 12)</div>
|
121
83
|
</Col>
|
122
84
|
</Row>
|
123
85
|
</Container>
|
@@ -2,29 +2,31 @@
|
|
2
2
|
import React from 'react';
|
3
3
|
import './GridLayout.scss';
|
4
4
|
import { ContainerProps, RowProps, ColProps } from './types';
|
5
|
+
import cx from 'classnames'
|
5
6
|
|
6
7
|
export const Container: React.FC<ContainerProps> = ({
|
7
8
|
children,
|
8
9
|
fluid = false,
|
9
10
|
gap = '0px',
|
11
|
+
className=''
|
10
12
|
}) => {
|
11
|
-
const
|
13
|
+
const containerClassName = fluid ? 'ff-container-fluid' : 'ff-container';
|
12
14
|
return (
|
13
|
-
<div className={className} style={{ gap }}>
|
15
|
+
<div className={cx(containerClassName,className)} style={{ gap }}>
|
14
16
|
{children}
|
15
17
|
</div>
|
16
18
|
);
|
17
19
|
};
|
18
20
|
|
19
|
-
export const Row: React.FC<RowProps> = ({ children, gap = '0px' }) => {
|
21
|
+
export const Row: React.FC<RowProps> = ({ children, gap = '0px',className='' }) => {
|
20
22
|
return (
|
21
|
-
<div className="ff-row" style={{ gap }}>
|
23
|
+
<div className={cx("ff-row",className)} style={{ gap }}>
|
22
24
|
{children}
|
23
25
|
</div>
|
24
26
|
);
|
25
27
|
};
|
26
28
|
|
27
|
-
export const Col: React.FC<ColProps> = ({ children, size = 12 }) => {
|
28
|
-
const
|
29
|
-
return <div className={className}>{children}</div>;
|
29
|
+
export const Col: React.FC<ColProps> = ({ children, size = 12,className='' }) => {
|
30
|
+
const colClassName = `ff-col-${size}`;
|
31
|
+
return <div className={cx(colClassName,className)}>{children}</div>;
|
30
32
|
};
|
@@ -25,6 +25,13 @@ export interface ContainerProps {
|
|
25
25
|
* @type {string}
|
26
26
|
*/
|
27
27
|
gap?: string;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Classname for Container
|
31
|
+
* @default ''
|
32
|
+
* @type {string}
|
33
|
+
*/
|
34
|
+
className?:string
|
28
35
|
}
|
29
36
|
|
30
37
|
export interface RowProps {
|
@@ -43,6 +50,12 @@ export interface RowProps {
|
|
43
50
|
* @type {string}
|
44
51
|
*/
|
45
52
|
gap?: string;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @default ''
|
56
|
+
* @type string
|
57
|
+
*/
|
58
|
+
className?:string
|
46
59
|
}
|
47
60
|
|
48
61
|
export interface ColProps {
|
@@ -61,4 +74,11 @@ export interface ColProps {
|
|
61
74
|
* @type {number}
|
62
75
|
*/
|
63
76
|
size?: number;
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @default ''
|
80
|
+
* @type string
|
81
|
+
*
|
82
|
+
*/
|
83
|
+
className?: string;
|
64
84
|
}
|
@@ -45,6 +45,13 @@ import ImpactListIcon from '../../assets/icons/impactList.svg?react';
|
|
45
45
|
import InfoIcon from '../../assets/icons/info_icon.svg?react';
|
46
46
|
import CalendarIcon from '../../assets/icons/calendar_icon.svg?react';
|
47
47
|
import HideIcon from '../../assets/icons/hide_icon.svg?react';
|
48
|
+
import CollapseIcon from '../../assets/icons/collapse-icon.svg?react';
|
49
|
+
import ExpandIcon from '../../assets/icons/expand-icon.svg?react';
|
50
|
+
import CopyIcon from '../../assets/icons/copy-icon.svg?react';
|
51
|
+
import DownloadFile from '../../assets/icons/download-icon.svg?react';
|
52
|
+
import RefreshIcon from '../../assets/icons/refresh-icon.svg?react';
|
53
|
+
import LicenseInfo from '../../assets/icons/license_info.svg?react';
|
54
|
+
import LicenseWarning from '../../assets/icons/license_warning.svg?react';
|
48
55
|
//icons
|
49
56
|
Components['delete_info'] = DeleteInfoIcon;
|
50
57
|
Components['success'] = ToastSuccessIcon;
|
@@ -90,5 +97,12 @@ Components['add_variable'] = AddVariable;
|
|
90
97
|
Components['info'] = InfoIcon;
|
91
98
|
Components['calendar_icon'] = CalendarIcon;
|
92
99
|
Components['hide_icon'] = HideIcon;
|
100
|
+
Components['collapse_icon'] = CollapseIcon;
|
101
|
+
Components['refresh_icon'] = RefreshIcon;
|
102
|
+
Components['download_file'] = DownloadFile;
|
103
|
+
Components['copy_icon'] = CopyIcon;
|
104
|
+
Components['expand_icon'] = ExpandIcon;
|
105
|
+
Components['license_info'] = LicenseInfo;
|
106
|
+
Components['license_warning'] = LicenseWarning;
|
93
107
|
|
94
108
|
export default Components;
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
2
|
+
import Modal from './Modal';
|
3
|
+
import { useState } from 'react';
|
4
|
+
import Button from '../Button';
|
5
|
+
|
6
|
+
const meta: Meta<typeof Modal> = {
|
7
|
+
title: 'Components/Modal',
|
8
|
+
component: Modal,
|
9
|
+
parameters: {
|
10
|
+
layout: 'centered',
|
11
|
+
},
|
12
|
+
tags: ['autodocs'],
|
13
|
+
};
|
14
|
+
|
15
|
+
type Story = StoryObj<typeof Modal>;
|
16
|
+
|
17
|
+
export const DefaultModalStory: Story = {
|
18
|
+
args: {
|
19
|
+
isOpen: true,
|
20
|
+
contentLabel: 'modal',
|
21
|
+
ariaHideApp: true,
|
22
|
+
isHeaderDisplayed: true,
|
23
|
+
headerContent: <h2>title</h2>,
|
24
|
+
children: <h2>Hello</h2>,
|
25
|
+
isFooterDisplayed:true,
|
26
|
+
footerContent: <Button variant="primary" label="continue" />,
|
27
|
+
},
|
28
|
+
};
|
29
|
+
|
30
|
+
export const Controlled: Story = {
|
31
|
+
render: () => {
|
32
|
+
const [openModal, setModal] = useState(false);
|
33
|
+
return (
|
34
|
+
<>
|
35
|
+
<Button
|
36
|
+
variant="primary"
|
37
|
+
onClick={() => {
|
38
|
+
setModal(true);
|
39
|
+
}}
|
40
|
+
>
|
41
|
+
Show Modal
|
42
|
+
</Button>
|
43
|
+
{openModal && (
|
44
|
+
<Modal
|
45
|
+
overlayClassName="custom-overlay"
|
46
|
+
isOpen={openModal}
|
47
|
+
onClose={() => {
|
48
|
+
setModal(false);
|
49
|
+
}}
|
50
|
+
headerContent={<div>title</div>}
|
51
|
+
isHeaderDisplayed={true}
|
52
|
+
children={<div>Hello</div>}
|
53
|
+
ariaHideApp={true}
|
54
|
+
isFooterDisplayed={true}
|
55
|
+
footerContent={<Button variant="primary" label='continue'/>}
|
56
|
+
/>
|
57
|
+
)}
|
58
|
+
</>
|
59
|
+
);
|
60
|
+
},
|
61
|
+
};
|
62
|
+
|
63
|
+
export default meta;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import React, { useContext, useEffect } from 'react';
|
2
|
+
import { createPortal } from 'react-dom';
|
3
|
+
import './modal.scss';
|
4
|
+
import { ModalProps } from './types';
|
5
|
+
import { ThemeContext } from '../ThemeProvider/ThemeProvider';
|
6
|
+
|
7
|
+
|
8
|
+
const Modal: React.FC<ModalProps> = ({
|
9
|
+
isOpen,
|
10
|
+
onClose,
|
11
|
+
contentLabel,
|
12
|
+
isHeaderDisplayed,
|
13
|
+
headerContent,
|
14
|
+
footerContent,
|
15
|
+
contentClassName,
|
16
|
+
isFooterDisplayed,
|
17
|
+
overlayClassName,
|
18
|
+
shouldCloseOnEsc = true,
|
19
|
+
ariaHideApp = true,
|
20
|
+
shouldCloseOnOverlayClick = true,
|
21
|
+
children,
|
22
|
+
}) => {
|
23
|
+
useEffect(() => {
|
24
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
25
|
+
if (e.key === 'Escape' && shouldCloseOnEsc) {
|
26
|
+
onClose();
|
27
|
+
}
|
28
|
+
};
|
29
|
+
|
30
|
+
if (isOpen) {
|
31
|
+
document.addEventListener('keydown', handleKeyDown);
|
32
|
+
if (ariaHideApp) {
|
33
|
+
document.body.style.overflow = 'hidden';
|
34
|
+
}
|
35
|
+
}
|
36
|
+
return () => {
|
37
|
+
document.removeEventListener('keydown', handleKeyDown);
|
38
|
+
if (ariaHideApp) {
|
39
|
+
document.body.style.overflow = '';
|
40
|
+
}
|
41
|
+
};
|
42
|
+
}, [isOpen, onClose, ariaHideApp, shouldCloseOnEsc]);
|
43
|
+
|
44
|
+
if (!isOpen) return null;
|
45
|
+
const themeContext = useContext(ThemeContext);
|
46
|
+
const currentTheme = themeContext?.currentTheme;
|
47
|
+
|
48
|
+
return createPortal(
|
49
|
+
<div
|
50
|
+
className={`ff-modal-overlay ${overlayClassName || ''}`}
|
51
|
+
onClick={shouldCloseOnOverlayClick ? onClose : undefined}
|
52
|
+
>
|
53
|
+
<div
|
54
|
+
className={`ff-modal-content ${currentTheme} ${contentClassName || ''}`}
|
55
|
+
onClick={(e) => e.stopPropagation()}
|
56
|
+
aria-label={contentLabel}
|
57
|
+
>
|
58
|
+
{isHeaderDisplayed && (
|
59
|
+
<div className="ff-modal-header">{headerContent}</div>
|
60
|
+
)}
|
61
|
+
{children}
|
62
|
+
</div>
|
63
|
+
{isFooterDisplayed && (
|
64
|
+
<div className="ff-modal-footer">{footerContent}</div>
|
65
|
+
)}
|
66
|
+
</div>,
|
67
|
+
document.body
|
68
|
+
);
|
69
|
+
};
|
70
|
+
|
71
|
+
export default Modal;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default } from './Modal';
|
@@ -0,0 +1,37 @@
|
|
1
|
+
@use '../../assets/styles/mixins' as *;
|
2
|
+
.ff-modal-overlay {
|
3
|
+
position: fixed;
|
4
|
+
top: 0;
|
5
|
+
left: 0;
|
6
|
+
width: 100%;
|
7
|
+
height: 100%;
|
8
|
+
background: var(--background-modal-color);
|
9
|
+
@include center-content;
|
10
|
+
flex-direction: column;
|
11
|
+
}
|
12
|
+
|
13
|
+
.ff-modal-content {
|
14
|
+
background: var(--ff-mini-modal-border);
|
15
|
+
position: relative;
|
16
|
+
max-width: 549px;
|
17
|
+
width: 100%;
|
18
|
+
border-radius: 12px 12px 0 0;
|
19
|
+
padding: 16px;
|
20
|
+
.ff-modal-header {
|
21
|
+
height: 32px;
|
22
|
+
width: 448px;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
.ff-modal-footer {
|
26
|
+
background-color: var(--expandable-menu-option-bg);
|
27
|
+
max-width: 549px;
|
28
|
+
width: 100%;
|
29
|
+
height: 32px;
|
30
|
+
border-radius: 0 0 12px 12px;
|
31
|
+
display: flex;
|
32
|
+
flex-direction: row;
|
33
|
+
justify-content: end;
|
34
|
+
align-items: center;
|
35
|
+
gap: 8px;
|
36
|
+
padding: 4px 16px;
|
37
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { ReactNode } from "react";
|
2
|
+
|
3
|
+
export interface ModalProps {
|
4
|
+
isOpen: boolean;
|
5
|
+
onClose: () => void;
|
6
|
+
|
7
|
+
/*** label value for aria-label */
|
8
|
+
contentLabel?: string;
|
9
|
+
|
10
|
+
/*** default header will be provided with title and close icon. */
|
11
|
+
isHeaderDisplayed: boolean;
|
12
|
+
|
13
|
+
/*** Title to be displayed in the header when defaultHeader is true*/
|
14
|
+
headerTitle?: string;
|
15
|
+
|
16
|
+
/*** Custom class names for the modal content */
|
17
|
+
contentClassName?: string;
|
18
|
+
|
19
|
+
/*** Custom class name for the overlay */
|
20
|
+
overlayClassName?: string;
|
21
|
+
|
22
|
+
/*** Whether the modal should close when the 'Escape' key is pressed */
|
23
|
+
shouldCloseOnEsc?: boolean;
|
24
|
+
|
25
|
+
/*** Whether to hide the app from screen readers when the modal is open */
|
26
|
+
ariaHideApp?: boolean; //for screen readers
|
27
|
+
|
28
|
+
/*** Whether the modal should close when clicking outside of it (on the overlay) */
|
29
|
+
shouldCloseOnOverlayClick?: boolean;
|
30
|
+
// shouldFocusAfterRender?: boolean;
|
31
|
+
// shouldReturnFocusAfterClose?: boolean;
|
32
|
+
headerContent?: string | ReactNode;
|
33
|
+
footerContent?: ReactNode;
|
34
|
+
/***Content to be displayed inside the modal */
|
35
|
+
children: ReactNode;
|
36
|
+
isFooterDisplayed: boolean;
|
37
|
+
}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
/* eslint-disable */
|
2
2
|
// @ts-nocheck
|
3
|
-
import './TableTree.scss';
|
4
3
|
import React, { ReactNode, useLayoutEffect, useRef, useState } from 'react';
|
5
4
|
import { prepareData } from '../../utils/TableCell/TableCell';
|
6
5
|
import Icon from '../Icon';
|
7
6
|
import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
|
8
7
|
|
9
8
|
import Checkbox from '../Checkbox';
|
9
|
+
import './TableTree.scss';
|
10
10
|
|
11
11
|
interface ColumnDataProps {
|
12
12
|
name: string;
|
@@ -1,21 +1,24 @@
|
|
1
|
-
import React, { createContext, useState } from 'react';
|
1
|
+
import React, { createContext, useState, useEffect } from 'react';
|
2
2
|
import { ThemeContextType, ThemeProviderProps, Theme } from './types';
|
3
3
|
import '../../assets/Themes/Theme.scss';
|
4
4
|
|
5
5
|
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
6
6
|
|
7
7
|
const ThemeProvider: React.FC<ThemeProviderProps> = ({ children, theme }) => {
|
8
|
-
const [currentTheme, setCurrentTheme] = useState<Theme>(
|
9
|
-
theme || 'ff-light-theme'
|
10
|
-
);
|
8
|
+
const [currentTheme, setCurrentTheme] = useState<Theme>(theme || 'ff-light-theme');
|
11
9
|
|
12
10
|
const applyTheme = (newTheme: Theme) => setCurrentTheme(newTheme);
|
13
11
|
|
12
|
+
useEffect(() => {
|
13
|
+
document.body.className = currentTheme;
|
14
|
+
return () => {
|
15
|
+
document.body.className = '';
|
16
|
+
};
|
17
|
+
}, [currentTheme]);
|
18
|
+
|
14
19
|
return (
|
15
|
-
<ThemeContext.Provider
|
16
|
-
|
17
|
-
>
|
18
|
-
<div className={currentTheme}>{children}</div>
|
20
|
+
<ThemeContext.Provider value={{ currentTheme, setCurrentTheme, applyTheme }}>
|
21
|
+
{children}
|
19
22
|
</ThemeContext.Provider>
|
20
23
|
);
|
21
24
|
};
|