@kwiz/fluentui 1.0.15 → 1.0.19
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 +34 -0
- package/LICENSE +21 -21
- package/README.md +26 -26
- package/package.json +72 -72
- package/src/_modules/config.ts +9 -9
- package/src/_modules/constants.ts +3 -3
- package/src/controls/accordion.tsx +48 -0
- package/src/controls/button.tsx +169 -169
- package/src/controls/centered.tsx +22 -22
- package/src/controls/date.tsx +39 -39
- package/src/controls/dropdown.tsx +51 -51
- package/src/controls/error-boundary.tsx +41 -41
- package/src/controls/field-editor.tsx +40 -40
- package/src/controls/file-upload.tsx +67 -67
- package/src/controls/horizontal.tsx +34 -34
- package/src/controls/input.tsx +60 -60
- package/src/controls/kwizoverflow.tsx +103 -102
- package/src/controls/list.tsx +117 -117
- package/src/controls/loading.tsx +10 -10
- package/src/controls/please-wait.tsx +32 -32
- package/src/controls/prompt.tsx +96 -96
- package/src/controls/search.tsx +65 -65
- package/src/controls/section.tsx +51 -51
- package/src/controls/svg.tsx +120 -120
- package/src/controls/toolbar.tsx +48 -48
- package/src/controls/vertical-content.tsx +49 -49
- package/src/controls/vertical.tsx +34 -34
- package/src/helpers/context.ts +39 -39
- package/src/helpers/hooks.tsx +335 -335
- package/src/index.ts +26 -25
- package/src/styles/styles.ts +87 -87
- package/src/styles/theme.ts +90 -90
- package/dist/_modules/build.d.ts +0 -2
- package/dist/_modules/build.js +0 -3
- package/dist/_modules/build.js.map +0 -1
- package/dist/_modules/config.d.ts +0 -1
- package/dist/_modules/config.js +0 -9
- package/dist/_modules/config.js.map +0 -1
- package/dist/_modules/constants.d.ts +0 -2
- package/dist/_modules/constants.js +0 -3
- package/dist/_modules/constants.js.map +0 -1
- package/dist/_modules/exports-index.d.ts +0 -1
- package/dist/_modules/exports-index.js +0 -2
- package/dist/_modules/exports-index.js.map +0 -1
- package/dist/controls/button.d.ts +0 -28
- package/dist/controls/button.js +0 -113
- package/dist/controls/button.js.map +0 -1
- package/dist/controls/centered.d.ts +0 -5
- package/dist/controls/centered.js +0 -14
- package/dist/controls/centered.js.map +0 -1
- package/dist/controls/date.d.ts +0 -8
- package/dist/controls/date.js +0 -32
- package/dist/controls/date.js.map +0 -1
- package/dist/controls/dropdown.d.ts +0 -29
- package/dist/controls/dropdown.js +0 -27
- package/dist/controls/dropdown.js.map +0 -1
- package/dist/controls/error-boundary.d.ts +0 -23
- package/dist/controls/error-boundary.js +0 -33
- package/dist/controls/error-boundary.js.map +0 -1
- package/dist/controls/exports-index.d.ts +0 -17
- package/dist/controls/exports-index.js +0 -18
- package/dist/controls/exports-index.js.map +0 -1
- package/dist/controls/field-editor.d.ts +0 -13
- package/dist/controls/field-editor.js +0 -15
- package/dist/controls/field-editor.js.map +0 -1
- package/dist/controls/file-upload.d.ts +0 -18
- package/dist/controls/file-upload.js +0 -41
- package/dist/controls/file-upload.js.map +0 -1
- package/dist/controls/horizontal.d.ts +0 -8
- package/dist/controls/horizontal.js +0 -23
- package/dist/controls/horizontal.js.map +0 -1
- package/dist/controls/input.d.ts +0 -13
- package/dist/controls/input.js +0 -43
- package/dist/controls/input.js.map +0 -1
- package/dist/controls/kwizoverflow.d.ts +0 -13
- package/dist/controls/kwizoverflow.js +0 -45
- package/dist/controls/kwizoverflow.js.map +0 -1
- package/dist/controls/list.d.ts +0 -21
- package/dist/controls/list.js +0 -72
- package/dist/controls/list.js.map +0 -1
- package/dist/controls/loading copy.d.ts +0 -5
- package/dist/controls/loading copy.js +0 -7
- package/dist/controls/loading copy.js.map +0 -1
- package/dist/controls/loading.d.ts +0 -5
- package/dist/controls/loading.js +0 -7
- package/dist/controls/loading.js.map +0 -1
- package/dist/controls/please-wait.d.ts +0 -18
- package/dist/controls/please-wait.js +0 -16
- package/dist/controls/please-wait.js.map +0 -1
- package/dist/controls/prompt.d.ts +0 -32
- package/dist/controls/prompt.js +0 -31
- package/dist/controls/prompt.js.map +0 -1
- package/dist/controls/search.d.ts +0 -13
- package/dist/controls/search.js +0 -47
- package/dist/controls/search.js.map +0 -1
- package/dist/controls/section.d.ts +0 -14
- package/dist/controls/section.js +0 -27
- package/dist/controls/section.js.map +0 -1
- package/dist/controls/svg.d.ts +0 -23
- package/dist/controls/svg.js +0 -45
- package/dist/controls/svg.js.map +0 -1
- package/dist/controls/toolbar.d.ts +0 -12
- package/dist/controls/toolbar.js +0 -23
- package/dist/controls/toolbar.js.map +0 -1
- package/dist/controls/vertical-content.d.ts +0 -6
- package/dist/controls/vertical-content.js +0 -37
- package/dist/controls/vertical-content.js.map +0 -1
- package/dist/controls/vertical.d.ts +0 -8
- package/dist/controls/vertical.js +0 -23
- package/dist/controls/vertical.js.map +0 -1
- package/dist/exports-index.d.ts +0 -3
- package/dist/exports-index.js +0 -4
- package/dist/exports-index.js.map +0 -1
- package/dist/helpers/context.d.ts +0 -26
- package/dist/helpers/context.js +0 -15
- package/dist/helpers/context.js.map +0 -1
- package/dist/helpers/hooks.d.ts +0 -62
- package/dist/helpers/hooks.js +0 -287
- package/dist/helpers/hooks.js.map +0 -1
- package/dist/index.d.ts +0 -24
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/styles/exports-index.d.ts +0 -2
- package/dist/styles/exports-index.js +0 -3
- package/dist/styles/exports-index.js.map +0 -1
- package/dist/styles/styles.d.ts +0 -19
- package/dist/styles/styles.js +0 -79
- package/dist/styles/styles.js.map +0 -1
- package/dist/styles/theme.d.ts +0 -6
- package/dist/styles/theme.js +0 -77
- package/dist/styles/theme.js.map +0 -1
package/src/controls/button.tsx
CHANGED
|
@@ -1,170 +1,170 @@
|
|
|
1
|
-
import { Button, ButtonProps, CompoundButton, compoundButtonClassNames, CompoundButtonProps, makeStyles, mergeClasses, tokens, Tooltip } from '@fluentui/react-components';
|
|
2
|
-
import { capitalizeFirstLetter, isFunction, isNullOrEmptyString, isNullOrUndefined, isString, PushNoDuplicate } from '@kwiz/common';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { useKWIZFluentContext } from '../helpers/context';
|
|
5
|
-
import { useCommonStyles, widthMedium } from '../styles/styles';
|
|
6
|
-
|
|
7
|
-
interface IProps {
|
|
8
|
-
title: string;//required
|
|
9
|
-
showTitleWithIcon?: boolean;
|
|
10
|
-
dontStretch?: boolean;
|
|
11
|
-
hideOnPrint?: boolean;
|
|
12
|
-
dontCenterText?: boolean;
|
|
13
|
-
hoverIcon?: JSX.Element;
|
|
14
|
-
hoverTitle?: string;
|
|
15
|
-
}
|
|
16
|
-
interface IPropsCompound extends IProps {
|
|
17
|
-
width?: string | number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type ButtonEXProps = IProps & ButtonProps;
|
|
21
|
-
export type CompoundButtonEXProps = IPropsCompound & CompoundButtonProps;
|
|
22
|
-
|
|
23
|
-
const useStyles = makeStyles({
|
|
24
|
-
buttonNoCenter: {
|
|
25
|
-
justifyContent: 'flex-start',
|
|
26
|
-
'& *': {
|
|
27
|
-
/* a button with no center that has content of a vertical, or multiple labels */
|
|
28
|
-
alignItems: 'flex-start'
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
danger: {
|
|
32
|
-
backgroundColor: tokens.colorStatusDangerBackground1,
|
|
33
|
-
color: tokens.colorStatusWarningForeground2,
|
|
34
|
-
|
|
35
|
-
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
36
|
-
color: tokens.colorStatusWarningForeground1
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
success: {
|
|
40
|
-
color: tokens.colorStatusSuccessForeground1,
|
|
41
|
-
|
|
42
|
-
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
43
|
-
color: tokens.colorStatusSuccessForeground1,
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
primarySubtle: {
|
|
47
|
-
color: tokens.colorBrandForeground1,
|
|
48
|
-
|
|
49
|
-
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
50
|
-
color: tokens.colorBrandForeground1,
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
dangerSubtle: {
|
|
54
|
-
color: tokens.colorStatusWarningForeground2,
|
|
55
|
-
|
|
56
|
-
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
57
|
-
color: tokens.colorStatusWarningForeground1
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
export const ButtonEX = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
64
|
-
const [hover, setHover] = React.useState(false);
|
|
65
|
-
const trackHover = !isNullOrEmptyString(props.hoverTitle) || !isNullOrUndefined(props.hoverIcon);
|
|
66
|
-
|
|
67
|
-
const title = hover && !isNullOrEmptyString(props.hoverTitle) ? props.hoverTitle
|
|
68
|
-
: props.title || props['aria-label'];
|
|
69
|
-
const icon = hover && !isNullOrUndefined(props.hoverIcon) ? props.hoverIcon : props.icon;
|
|
70
|
-
let hasIcon = !isNullOrUndefined(icon);
|
|
71
|
-
let hasText = props.children || !hasIcon || (hasIcon && props.showTitleWithIcon === true);
|
|
72
|
-
|
|
73
|
-
const commonCssNames = useCommonStyles();
|
|
74
|
-
const cssNames = useStyles();
|
|
75
|
-
let css: string[] = [];
|
|
76
|
-
|
|
77
|
-
if (props.hideOnPrint) PushNoDuplicate(css, commonCssNames.printHide);
|
|
78
|
-
if (props.dontCenterText) PushNoDuplicate(css, cssNames.buttonNoCenter);
|
|
79
|
-
|
|
80
|
-
if (!isNullOrEmptyString(props.className)) css.push(...props.className.split(' '));
|
|
81
|
-
|
|
82
|
-
let btn = <Button ref={ref} appearance='subtle' {...props} className={mergeClasses(...css)}
|
|
83
|
-
aria-label={title} title={undefined} icon={icon}
|
|
84
|
-
onMouseEnter={trackHover ? (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
85
|
-
setHover(true);
|
|
86
|
-
if (isFunction(props.onMouseEnter))
|
|
87
|
-
props.onMouseEnter(e as any);
|
|
88
|
-
} : props.onMouseEnter as any}
|
|
89
|
-
onMouseLeave={trackHover ? (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
90
|
-
setHover(false);
|
|
91
|
-
if (isFunction(props.onMouseLeave))
|
|
92
|
-
props.onMouseLeave(e as any);
|
|
93
|
-
} : props.onMouseLeave as any}
|
|
94
|
-
>{props.children ||
|
|
95
|
-
//no icon? will show the title by default
|
|
96
|
-
(hasText && capitalizeFirstLetter(title))}</Button>;
|
|
97
|
-
if (!hasText || props.children)//icon only or when content is different than props.title
|
|
98
|
-
btn = <Tooltip showDelay={1000} relationship='label' withArrow appearance='inverted' content={title}>
|
|
99
|
-
{btn}
|
|
100
|
-
</Tooltip>;
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
props.dontStretch ? <div>{btn}</div> : btn
|
|
104
|
-
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
export const ButtonEXSecondary = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
108
|
-
const ctx = useKWIZFluentContext();
|
|
109
|
-
return (
|
|
110
|
-
<ButtonEX ref={ref} appearance='secondary' shape={ctx.buttonShape} {...props}></ButtonEX>
|
|
111
|
-
);
|
|
112
|
-
});
|
|
113
|
-
export const ButtonEXPrimary = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
114
|
-
return (
|
|
115
|
-
<ButtonEXSecondary ref={ref} appearance='primary' {...props}>{props.children}</ButtonEXSecondary>
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
export const ButtonEXDanger = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
119
|
-
const cssNames = useStyles();
|
|
120
|
-
return (
|
|
121
|
-
<ButtonEXSecondary ref={ref} className={props.disabled ? undefined : cssNames.danger} {...props}>{props.children}</ButtonEXSecondary>
|
|
122
|
-
);
|
|
123
|
-
});
|
|
124
|
-
export const ButtonEXSuccess = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
125
|
-
const cssNames = useStyles();
|
|
126
|
-
return (
|
|
127
|
-
<ButtonEX ref={ref} className={cssNames.success} {...props}>{props.children}</ButtonEX>
|
|
128
|
-
);
|
|
129
|
-
});
|
|
130
|
-
export const ButtonEXPrimarySubtle = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
131
|
-
const cssNames = useStyles();
|
|
132
|
-
return (
|
|
133
|
-
<ButtonEX ref={ref} className={props.disabled ? undefined : cssNames.primarySubtle} {...props}>{props.children}</ButtonEX>
|
|
134
|
-
);
|
|
135
|
-
});
|
|
136
|
-
export const ButtonEXDangerSubtle = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
137
|
-
const cssNames = useStyles();
|
|
138
|
-
return (
|
|
139
|
-
<ButtonEX ref={ref} className={props.disabled ? undefined : cssNames.dangerSubtle} {...props}>{props.children}</ButtonEX>
|
|
140
|
-
);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
export const CompoundButtonEX = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
144
|
-
let title = props.title || props['aria-label'];
|
|
145
|
-
let tooltip = isString(props.secondaryContent) ? props.secondaryContent : title;
|
|
146
|
-
let max = typeof (props.width) === "undefined" ? widthMedium : props.width;
|
|
147
|
-
return (
|
|
148
|
-
<Tooltip showDelay={1000} relationship='label' withArrow appearance='inverted' content={tooltip}>
|
|
149
|
-
<CompoundButton ref={ref} appearance='subtle' style={{ justifyContent: "flex-start", maxWidth: max }} {...props} aria-label={tooltip} title={undefined}>
|
|
150
|
-
{props.children || capitalizeFirstLetter(title)}</CompoundButton>
|
|
151
|
-
</Tooltip>
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
export const CompoundButtonEXSecondary = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
155
|
-
const ctx = useKWIZFluentContext();
|
|
156
|
-
return (
|
|
157
|
-
<CompoundButtonEX ref={ref} appearance='secondary' shape={ctx.buttonShape} {...props}></CompoundButtonEX>
|
|
158
|
-
);
|
|
159
|
-
});
|
|
160
|
-
export const CompoundButtonEXPrimary = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
161
|
-
return (
|
|
162
|
-
<CompoundButtonEXSecondary ref={ref} appearance='primary' {...props}>{props.children}</CompoundButtonEXSecondary>
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
export const CompoundButtonEXDanger = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
166
|
-
const cssNames = useStyles();
|
|
167
|
-
return (
|
|
168
|
-
<CompoundButtonEXSecondary ref={ref} className={cssNames.danger} {...props}>{props.children}</CompoundButtonEXSecondary>
|
|
169
|
-
);
|
|
1
|
+
import { Button, ButtonProps, CompoundButton, compoundButtonClassNames, CompoundButtonProps, makeStyles, mergeClasses, tokens, Tooltip } from '@fluentui/react-components';
|
|
2
|
+
import { capitalizeFirstLetter, isFunction, isNullOrEmptyString, isNullOrUndefined, isString, PushNoDuplicate } from '@kwiz/common';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useKWIZFluentContext } from '../helpers/context';
|
|
5
|
+
import { useCommonStyles, widthMedium } from '../styles/styles';
|
|
6
|
+
|
|
7
|
+
interface IProps {
|
|
8
|
+
title: string;//required
|
|
9
|
+
showTitleWithIcon?: boolean;
|
|
10
|
+
dontStretch?: boolean;
|
|
11
|
+
hideOnPrint?: boolean;
|
|
12
|
+
dontCenterText?: boolean;
|
|
13
|
+
hoverIcon?: JSX.Element;
|
|
14
|
+
hoverTitle?: string;
|
|
15
|
+
}
|
|
16
|
+
interface IPropsCompound extends IProps {
|
|
17
|
+
width?: string | number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ButtonEXProps = IProps & ButtonProps;
|
|
21
|
+
export type CompoundButtonEXProps = IPropsCompound & CompoundButtonProps;
|
|
22
|
+
|
|
23
|
+
const useStyles = makeStyles({
|
|
24
|
+
buttonNoCenter: {
|
|
25
|
+
justifyContent: 'flex-start',
|
|
26
|
+
'& *': {
|
|
27
|
+
/* a button with no center that has content of a vertical, or multiple labels */
|
|
28
|
+
alignItems: 'flex-start'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
danger: {
|
|
32
|
+
backgroundColor: tokens.colorStatusDangerBackground1,
|
|
33
|
+
color: tokens.colorStatusWarningForeground2,
|
|
34
|
+
|
|
35
|
+
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
36
|
+
color: tokens.colorStatusWarningForeground1
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
success: {
|
|
40
|
+
color: tokens.colorStatusSuccessForeground1,
|
|
41
|
+
|
|
42
|
+
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
43
|
+
color: tokens.colorStatusSuccessForeground1,
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
primarySubtle: {
|
|
47
|
+
color: tokens.colorBrandForeground1,
|
|
48
|
+
|
|
49
|
+
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
50
|
+
color: tokens.colorBrandForeground1,
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
dangerSubtle: {
|
|
54
|
+
color: tokens.colorStatusWarningForeground2,
|
|
55
|
+
|
|
56
|
+
[`& .${compoundButtonClassNames.secondaryContent}`]: {
|
|
57
|
+
color: tokens.colorStatusWarningForeground1
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
export const ButtonEX = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
64
|
+
const [hover, setHover] = React.useState(false);
|
|
65
|
+
const trackHover = !isNullOrEmptyString(props.hoverTitle) || !isNullOrUndefined(props.hoverIcon);
|
|
66
|
+
|
|
67
|
+
const title = hover && !isNullOrEmptyString(props.hoverTitle) ? props.hoverTitle
|
|
68
|
+
: props.title || props['aria-label'];
|
|
69
|
+
const icon = hover && !isNullOrUndefined(props.hoverIcon) ? props.hoverIcon : props.icon;
|
|
70
|
+
let hasIcon = !isNullOrUndefined(icon);
|
|
71
|
+
let hasText = props.children || !hasIcon || (hasIcon && props.showTitleWithIcon === true);
|
|
72
|
+
|
|
73
|
+
const commonCssNames = useCommonStyles();
|
|
74
|
+
const cssNames = useStyles();
|
|
75
|
+
let css: string[] = [];
|
|
76
|
+
|
|
77
|
+
if (props.hideOnPrint) PushNoDuplicate(css, commonCssNames.printHide);
|
|
78
|
+
if (props.dontCenterText) PushNoDuplicate(css, cssNames.buttonNoCenter);
|
|
79
|
+
|
|
80
|
+
if (!isNullOrEmptyString(props.className)) css.push(...props.className.split(' '));
|
|
81
|
+
|
|
82
|
+
let btn = <Button ref={ref} appearance='subtle' {...props} className={mergeClasses(...css)}
|
|
83
|
+
aria-label={title} title={undefined} icon={icon}
|
|
84
|
+
onMouseEnter={trackHover ? (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
85
|
+
setHover(true);
|
|
86
|
+
if (isFunction(props.onMouseEnter))
|
|
87
|
+
props.onMouseEnter(e as any);
|
|
88
|
+
} : props.onMouseEnter as any}
|
|
89
|
+
onMouseLeave={trackHover ? (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
90
|
+
setHover(false);
|
|
91
|
+
if (isFunction(props.onMouseLeave))
|
|
92
|
+
props.onMouseLeave(e as any);
|
|
93
|
+
} : props.onMouseLeave as any}
|
|
94
|
+
>{props.children ||
|
|
95
|
+
//no icon? will show the title by default
|
|
96
|
+
(hasText && capitalizeFirstLetter(title))}</Button>;
|
|
97
|
+
if (!hasText || props.children)//icon only or when content is different than props.title
|
|
98
|
+
btn = <Tooltip showDelay={1000} relationship='label' withArrow appearance='inverted' content={title}>
|
|
99
|
+
{btn}
|
|
100
|
+
</Tooltip>;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
props.dontStretch ? <div>{btn}</div> : btn
|
|
104
|
+
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
export const ButtonEXSecondary = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
108
|
+
const ctx = useKWIZFluentContext();
|
|
109
|
+
return (
|
|
110
|
+
<ButtonEX ref={ref} appearance='secondary' shape={ctx.buttonShape} {...props}></ButtonEX>
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
export const ButtonEXPrimary = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
114
|
+
return (
|
|
115
|
+
<ButtonEXSecondary ref={ref} appearance='primary' {...props}>{props.children}</ButtonEXSecondary>
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
export const ButtonEXDanger = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
119
|
+
const cssNames = useStyles();
|
|
120
|
+
return (
|
|
121
|
+
<ButtonEXSecondary ref={ref} className={props.disabled ? undefined : cssNames.danger} {...props}>{props.children}</ButtonEXSecondary>
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
export const ButtonEXSuccess = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
125
|
+
const cssNames = useStyles();
|
|
126
|
+
return (
|
|
127
|
+
<ButtonEX ref={ref} className={cssNames.success} {...props}>{props.children}</ButtonEX>
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
export const ButtonEXPrimarySubtle = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
131
|
+
const cssNames = useStyles();
|
|
132
|
+
return (
|
|
133
|
+
<ButtonEX ref={ref} className={props.disabled ? undefined : cssNames.primarySubtle} {...props}>{props.children}</ButtonEX>
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
export const ButtonEXDangerSubtle = React.forwardRef<HTMLButtonElement, (ButtonEXProps)>((props, ref) => {
|
|
137
|
+
const cssNames = useStyles();
|
|
138
|
+
return (
|
|
139
|
+
<ButtonEX ref={ref} className={props.disabled ? undefined : cssNames.dangerSubtle} {...props}>{props.children}</ButtonEX>
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const CompoundButtonEX = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
144
|
+
let title = props.title || props['aria-label'];
|
|
145
|
+
let tooltip = isString(props.secondaryContent) ? props.secondaryContent : title;
|
|
146
|
+
let max = typeof (props.width) === "undefined" ? widthMedium : props.width;
|
|
147
|
+
return (
|
|
148
|
+
<Tooltip showDelay={1000} relationship='label' withArrow appearance='inverted' content={tooltip}>
|
|
149
|
+
<CompoundButton ref={ref} appearance='subtle' style={{ justifyContent: "flex-start", maxWidth: max }} {...props} aria-label={tooltip} title={undefined}>
|
|
150
|
+
{props.children || capitalizeFirstLetter(title)}</CompoundButton>
|
|
151
|
+
</Tooltip>
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
export const CompoundButtonEXSecondary = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
155
|
+
const ctx = useKWIZFluentContext();
|
|
156
|
+
return (
|
|
157
|
+
<CompoundButtonEX ref={ref} appearance='secondary' shape={ctx.buttonShape} {...props}></CompoundButtonEX>
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
export const CompoundButtonEXPrimary = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
161
|
+
return (
|
|
162
|
+
<CompoundButtonEXSecondary ref={ref} appearance='primary' {...props}>{props.children}</CompoundButtonEXSecondary>
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
export const CompoundButtonEXDanger = React.forwardRef<HTMLButtonElement, (CompoundButtonEXProps)>((props, ref) => {
|
|
166
|
+
const cssNames = useStyles();
|
|
167
|
+
return (
|
|
168
|
+
<CompoundButtonEXSecondary ref={ref} className={cssNames.danger} {...props}>{props.children}</CompoundButtonEXSecondary>
|
|
169
|
+
);
|
|
170
170
|
});
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { makeStyles } from '@fluentui/react-components';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { Horizontal } from './horizontal';
|
|
4
|
-
import { Vertical } from './vertical';
|
|
5
|
-
|
|
6
|
-
const useStyles = makeStyles({
|
|
7
|
-
center: {
|
|
8
|
-
justifyContent: 'center'
|
|
9
|
-
},
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
interface IProps {
|
|
13
|
-
}
|
|
14
|
-
export const Centered: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
|
15
|
-
const cssNames = useStyles();
|
|
16
|
-
return (
|
|
17
|
-
<Vertical main css={[cssNames.center]}>
|
|
18
|
-
<Horizontal css={[cssNames.center]}>
|
|
19
|
-
{props.children}
|
|
20
|
-
</Horizontal>
|
|
21
|
-
</Vertical>
|
|
22
|
-
);
|
|
1
|
+
import { makeStyles } from '@fluentui/react-components';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Horizontal } from './horizontal';
|
|
4
|
+
import { Vertical } from './vertical';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles({
|
|
7
|
+
center: {
|
|
8
|
+
justifyContent: 'center'
|
|
9
|
+
},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
interface IProps {
|
|
13
|
+
}
|
|
14
|
+
export const Centered: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
|
15
|
+
const cssNames = useStyles();
|
|
16
|
+
return (
|
|
17
|
+
<Vertical main css={[cssNames.center]}>
|
|
18
|
+
<Horizontal css={[cssNames.center]}>
|
|
19
|
+
{props.children}
|
|
20
|
+
</Horizontal>
|
|
21
|
+
</Vertical>
|
|
22
|
+
);
|
|
23
23
|
}
|
package/src/controls/date.tsx
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { DatePicker, DatePickerProps } from '@fluentui/react-datepicker-compat';
|
|
2
|
-
import { CalendarCancelRegular } from '@fluentui/react-icons';
|
|
3
|
-
import { isDate, isFunction, isNullOrEmptyString } from '@kwiz/common';
|
|
4
|
-
import * as React from 'react';
|
|
5
|
-
import { useKWIZFluentContext } from '../helpers/context';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
interface IProps extends DatePickerProps {
|
|
9
|
-
onOK?: () => void;
|
|
10
|
-
onCancel?: () => void;
|
|
11
|
-
}
|
|
12
|
-
export const DatePickerEx: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
|
13
|
-
const ctx = useKWIZFluentContext();
|
|
14
|
-
const [showClear, setShowClear] = React.useState(isDate(props.value));
|
|
15
|
-
const reset = React.useCallback(() => {
|
|
16
|
-
setShowClear(false);
|
|
17
|
-
if (isFunction(props.onSelectDate)) props.onSelectDate(undefined);
|
|
18
|
-
}, [showClear]);
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<DatePicker appearance={ctx.inputAppearance} mountNode={ctx.mountNode} {...props}
|
|
22
|
-
onSelectDate={(date) => {
|
|
23
|
-
setShowClear(isDate(date));
|
|
24
|
-
if (isFunction(props.onSelectDate)) props.onSelectDate(date);
|
|
25
|
-
}}
|
|
26
|
-
onChange={(e, data) => {
|
|
27
|
-
setShowClear(!isNullOrEmptyString(data.value));
|
|
28
|
-
if (isFunction(props.onChange)) props.onChange(e, data);
|
|
29
|
-
}}
|
|
30
|
-
onKeyDown={isFunction(props.onOK) || isFunction(props.onCancel)
|
|
31
|
-
? e => {
|
|
32
|
-
if (isFunction(props.onOK) && e.key === "Enter") props.onOK();
|
|
33
|
-
else if (isFunction(props.onCancel) && e.key === "Escape") props.onCancel();
|
|
34
|
-
}
|
|
35
|
-
: undefined
|
|
36
|
-
}
|
|
37
|
-
contentBefore={showClear && <CalendarCancelRegular title='Clear' onClick={() => reset()} />}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
1
|
+
import { DatePicker, DatePickerProps } from '@fluentui/react-datepicker-compat';
|
|
2
|
+
import { CalendarCancelRegular } from '@fluentui/react-icons';
|
|
3
|
+
import { isDate, isFunction, isNullOrEmptyString } from '@kwiz/common';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { useKWIZFluentContext } from '../helpers/context';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
interface IProps extends DatePickerProps {
|
|
9
|
+
onOK?: () => void;
|
|
10
|
+
onCancel?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export const DatePickerEx: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
|
|
13
|
+
const ctx = useKWIZFluentContext();
|
|
14
|
+
const [showClear, setShowClear] = React.useState(isDate(props.value));
|
|
15
|
+
const reset = React.useCallback(() => {
|
|
16
|
+
setShowClear(false);
|
|
17
|
+
if (isFunction(props.onSelectDate)) props.onSelectDate(undefined);
|
|
18
|
+
}, [showClear]);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<DatePicker appearance={ctx.inputAppearance} mountNode={ctx.mountNode} {...props}
|
|
22
|
+
onSelectDate={(date) => {
|
|
23
|
+
setShowClear(isDate(date));
|
|
24
|
+
if (isFunction(props.onSelectDate)) props.onSelectDate(date);
|
|
25
|
+
}}
|
|
26
|
+
onChange={(e, data) => {
|
|
27
|
+
setShowClear(!isNullOrEmptyString(data.value));
|
|
28
|
+
if (isFunction(props.onChange)) props.onChange(e, data);
|
|
29
|
+
}}
|
|
30
|
+
onKeyDown={isFunction(props.onOK) || isFunction(props.onCancel)
|
|
31
|
+
? e => {
|
|
32
|
+
if (isFunction(props.onOK) && e.key === "Enter") props.onOK();
|
|
33
|
+
else if (isFunction(props.onCancel) && e.key === "Escape") props.onCancel();
|
|
34
|
+
}
|
|
35
|
+
: undefined
|
|
36
|
+
}
|
|
37
|
+
contentBefore={showClear && <CalendarCancelRegular title='Clear' onClick={() => reset()} />}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
40
|
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { Dropdown, DropdownProps, Option } from '@fluentui/react-components';
|
|
2
|
-
import { filterEmptyEntries, firstOrNull, isNullOrUndefined } from '@kwiz/common';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { useKWIZFluentContext } from '../helpers/context';
|
|
5
|
-
|
|
6
|
-
type ForwardProps = Omit<DropdownProps, "onSelect" | "selectedOptions" | "clearable">;
|
|
7
|
-
|
|
8
|
-
interface IProps<dataType, keyType extends string = string> extends ForwardProps {
|
|
9
|
-
required?: boolean;
|
|
10
|
-
selected: keyType | keyType[];
|
|
11
|
-
items: {
|
|
12
|
-
key: keyType, value: string, data?: dataType,
|
|
13
|
-
/** display complex controls in the drop down */
|
|
14
|
-
option?: JSX.Element;
|
|
15
|
-
}[];
|
|
16
|
-
onSelect: (
|
|
17
|
-
/** the specific option that was selected/unselected */
|
|
18
|
-
option: { key: keyType, value: string, data?: dataType },
|
|
19
|
-
/** only sent for multi select - all selected options, in case of multi select */
|
|
20
|
-
options?: { key: keyType, value: string, data?: dataType }[]) => void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function $DropdownEX<keyType extends string = string, dataType = never>(props: IProps<dataType, keyType>, ref: React.ForwardedRef<HTMLButtonElement>) {
|
|
24
|
-
const ctx = useKWIZFluentContext();
|
|
25
|
-
const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
|
|
26
|
-
|
|
27
|
-
//sometimes control will lose value when re-rendered
|
|
28
|
-
//use case: public forms when editing other fields after the dropdown was set
|
|
29
|
-
//re-set the text value manually to fix
|
|
30
|
-
let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
|
|
31
|
-
let v = firstOrNull(props.items, i => i.key === s);
|
|
32
|
-
return v ? v.value : ''
|
|
33
|
-
})).join(', ');
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<Dropdown {...{ ...props, onSelect: undefined }} ref={ref} clearable={!props.required && !props.multiselect}
|
|
37
|
-
appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
|
|
38
|
-
selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
|
|
39
|
-
let o = firstOrNull(props.items, i => i.key === data.optionValue);
|
|
40
|
-
if (props.multiselect) {
|
|
41
|
-
let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
|
|
42
|
-
props.onSelect(o, current);
|
|
43
|
-
}
|
|
44
|
-
else props.onSelect(o);
|
|
45
|
-
}}>
|
|
46
|
-
{props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
|
|
47
|
-
</Dropdown>
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
1
|
+
import { Dropdown, DropdownProps, Option } from '@fluentui/react-components';
|
|
2
|
+
import { filterEmptyEntries, firstOrNull, isNullOrUndefined } from '@kwiz/common';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useKWIZFluentContext } from '../helpers/context';
|
|
5
|
+
|
|
6
|
+
type ForwardProps = Omit<DropdownProps, "onSelect" | "selectedOptions" | "clearable">;
|
|
7
|
+
|
|
8
|
+
interface IProps<dataType, keyType extends string = string> extends ForwardProps {
|
|
9
|
+
required?: boolean;
|
|
10
|
+
selected: keyType | keyType[];
|
|
11
|
+
items: {
|
|
12
|
+
key: keyType, value: string, data?: dataType,
|
|
13
|
+
/** display complex controls in the drop down */
|
|
14
|
+
option?: JSX.Element;
|
|
15
|
+
}[];
|
|
16
|
+
onSelect: (
|
|
17
|
+
/** the specific option that was selected/unselected */
|
|
18
|
+
option: { key: keyType, value: string, data?: dataType },
|
|
19
|
+
/** only sent for multi select - all selected options, in case of multi select */
|
|
20
|
+
options?: { key: keyType, value: string, data?: dataType }[]) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function $DropdownEX<keyType extends string = string, dataType = never>(props: IProps<dataType, keyType>, ref: React.ForwardedRef<HTMLButtonElement>) {
|
|
24
|
+
const ctx = useKWIZFluentContext();
|
|
25
|
+
const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
|
|
26
|
+
|
|
27
|
+
//sometimes control will lose value when re-rendered
|
|
28
|
+
//use case: public forms when editing other fields after the dropdown was set
|
|
29
|
+
//re-set the text value manually to fix
|
|
30
|
+
let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
|
|
31
|
+
let v = firstOrNull(props.items, i => i.key === s);
|
|
32
|
+
return v ? v.value : ''
|
|
33
|
+
})).join(', ');
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Dropdown {...{ ...props, onSelect: undefined }} ref={ref} clearable={!props.required && !props.multiselect}
|
|
37
|
+
appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
|
|
38
|
+
selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
|
|
39
|
+
let o = firstOrNull(props.items, i => i.key === data.optionValue);
|
|
40
|
+
if (props.multiselect) {
|
|
41
|
+
let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
|
|
42
|
+
props.onSelect(o, current);
|
|
43
|
+
}
|
|
44
|
+
else props.onSelect(o);
|
|
45
|
+
}}>
|
|
46
|
+
{props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
|
|
47
|
+
</Dropdown>
|
|
48
|
+
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
52
|
export const DropdownEX = React.forwardRef($DropdownEX);
|
|
@@ -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
|
}
|