@kwiz/fluentui 1.0.77 → 1.0.79

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.
Files changed (90) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +53 -53
  3. package/dist/controls/svg.js +21 -21
  4. package/dist/controls/svg.js.map +1 -1
  5. package/dist/helpers/hooks.d.ts +1 -1
  6. package/dist/helpers/hooks.js +43 -30
  7. package/dist/helpers/hooks.js.map +1 -1
  8. package/package.json +85 -85
  9. package/.dependency-cruiser.js +0 -399
  10. package/.github/workflows/npm-publish.yml +0 -24
  11. package/dist/@types/forwardRef.d.ts +0 -0
  12. package/dist/@types/forwardRef.js +0 -1
  13. package/dist/@types/forwardRef.js.map +0 -1
  14. package/dist/controls/error-boundary copy.d.ts +0 -23
  15. package/dist/controls/error-boundary copy.js +0 -33
  16. package/dist/controls/error-boundary copy.js.map +0 -1
  17. package/dist/helpers/common.d.ts +0 -4
  18. package/dist/helpers/common.js +0 -2
  19. package/dist/helpers/common.js.map +0 -1
  20. package/dist/helpers/context.d.ts +0 -26
  21. package/dist/helpers/context.js +0 -15
  22. package/dist/helpers/context.js.map +0 -1
  23. package/dist/helpers/drag-drop/exports.d.ts +0 -12
  24. package/dist/helpers/drag-drop/exports.js +0 -3
  25. package/dist/helpers/drag-drop/exports.js.map +0 -1
  26. package/dist/helpers/exports.d.ts +0 -7
  27. package/dist/helpers/exports.js +0 -8
  28. package/dist/helpers/exports.js.map +0 -1
  29. package/src/_modules/config.ts +0 -9
  30. package/src/_modules/constants.ts +0 -3
  31. package/src/controls/ColorPickerDialog.tsx +0 -84
  32. package/src/controls/accordion.tsx +0 -62
  33. package/src/controls/button.tsx +0 -181
  34. package/src/controls/canvas/CustomEventTargetBase.ts +0 -33
  35. package/src/controls/canvas/DrawPad.tsx +0 -297
  36. package/src/controls/canvas/DrawPadManager.ts +0 -695
  37. package/src/controls/canvas/bezier.ts +0 -110
  38. package/src/controls/canvas/point.ts +0 -45
  39. package/src/controls/card-list.tsx +0 -32
  40. package/src/controls/card.tsx +0 -78
  41. package/src/controls/centered.tsx +0 -15
  42. package/src/controls/date.tsx +0 -88
  43. package/src/controls/diagram-picker.tsx +0 -97
  44. package/src/controls/divider.tsx +0 -16
  45. package/src/controls/dropdown.tsx +0 -67
  46. package/src/controls/error-boundary.tsx +0 -42
  47. package/src/controls/field-editor.tsx +0 -43
  48. package/src/controls/file-upload.tsx +0 -156
  49. package/src/controls/horizontal.tsx +0 -49
  50. package/src/controls/html-editor/editor.tsx +0 -182
  51. package/src/controls/index.ts +0 -33
  52. package/src/controls/input.tsx +0 -161
  53. package/src/controls/kwizoverflow.tsx +0 -107
  54. package/src/controls/list.tsx +0 -120
  55. package/src/controls/loading.tsx +0 -11
  56. package/src/controls/menu.tsx +0 -196
  57. package/src/controls/merge-text.tsx +0 -126
  58. package/src/controls/please-wait.tsx +0 -33
  59. package/src/controls/progress-bar.tsx +0 -110
  60. package/src/controls/prompt.tsx +0 -122
  61. package/src/controls/qrcode.tsx +0 -37
  62. package/src/controls/search.tsx +0 -72
  63. package/src/controls/section.tsx +0 -134
  64. package/src/controls/svg.tsx +0 -139
  65. package/src/controls/toolbar.tsx +0 -47
  66. package/src/controls/vertical-content.tsx +0 -50
  67. package/src/controls/vertical.tsx +0 -43
  68. package/src/helpers/block-nav.tsx +0 -89
  69. package/src/helpers/context-const.ts +0 -30
  70. package/src/helpers/context-export.tsx +0 -78
  71. package/src/helpers/context-internal.ts +0 -14
  72. package/src/helpers/drag-drop/drag-drop-container.tsx +0 -54
  73. package/src/helpers/drag-drop/drag-drop-context-internal.tsx +0 -10
  74. package/src/helpers/drag-drop/drag-drop-context.tsx +0 -62
  75. package/src/helpers/drag-drop/drag-drop.types.ts +0 -21
  76. package/src/helpers/drag-drop/index.ts +0 -12
  77. package/src/helpers/drag-drop/readme.md +0 -76
  78. package/src/helpers/drag-drop/use-draggable.ts +0 -48
  79. package/src/helpers/drag-drop/use-droppable.ts +0 -39
  80. package/src/helpers/forwardRef.ts +0 -7
  81. package/src/helpers/hooks-events.ts +0 -150
  82. package/src/helpers/hooks.tsx +0 -163
  83. package/src/helpers/index.ts +0 -8
  84. package/src/helpers/use-alerts.tsx +0 -75
  85. package/src/helpers/use-editable-control.tsx +0 -38
  86. package/src/helpers/use-toast.tsx +0 -30
  87. package/src/index.ts +0 -3
  88. package/src/styles/index.ts +0 -1
  89. package/src/styles/styles.ts +0 -105
  90. package/src/styles/theme.ts +0 -91
@@ -1,110 +0,0 @@
1
- import { BasicPoint, Point } from './point';
2
-
3
- export class Bezier {
4
- public static fromPoints(
5
- points: Point[],
6
- widths: { start: number; end: number; },
7
- ): Bezier {
8
- const c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2;
9
- const c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1;
10
-
11
- return new Bezier(points[1], c2, c3, points[2], widths.start, widths.end);
12
- }
13
-
14
- private static calculateControlPoints(
15
- s1: BasicPoint,
16
- s2: BasicPoint,
17
- s3: BasicPoint,
18
- ): {
19
- c1: BasicPoint;
20
- c2: BasicPoint;
21
- } {
22
- const dx1 = s1.x - s2.x;
23
- const dy1 = s1.y - s2.y;
24
- const dx2 = s2.x - s3.x;
25
- const dy2 = s2.y - s3.y;
26
-
27
- const m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
28
- const m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
29
-
30
- const l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
31
- const l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
32
-
33
- const dxm = m1.x - m2.x;
34
- const dym = m1.y - m2.y;
35
-
36
- const k = (l1 + l2) === 0 ? l2 : l2 / (l1 + l2);
37
-
38
- const cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
39
-
40
- const tx = s2.x - cm.x;
41
- const ty = s2.y - cm.y;
42
-
43
- return {
44
- c1: new Point(m1.x + tx, m1.y + ty),
45
- c2: new Point(m2.x + tx, m2.y + ty),
46
- };
47
- }
48
-
49
- public constructor(
50
- public startPoint: Point,
51
- public control2: BasicPoint,
52
- public control1: BasicPoint,
53
- public endPoint: Point,
54
- public startWidth: number,
55
- public endWidth: number,
56
- ) { }
57
-
58
- // Returns approximated length. Code taken from https://www.lemoda.net/maths/bezier-length/index.html.
59
- public length(): number {
60
- const steps = 10;
61
- let length = 0;
62
- let px;
63
- let py;
64
-
65
- for (let i = 0; i <= steps; i += 1) {
66
- const t = i / steps;
67
- const cx = this.point(
68
- t,
69
- this.startPoint.x,
70
- this.control1.x,
71
- this.control2.x,
72
- this.endPoint.x,
73
- );
74
- const cy = this.point(
75
- t,
76
- this.startPoint.y,
77
- this.control1.y,
78
- this.control2.y,
79
- this.endPoint.y,
80
- );
81
-
82
- if (i > 0) {
83
- const xdiff = cx - (px as number);
84
- const ydiff = cy - (py as number);
85
-
86
- length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
87
- }
88
-
89
- px = cx;
90
- py = cy;
91
- }
92
-
93
- return length;
94
- }
95
-
96
- // Calculate parametric value of x or y given t and the four point coordinates of a cubic bezier curve.
97
- private point(
98
- t: number,
99
- start: number,
100
- c1: number,
101
- c2: number,
102
- end: number,
103
- ): number {
104
- // prettier-ignore
105
- return (start * (1.0 - t) * (1.0 - t) * (1.0 - t))
106
- + (3.0 * c1 * (1.0 - t) * (1.0 - t) * t)
107
- + (3.0 * c2 * (1.0 - t) * t * t)
108
- + (end * t * t * t);
109
- }
110
- }
@@ -1,45 +0,0 @@
1
- // Interface for point data structure used e.g. in SignaturePad#fromData method
2
- export interface BasicPoint {
3
- x: number;
4
- y: number;
5
- pressure: number;
6
- time: number;
7
- }
8
-
9
- export class Point implements BasicPoint {
10
- public x: number;
11
- public y: number;
12
- public pressure: number;
13
- public time: number;
14
-
15
- public constructor(x: number, y: number, pressure?: number, time?: number) {
16
- if (isNaN(x) || isNaN(y)) {
17
- throw new Error(`Point is invalid: (${x}, ${y})`);
18
- }
19
- this.x = +x;
20
- this.y = +y;
21
- this.pressure = pressure || 0;
22
- this.time = time || Date.now();
23
- }
24
-
25
- public distanceTo(start: BasicPoint): number {
26
- return Math.sqrt(
27
- Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2),
28
- );
29
- }
30
-
31
- public equals(other: BasicPoint): boolean {
32
- return (
33
- this.x === other.x &&
34
- this.y === other.y &&
35
- this.pressure === other.pressure &&
36
- this.time === other.time
37
- );
38
- }
39
-
40
- public velocityFrom(start: BasicPoint): number {
41
- return this.time !== start.time
42
- ? this.distanceTo(start) / (this.time - start.time)
43
- : 0;
44
- }
45
- }
@@ -1,32 +0,0 @@
1
- import { makeStyles } from '@fluentui/react-components';
2
- import React from 'react';
3
- import { CardEX, iCardProps } from './card';
4
- import { Centered } from './centered';
5
- import { Horizontal } from './horizontal';
6
-
7
- const useStyles = makeStyles({
8
- emptyList: {
9
- position: "absolute", top: 0, bottom: 0, left: 0, right: 0,
10
- display: "flex",
11
- zIndex: -1
12
- }
13
- });
14
- interface iProps {
15
- cards: iCardProps[];
16
- /** centered back-fill control */
17
- backfill?: JSX.Element;
18
- }
19
- export const CardList: React.FunctionComponent<React.PropsWithChildren<iProps>> = (props) => {
20
- const classes = useStyles();
21
- return (
22
- <Horizontal main wrap>
23
- {props.backfill && <div className={classes.emptyList}>
24
- <Centered>
25
- {props.backfill}
26
- </Centered>
27
- </div>}
28
-
29
- {props.cards.map((card, idx) => <CardEX key={`i${idx}`} {...card} />)}
30
- </Horizontal>
31
- );
32
- }
@@ -1,78 +0,0 @@
1
- import { Card, CardFooter, cardFooterClassNames, CardHeader, CardPreview, Label, makeStyles, tokens } from '@fluentui/react-components';
2
- import { FluentIcon, MoreVerticalRegular } from '@fluentui/react-icons';
3
- import { isNotEmptyArray, isNotEmptyString, isNullOrEmptyArray, isNullOrUndefined } from '@kwiz/common';
4
- import React from 'react';
5
- import { iMenuItemEX, MenuEx } from './menu';
6
-
7
- const useStyles = makeStyles({
8
- card: {
9
- height: '225px',
10
- width: '190px',
11
- [`& .${cardFooterClassNames.root}>button`]: {
12
- display: "none"
13
- },
14
- "&:hover": {
15
- backgroundColor: tokens.colorNeutralBackground1Hover,
16
- [`& .${cardFooterClassNames.root}>button`]: {
17
- display: "block"
18
- }
19
- }
20
- },
21
- previewContent: {
22
- textAlign: "center",
23
- backgroundColor: tokens.colorBrandBackground,
24
- color: tokens.colorBrandBackground2
25
- },
26
- previewContentNoDescription: {
27
- textAlign: "center",
28
- color: tokens.colorBrandBackground,
29
- paddingTop: '20%'
30
- },
31
- cardIcon: {
32
- height: '120px',
33
- width: '100px'
34
-
35
- },
36
- cardLabels: {
37
- whiteSpace: "nowrap",
38
- overflow: "hidden",
39
- textOverflow: "ellipsis",
40
- maxWidth: '166px'
41
- },
42
- })
43
-
44
- export interface iCardProps {
45
- title: string;
46
- description?: string;
47
- icon: FluentIcon;
48
- menuItems?: iMenuItemEX[];
49
- footer?: JSX.Element;
50
- onClick: React.MouseEventHandler<HTMLDivElement>;
51
- }
52
- export const CardEX: React.FunctionComponent<React.PropsWithChildren<iCardProps>> = (props) => {
53
- const classes = useStyles();
54
- const hasDescription = isNotEmptyString(props.description);
55
- const hasActions = isNotEmptyArray(props.menuItems) || !isNullOrUndefined(props.footer);
56
- return (
57
- <Card className={classes.card} onClick={props.onClick}>
58
- <CardPreview>
59
- <div className={hasDescription ? classes.previewContent : classes.previewContentNoDescription}>
60
- <props.icon className={classes.cardIcon} />
61
- {!hasDescription && <>
62
- <br />
63
- <Label>{props.title}</Label>
64
- </>}
65
- </div>
66
- </CardPreview>
67
- {hasDescription && <CardHeader
68
- header={<Label className={classes.cardLabels}>{props.title}</Label>}
69
- description={<Label className={classes.cardLabels} size='small'>{props.description}</Label>}
70
- />}
71
- {hasActions && <CardFooter action={isNullOrEmptyArray(props.menuItems)
72
- ? undefined
73
- : <MenuEx trigger={{ title: 'more', icon: <MoreVerticalRegular /> }}
74
- items={props.menuItems} />}>
75
- {props.footer}
76
- </CardFooter>}
77
- </Card>);
78
- }
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
- import { Horizontal } from './horizontal';
3
- import { Vertical } from './vertical';
4
-
5
- interface IProps {
6
- }
7
- export const Centered: React.FunctionComponent<React.PropsWithChildren<IProps>> = (props) => {
8
- return (
9
- <Vertical main vCentered>
10
- <Horizontal hCentered>
11
- {props.children}
12
- </Horizontal>
13
- </Vertical>
14
- );
15
- }
@@ -1,88 +0,0 @@
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
- }
@@ -1,97 +0,0 @@
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
- });
@@ -1,16 +0,0 @@
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
- });
@@ -1,67 +0,0 @@
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
- }
@@ -1,42 +0,0 @@
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
- }
@@ -1,43 +0,0 @@
1
- import { Field, mergeClasses } from '@fluentui/react-components';
2
- import { isNullOrUndefined } from '@kwiz/common';
3
- import React from 'react';
4
- import { GetLogger } from '../_modules/config';
5
- import { InputEx, TextAreaEx } from './input';
6
-
7
- const logger = GetLogger('FieldEditor');
8
-
9
- interface IProps {
10
- required?: boolean;
11
- error?: string;
12
- value: string;
13
- onChange: (newValue: string) => void;
14
- css: string[];
15
- label: string;
16
- description?: string;
17
- type?: "text" | "multiline";
18
- allowTab?: boolean;
19
- }
20
- export const FieldEditor: React.FunctionComponent<IProps> = (props) => {
21
- if (isNullOrUndefined(props.value)) {
22
- logger.error(`${props.label}: value should not be null`);
23
- }
24
- return (
25
- <Field required={props.required}
26
- validationMessage={props.error || props.description}
27
- validationState={props.error ? "error" : "none"}>
28
- {props.type === "multiline"
29
- ? <TextAreaEx className={props.css && mergeClasses(...props.css)}
30
- required={props.required}
31
- placeholder={props.label}
32
- value={props.value || ""}
33
- allowTab={props.allowTab}
34
- onValueChange={(e, data) => props.onChange(data.value)}
35
- />
36
- : <InputEx className={props.css && mergeClasses(...props.css)}
37
- required={props.required}
38
- placeholder={props.label}
39
- value={props.value || ""}
40
- onChange={(e, data) => props.onChange(data.value)} />}
41
- </Field>
42
- );
43
- }