ish-ui 1.2.9 → 1.3.1
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/dist/appBar/AppBarHelpMenu.js +1 -1
- package/dist/colorPicker/ColorPicker.js +2 -2
- package/dist/dialog/BrowserWarning.js +1 -1
- package/dist/dialog/message/Message.js +21 -15
- package/dist/dynamicSizeList/DynamicSizeList.d.ts +21 -12
- package/dist/dynamicSizeList/DynamicSizeList.js +30 -157
- package/dist/fieldMessage/styles.d.ts +2 -2
- package/dist/fileUploader/FileUploaderDialog.js +8 -1
- package/dist/formFields/AutosizeInput.d.ts +14 -0
- package/dist/formFields/AutosizeInput.js +156 -0
- package/dist/formFields/CheckboxField.d.ts +4 -2
- package/dist/formFields/ColoredCheckBox.js +5 -2
- package/dist/formFields/EditInPlaceDateTimeField.js +35 -36
- package/dist/formFields/EditInPlaceField.js +8 -9
- package/dist/formFields/EditInPlaceFieldBase.d.ts +2 -3
- package/dist/formFields/EditInPlaceFieldBase.js +7 -14
- package/dist/formFields/EditInPlaceFileField.js +2 -2
- package/dist/formFields/EditInPlaceMoneyField.js +2 -2
- package/dist/formFields/EditInPlacePhoneField.js +13 -3
- package/dist/formFields/EditInPlaceSearchSelect.js +6 -3
- package/dist/formFields/SelectCustomComponents.d.ts +18 -4
- package/dist/formFields/SelectCustomComponents.js +36 -20
- package/dist/formFields/Switch.d.ts +3 -1
- package/dist/markdownEditor/WysiwygEditor.js +14 -16
- package/dist/markdownEditor/utils/index.d.ts +1 -1
- package/dist/model/Fields.d.ts +1 -6
- package/dist/styles/makeStyles.d.ts +8 -25
- package/dist/styles/makeStyles.js +9 -3
- package/dist/tagsInput/AddTagMenu.d.ts +2 -2
- package/dist/tagsInput/AddTagMenu.js +8 -5
- package/dist/tagsInput/AddTagMenuItem.d.ts +2 -2
- package/dist/tagsInput/AddTagMenuItem.js +1 -1
- package/dist/tagsInput/TagInputList.js +112 -160
- package/dist/themes/ishTheme.js +13 -3
- package/dist/utils/DOM/index.d.ts +0 -1
- package/dist/utils/DOM/index.js +0 -1
- package/dist/utils/dates/formatTimezone.js +3 -3
- package/dist/utils/formatting/index.d.ts +1 -1
- package/dist/utils/hooks/index.d.ts +16 -0
- package/dist/utils/hooks/index.js +31 -1
- package/dist/utils/tags/index.d.ts +1 -1
- package/dist/utils/tags/index.js +1 -1
- package/package.json +85 -72
- package/tsconfig.prod.json +3 -0
- package/dist/utils/DOM/getCaretCoordinates.d.ts +0 -6
- package/dist/utils/DOM/getCaretCoordinates.js +0 -109
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { withStyles } from 'tss-react/mui';
|
|
3
|
-
import HelpOutline from '@mui/icons-material/
|
|
3
|
+
import HelpOutline from '@mui/icons-material/HelpOutlineOutlined';
|
|
4
4
|
import IconButton from '@mui/material/IconButton';
|
|
5
5
|
import Typography from '@mui/material/Typography';
|
|
6
6
|
import Menu from '@mui/material/Menu';
|
|
@@ -9,7 +9,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
|
9
9
|
import ButtonBase from '@mui/material/ButtonBase';
|
|
10
10
|
import Popper from '@mui/material/Popper';
|
|
11
11
|
import { AlphaPicker, HuePicker } from 'react-color';
|
|
12
|
-
import { ClickAwayListener } from '@mui/
|
|
12
|
+
import { ClickAwayListener } from '@mui/material';
|
|
13
13
|
import Paper from '@mui/material/Paper';
|
|
14
14
|
import Grow from '@mui/material/Grow';
|
|
15
15
|
import { stopEventPropagation } from '../utils/events';
|
|
@@ -87,7 +87,7 @@ const ColorPickerBase = React.memo(({ color, input: { value, onChange }, Transit
|
|
|
87
87
|
const { classes, cx } = useStyles();
|
|
88
88
|
const [hueColor, setHueColor] = useState(color);
|
|
89
89
|
const [alfaColor, setAlfaColor] = useState(color);
|
|
90
|
-
const hueRef = useRef();
|
|
90
|
+
const hueRef = useRef(undefined);
|
|
91
91
|
const onHueChange = useCallback(color => {
|
|
92
92
|
setHueColor(color.hsv);
|
|
93
93
|
setAlfaColor(color.hsv);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Alert } from '@mui/
|
|
1
|
+
import { Alert } from '@mui/material';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
const BROWSER_WARNING_TEXT = 'Your current browser is not supported. Please ensure you are using an up to date version of Chrome, Firefox or Edge.';
|
|
4
4
|
export const isOldIE = () => {
|
|
@@ -50,21 +50,27 @@ const Message = ({ opened, text, clearMessage, success, persist }) => {
|
|
|
50
50
|
horizontal: 'left'
|
|
51
51
|
}, classes: {
|
|
52
52
|
root: classes.autoWidthRoot
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
}, slotProps: {
|
|
54
|
+
content: {
|
|
55
|
+
classes: {
|
|
56
|
+
root: cx(classes.autoWidth, {
|
|
57
|
+
[classes.success]: success
|
|
58
|
+
}),
|
|
59
|
+
message: persist ? classes.fullScreenMessage : undefined
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
clickAwayListener: {
|
|
63
|
+
onClickAway: handleClose
|
|
59
64
|
}
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
}, autoHideDuration: persist ? null : 6000, onClose: handleClose, disableWindowBlurListener: persist }, React.createElement(Alert, { variant: "filled", severity: success ? 'success' : 'error', classes: {
|
|
66
|
+
// MUI 9 replaced the variant+severity class keys (`standardError`,
|
|
67
|
+
// `standardSuccess`) with separate `standard` and `colorError` /
|
|
68
|
+
// `colorSuccess` keys. Both were already inert here because this
|
|
69
|
+
// Alert renders with `variant="filled"`, so they are dropped rather
|
|
70
|
+
// than remapped — remapping to `colorError`/`colorSuccess` would
|
|
71
|
+
// newly apply styling that has never been active.
|
|
72
|
+
message: 'text-pre-wrap'
|
|
73
|
+
}, action: (React.createElement(IconButton, { key: "close", "aria-label": "Close", color: "inherit", className: classes.close, onClick: clearMessage },
|
|
74
|
+
React.createElement(CloseIcon, null))) }, text)));
|
|
69
75
|
};
|
|
70
76
|
export default Message;
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export interface DynamicSizeListProps {
|
|
3
|
+
/** Component rendering a single row; receives `data`, `index` and `style`. */
|
|
4
|
+
children: any;
|
|
5
|
+
itemCount: number;
|
|
6
|
+
itemData?: any;
|
|
7
|
+
height?: number | string;
|
|
8
|
+
width?: number | string;
|
|
9
|
+
/** Row height assumed before a row has been measured. */
|
|
10
|
+
estimatedItemSize?: number;
|
|
4
11
|
listRef?: any;
|
|
12
|
+
className?: string;
|
|
13
|
+
overscanCount?: number;
|
|
5
14
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
rowSizes: any[];
|
|
9
|
-
componentDidMount(): void;
|
|
10
|
-
attachRefs: (node: any) => void;
|
|
11
|
-
render(): React.JSX.Element;
|
|
12
|
-
scrollToItem(index: any, align: any): void;
|
|
13
|
-
renderItem: (props: any) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
14
|
-
handleNewMeasurements: (index: any, newSize: any) => void;
|
|
15
|
-
getItemSize: (index: any) => any;
|
|
15
|
+
export interface DynamicSizeListApi {
|
|
16
|
+
scrollToItem(index: number, align?: 'auto' | 'center' | 'end' | 'smart' | 'start'): void;
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Variable-height virtualised list.
|
|
20
|
+
*
|
|
21
|
+
* react-window v2 measures dynamic rows itself through `useDynamicRowHeight`,
|
|
22
|
+
* which replaces the ResizeObserver-based row measurer this component used to
|
|
23
|
+
* carry against v1's `VariableSizeList`.
|
|
24
|
+
*/
|
|
25
|
+
declare const DynamicSizeList: React.ForwardRefExoticComponent<DynamicSizeListProps & React.RefAttributes<DynamicSizeListApi>>;
|
|
17
26
|
export default DynamicSizeList;
|
|
@@ -5,163 +5,36 @@
|
|
|
5
5
|
*
|
|
6
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
7
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const { handleNewMeasurements, index } = this.props;
|
|
28
|
-
const node = this._node;
|
|
29
|
-
if (node) {
|
|
30
|
-
const { height, width } = node.getBoundingClientRect();
|
|
31
|
-
const isVisible = height > 0 || width > 0;
|
|
32
|
-
if (isVisible) {
|
|
33
|
-
const newSize = Math.ceil(height);
|
|
34
|
-
handleNewMeasurements(index, newSize);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
this._refSetter = ref => {
|
|
39
|
-
if (this._resizeObserver !== null && this._node !== null) {
|
|
40
|
-
this._resizeObserver.unobserve(this._node);
|
|
41
|
-
}
|
|
42
|
-
if (ref) {
|
|
43
|
-
this._node = ref;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
this._node = null;
|
|
47
|
-
}
|
|
48
|
-
if (this._resizeObserver !== null && this._node !== null) {
|
|
49
|
-
this._resizeObserver.observe(this._node);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
this._onResize = entries => {
|
|
53
|
-
const _this = this;
|
|
54
|
-
window.requestAnimationFrame(() => {
|
|
55
|
-
if (!Array.isArray(entries) || !entries.length) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
_this._measureItem();
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
componentDidMount() {
|
|
63
|
-
this._measureItem();
|
|
64
|
-
// @ts-ignore
|
|
65
|
-
if (typeof window.ResizeObserver !== 'undefined') {
|
|
66
|
-
// @ts-ignore
|
|
67
|
-
this._resizeObserver = new window.ResizeObserver(this._onResize);
|
|
68
|
-
if (this._node !== null) {
|
|
69
|
-
this._resizeObserver.observe(this._node);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
//
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
componentWillUnmount() {
|
|
77
|
-
if (this._resizeObserver !== null) {
|
|
78
|
-
this._resizeObserver.disconnect();
|
|
79
|
-
this._resizeObserver = null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
render() {
|
|
83
|
-
return React.cloneElement(this.props.item, {
|
|
84
|
-
ref: this._refSetter
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
class DynamicSizeList extends React.Component {
|
|
89
|
-
constructor() {
|
|
90
|
-
super(...arguments);
|
|
91
|
-
this.listRef = React.createRef();
|
|
92
|
-
this.rowSizes = [];
|
|
93
|
-
this.attachRefs = node => {
|
|
94
|
-
const { listRef } = this.props;
|
|
95
|
-
if (node) {
|
|
96
|
-
if (!this.listRef.current) {
|
|
97
|
-
// @ts-ignore
|
|
98
|
-
this.listRef.current = node;
|
|
99
|
-
}
|
|
100
|
-
if (typeof listRef === 'function') {
|
|
101
|
-
listRef(node);
|
|
102
|
-
}
|
|
103
|
-
if (typeof listRef === 'object') {
|
|
104
|
-
listRef.current = node;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
this.renderItem = props => {
|
|
109
|
-
// clear height
|
|
110
|
-
if (props.style.height !== undefined) {
|
|
111
|
-
props.style.height = undefined;
|
|
112
|
-
}
|
|
113
|
-
return React.createElement(ItemMeasurer, {
|
|
114
|
-
index: props.index,
|
|
115
|
-
// @ts-ignore
|
|
116
|
-
item: React.createElement(this.props.children, props),
|
|
117
|
-
handleNewMeasurements: this.handleNewMeasurements
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
this.handleNewMeasurements = (index, newSize) => {
|
|
121
|
-
const itemSizeDelta = newSize - this.getItemSize(index);
|
|
122
|
-
if (itemSizeDelta !== 0) {
|
|
123
|
-
this.rowSizes[index] = newSize;
|
|
124
|
-
const ref = this.listRef.current;
|
|
125
|
-
if (ref) {
|
|
126
|
-
const { isScrolling, scrollDirection } = ref.state;
|
|
127
|
-
if (isScrolling && scrollDirection === 'backward') {
|
|
128
|
-
ref._outerRef.scrollBy({
|
|
129
|
-
top: itemSizeDelta,
|
|
130
|
-
left: 0,
|
|
131
|
-
behavior: 'auto'
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
ref.resetAfterIndex(index, true);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
this.getItemSize = index => {
|
|
139
|
-
// https://react-window.now.sh/#/api/VariableSizeList
|
|
140
|
-
const defaultEstimatedItemSize = 50;
|
|
141
|
-
return (this.rowSizes[index]
|
|
142
|
-
|| this.props.estimatedItemSize
|
|
143
|
-
|| defaultEstimatedItemSize);
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
componentDidMount() {
|
|
147
|
-
const ref = this.listRef.current;
|
|
148
|
-
if (ref) {
|
|
149
|
-
ref.resetAfterIndex(0, true);
|
|
8
|
+
import React, { useImperativeHandle, useRef } from 'react';
|
|
9
|
+
import { List, useDynamicRowHeight } from 'react-window';
|
|
10
|
+
/**
|
|
11
|
+
* Variable-height virtualised list.
|
|
12
|
+
*
|
|
13
|
+
* react-window v2 measures dynamic rows itself through `useDynamicRowHeight`,
|
|
14
|
+
* which replaces the ResizeObserver-based row measurer this component used to
|
|
15
|
+
* carry against v1's `VariableSizeList`.
|
|
16
|
+
*/
|
|
17
|
+
const DynamicSizeList = React.forwardRef(({ children, itemCount, itemData, height, width, estimatedItemSize, listRef, className, overscanCount, }, ref) => {
|
|
18
|
+
const defaultEstimatedItemSize = 50;
|
|
19
|
+
const rowHeight = useDynamicRowHeight({
|
|
20
|
+
defaultRowHeight: estimatedItemSize || defaultEstimatedItemSize,
|
|
21
|
+
});
|
|
22
|
+
const listApi = useRef(undefined);
|
|
23
|
+
const attachRefs = node => {
|
|
24
|
+
listApi.current = node;
|
|
25
|
+
if (typeof listRef === 'function') {
|
|
26
|
+
listRef(node);
|
|
150
27
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const _a = this.props, { children } = _a, rest = __rest(_a, ["children"]);
|
|
154
|
-
return (React.createElement(VariableSizeList, Object.assign({}, rest, { ref: this.attachRefs, itemSize: this.getItemSize }), this.renderItem));
|
|
155
|
-
}
|
|
156
|
-
scrollToItem(index, align) {
|
|
157
|
-
const ref = this.listRef.current;
|
|
158
|
-
if (ref) {
|
|
159
|
-
ref.scrollToItem(index, align);
|
|
160
|
-
//
|
|
161
|
-
window.requestAnimationFrame(() => {
|
|
162
|
-
ref.scrollToItem(index, align);
|
|
163
|
-
});
|
|
28
|
+
else if (listRef && typeof listRef === 'object') {
|
|
29
|
+
listRef.current = node;
|
|
164
30
|
}
|
|
165
|
-
}
|
|
166
|
-
|
|
31
|
+
};
|
|
32
|
+
useImperativeHandle(ref, () => ({
|
|
33
|
+
scrollToItem: (index, align) => {
|
|
34
|
+
var _a;
|
|
35
|
+
(_a = listApi.current) === null || _a === void 0 ? void 0 : _a.scrollToRow({ index, align });
|
|
36
|
+
},
|
|
37
|
+
}), []);
|
|
38
|
+
return (React.createElement(List, { className: className, style: { height, width }, listRef: attachRefs, rowComponent: children, rowProps: { data: itemData }, rowCount: itemCount, rowHeight: rowHeight, overscanCount: overscanCount }));
|
|
39
|
+
});
|
|
167
40
|
export default DynamicSizeList;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AppTheme } from '../model';
|
|
2
|
-
|
|
2
|
+
export default _default;
|
|
3
|
+
declare function _default(theme: AppTheme): {
|
|
3
4
|
root: {
|
|
4
5
|
marginTop: string;
|
|
5
6
|
paddingBottom: string;
|
|
@@ -11,4 +12,3 @@ declare const _default: (theme: AppTheme) => {
|
|
|
11
12
|
marginRight: string;
|
|
12
13
|
};
|
|
13
14
|
};
|
|
14
|
-
export default _default;
|
|
@@ -87,7 +87,14 @@ const FileUploaderDialog = (props => {
|
|
|
87
87
|
"Please upload only:",
|
|
88
88
|
' ',
|
|
89
89
|
acceptText())))))));
|
|
90
|
-
return dialog ? (React.createElement(Dialog, { ref: fileRef, open: opened,
|
|
90
|
+
return dialog ? (React.createElement(Dialog, { ref: fileRef, open: opened,
|
|
91
|
+
// MUI 9 removed `disableEscapeKeyDown`; ignoring the `escapeKeyDown`
|
|
92
|
+
// close reason preserves the previous behaviour.
|
|
93
|
+
onClose: onClose && ((event, reason) => {
|
|
94
|
+
if (reason !== 'escapeKeyDown') {
|
|
95
|
+
onClose();
|
|
96
|
+
}
|
|
97
|
+
}), classes: {
|
|
91
98
|
paper: 'w-100'
|
|
92
99
|
} },
|
|
93
100
|
React.createElement("div", null,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface AutosizeInputProps extends React.ComponentPropsWithRef<"input"> {
|
|
3
|
+
placeholder?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Space kept free after the text, in px. Defaults to the advance width of a
|
|
6
|
+
* single space in the input's resolved font, so the caret always fits without
|
|
7
|
+
* the value scrolling inside the input.
|
|
8
|
+
*/
|
|
9
|
+
reserveWidth?: number;
|
|
10
|
+
/** MUI InputBase hands the DOM node over through this prop instead of `ref`. */
|
|
11
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
12
|
+
}
|
|
13
|
+
export declare const AutosizeInput: React.FC<AutosizeInputProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
13
|
+
/**
|
|
14
|
+
* The space is measured as the difference between these two strings instead of
|
|
15
|
+
* on its own: a span holding nothing but whitespace is not reliably measurable,
|
|
16
|
+
* and differencing also folds letter- and word-spacing into the result. Both
|
|
17
|
+
* samples use `M` so that a copied `text-transform` cannot change them.
|
|
18
|
+
*/
|
|
19
|
+
const SPACE_SAMPLE = "M M";
|
|
20
|
+
const NO_SPACE_SAMPLE = "MM";
|
|
21
|
+
/** Every property that can change the advance width of a string. */
|
|
22
|
+
const TYPOGRAPHY_PROPS = [
|
|
23
|
+
"font-family",
|
|
24
|
+
"font-size",
|
|
25
|
+
"font-weight",
|
|
26
|
+
"font-style",
|
|
27
|
+
"font-stretch",
|
|
28
|
+
"font-variant",
|
|
29
|
+
"font-feature-settings",
|
|
30
|
+
"font-variation-settings",
|
|
31
|
+
"font-kerning",
|
|
32
|
+
"font-optical-sizing",
|
|
33
|
+
"letter-spacing",
|
|
34
|
+
"word-spacing",
|
|
35
|
+
"text-transform"
|
|
36
|
+
];
|
|
37
|
+
const measureStyle = {
|
|
38
|
+
// Typography is copied from the input itself once mounted, `inherit` is just
|
|
39
|
+
// the starting approximation
|
|
40
|
+
font: "inherit",
|
|
41
|
+
letterSpacing: "inherit",
|
|
42
|
+
textTransform: "inherit",
|
|
43
|
+
position: "absolute",
|
|
44
|
+
top: 0,
|
|
45
|
+
left: 0,
|
|
46
|
+
visibility: "hidden",
|
|
47
|
+
pointerEvents: "none",
|
|
48
|
+
whiteSpace: "pre",
|
|
49
|
+
height: 0,
|
|
50
|
+
padding: 0,
|
|
51
|
+
border: "none",
|
|
52
|
+
margin: 0
|
|
53
|
+
};
|
|
54
|
+
/** Bumped when webfonts finish loading, which invalidates cached glyph metrics. */
|
|
55
|
+
let fontEpoch = 0;
|
|
56
|
+
const spaceWidthCache = new Map();
|
|
57
|
+
/**
|
|
58
|
+
* Copies the typography of `source` onto `targets` and returns a signature of
|
|
59
|
+
* the applied values, usable as a cache key for font dependent measurements.
|
|
60
|
+
*/
|
|
61
|
+
const copyTypography = (source, targets) => {
|
|
62
|
+
const computed = window.getComputedStyle(source);
|
|
63
|
+
return TYPOGRAPHY_PROPS.map(prop => {
|
|
64
|
+
const propValue = computed.getPropertyValue(prop);
|
|
65
|
+
targets.forEach(target => target.style.setProperty(prop, propValue));
|
|
66
|
+
return propValue;
|
|
67
|
+
}).join("|");
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Advance width of a single space under the current font settings, used as the
|
|
71
|
+
* trailing buffer instead of a hardcoded pixel constant so that it scales with
|
|
72
|
+
* the font size while staying as narrow as the typography allows.
|
|
73
|
+
*/
|
|
74
|
+
const getSpaceWidth = (probe, typographySignature) => {
|
|
75
|
+
const cacheKey = `${fontEpoch}|${typographySignature}`;
|
|
76
|
+
const cached = spaceWidthCache.get(cacheKey);
|
|
77
|
+
if (cached !== undefined)
|
|
78
|
+
return cached;
|
|
79
|
+
probe.textContent = SPACE_SAMPLE;
|
|
80
|
+
const withSpace = probe.getBoundingClientRect().width;
|
|
81
|
+
probe.textContent = NO_SPACE_SAMPLE;
|
|
82
|
+
const withoutSpace = probe.getBoundingClientRect().width;
|
|
83
|
+
probe.textContent = "";
|
|
84
|
+
const spaceWidth = Math.max(withSpace - withoutSpace, 0);
|
|
85
|
+
spaceWidthCache.set(cacheKey, spaceWidth);
|
|
86
|
+
return spaceWidth;
|
|
87
|
+
};
|
|
88
|
+
export const AutosizeInput = (_a) => {
|
|
89
|
+
var { placeholder, reserveWidth, inputRef, ref } = _a, props = __rest(_a, ["placeholder", "reserveWidth", "inputRef", "ref"]);
|
|
90
|
+
const [value, setValue] = useState(props.value || "");
|
|
91
|
+
const [width, setWidth] = useState(0);
|
|
92
|
+
const spanRef = useRef(null);
|
|
93
|
+
const probeRef = useRef(null);
|
|
94
|
+
const inputNode = useRef(null);
|
|
95
|
+
const setInputNode = useCallback((node) => {
|
|
96
|
+
inputNode.current = node;
|
|
97
|
+
[ref, inputRef].forEach(target => {
|
|
98
|
+
if (typeof target === "function")
|
|
99
|
+
target(node);
|
|
100
|
+
else if (target)
|
|
101
|
+
target.current = node;
|
|
102
|
+
});
|
|
103
|
+
}, [ref, inputRef]);
|
|
104
|
+
const measure = useCallback(() => {
|
|
105
|
+
const span = spanRef.current;
|
|
106
|
+
const probe = probeRef.current;
|
|
107
|
+
const input = inputNode.current;
|
|
108
|
+
if (!span || !probe || !input)
|
|
109
|
+
return;
|
|
110
|
+
// Measuring against the input's own computed typography keeps the two in
|
|
111
|
+
// sync even when the font is applied by a class rather than inherited
|
|
112
|
+
const typographySignature = copyTypography(input, [span, probe]);
|
|
113
|
+
// getBoundingClientRect keeps the sub pixel part that offsetWidth truncates
|
|
114
|
+
const textWidth = span.getBoundingClientRect().width;
|
|
115
|
+
const reserve = reserveWidth !== null && reserveWidth !== void 0 ? reserveWidth : getSpaceWidth(probe, typographySignature);
|
|
116
|
+
// Deliberately not rounded up: `Math.ceil` inflated the trailing gap by up
|
|
117
|
+
// to a full pixel, which is a fifth of a space at body font sizes. Layout is
|
|
118
|
+
// sub pixel accurate, so a fractional width keeps the gap exactly one space
|
|
119
|
+
setWidth(textWidth + reserve);
|
|
120
|
+
}, [reserveWidth]);
|
|
121
|
+
// Layout effect, so the width is correct in the same frame the value changes
|
|
122
|
+
useLayoutEffect(measure, [measure, value, placeholder]);
|
|
123
|
+
// Re-measure when the text changes size for reasons React cannot see: late
|
|
124
|
+
// loading webfonts, theme driven typography swaps, zoom, becoming visible
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (typeof ResizeObserver === "undefined" || !spanRef.current)
|
|
127
|
+
return;
|
|
128
|
+
const observer = new ResizeObserver(measure);
|
|
129
|
+
observer.observe(spanRef.current);
|
|
130
|
+
return () => observer.disconnect();
|
|
131
|
+
}, [measure]);
|
|
132
|
+
// A webfont replacing the fallback face keeps the same computed values, so the
|
|
133
|
+
// cached glyph metrics have to be invalidated explicitly
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
const fonts = document.fonts;
|
|
136
|
+
if (!fonts)
|
|
137
|
+
return;
|
|
138
|
+
const onLoadingDone = () => {
|
|
139
|
+
fontEpoch += 1;
|
|
140
|
+
measure();
|
|
141
|
+
};
|
|
142
|
+
fonts.addEventListener("loadingdone", onLoadingDone);
|
|
143
|
+
return () => fonts.removeEventListener("loadingdone", onLoadingDone);
|
|
144
|
+
}, [measure]);
|
|
145
|
+
const handleChange = (e) => {
|
|
146
|
+
setValue(e.target.value);
|
|
147
|
+
if (props.onChange)
|
|
148
|
+
props.onChange(e);
|
|
149
|
+
};
|
|
150
|
+
return (React.createElement("div", { style: { display: "inline-block", position: "relative" } },
|
|
151
|
+
React.createElement("span", { ref: spanRef, style: measureStyle, "aria-hidden": true }, value || placeholder || ""),
|
|
152
|
+
React.createElement("span", { ref: probeRef, style: measureStyle, "aria-hidden": true }),
|
|
153
|
+
React.createElement("input", Object.assign({}, props, { ref: setInputNode, type: "text", value: value, onChange: handleChange, placeholder: placeholder, style: Object.assign(Object.assign({}, props.style), { letterSpacing: "inherit", textTransform: "inherit", width: `${width}px`, boxSizing: "border-box",
|
|
154
|
+
// CRITICAL: Padding and borders must be 0, the measuring span has none either
|
|
155
|
+
paddingLeft: 0, paddingRight: 0, borderLeft: "none", borderRight: "none", margin: 0, textOverflow: "unset" }) }))));
|
|
156
|
+
};
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* */
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { CheckboxFieldProps, FieldInputProps } from '../model';
|
|
6
|
-
import { CheckboxProps } from '@mui/material
|
|
7
|
-
|
|
6
|
+
import { CheckboxProps } from '@mui/material';
|
|
7
|
+
declare const StyledCheckboxBase: (props: any) => React.JSX.Element;
|
|
8
|
+
export declare const StyledCheckbox: typeof StyledCheckboxBase;
|
|
8
9
|
export declare function CheckboxField<IP extends FieldInputProps>({ input, color, disabled, stringValue, className, uncheckedClass, onChangeHandler, stopPropagation, ...rest }: CheckboxFieldProps<IP> & CheckboxProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -16,7 +16,7 @@ import { useStyles } from 'tss-react/mui';
|
|
|
16
16
|
export function ColoredCheckBox({ input, label, color, className, disabled }) {
|
|
17
17
|
const { cx } = useStyles();
|
|
18
18
|
const theme = useAppTheme();
|
|
19
|
-
const inputRef = useRef();
|
|
19
|
+
const inputRef = useRef(null);
|
|
20
20
|
const onClick = useCallback(() => {
|
|
21
21
|
inputRef.current.click();
|
|
22
22
|
}, [inputRef.current]);
|
|
@@ -34,7 +34,10 @@ export function ColoredCheckBox({ input, label, color, className, disabled }) {
|
|
|
34
34
|
backgroundColor: input.value ? `${color}` : alpha(`${color}`, 0.1),
|
|
35
35
|
color: theme => theme.palette.getContrastText(`${color}`)
|
|
36
36
|
} }, input.value && React.createElement(FontAwesomeIcon, { fixedWidth: true, icon: "check" })),
|
|
37
|
-
label && React.createElement(Typography, { variant: "caption",
|
|
37
|
+
label && React.createElement(Typography, { variant: "caption", sx: {
|
|
38
|
+
// MUI 9 no longer accepts system props such as `fontWeight`
|
|
39
|
+
// directly on Typography.
|
|
40
|
+
fontWeight: 400,
|
|
38
41
|
marginLeft: 1,
|
|
39
42
|
textDecoration: input.value ? 'line-through' : 'unset',
|
|
40
43
|
color: theme => (input.value ? theme.palette.text.disabled : 'unset'),
|
|
@@ -163,44 +163,43 @@ function EditInPlaceDateTimeField({ type, formatDate, formatTime, formatDateTime
|
|
|
163
163
|
[classes.inlineContainer]: inline,
|
|
164
164
|
'pointer-events-none': disabled
|
|
165
165
|
}) },
|
|
166
|
-
React.createElement("div", { id: input.name, className: "w-100" },
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
React.createElement("div", { id: input.name, className: "w-100" }, React.createElement(DateTimeField, { type: type, toolbarTitle: label, open: pickerOpened, value: dateValue, onChange: onChange, onClose: onClose, slots: {
|
|
167
|
+
field: EditInPlaceFieldBase
|
|
168
|
+
}, slotProps: {
|
|
169
|
+
field: {
|
|
170
|
+
name: input.name,
|
|
171
|
+
value: textValue,
|
|
172
|
+
variant,
|
|
173
|
+
error,
|
|
174
|
+
invalid,
|
|
175
|
+
inline,
|
|
176
|
+
label,
|
|
177
|
+
warning,
|
|
178
|
+
fieldClasses,
|
|
179
|
+
rightAligned,
|
|
180
|
+
disabled,
|
|
181
|
+
labelAdornment,
|
|
182
|
+
placeholder,
|
|
183
|
+
shrink: Boolean(label || input.value),
|
|
184
|
+
editIcon: React.createElement(IconButton, { tabIndex: -1, onClick: openPicker, sx: variant === 'outlined' ? {
|
|
185
|
+
marginRight: -1
|
|
186
|
+
} : null, classes: {
|
|
187
|
+
root: cx(fieldClasses.text, inline && classes.inlinePickerButton)
|
|
188
|
+
} }, type === 'time'
|
|
189
|
+
? React.createElement(QueryBuilder, { fontSize: "inherit", color: "inherit" })
|
|
190
|
+
: React.createElement(DateRange, { color: "inherit", fontSize: "inherit" })),
|
|
191
|
+
InputProps: {
|
|
192
|
+
type: 'text',
|
|
193
|
+
onFocus: input.onFocus,
|
|
194
|
+
inputRef: inputNode,
|
|
172
195
|
value: textValue,
|
|
173
|
-
|
|
174
|
-
error,
|
|
175
|
-
invalid,
|
|
176
|
-
inline,
|
|
177
|
-
label,
|
|
178
|
-
warning,
|
|
179
|
-
fieldClasses,
|
|
180
|
-
rightAligned,
|
|
196
|
+
onKeyPress,
|
|
181
197
|
disabled,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
editIcon: React.createElement(IconButton, { tabIndex: -1, onClick: openPicker, sx: variant === 'outlined' ? {
|
|
186
|
-
marginRight: -1
|
|
187
|
-
} : null, classes: {
|
|
188
|
-
root: cx(fieldClasses.text, inline && classes.inlinePickerButton)
|
|
189
|
-
} }, type === 'time'
|
|
190
|
-
? React.createElement(QueryBuilder, { fontSize: "inherit", color: "inherit" })
|
|
191
|
-
: React.createElement(DateRange, { color: "inherit", fontSize: "inherit" })),
|
|
192
|
-
InputProps: {
|
|
193
|
-
type: 'text',
|
|
194
|
-
onFocus: input.onFocus,
|
|
195
|
-
inputRef: inputNode,
|
|
196
|
-
value: textValue,
|
|
197
|
-
onKeyPress,
|
|
198
|
-
disabled,
|
|
199
|
-
onBlur,
|
|
200
|
-
onKeyDown: onEnterPress,
|
|
201
|
-
onChange: onInputChange
|
|
202
|
-
}
|
|
198
|
+
onBlur,
|
|
199
|
+
onKeyDown: onEnterPress,
|
|
200
|
+
onChange: onInputChange
|
|
203
201
|
}
|
|
204
|
-
}
|
|
202
|
+
}
|
|
203
|
+
} }))));
|
|
205
204
|
}
|
|
206
205
|
export default EditInPlaceDateTimeField;
|
|
@@ -41,14 +41,13 @@ function EditInPlaceField({ inputRef, input, label, maxLength, disabled, min, ma
|
|
|
41
41
|
return (React.createElement("div", { id: input.name, className: cx(className, 'outline-none', {
|
|
42
42
|
[classes.rightAligned]: rightAligned,
|
|
43
43
|
[classes.inlineContainer]: inline
|
|
44
|
-
}) },
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
type }, InputProps.inputProps || {}), value: inputValue, onChange: v => (type === 'number' && max && Number(v) > Number(max) ? null : input.onChange(v)) }, InputProps) })));
|
|
44
|
+
}) }, React.createElement(EditInPlaceFieldBase, { name: input.name, value: inputValue, variant: variant, error: error, invalid: invalid, inline: inline, label: label, warning: warning, fieldClasses: fieldClasses, endAdornmentClass: classes.endAdornment, rightAligned: rightAligned, shrink: Boolean(label || input.value), disabled: disabled, labelAdornment: labelAdornment, placeholder: placeholder, hideArrows: ['percentage', 'number'].includes(type), editIcon: editIcon === undefined ? React.createElement(Edit, { fontSize: inline ? 'inherit' : undefined }) : editIcon, InputProps: Object.assign({ multiline,
|
|
45
|
+
onKeyPress,
|
|
46
|
+
onBlur, onFocus: input.onFocus, maxRows: truncateLines, inputProps: Object.assign({ ref: inputRef, maxLength,
|
|
47
|
+
step,
|
|
48
|
+
min,
|
|
49
|
+
max,
|
|
50
|
+
onKeyDown,
|
|
51
|
+
type }, InputProps.inputProps || {}), value: inputValue, onChange: v => (type === 'number' && max && Number(v) > Number(max) ? null : input.onChange(v)) }, InputProps) })));
|
|
53
52
|
}
|
|
54
53
|
export default EditInPlaceField;
|