@kwiz/fluentui 1.0.73 → 1.0.75
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/.github/workflows/npm-publish.yml +24 -24
- package/LICENSE +21 -21
- package/README.md +53 -53
- package/dist/@types/forwardRef.d.ts +0 -0
- package/dist/@types/forwardRef.js +1 -0
- package/dist/@types/forwardRef.js.map +1 -0
- package/dist/controls/error-boundary copy.d.ts +23 -0
- package/dist/controls/error-boundary copy.js +33 -0
- package/dist/controls/error-boundary copy.js.map +1 -0
- package/dist/controls/menu.js +2 -2
- package/dist/controls/menu.js.map +1 -1
- package/dist/controls/search.js +19 -11
- package/dist/controls/search.js.map +1 -1
- package/dist/controls/svg.js +21 -21
- package/dist/controls/svg.js.map +1 -1
- package/dist/helpers/common.d.ts +4 -0
- package/dist/helpers/common.js +2 -0
- package/dist/helpers/common.js.map +1 -0
- package/dist/helpers/context.d.ts +26 -0
- package/dist/helpers/context.js +15 -0
- package/dist/helpers/context.js.map +1 -0
- package/dist/helpers/drag-drop/exports.d.ts +12 -0
- package/dist/helpers/drag-drop/exports.js +3 -0
- package/dist/helpers/drag-drop/exports.js.map +1 -0
- package/dist/helpers/exports.d.ts +7 -0
- package/dist/helpers/exports.js +8 -0
- package/dist/helpers/exports.js.map +1 -0
- package/dist/helpers/use-editable-control.d.ts +1 -1
- package/dist/helpers/use-editable-control.js.map +1 -1
- package/package.json +85 -84
- package/src/_modules/config.ts +9 -9
- package/src/_modules/constants.ts +3 -3
- package/src/controls/ColorPickerDialog.tsx +83 -83
- package/src/controls/accordion.tsx +62 -62
- package/src/controls/button.tsx +180 -180
- package/src/controls/canvas/CustomEventTargetBase.ts +32 -32
- package/src/controls/canvas/DrawPad.tsx +296 -296
- package/src/controls/canvas/DrawPadManager.ts +694 -694
- package/src/controls/canvas/bezier.ts +109 -109
- package/src/controls/canvas/point.ts +44 -44
- package/src/controls/card-list.tsx +31 -31
- package/src/controls/card.tsx +77 -77
- package/src/controls/centered.tsx +14 -14
- package/src/controls/date.tsx +87 -87
- package/src/controls/diagram-picker.tsx +96 -96
- package/src/controls/divider.tsx +15 -15
- package/src/controls/dropdown.tsx +66 -66
- package/src/controls/error-boundary.tsx +41 -41
- package/src/controls/field-editor.tsx +42 -42
- package/src/controls/file-upload.tsx +155 -155
- package/src/controls/horizontal.tsx +48 -48
- package/src/controls/html-editor/editor.tsx +182 -182
- package/src/controls/index.ts +33 -33
- package/src/controls/input.tsx +160 -160
- package/src/controls/kwizoverflow.tsx +106 -106
- package/src/controls/list.tsx +119 -119
- package/src/controls/loading.tsx +10 -10
- package/src/controls/menu.tsx +173 -173
- package/src/controls/merge-text.tsx +126 -126
- package/src/controls/please-wait.tsx +32 -32
- package/src/controls/progress-bar.tsx +109 -109
- package/src/controls/prompt.tsx +121 -121
- package/src/controls/qrcode.tsx +36 -36
- package/src/controls/search.tsx +71 -61
- package/src/controls/section.tsx +133 -133
- package/src/controls/svg.tsx +138 -138
- package/src/controls/toolbar.tsx +46 -46
- package/src/controls/vertical-content.tsx +49 -49
- package/src/controls/vertical.tsx +42 -42
- package/src/helpers/block-nav.tsx +88 -88
- package/src/helpers/context-const.ts +29 -29
- package/src/helpers/context-export.tsx +77 -77
- package/src/helpers/context-internal.ts +13 -13
- package/src/helpers/drag-drop/drag-drop-container.tsx +53 -53
- package/src/helpers/drag-drop/drag-drop-context-internal.tsx +9 -9
- package/src/helpers/drag-drop/drag-drop-context.tsx +61 -61
- package/src/helpers/drag-drop/drag-drop.types.ts +21 -21
- package/src/helpers/drag-drop/index.ts +12 -12
- package/src/helpers/drag-drop/readme.md +75 -75
- package/src/helpers/drag-drop/use-draggable.ts +47 -47
- package/src/helpers/drag-drop/use-droppable.ts +38 -38
- package/src/helpers/forwardRef.ts +7 -7
- package/src/helpers/hooks-events.ts +149 -149
- package/src/helpers/hooks.tsx +141 -141
- package/src/helpers/index.ts +8 -8
- package/src/helpers/use-alerts.tsx +74 -74
- package/src/helpers/use-editable-control.tsx +37 -37
- package/src/helpers/use-toast.tsx +29 -29
- package/src/index.ts +2 -2
- package/src/styles/index.ts +1 -1
- package/src/styles/styles.ts +104 -104
- package/src/styles/theme.ts +90 -90
package/src/controls/date.tsx
CHANGED
@@ -1,88 +1,88 @@
|
|
1
|
-
import { DatePicker, DatePickerProps } from '@fluentui/react-datepicker-compat';
|
2
|
-
import { TimePicker, TimePickerProps } from '@fluentui/react-timepicker-compat';
|
3
|
-
|
4
|
-
import { CalendarCancelRegular } from '@fluentui/react-icons';
|
5
|
-
import { isDate } from '@kwiz/common';
|
6
|
-
import * as React from 'react';
|
7
|
-
import { useKWIZFluentContext } from '../helpers/context-internal';
|
8
|
-
import { useStateEX } from '../helpers';
|
9
|
-
import { Horizontal } from './horizontal';
|
10
|
-
|
11
|
-
interface IProps {
|
12
|
-
onDateChange: (newDateObject: Date) => void;
|
13
|
-
value: Date;
|
14
|
-
showTime?: boolean;
|
15
|
-
datePickerProps?: DatePickerProps;
|
16
|
-
timePickerProps?: TimePickerProps;
|
17
|
-
/** don't allow to clear the value */
|
18
|
-
required?: boolean;
|
19
|
-
}
|
20
|
-
export const DatePickerEx: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
21
|
-
const ctx = useKWIZFluentContext();
|
22
|
-
|
23
|
-
//time value will always have a value even when clearing the date
|
24
|
-
const [timeValue, setTimeValue] = useStateEX<Date>(isDate(props.value) ? props.value : new Date());
|
25
|
-
const { showClear, dateValue } = React.useMemo(() => {
|
26
|
-
const showClear = !props.required && isDate(props.value);
|
27
|
-
const dateValue = props.value;
|
28
|
-
return { showClear, dateValue };
|
29
|
-
}, [props.value]);
|
30
|
-
|
31
|
-
function reset() {
|
32
|
-
props.onDateChange(null);
|
33
|
-
}
|
34
|
-
|
35
|
-
const changeDateHandler = React.useCallback((newDateValue: Date): void => {
|
36
|
-
const newDate = new Date(newDateValue);
|
37
|
-
// Use the old time values.
|
38
|
-
newDate.setHours(
|
39
|
-
timeValue ? timeValue.getHours() : 0,
|
40
|
-
timeValue ? timeValue.getMinutes() : 0, 0, 0
|
41
|
-
);
|
42
|
-
props.onDateChange(newDate);
|
43
|
-
}, [timeValue, props.onDateChange]);
|
44
|
-
|
45
|
-
const changeTimeHandler = React.useCallback((newTimeValue: Date): void => {
|
46
|
-
//update our state
|
47
|
-
setTimeValue(newTimeValue);
|
48
|
-
// Use the old date value.
|
49
|
-
const newDate = isDate(dateValue) ? new Date(dateValue) : new Date();
|
50
|
-
newDate.setHours(
|
51
|
-
newTimeValue.getHours(),
|
52
|
-
newTimeValue.getMinutes(), 0, 0
|
53
|
-
);
|
54
|
-
props.onDateChange(newDate);
|
55
|
-
}, [dateValue]);
|
56
|
-
|
57
|
-
const DatePickerControl = <DatePicker
|
58
|
-
{...(props.datePickerProps || {})}
|
59
|
-
appearance={ctx.inputAppearance}
|
60
|
-
mountNode={ctx.mountNode}
|
61
|
-
value={isDate(dateValue) ? dateValue : null}
|
62
|
-
onSelectDate={(newDate) => {
|
63
|
-
changeDateHandler(newDate);
|
64
|
-
}}
|
65
|
-
contentBefore={showClear && <CalendarCancelRegular title='Clear' onClick={() => reset()} />}
|
66
|
-
/>
|
67
|
-
|
68
|
-
const TimePickerControl = <TimePicker
|
69
|
-
appearance={ctx.inputAppearance}
|
70
|
-
mountNode={ctx.mountNode}
|
71
|
-
{...props.timePickerProps}
|
72
|
-
//only show time value when there is a selected date. timeValue will never be null.
|
73
|
-
value={isDate(dateValue) ? timeValue.toLocaleTimeString("en", { hour: "2-digit", minute: "2-digit", hour12: true }) : ""}
|
74
|
-
onTimeChange={(e, date) => {
|
75
|
-
const newDate = date.selectedTime;
|
76
|
-
changeTimeHandler(newDate);
|
77
|
-
}}
|
78
|
-
/>
|
79
|
-
|
80
|
-
return (
|
81
|
-
props.showTime
|
82
|
-
? <Horizontal>
|
83
|
-
{DatePickerControl}
|
84
|
-
{TimePickerControl}
|
85
|
-
</Horizontal>
|
86
|
-
: DatePickerControl
|
87
|
-
);
|
1
|
+
import { DatePicker, DatePickerProps } from '@fluentui/react-datepicker-compat';
|
2
|
+
import { TimePicker, TimePickerProps } from '@fluentui/react-timepicker-compat';
|
3
|
+
|
4
|
+
import { CalendarCancelRegular } from '@fluentui/react-icons';
|
5
|
+
import { isDate } from '@kwiz/common';
|
6
|
+
import * as React from 'react';
|
7
|
+
import { useKWIZFluentContext } from '../helpers/context-internal';
|
8
|
+
import { useStateEX } from '../helpers';
|
9
|
+
import { Horizontal } from './horizontal';
|
10
|
+
|
11
|
+
interface IProps {
|
12
|
+
onDateChange: (newDateObject: Date) => void;
|
13
|
+
value: Date;
|
14
|
+
showTime?: boolean;
|
15
|
+
datePickerProps?: DatePickerProps;
|
16
|
+
timePickerProps?: TimePickerProps;
|
17
|
+
/** don't allow to clear the value */
|
18
|
+
required?: boolean;
|
19
|
+
}
|
20
|
+
export const DatePickerEx: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
21
|
+
const ctx = useKWIZFluentContext();
|
22
|
+
|
23
|
+
//time value will always have a value even when clearing the date
|
24
|
+
const [timeValue, setTimeValue] = useStateEX<Date>(isDate(props.value) ? props.value : new Date());
|
25
|
+
const { showClear, dateValue } = React.useMemo(() => {
|
26
|
+
const showClear = !props.required && isDate(props.value);
|
27
|
+
const dateValue = props.value;
|
28
|
+
return { showClear, dateValue };
|
29
|
+
}, [props.value]);
|
30
|
+
|
31
|
+
function reset() {
|
32
|
+
props.onDateChange(null);
|
33
|
+
}
|
34
|
+
|
35
|
+
const changeDateHandler = React.useCallback((newDateValue: Date): void => {
|
36
|
+
const newDate = new Date(newDateValue);
|
37
|
+
// Use the old time values.
|
38
|
+
newDate.setHours(
|
39
|
+
timeValue ? timeValue.getHours() : 0,
|
40
|
+
timeValue ? timeValue.getMinutes() : 0, 0, 0
|
41
|
+
);
|
42
|
+
props.onDateChange(newDate);
|
43
|
+
}, [timeValue, props.onDateChange]);
|
44
|
+
|
45
|
+
const changeTimeHandler = React.useCallback((newTimeValue: Date): void => {
|
46
|
+
//update our state
|
47
|
+
setTimeValue(newTimeValue);
|
48
|
+
// Use the old date value.
|
49
|
+
const newDate = isDate(dateValue) ? new Date(dateValue) : new Date();
|
50
|
+
newDate.setHours(
|
51
|
+
newTimeValue.getHours(),
|
52
|
+
newTimeValue.getMinutes(), 0, 0
|
53
|
+
);
|
54
|
+
props.onDateChange(newDate);
|
55
|
+
}, [dateValue]);
|
56
|
+
|
57
|
+
const DatePickerControl = <DatePicker
|
58
|
+
{...(props.datePickerProps || {})}
|
59
|
+
appearance={ctx.inputAppearance}
|
60
|
+
mountNode={ctx.mountNode}
|
61
|
+
value={isDate(dateValue) ? dateValue : null}
|
62
|
+
onSelectDate={(newDate) => {
|
63
|
+
changeDateHandler(newDate);
|
64
|
+
}}
|
65
|
+
contentBefore={showClear && <CalendarCancelRegular title='Clear' onClick={() => reset()} />}
|
66
|
+
/>
|
67
|
+
|
68
|
+
const TimePickerControl = <TimePicker
|
69
|
+
appearance={ctx.inputAppearance}
|
70
|
+
mountNode={ctx.mountNode}
|
71
|
+
{...props.timePickerProps}
|
72
|
+
//only show time value when there is a selected date. timeValue will never be null.
|
73
|
+
value={isDate(dateValue) ? timeValue.toLocaleTimeString("en", { hour: "2-digit", minute: "2-digit", hour12: true }) : ""}
|
74
|
+
onTimeChange={(e, date) => {
|
75
|
+
const newDate = date.selectedTime;
|
76
|
+
changeTimeHandler(newDate);
|
77
|
+
}}
|
78
|
+
/>
|
79
|
+
|
80
|
+
return (
|
81
|
+
props.showTime
|
82
|
+
? <Horizontal>
|
83
|
+
{DatePickerControl}
|
84
|
+
{TimePickerControl}
|
85
|
+
</Horizontal>
|
86
|
+
: DatePickerControl
|
87
|
+
);
|
88
88
|
}
|
@@ -1,97 +1,97 @@
|
|
1
|
-
import { Dialog, DialogBody, DialogContent, DialogSurface, DialogTitle, DialogTrigger, makeStyles, shorthands, Switch, tokens } from '@fluentui/react-components';
|
2
|
-
import { ImageSparkleRegular } from '@fluentui/react-icons';
|
3
|
-
import { DiagramOptions, stockUrl } from '@kwiz/common';
|
4
|
-
import React from 'react';
|
5
|
-
import { useKWIZFluentContext } from '../helpers/context-internal';
|
6
|
-
import { useStateEX } from '../helpers';
|
7
|
-
import { ButtonEXPrimarySubtle } from './button';
|
8
|
-
import { Horizontal } from './horizontal';
|
9
|
-
import { Section } from './section';
|
10
|
-
|
11
|
-
const useStyles = makeStyles({
|
12
|
-
dialog: {
|
13
|
-
maxWidth: '70vw',
|
14
|
-
width: '70vw',
|
15
|
-
},
|
16
|
-
dialogBody: {
|
17
|
-
maxHeight: '60vh',
|
18
|
-
},
|
19
|
-
diagramWrapper: {
|
20
|
-
justifyContent: "center",
|
21
|
-
alignContent: "center"
|
22
|
-
},
|
23
|
-
diagram: {
|
24
|
-
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
25
|
-
padding: tokens.spacingHorizontalS,
|
26
|
-
"&:hover": {
|
27
|
-
...shorthands.borderColor(tokens.colorBrandBackground),
|
28
|
-
},
|
29
|
-
"&>img": {
|
30
|
-
width: "180px"
|
31
|
-
},
|
32
|
-
},
|
33
|
-
});
|
34
|
-
|
35
|
-
interface iProps {
|
36
|
-
onSelect?: (diagram: { url: string; name: string; }) => void;
|
37
|
-
onSelectBase64?: (diagram: string) => void;
|
38
|
-
trigger?: JSX.Element;
|
39
|
-
hiRes?: boolean;
|
40
|
-
onlyTransparent?: boolean;
|
41
|
-
}
|
42
|
-
export const DiagramPicker = React.forwardRef<HTMLDivElement, (React.PropsWithChildren<iProps>)>((props, ref) => {
|
43
|
-
const ctx = useKWIZFluentContext();
|
44
|
-
const classes = useStyles();
|
45
|
-
const [isOpen, setIsOpen] = useStateEX(false);
|
46
|
-
const [hiRes, setHiRes] = useStateEX(props.hiRes);
|
47
|
-
let options = (hiRes ? DiagramOptions.hiRes : DiagramOptions.options);
|
48
|
-
if (props.onlyTransparent) options = options.filter(o => o.name.endsWith(', transparent'));
|
49
|
-
return (
|
50
|
-
<Dialog open={isOpen} onOpenChange={(e, data) => {
|
51
|
-
setIsOpen(data.open);
|
52
|
-
}}>
|
53
|
-
<DialogTrigger disableButtonEnhancement>
|
54
|
-
{props.trigger || <ButtonEXPrimarySubtle icon={<ImageSparkleRegular />} title='Open gallery' showTitleWithIcon dontCenterText />}
|
55
|
-
</DialogTrigger>
|
56
|
-
<DialogSurface mountNode={ctx.mountNode} className={classes.dialog}>
|
57
|
-
<DialogBody className={classes.dialogBody}>
|
58
|
-
<DialogTitle>Choose a diagram</DialogTitle>
|
59
|
-
<DialogContent>
|
60
|
-
<Switch checked={hiRes === true}
|
61
|
-
onChange={(e, data) => {
|
62
|
-
setHiRes(data.checked === true);
|
63
|
-
}}
|
64
|
-
label="High resolution diagrams"
|
65
|
-
/>
|
66
|
-
<Horizontal main wrap css={[classes.diagramWrapper]}>
|
67
|
-
{options
|
68
|
-
.map(diagram => <Section key={diagram.name} css={[classes.diagram]}
|
69
|
-
title={diagram.name}
|
70
|
-
onClick={async () => {
|
71
|
-
const fullUrl = `${stockUrl}/${diagram.url}`;
|
72
|
-
props.onSelect?.({ name: diagram.name, url: fullUrl });
|
73
|
-
if (props.onSelectBase64) {
|
74
|
-
const result = await fetch(fullUrl);
|
75
|
-
const blob = await result.blob();
|
76
|
-
const reader = new FileReader();
|
77
|
-
reader.onload = function () {
|
78
|
-
props.onSelectBase64?.(reader.result as string);
|
79
|
-
};
|
80
|
-
reader.readAsDataURL(blob);
|
81
|
-
}
|
82
|
-
setIsOpen(false);
|
83
|
-
}}>
|
84
|
-
<img src={`${stockUrl}/${diagram.url}`} />
|
85
|
-
</Section>)}
|
86
|
-
</Horizontal>
|
87
|
-
</DialogContent>
|
88
|
-
{/* <DialogActions>
|
89
|
-
<DialogTrigger disableButtonEnhancement>
|
90
|
-
<Button appearance="secondary">Cancel</Button>
|
91
|
-
</DialogTrigger>
|
92
|
-
<Button appearance="primary">Save</Button>
|
93
|
-
</DialogActions> */}
|
94
|
-
</DialogBody>
|
95
|
-
</DialogSurface>
|
96
|
-
</Dialog>);
|
1
|
+
import { Dialog, DialogBody, DialogContent, DialogSurface, DialogTitle, DialogTrigger, makeStyles, shorthands, Switch, tokens } from '@fluentui/react-components';
|
2
|
+
import { ImageSparkleRegular } from '@fluentui/react-icons';
|
3
|
+
import { DiagramOptions, stockUrl } from '@kwiz/common';
|
4
|
+
import React from 'react';
|
5
|
+
import { useKWIZFluentContext } from '../helpers/context-internal';
|
6
|
+
import { useStateEX } from '../helpers';
|
7
|
+
import { ButtonEXPrimarySubtle } from './button';
|
8
|
+
import { Horizontal } from './horizontal';
|
9
|
+
import { Section } from './section';
|
10
|
+
|
11
|
+
const useStyles = makeStyles({
|
12
|
+
dialog: {
|
13
|
+
maxWidth: '70vw',
|
14
|
+
width: '70vw',
|
15
|
+
},
|
16
|
+
dialogBody: {
|
17
|
+
maxHeight: '60vh',
|
18
|
+
},
|
19
|
+
diagramWrapper: {
|
20
|
+
justifyContent: "center",
|
21
|
+
alignContent: "center"
|
22
|
+
},
|
23
|
+
diagram: {
|
24
|
+
border: `1px solid ${tokens.colorNeutralStroke1}`,
|
25
|
+
padding: tokens.spacingHorizontalS,
|
26
|
+
"&:hover": {
|
27
|
+
...shorthands.borderColor(tokens.colorBrandBackground),
|
28
|
+
},
|
29
|
+
"&>img": {
|
30
|
+
width: "180px"
|
31
|
+
},
|
32
|
+
},
|
33
|
+
});
|
34
|
+
|
35
|
+
interface iProps {
|
36
|
+
onSelect?: (diagram: { url: string; name: string; }) => void;
|
37
|
+
onSelectBase64?: (diagram: string) => void;
|
38
|
+
trigger?: JSX.Element;
|
39
|
+
hiRes?: boolean;
|
40
|
+
onlyTransparent?: boolean;
|
41
|
+
}
|
42
|
+
export const DiagramPicker = React.forwardRef<HTMLDivElement, (React.PropsWithChildren<iProps>)>((props, ref) => {
|
43
|
+
const ctx = useKWIZFluentContext();
|
44
|
+
const classes = useStyles();
|
45
|
+
const [isOpen, setIsOpen] = useStateEX(false);
|
46
|
+
const [hiRes, setHiRes] = useStateEX(props.hiRes);
|
47
|
+
let options = (hiRes ? DiagramOptions.hiRes : DiagramOptions.options);
|
48
|
+
if (props.onlyTransparent) options = options.filter(o => o.name.endsWith(', transparent'));
|
49
|
+
return (
|
50
|
+
<Dialog open={isOpen} onOpenChange={(e, data) => {
|
51
|
+
setIsOpen(data.open);
|
52
|
+
}}>
|
53
|
+
<DialogTrigger disableButtonEnhancement>
|
54
|
+
{props.trigger || <ButtonEXPrimarySubtle icon={<ImageSparkleRegular />} title='Open gallery' showTitleWithIcon dontCenterText />}
|
55
|
+
</DialogTrigger>
|
56
|
+
<DialogSurface mountNode={ctx.mountNode} className={classes.dialog}>
|
57
|
+
<DialogBody className={classes.dialogBody}>
|
58
|
+
<DialogTitle>Choose a diagram</DialogTitle>
|
59
|
+
<DialogContent>
|
60
|
+
<Switch checked={hiRes === true}
|
61
|
+
onChange={(e, data) => {
|
62
|
+
setHiRes(data.checked === true);
|
63
|
+
}}
|
64
|
+
label="High resolution diagrams"
|
65
|
+
/>
|
66
|
+
<Horizontal main wrap css={[classes.diagramWrapper]}>
|
67
|
+
{options
|
68
|
+
.map(diagram => <Section key={diagram.name} css={[classes.diagram]}
|
69
|
+
title={diagram.name}
|
70
|
+
onClick={async () => {
|
71
|
+
const fullUrl = `${stockUrl}/${diagram.url}`;
|
72
|
+
props.onSelect?.({ name: diagram.name, url: fullUrl });
|
73
|
+
if (props.onSelectBase64) {
|
74
|
+
const result = await fetch(fullUrl);
|
75
|
+
const blob = await result.blob();
|
76
|
+
const reader = new FileReader();
|
77
|
+
reader.onload = function () {
|
78
|
+
props.onSelectBase64?.(reader.result as string);
|
79
|
+
};
|
80
|
+
reader.readAsDataURL(blob);
|
81
|
+
}
|
82
|
+
setIsOpen(false);
|
83
|
+
}}>
|
84
|
+
<img src={`${stockUrl}/${diagram.url}`} />
|
85
|
+
</Section>)}
|
86
|
+
</Horizontal>
|
87
|
+
</DialogContent>
|
88
|
+
{/* <DialogActions>
|
89
|
+
<DialogTrigger disableButtonEnhancement>
|
90
|
+
<Button appearance="secondary">Cancel</Button>
|
91
|
+
</DialogTrigger>
|
92
|
+
<Button appearance="primary">Save</Button>
|
93
|
+
</DialogActions> */}
|
94
|
+
</DialogBody>
|
95
|
+
</DialogSurface>
|
96
|
+
</Dialog>);
|
97
97
|
});
|
package/src/controls/divider.tsx
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
import { Divider, DividerProps, makeStyles, mergeClasses } from '@fluentui/react-components';
|
2
|
-
import React from 'react';
|
3
|
-
|
4
|
-
const useStyles = makeStyles({
|
5
|
-
separator: {
|
6
|
-
flexGrow: 0
|
7
|
-
}
|
8
|
-
});
|
9
|
-
interface IProps extends DividerProps {
|
10
|
-
}
|
11
|
-
export const DividerEX = React.forwardRef<HTMLDivElement, (React.PropsWithChildren<IProps>)>((props, ref) => {
|
12
|
-
const cssNames = useStyles();
|
13
|
-
return (
|
14
|
-
<Divider ref={ref} {...props} className={mergeClasses(cssNames.separator, props.className)} />
|
15
|
-
);
|
1
|
+
import { Divider, DividerProps, makeStyles, mergeClasses } from '@fluentui/react-components';
|
2
|
+
import React from 'react';
|
3
|
+
|
4
|
+
const useStyles = makeStyles({
|
5
|
+
separator: {
|
6
|
+
flexGrow: 0
|
7
|
+
}
|
8
|
+
});
|
9
|
+
interface IProps extends DividerProps {
|
10
|
+
}
|
11
|
+
export const DividerEX = React.forwardRef<HTMLDivElement, (React.PropsWithChildren<IProps>)>((props, ref) => {
|
12
|
+
const cssNames = useStyles();
|
13
|
+
return (
|
14
|
+
<Divider ref={ref} {...props} className={mergeClasses(cssNames.separator, props.className)} />
|
15
|
+
);
|
16
16
|
});
|
@@ -1,67 +1,67 @@
|
|
1
|
-
import { Dropdown, DropdownProps, makeStyles, mergeClasses, Option } from '@fluentui/react-components';
|
2
|
-
import { filterEmptyEntries, firstOrNull, isNullOrUndefined } from '@kwiz/common';
|
3
|
-
import React from 'react';
|
4
|
-
import { GetLogger } from '../_modules/config';
|
5
|
-
import { useKWIZFluentContext } from '../helpers/context-internal';
|
6
|
-
|
7
|
-
const logger = GetLogger("DropdownEX");
|
8
|
-
|
9
|
-
const useStyles = makeStyles({
|
10
|
-
root: {
|
11
|
-
minWidth: "auto"
|
12
|
-
},
|
13
|
-
});
|
14
|
-
|
15
|
-
type ForwardProps = Omit<DropdownProps, "onSelect" | "selectedOptions" | "clearable">;
|
16
|
-
|
17
|
-
interface IProps<keyType, dataType> extends ForwardProps {
|
18
|
-
required?: boolean;
|
19
|
-
selected: keyType | keyType[];
|
20
|
-
items: {
|
21
|
-
key: keyType, value: string, data?: dataType,
|
22
|
-
/** display complex controls in the drop down */
|
23
|
-
option?: JSX.Element;
|
24
|
-
}[];
|
25
|
-
onSelect: (
|
26
|
-
/** the specific option that was selected/unselected */
|
27
|
-
option: { key: keyType, value: string, data?: dataType },
|
28
|
-
/** only sent for multi select - all selected options, in case of multi select */
|
29
|
-
options?: { key: keyType, value: string, data?: dataType }[]) => void;
|
30
|
-
}
|
31
|
-
|
32
|
-
function $DropdownEX<keyType extends string = string, dataType = never>(props: IProps<keyType, dataType>, ref: React.ForwardedRef<HTMLButtonElement>) {
|
33
|
-
const classes = useStyles();
|
34
|
-
const ctx = useKWIZFluentContext();
|
35
|
-
const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
|
36
|
-
|
37
|
-
//sometimes control will lose value when re-rendered
|
38
|
-
//use case: public forms when editing other fields after the dropdown was set
|
39
|
-
//re-set the text value manually to fix
|
40
|
-
let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
|
41
|
-
let v = firstOrNull(props.items, i => i.key === s);
|
42
|
-
return v ? v.value : ''
|
43
|
-
})).join(', ');
|
44
|
-
|
45
|
-
return (
|
46
|
-
<Dropdown {...{ ...props, onSelect: undefined }} className={mergeClasses(classes.root, props.className)} ref={ref} clearable={!props.required && !props.multiselect}
|
47
|
-
appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
|
48
|
-
selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
|
49
|
-
let o = firstOrNull(props.items, i => i.key === data.optionValue);
|
50
|
-
if (props.multiselect) {
|
51
|
-
let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
|
52
|
-
props.onSelect(o, current);
|
53
|
-
}
|
54
|
-
else props.onSelect(o);
|
55
|
-
}}>
|
56
|
-
{props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
|
57
|
-
</Dropdown>
|
58
|
-
);
|
59
|
-
}
|
60
|
-
|
61
|
-
export const DropdownEX = React.forwardRef($DropdownEX);
|
62
|
-
|
63
|
-
/** @deprecated use normal DropdownEX it is now generic */
|
64
|
-
export function getDropdownEX<keyType extends string = string, dataType = never>() {
|
65
|
-
logger.warn('getDropdownEX is deprecated. use DropdownEX it now supports generic types');
|
66
|
-
return React.forwardRef($DropdownEX<keyType, dataType>);
|
1
|
+
import { Dropdown, DropdownProps, makeStyles, mergeClasses, Option } from '@fluentui/react-components';
|
2
|
+
import { filterEmptyEntries, firstOrNull, isNullOrUndefined } from '@kwiz/common';
|
3
|
+
import React from 'react';
|
4
|
+
import { GetLogger } from '../_modules/config';
|
5
|
+
import { useKWIZFluentContext } from '../helpers/context-internal';
|
6
|
+
|
7
|
+
const logger = GetLogger("DropdownEX");
|
8
|
+
|
9
|
+
const useStyles = makeStyles({
|
10
|
+
root: {
|
11
|
+
minWidth: "auto"
|
12
|
+
},
|
13
|
+
});
|
14
|
+
|
15
|
+
type ForwardProps = Omit<DropdownProps, "onSelect" | "selectedOptions" | "clearable">;
|
16
|
+
|
17
|
+
interface IProps<keyType, dataType> extends ForwardProps {
|
18
|
+
required?: boolean;
|
19
|
+
selected: keyType | keyType[];
|
20
|
+
items: {
|
21
|
+
key: keyType, value: string, data?: dataType,
|
22
|
+
/** display complex controls in the drop down */
|
23
|
+
option?: JSX.Element;
|
24
|
+
}[];
|
25
|
+
onSelect: (
|
26
|
+
/** the specific option that was selected/unselected */
|
27
|
+
option: { key: keyType, value: string, data?: dataType },
|
28
|
+
/** only sent for multi select - all selected options, in case of multi select */
|
29
|
+
options?: { key: keyType, value: string, data?: dataType }[]) => void;
|
30
|
+
}
|
31
|
+
|
32
|
+
function $DropdownEX<keyType extends string = string, dataType = never>(props: IProps<keyType, dataType>, ref: React.ForwardedRef<HTMLButtonElement>) {
|
33
|
+
const classes = useStyles();
|
34
|
+
const ctx = useKWIZFluentContext();
|
35
|
+
const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
|
36
|
+
|
37
|
+
//sometimes control will lose value when re-rendered
|
38
|
+
//use case: public forms when editing other fields after the dropdown was set
|
39
|
+
//re-set the text value manually to fix
|
40
|
+
let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
|
41
|
+
let v = firstOrNull(props.items, i => i.key === s);
|
42
|
+
return v ? v.value : ''
|
43
|
+
})).join(', ');
|
44
|
+
|
45
|
+
return (
|
46
|
+
<Dropdown {...{ ...props, onSelect: undefined }} className={mergeClasses(classes.root, props.className)} ref={ref} clearable={!props.required && !props.multiselect}
|
47
|
+
appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
|
48
|
+
selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
|
49
|
+
let o = firstOrNull(props.items, i => i.key === data.optionValue);
|
50
|
+
if (props.multiselect) {
|
51
|
+
let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
|
52
|
+
props.onSelect(o, current);
|
53
|
+
}
|
54
|
+
else props.onSelect(o);
|
55
|
+
}}>
|
56
|
+
{props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
|
57
|
+
</Dropdown>
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
export const DropdownEX = React.forwardRef($DropdownEX);
|
62
|
+
|
63
|
+
/** @deprecated use normal DropdownEX it is now generic */
|
64
|
+
export function getDropdownEX<keyType extends string = string, dataType = never>() {
|
65
|
+
logger.warn('getDropdownEX is deprecated. use DropdownEX it now supports generic types');
|
66
|
+
return React.forwardRef($DropdownEX<keyType, dataType>);
|
67
67
|
}
|
@@ -1,42 +1,42 @@
|
|
1
|
-
import * as React from "react";
|
2
|
-
import { GetLogger } from "../_modules/config";
|
3
|
-
|
4
|
-
const logger = GetLogger("ErrorBoundary");
|
5
|
-
|
6
|
-
interface iProps {
|
7
|
-
errorComponent?: JSX.Element,
|
8
|
-
/** If changeMarker changes, it will check the error again */
|
9
|
-
changeMarker: string | number
|
10
|
-
}
|
11
|
-
interface iState { hasError: boolean; marker: string | number; }
|
12
|
-
export class ErrorBoundary extends React.Component<React.PropsWithChildren<iProps>, iState> {
|
13
|
-
constructor(props: iProps) {
|
14
|
-
super(props);
|
15
|
-
this.state = { hasError: false, marker: props.changeMarker };
|
16
|
-
}
|
17
|
-
|
18
|
-
static getDerivedStateFromError(error) {
|
19
|
-
// Update state so the next render will show the fallback UI.
|
20
|
-
return { hasError: true };
|
21
|
-
}
|
22
|
-
static getDerivedStateFromProps(props: iProps, state: iState) {
|
23
|
-
if (props.changeMarker !== state.marker)
|
24
|
-
return { hasError: false, marker: props.changeMarker };
|
25
|
-
else return null;
|
26
|
-
}
|
27
|
-
|
28
|
-
componentDidCatch(error, errorInfo) {
|
29
|
-
// You can also log the error to an error reporting service
|
30
|
-
logger.error(error);
|
31
|
-
logger.error(errorInfo);
|
32
|
-
}
|
33
|
-
|
34
|
-
render() {
|
35
|
-
if (this.state.hasError) {
|
36
|
-
// You can render any custom fallback UI
|
37
|
-
return this.props.errorComponent || <h1>Something went wrong.</h1>;
|
38
|
-
}
|
39
|
-
|
40
|
-
return this.props.children;
|
41
|
-
}
|
1
|
+
import * as React from "react";
|
2
|
+
import { GetLogger } from "../_modules/config";
|
3
|
+
|
4
|
+
const logger = GetLogger("ErrorBoundary");
|
5
|
+
|
6
|
+
interface iProps {
|
7
|
+
errorComponent?: JSX.Element,
|
8
|
+
/** If changeMarker changes, it will check the error again */
|
9
|
+
changeMarker: string | number
|
10
|
+
}
|
11
|
+
interface iState { hasError: boolean; marker: string | number; }
|
12
|
+
export class ErrorBoundary extends React.Component<React.PropsWithChildren<iProps>, iState> {
|
13
|
+
constructor(props: iProps) {
|
14
|
+
super(props);
|
15
|
+
this.state = { hasError: false, marker: props.changeMarker };
|
16
|
+
}
|
17
|
+
|
18
|
+
static getDerivedStateFromError(error) {
|
19
|
+
// Update state so the next render will show the fallback UI.
|
20
|
+
return { hasError: true };
|
21
|
+
}
|
22
|
+
static getDerivedStateFromProps(props: iProps, state: iState) {
|
23
|
+
if (props.changeMarker !== state.marker)
|
24
|
+
return { hasError: false, marker: props.changeMarker };
|
25
|
+
else return null;
|
26
|
+
}
|
27
|
+
|
28
|
+
componentDidCatch(error, errorInfo) {
|
29
|
+
// You can also log the error to an error reporting service
|
30
|
+
logger.error(error);
|
31
|
+
logger.error(errorInfo);
|
32
|
+
}
|
33
|
+
|
34
|
+
render() {
|
35
|
+
if (this.state.hasError) {
|
36
|
+
// You can render any custom fallback UI
|
37
|
+
return this.props.errorComponent || <h1>Something went wrong.</h1>;
|
38
|
+
}
|
39
|
+
|
40
|
+
return this.props.children;
|
41
|
+
}
|
42
42
|
}
|