ish-ui 1.0.2
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/.eslintrc.json +39 -0
- package/.gitattributes +3 -0
- package/.github/workflows/release-package.yml +33 -0
- package/.prettierrc +5 -0
- package/README.md +80 -0
- package/assets/fonts/inter/Inter-Italic.var.woff2 +0 -0
- package/assets/fonts/inter/Inter-Roman.var.woff2 +0 -0
- package/assets/fonts/inter/LICENSE.txt +92 -0
- package/assets/fonts/inter/index.d.ts +10 -0
- package/assets/fonts/inter/inter.scss +17 -0
- package/package.json +108 -0
- package/src/actions/FieldProcessing.ts +21 -0
- package/src/actions/index.ts +10 -0
- package/src/appBar/AppBarHelpMenu.tsx +139 -0
- package/src/appBar/index.ts +9 -0
- package/src/buttons/AddButton.tsx +30 -0
- package/src/buttons/TimetableButton.tsx +19 -0
- package/src/buttons/index.ts +10 -0
- package/src/colorPicker/ColorPicker.tsx +223 -0
- package/src/colorPicker/index.ts +9 -0
- package/src/dialog/BrowserWarning.tsx +24 -0
- package/src/dialog/confirm/ConfirmBase.tsx +59 -0
- package/src/dialog/index.ts +11 -0
- package/src/dialog/message/Message.tsx +140 -0
- package/src/documents/DocumentIconsChooser.tsx +69 -0
- package/src/documents/index.ts +10 -0
- package/src/documents/utils/index.tsx +71 -0
- package/src/dynamicSizeList/DynamicSizeList.tsx +208 -0
- package/src/dynamicSizeList/index.ts +9 -0
- package/src/fieldMessage/ErrorMessage.tsx +28 -0
- package/src/fieldMessage/WarningMessage.tsx +28 -0
- package/src/fieldMessage/index.ts +11 -0
- package/src/fieldMessage/styles.ts +21 -0
- package/src/fileUploader/FileUploaderDialog.tsx +158 -0
- package/src/fileUploader/index.ts +9 -0
- package/src/formFields/CheckboxField.tsx +90 -0
- package/src/formFields/CodeEditorField.tsx +103 -0
- package/src/formFields/ColoredCheckBox.tsx +74 -0
- package/src/formFields/DateTimeField.tsx +61 -0
- package/src/formFields/EditInPlaceDateTimeField.tsx +285 -0
- package/src/formFields/EditInPlaceDurationField.tsx +79 -0
- package/src/formFields/EditInPlaceField.tsx +131 -0
- package/src/formFields/EditInPlaceFieldBase.tsx +241 -0
- package/src/formFields/EditInPlaceFileField.tsx +67 -0
- package/src/formFields/EditInPlaceMoneyField.tsx +64 -0
- package/src/formFields/EditInPlacePhoneField.tsx +97 -0
- package/src/formFields/EditInPlaceSearchSelect.tsx +562 -0
- package/src/formFields/FieldAdornments.tsx +70 -0
- package/src/formFields/FilePreview.tsx +149 -0
- package/src/formFields/FormRadioButtons.tsx +62 -0
- package/src/formFields/SelectCustomComponents.tsx +228 -0
- package/src/formFields/Switch.tsx +146 -0
- package/src/formFields/TextField.tsx +60 -0
- package/src/formFields/UneditableBase.tsx +101 -0
- package/src/formFields/index.ts +27 -0
- package/src/index.ts +26 -0
- package/src/layout/InfoPill.tsx +36 -0
- package/src/layout/index.ts +10 -0
- package/src/layout/resizable/ResizableWrapper.tsx +87 -0
- package/src/markdownEditor/HtmlEditor.tsx +44 -0
- package/src/markdownEditor/WysiwygEditor.tsx +137 -0
- package/src/markdownEditor/index.ts +12 -0
- package/src/markdownEditor/style.ts +188 -0
- package/src/markdownEditor/utils/index.ts +48 -0
- package/src/model/AppBar.ts +20 -0
- package/src/model/CommomObjects.ts +8 -0
- package/src/model/CommonFunctions.ts +20 -0
- package/src/model/Confirm.ts +27 -0
- package/src/model/Fields.ts +254 -0
- package/src/model/NestedEntity.ts +14 -0
- package/src/model/Theme.ts +42 -0
- package/src/model/index.ts +16 -0
- package/src/styles/GlobalStylesProvider.tsx +520 -0
- package/src/styles/StylesProviderCustom.tsx +8 -0
- package/src/styles/animateStyles.ts +94 -0
- package/src/styles/bootstrap.ts +503 -0
- package/src/styles/hooks.ts +44 -0
- package/src/styles/index.ts +18 -0
- package/src/styles/makeStyles.ts +21 -0
- package/src/styles/mixins/common.ts +40 -0
- package/src/styles/mixins/keyframes.ts +16 -0
- package/src/styles/mixins/prefixer.ts +21 -0
- package/src/tagsInput/AddTagMenu.tsx +74 -0
- package/src/tagsInput/AddTagMenuItem.tsx +50 -0
- package/src/tagsInput/TagInputList.tsx +428 -0
- package/src/tagsInput/index.ts +4 -0
- package/src/themes/appTheme.ts +324 -0
- package/src/themes/index.ts +10 -0
- package/src/themes/ishTheme.ts +401 -0
- package/src/timetable/datePeriodFilter/DayPeriodIcons.tsx +95 -0
- package/src/timetable/datePeriodFilter/index.ts +10 -0
- package/src/timetable/index.ts +11 -0
- package/src/timetable/miniCalendar/CalendarDay.tsx +109 -0
- package/src/timetable/miniCalendar/CalendarHeader.tsx +37 -0
- package/src/timetable/miniCalendar/CalendarWeekPanel.tsx +35 -0
- package/src/timetable/miniCalendar/WeekDay.tsx +49 -0
- package/src/timetable/miniCalendar/index.ts +13 -0
- package/src/utils/DOM/Links.ts +17 -0
- package/src/utils/DOM/getCaretCoordinates.ts +122 -0
- package/src/utils/DOM/getOS.ts +32 -0
- package/src/utils/DOM/index.ts +34 -0
- package/src/utils/dates/datesNormalizing.ts +4 -0
- package/src/utils/dates/format.ts +52 -0
- package/src/utils/dates/formatRelative.ts +22 -0
- package/src/utils/dates/formatString.ts +233 -0
- package/src/utils/dates/formatTimezone.ts +37 -0
- package/src/utils/dates/index.ts +15 -0
- package/src/utils/dates/timetable.ts +46 -0
- package/src/utils/events/index.ts +8 -0
- package/src/utils/fields/index.ts +23 -0
- package/src/utils/formatting/PhoneMasks.ts +320 -0
- package/src/utils/formatting/index.tsx +20 -0
- package/src/utils/hooks/index.ts +19 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/numbers/decimalCalculation.ts +26 -0
- package/src/utils/numbers/index.ts +11 -0
- package/src/utils/numbers/numbersNormalizing.ts +52 -0
- package/src/utils/stubs/index.tsx +12 -0
- package/src/utils/tags/index.ts +53 -0
- package/tools/webpack/webpack.aliases.js +13 -0
- package/tools/webpack/webpack.config.dev.js +29 -0
- package/tools/webpack/webpack.config.prod.js +36 -0
- package/tools/webpack/webpack.helpers.js +26 -0
- package/tools/webpack/webpack.plugins.js +15 -0
- package/tools/webpack/webpack.rules.js +51 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import React, { useCallback } from 'react';
|
|
11
|
+
import {
|
|
12
|
+
FormControl, FormHelperText, Input, InputLabel
|
|
13
|
+
} from '@mui/material';
|
|
14
|
+
import InputAdornment from '@mui/material/InputAdornment';
|
|
15
|
+
import { makeAppStyles } from '@src/styles';
|
|
16
|
+
import { LinkAdornment } from './FieldAdornments';
|
|
17
|
+
import { formatCurrency, openInternalLink } from '@src/utils';
|
|
18
|
+
|
|
19
|
+
const useStyles = makeAppStyles({
|
|
20
|
+
rightAlignedLabel: {
|
|
21
|
+
left: 'unset',
|
|
22
|
+
right: 0,
|
|
23
|
+
transformOrigin: '100% 0'
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
interface UneditableProps {
|
|
28
|
+
value: string | number;
|
|
29
|
+
label: string;
|
|
30
|
+
labelAdornment?: any;
|
|
31
|
+
url?: string;
|
|
32
|
+
currencySymbol?: string;
|
|
33
|
+
money?: boolean;
|
|
34
|
+
multiline?: boolean;
|
|
35
|
+
rightAligned?: boolean;
|
|
36
|
+
className?: string;
|
|
37
|
+
placeholder?: string;
|
|
38
|
+
error?: string;
|
|
39
|
+
format?: (value) => any;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const UneditableBase = React.memo<UneditableProps>(props => {
|
|
43
|
+
const {
|
|
44
|
+
label, labelAdornment, placeholder = 'No value', rightAligned, value, url, money, currencySymbol, className, format, multiline, error
|
|
45
|
+
} = props;
|
|
46
|
+
|
|
47
|
+
const classes = useStyles();
|
|
48
|
+
const inputId = `input-${label.toLowerCase().replace(' ', '-')}`;
|
|
49
|
+
|
|
50
|
+
const openLink = useCallback(() => {
|
|
51
|
+
openInternalLink(url);
|
|
52
|
+
}, [url]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<FormControl
|
|
56
|
+
className={clsx(className, money && 'money')}
|
|
57
|
+
error={Boolean(error)}
|
|
58
|
+
variant="standard"
|
|
59
|
+
fullWidth
|
|
60
|
+
>
|
|
61
|
+
<InputLabel
|
|
62
|
+
shrink
|
|
63
|
+
classes={{
|
|
64
|
+
root: rightAligned ? classes.rightAlignedLabel : null
|
|
65
|
+
}}
|
|
66
|
+
htmlFor={inputId}
|
|
67
|
+
>
|
|
68
|
+
{label}
|
|
69
|
+
{url && <LinkAdornment link={url} className="pl-0-5" clickHandler={openLink} />}
|
|
70
|
+
{labelAdornment && (
|
|
71
|
+
<span className="pl-0-5">
|
|
72
|
+
{labelAdornment}
|
|
73
|
+
{' '}
|
|
74
|
+
</span>
|
|
75
|
+
)}
|
|
76
|
+
</InputLabel>
|
|
77
|
+
<Input
|
|
78
|
+
id={inputId}
|
|
79
|
+
startAdornment={money && <InputAdornment position="start">{currencySymbol}</InputAdornment>}
|
|
80
|
+
value={
|
|
81
|
+
money
|
|
82
|
+
? formatCurrency(value, '')
|
|
83
|
+
: value
|
|
84
|
+
? (format
|
|
85
|
+
? (format(value))
|
|
86
|
+
: (value)
|
|
87
|
+
) : ('')
|
|
88
|
+
}
|
|
89
|
+
multiline={multiline}
|
|
90
|
+
placeholder={placeholder}
|
|
91
|
+
inputProps={{
|
|
92
|
+
className: rightAligned && 'text-end'
|
|
93
|
+
}}
|
|
94
|
+
disabled
|
|
95
|
+
/>
|
|
96
|
+
<FormHelperText>{error}</FormHelperText>
|
|
97
|
+
</FormControl>
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export default UneditableBase;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './CheckboxField';
|
|
10
|
+
export * from './CodeEditorField';
|
|
11
|
+
export * from './ColoredCheckBox';
|
|
12
|
+
export * from './DateTimeField';
|
|
13
|
+
export * from './EditInPlaceDateTimeField';
|
|
14
|
+
export * from './EditInPlaceDurationField';
|
|
15
|
+
export * from './EditInPlaceField';
|
|
16
|
+
export * from './EditInPlaceFieldBase';
|
|
17
|
+
export * from './EditInPlaceFileField';
|
|
18
|
+
export * from './EditInPlaceMoneyField';
|
|
19
|
+
export * from './EditInPlacePhoneField';
|
|
20
|
+
export * from './EditInPlaceSearchSelect';
|
|
21
|
+
export * from './FieldAdornments';
|
|
22
|
+
export * from './FilePreview';
|
|
23
|
+
export * from './FormRadioButtons';
|
|
24
|
+
export * from './SelectCustomComponents';
|
|
25
|
+
export * from './Switch';
|
|
26
|
+
export * from './TextField';
|
|
27
|
+
export * from './UneditableBase';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './actions';
|
|
10
|
+
export * from './appBar';
|
|
11
|
+
export * from './buttons';
|
|
12
|
+
export * from './colorPicker';
|
|
13
|
+
export * from './dialog';
|
|
14
|
+
export * from './documents';
|
|
15
|
+
export * from './dynamicSizeList';
|
|
16
|
+
export * from './fieldMessage';
|
|
17
|
+
export * from './fileUploader';
|
|
18
|
+
export * from './formFields';
|
|
19
|
+
export * from './layout';
|
|
20
|
+
export * from './markdownEditor';
|
|
21
|
+
export * from './model';
|
|
22
|
+
export * from './styles';
|
|
23
|
+
export * from './tagsInput';
|
|
24
|
+
export * from './themes';
|
|
25
|
+
export * from './utils';
|
|
26
|
+
export * from './timetable';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2022.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Chip } from '@mui/material';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { alpha } from '@mui/material/styles';
|
|
12
|
+
import { makeAppStyles } from '@src/styles';
|
|
13
|
+
|
|
14
|
+
const useStyles = makeAppStyles<Props>(theme => ({
|
|
15
|
+
chip: {
|
|
16
|
+
textTransform: 'uppercase',
|
|
17
|
+
fontWeight: 600,
|
|
18
|
+
fontSize: '12px',
|
|
19
|
+
marginLeft: theme.spacing(1),
|
|
20
|
+
color: ({ color }) => theme.palette[color].light,
|
|
21
|
+
backgroundColor: ({ color }) => alpha(theme.palette[color].light, 0.15)
|
|
22
|
+
}
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
interface Props {
|
|
26
|
+
label: string;
|
|
27
|
+
color?: 'success' | 'primary';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const InfoPill = ({ label, color = label === 'custom' ? 'primary' : 'success' }: Props) => {
|
|
31
|
+
const classes = useStyles({ label, color });
|
|
32
|
+
|
|
33
|
+
return <Chip className={classes.chip} label={label} size="small" />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default InfoPill;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './resizable/ResizableWrapper';
|
|
10
|
+
export * from './InfoPill';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Resizable } from 're-resizable';
|
|
3
|
+
import { withStyles, createStyles } from '@mui/styles';
|
|
4
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
import { AppTheme } from '@src/model';
|
|
7
|
+
|
|
8
|
+
const LIST_SIDE_BAR_DEFAULT_WIDTH = 265;
|
|
9
|
+
|
|
10
|
+
const styles = (theme: AppTheme) =>
|
|
11
|
+
createStyles({
|
|
12
|
+
sideBar: {
|
|
13
|
+
borderRight: `1px solid ${theme.palette.divider}`,
|
|
14
|
+
display: 'flex',
|
|
15
|
+
paddingRight: '1px',
|
|
16
|
+
'&.d-none': {
|
|
17
|
+
display: 'none'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
sideBarWrapper: {
|
|
21
|
+
overflowX: 'hidden',
|
|
22
|
+
overflowY: 'auto',
|
|
23
|
+
flex: 1
|
|
24
|
+
},
|
|
25
|
+
line: {
|
|
26
|
+
height: '100%',
|
|
27
|
+
width: '2px',
|
|
28
|
+
transition: 'background 120ms ease-in-out',
|
|
29
|
+
},
|
|
30
|
+
resizeLine: {
|
|
31
|
+
zIndex: theme.zIndex.drawer,
|
|
32
|
+
display: 'flex',
|
|
33
|
+
justifyContent: 'center',
|
|
34
|
+
'&:active $line, &:hover $line': {
|
|
35
|
+
background: `${theme.palette.secondary.main}`,
|
|
36
|
+
overflow: 'visible'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
interface Props {
|
|
42
|
+
sidebarWidth: number;
|
|
43
|
+
minWidth?: number | string;
|
|
44
|
+
maxWidth?: number | string;
|
|
45
|
+
onResizeStop?: any;
|
|
46
|
+
onResize?: any;
|
|
47
|
+
classes?: any;
|
|
48
|
+
className?: any;
|
|
49
|
+
ignoreScreenWidth?: boolean;
|
|
50
|
+
children?: any;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const ResizableWrapper = (props: Props) => {
|
|
54
|
+
const {
|
|
55
|
+
classes,
|
|
56
|
+
onResizeStop,
|
|
57
|
+
onResize,
|
|
58
|
+
sidebarWidth,
|
|
59
|
+
minWidth,
|
|
60
|
+
maxWidth,
|
|
61
|
+
children,
|
|
62
|
+
className,
|
|
63
|
+
ignoreScreenWidth
|
|
64
|
+
} = props;
|
|
65
|
+
|
|
66
|
+
return useMediaQuery('(min-width:992px)') || ignoreScreenWidth ? (
|
|
67
|
+
<Resizable
|
|
68
|
+
size={{ width: sidebarWidth, height: '100%' }}
|
|
69
|
+
minWidth={minWidth || LIST_SIDE_BAR_DEFAULT_WIDTH}
|
|
70
|
+
maxWidth={maxWidth}
|
|
71
|
+
onResizeStop={onResizeStop}
|
|
72
|
+
onResize={onResize}
|
|
73
|
+
enable={{ right: true }}
|
|
74
|
+
className={clsx(classes.sideBar, className)}
|
|
75
|
+
handleClasses={{ right: classes.resizeLine }}
|
|
76
|
+
handleComponent={{ right: <div className={props.classes.line} /> }}
|
|
77
|
+
>
|
|
78
|
+
<div className={classes.sideBarWrapper}>{children}</div>
|
|
79
|
+
</Resizable>
|
|
80
|
+
) : (
|
|
81
|
+
children
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const wrapped: any = (withStyles(styles)(ResizableWrapper) as any);
|
|
86
|
+
|
|
87
|
+
export default wrapped as React.FC<Props>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { FunctionComponent } from 'react';
|
|
2
|
+
import AceEditor from 'react-ace';
|
|
3
|
+
import 'ace-builds/webpack-resolver';
|
|
4
|
+
import 'ace-builds/src-noconflict/mode-html';
|
|
5
|
+
import 'ace-builds/src-noconflict/mode-textile';
|
|
6
|
+
import 'ace-builds/src-noconflict/theme-tomorrow';
|
|
7
|
+
import 'ace-builds/src-noconflict/ext-language_tools';
|
|
8
|
+
import 'ace-builds/src-noconflict/snippets/html';
|
|
9
|
+
import 'ace-builds/src-noconflict/snippets/textile';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
value?: string;
|
|
13
|
+
mode?: string;
|
|
14
|
+
onChange?: (html) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const HtmlEditor = props => {
|
|
18
|
+
const { value, onChange, mode = 'html' } = props;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<AceEditor
|
|
22
|
+
mode={mode}
|
|
23
|
+
theme="tomorrow"
|
|
24
|
+
fontSize={14}
|
|
25
|
+
height="200px"
|
|
26
|
+
showGutter={false}
|
|
27
|
+
width="100%"
|
|
28
|
+
wrapEnabled
|
|
29
|
+
highlightActiveLine
|
|
30
|
+
enableLiveAutocompletion={mode === 'html'}
|
|
31
|
+
enableBasicAutocompletion={mode === 'html'}
|
|
32
|
+
setOptions={{
|
|
33
|
+
enableSnippets: true,
|
|
34
|
+
showLineNumbers: true,
|
|
35
|
+
tabSize: 2,
|
|
36
|
+
}}
|
|
37
|
+
editorProps={{ $blockScrolling: Infinity }}
|
|
38
|
+
defaultValue={value}
|
|
39
|
+
onChange={onChange}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default HtmlEditor as FunctionComponent<Props>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2022.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
|
|
11
|
+
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
|
|
12
|
+
import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat';
|
|
13
|
+
import SourceEditing from '@ckeditor/ckeditor5-source-editing/src/sourceediting';
|
|
14
|
+
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
|
|
15
|
+
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
|
|
16
|
+
import HeadingPlugin from '@ckeditor/ckeditor5-heading/src/heading';
|
|
17
|
+
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
|
|
18
|
+
import ListPlugin from '@ckeditor/ckeditor5-list/src/list';
|
|
19
|
+
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph';
|
|
20
|
+
import Markdown from '@ckeditor/ckeditor5-markdown-gfm/src/markdown';
|
|
21
|
+
import Table from '@ckeditor/ckeditor5-table/src/table';
|
|
22
|
+
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
|
|
23
|
+
import Image from '@ckeditor/ckeditor5-image/src/image';
|
|
24
|
+
import LinkImage from '@ckeditor/ckeditor5-link/src/linkimage';
|
|
25
|
+
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
|
|
26
|
+
import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
|
|
27
|
+
import { CKEditor } from '@ckeditor/ckeditor5-react/dist/ckeditor';
|
|
28
|
+
import { createRoot } from 'react-dom/client';
|
|
29
|
+
import CodeIcon from '@mui/icons-material/Code';
|
|
30
|
+
|
|
31
|
+
const SourceEditingSwitch = () => (
|
|
32
|
+
<div className="ck_source_edit_custom">
|
|
33
|
+
<CodeIcon className="ck_code_icon_custom" />
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const config = {
|
|
38
|
+
plugins: [
|
|
39
|
+
Markdown,
|
|
40
|
+
SourceEditing,
|
|
41
|
+
EssentialsPlugin,
|
|
42
|
+
AutoformatPlugin,
|
|
43
|
+
BoldPlugin,
|
|
44
|
+
ItalicPlugin,
|
|
45
|
+
HeadingPlugin,
|
|
46
|
+
LinkPlugin,
|
|
47
|
+
ListPlugin,
|
|
48
|
+
ParagraphPlugin,
|
|
49
|
+
Table,
|
|
50
|
+
TableToolbar,
|
|
51
|
+
Image,
|
|
52
|
+
LinkImage,
|
|
53
|
+
ImageStyle,
|
|
54
|
+
ImageCaption,
|
|
55
|
+
],
|
|
56
|
+
toolbar: [
|
|
57
|
+
'heading',
|
|
58
|
+
'bold',
|
|
59
|
+
'italic',
|
|
60
|
+
'link',
|
|
61
|
+
'bulletedList',
|
|
62
|
+
'numberedList',
|
|
63
|
+
'insertTable',
|
|
64
|
+
'sourceEditing',
|
|
65
|
+
],
|
|
66
|
+
table: {
|
|
67
|
+
defaultHeadings: { rows: 1 },
|
|
68
|
+
contentToolbar: ['tableColumn', 'tableRow']
|
|
69
|
+
},
|
|
70
|
+
heading: {
|
|
71
|
+
options: [
|
|
72
|
+
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
|
|
73
|
+
{
|
|
74
|
+
model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
interface Props {
|
|
90
|
+
value?: string;
|
|
91
|
+
onChange?: (val: any) => void;
|
|
92
|
+
wysiwygRef?: any;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const WysiwygEditor: React.FC<Props> = ({
|
|
96
|
+
value,
|
|
97
|
+
onChange,
|
|
98
|
+
wysiwygRef
|
|
99
|
+
}) => {
|
|
100
|
+
|
|
101
|
+
const onReady = editor => {
|
|
102
|
+
wysiwygRef.current = editor;
|
|
103
|
+
|
|
104
|
+
const sourceEdit = document.querySelector<any>('.ck-source-editing-button');
|
|
105
|
+
sourceEdit.dataset.ckeTooltipText = 'Edit source';
|
|
106
|
+
sourceEdit.dataset.ckeTooltipPosition = 's';
|
|
107
|
+
|
|
108
|
+
const root = createRoot(sourceEdit);
|
|
109
|
+
|
|
110
|
+
root.render(
|
|
111
|
+
<SourceEditingSwitch />
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
editor.plugins.get('SourceEditing').on('change:isSourceEditingMode', () => {
|
|
115
|
+
const sourceEdit = document.querySelector('.ck-source-editing-button');
|
|
116
|
+
if (sourceEdit) {
|
|
117
|
+
root.render(
|
|
118
|
+
<SourceEditingSwitch/>,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const onChangeHandler = (e, editor) => onChange(editor.getData());
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<CKEditor
|
|
128
|
+
editor={ClassicEditor}
|
|
129
|
+
config={config}
|
|
130
|
+
data={value}
|
|
131
|
+
onChange={onChangeHandler}
|
|
132
|
+
onReady={onReady}
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export default WysiwygEditor;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2023.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './utils/index';
|
|
10
|
+
export * from './style';
|
|
11
|
+
export * from './HtmlEditor';
|
|
12
|
+
export * from './WysiwygEditor';
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright ish group pty ltd 2022.
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
*
|
|
6
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { makeStyles } from '@mui/styles';
|
|
10
|
+
import { AppTheme } from '@src/model';
|
|
11
|
+
|
|
12
|
+
export const useStyles = makeStyles((theme: AppTheme) => ({
|
|
13
|
+
hoverIcon: {
|
|
14
|
+
opacity: 0.5,
|
|
15
|
+
visibility: 'hidden',
|
|
16
|
+
marginLeft: theme.spacing(1)
|
|
17
|
+
},
|
|
18
|
+
editable: {
|
|
19
|
+
display: 'inline-flex',
|
|
20
|
+
cursor: 'text',
|
|
21
|
+
color: theme.palette.text.primaryEditable,
|
|
22
|
+
minHeight: '32px',
|
|
23
|
+
padding: '4px 0 4px',
|
|
24
|
+
marginTop: theme.spacing(2),
|
|
25
|
+
fontWeight: 400,
|
|
26
|
+
justifyContent: 'space-between',
|
|
27
|
+
alignItems: 'flex-end',
|
|
28
|
+
'&:hover $hoverIcon': {
|
|
29
|
+
visibility: 'visible'
|
|
30
|
+
},
|
|
31
|
+
'&:before': {
|
|
32
|
+
borderBottom: '1px solid transparent',
|
|
33
|
+
left: 0,
|
|
34
|
+
bottom: '4px',
|
|
35
|
+
content: '\' \'',
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
right: 0,
|
|
38
|
+
transition: theme.transitions.create('border-bottom-color', {
|
|
39
|
+
duration: theme.transitions.duration.standard,
|
|
40
|
+
easing: theme.transitions.easing.easeInOut
|
|
41
|
+
}),
|
|
42
|
+
pointerEvents: 'none'
|
|
43
|
+
},
|
|
44
|
+
'&:hover:before': {
|
|
45
|
+
borderBottom: `1px solid ${theme.palette.primary.main}`
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
editorArea: {
|
|
49
|
+
'&#editorRoot': {
|
|
50
|
+
'& .ck-dropdown__button .ck-button__label': {
|
|
51
|
+
fontSize: '14px'
|
|
52
|
+
},
|
|
53
|
+
cursor: 'text',
|
|
54
|
+
overflowY: 'auto',
|
|
55
|
+
position: 'relative',
|
|
56
|
+
'& .ck-list__item .ck-button': {
|
|
57
|
+
height: 'unset',
|
|
58
|
+
padding: '5px 10px'
|
|
59
|
+
},
|
|
60
|
+
'& .ck-list__item .ck-heading_heading3': {
|
|
61
|
+
fontSize: '15px'
|
|
62
|
+
},
|
|
63
|
+
'& .ck-list__item .ck-heading_heading4': {
|
|
64
|
+
fontSize: '14px'
|
|
65
|
+
},
|
|
66
|
+
'& .ck-toolbar': {
|
|
67
|
+
height: '45px',
|
|
68
|
+
background: theme.table.contrastRow.main
|
|
69
|
+
},
|
|
70
|
+
'& .ck-list__item': {
|
|
71
|
+
fontSize: '15px'
|
|
72
|
+
},
|
|
73
|
+
'& .ck-dropdown': {
|
|
74
|
+
fontSize: '15px'
|
|
75
|
+
},
|
|
76
|
+
'& .ck.ck-dropdown .ck-button__label': {
|
|
77
|
+
fontFamily: 'Inter, sans-serif',
|
|
78
|
+
overflow: 'visible',
|
|
79
|
+
width: '120px'
|
|
80
|
+
},
|
|
81
|
+
'& .content-mode-wrapper': {
|
|
82
|
+
position: 'absolute',
|
|
83
|
+
right: '10px',
|
|
84
|
+
top: '6px',
|
|
85
|
+
padding: '5px',
|
|
86
|
+
zIndex: 1000,
|
|
87
|
+
'& .content-mode': {
|
|
88
|
+
maxWidth: '85px',
|
|
89
|
+
border: 0,
|
|
90
|
+
boxShadow: 'none',
|
|
91
|
+
backgroundColor: 'black',
|
|
92
|
+
color: 'white',
|
|
93
|
+
padding: '2px',
|
|
94
|
+
fontSize: '9px',
|
|
95
|
+
'&:hover': {
|
|
96
|
+
backgroundColor: theme.palette.primary.main,
|
|
97
|
+
color: theme.palette.primary.contrastText,
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
'& .ck-editor': {
|
|
102
|
+
'& .ck-content': {
|
|
103
|
+
resize: 'vertical',
|
|
104
|
+
maxHeight: '80vh',
|
|
105
|
+
minHeight: '200px',
|
|
106
|
+
fontFamily: 'Inter, sans-serif',
|
|
107
|
+
fontWeight: 400,
|
|
108
|
+
fontSize: '14px',
|
|
109
|
+
color: 'black'
|
|
110
|
+
},
|
|
111
|
+
'& .ck-content .table': {
|
|
112
|
+
marginLeft: 0
|
|
113
|
+
},
|
|
114
|
+
'& .ck-toolbar': {
|
|
115
|
+
padding: '3px'
|
|
116
|
+
},
|
|
117
|
+
'& .ck-source-editing-button': {
|
|
118
|
+
marginLeft: 'auto',
|
|
119
|
+
marginRight: '44px'
|
|
120
|
+
},
|
|
121
|
+
'& .ck-source-editing-button > *': {
|
|
122
|
+
visibility: 'hidden'
|
|
123
|
+
},
|
|
124
|
+
'& .ck-source-editing-button .ck_source_edit_custom': {
|
|
125
|
+
visibility: 'visible'
|
|
126
|
+
},
|
|
127
|
+
'& .ck-source-editing-button .ck_code_icon_custom': {
|
|
128
|
+
width: '24px'
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
'&.ace-wrapper': {
|
|
132
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
133
|
+
paddingTop: '44px',
|
|
134
|
+
background: theme.table.contrastRow.main,
|
|
135
|
+
'& .ace_editor': {
|
|
136
|
+
borderTop: `1px solid ${theme.palette.divider}`
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
previewFrame: {
|
|
142
|
+
width: '100%',
|
|
143
|
+
maxHeight: '300px',
|
|
144
|
+
overflow: 'auto',
|
|
145
|
+
fontSize: '16px',
|
|
146
|
+
'& > div': {
|
|
147
|
+
width: '100%'
|
|
148
|
+
},
|
|
149
|
+
'& h1,h2,h3,h4': {
|
|
150
|
+
all: 'revert'
|
|
151
|
+
},
|
|
152
|
+
'& table': {
|
|
153
|
+
marginLeft: 0,
|
|
154
|
+
marginRight: 'auto',
|
|
155
|
+
borderCollapse: 'collapse',
|
|
156
|
+
borderSpacing: 0,
|
|
157
|
+
border: '1px double #b3b3b3',
|
|
158
|
+
'& th': {
|
|
159
|
+
textAlign: 'left',
|
|
160
|
+
fontWeight: 700,
|
|
161
|
+
background: 'hsla(0,0%,0%,5%)',
|
|
162
|
+
minWidth: '2em',
|
|
163
|
+
padding: '0.4em',
|
|
164
|
+
border: '1px solid #bfbfbf'
|
|
165
|
+
},
|
|
166
|
+
'& td': {
|
|
167
|
+
minWidth: '2em',
|
|
168
|
+
padding: '0.4em',
|
|
169
|
+
border: '1px solid #bfbfbf'
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
readonly: {
|
|
174
|
+
fontWeight: 300,
|
|
175
|
+
pointerEvents: 'none'
|
|
176
|
+
},
|
|
177
|
+
textField: {
|
|
178
|
+
paddingLeft: '0',
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
paddingBottom: `${theme.spacing(2) - 3}`,
|
|
181
|
+
margin: 0
|
|
182
|
+
},
|
|
183
|
+
'@global': {
|
|
184
|
+
'.ck.ck-balloon-panel.ck-balloon-panel_visible': {
|
|
185
|
+
zIndex: 2000
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}));
|