@kwiz/fluentui 1.0.44 → 1.0.46

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,11 @@
1
- import { ButtonProps, makeStyles, shorthands, tokens } from "@fluentui/react-components";
1
+ import { makeStyles, shorthands, tokens } from "@fluentui/react-components";
2
2
  import { ArrowUploadRegular } from "@fluentui/react-icons";
3
3
  import { isFunction, isNotEmptyArray, isNotEmptyString, isNullOrEmptyString, lastOrNull } from '@kwiz/common';
4
4
  import * as React from "react";
5
5
  import { useDragDropContext } from "../helpers/drag-drop/drag-drop-context";
6
6
  import { dropFiles } from "../helpers/drag-drop/exports";
7
7
  import { useEffectOnlyOnMount } from "../helpers/hooks";
8
- import { ButtonEX, CompoundButtonEXSecondary } from "./button";
8
+ import { ButtonEX, ButtonEXProps, CompoundButtonEXSecondary } from "./button";
9
9
 
10
10
  const useStyles = makeStyles({
11
11
  addRowIsOver: {
@@ -24,7 +24,7 @@ interface iProps {
24
24
  icon?: JSX.Element;
25
25
  onChange?: (newFile: File | File[], errors: string[]) => void;
26
26
  asBase64?: (files: base64Result[], errors: string[]) => void;
27
- buttonProps?: ButtonProps;
27
+ buttonProps?: Partial<ButtonEXProps>;
28
28
  disabled?: boolean;
29
29
  /** limit file size in MB, for the asBase64 */
30
30
  fileSizeLimit?: number;
@@ -1,7 +1,9 @@
1
- import { GriffelStyle, Input, InputProps, makeStyles, mergeClasses, Textarea, TextareaProps } from '@fluentui/react-components';
2
- import { isFunction } from '@kwiz/common';
1
+ import { GriffelStyle, Input, InputOnChangeData, InputProps, Label, makeStyles, mergeClasses, Textarea, TextareaProps } from '@fluentui/react-components';
2
+ import { isFunction, isNullOrNaN, isNullOrUndefined, isNumber } from '@kwiz/common';
3
3
  import React from 'react';
4
4
  import { useKWIZFluentContext } from '../helpers/context';
5
+ import { useCommonStyles } from '../styles/styles';
6
+ import { Vertical } from './vertical';
5
7
 
6
8
 
7
9
  interface IProps extends InputProps {
@@ -58,4 +60,35 @@ export const TextAreaEx: React.FunctionComponent<React.PropsWithChildren<IPropsT
58
60
  recalcHeight();
59
61
  }} />
60
62
  );
63
+ }
64
+
65
+
66
+ interface INumberProps extends Omit<IProps, "value" | "onChange" | "defaultValue" | "inputMode"> {
67
+ defaultValue?: number;
68
+ onChange: (value: number) => void;
69
+ allowDecimals?: boolean;
70
+ /** if sent true - onChange will only be called when a valid non-empty value is being set */
71
+ required?: boolean;
72
+ }
73
+ export const InputNumberEx: React.FunctionComponent<React.PropsWithChildren<INumberProps>> = (props) => {
74
+ const commonStyles = useCommonStyles();
75
+ const [valueStr, setValueStr] = React.useState(isNumber(props.defaultValue) ? `${props.defaultValue}` : '');
76
+ const [isValid, setIsValid] = React.useState(true);
77
+ const onChange = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>, data: InputOnChangeData) => {
78
+ const newValue = data.value;
79
+ setValueStr(newValue);//update text box anyways
80
+ const asNumber = props.allowDecimals ? parseFloat(newValue) : parseInt(newValue, 10);
81
+ const isValid = props.required ? !isNullOrNaN(asNumber) : isNullOrUndefined(asNumber) || !isNaN(asNumber);
82
+ setIsValid(isValid);
83
+ props.onChange(isValid ? asNumber : null);
84
+ }, [props.allowDecimals]);
85
+
86
+ const passProps: IProps = { ...props, defaultValue: undefined, value: undefined, onChange: undefined };
87
+
88
+ return (
89
+ <Vertical nogap>
90
+ <InputEx inputMode={props.allowDecimals ? "decimal" : "numeric"} {...passProps} value={valueStr} onChange={onChange} />
91
+ {!isValid && <Label className={commonStyles.validationLabel}>this is not a valid value</Label>}
92
+ </Vertical>
93
+ );
61
94
  }
@@ -1,5 +1,5 @@
1
1
  import { Label, Link, makeStyles, Toast, ToastBody, Toaster, ToastFooter, ToastIntent, ToastTitle, useId, useToastController } from "@fluentui/react-components";
2
- import { IDictionary, isDebug, isFunction, isNotEmptyArray, isNullOrEmptyString, jsonClone, jsonStringify, LoggerLevel, objectsEqual, wrapFunction } from "@kwiz/common";
2
+ import { IDictionary, isDebug, isFunction, isNotEmptyArray, isNullOrEmptyString, isPrimitiveValue, jsonClone, jsonStringify, LoggerLevel, objectsEqual, wrapFunction } from "@kwiz/common";
3
3
  import { MutableRefObject, SetStateAction, useCallback, useEffect, useRef, useState } from "react";
4
4
  import { GetLogger } from "../_modules/config";
5
5
  import { IPrompterProps, Prompter } from "../controls/prompt";
@@ -76,8 +76,14 @@ export function useStateEX<ValueType>(initialValue: ValueType, options?: {
76
76
 
77
77
 
78
78
  let setValueWithEvents = wrapFunction(setValueWithCheck, {
79
- before: newValue => isFunction(options.onChange) ? options.onChange(newValue) : newValue,
80
- after: newValue => currentValue.current = newValue as ValueType
79
+ before: (newValue: ValueType) => isFunction(options.onChange) ? options.onChange(newValue) : newValue,
80
+ after: (newValue: ValueType) => currentValue.current = isPrimitiveValue(newValue) || isFunction(newValue)
81
+ ? newValue
82
+ //fix skipUpdateIfSame for complex objects
83
+ //if we don't clone it, currentValue.current will be a ref to the value in the owner
84
+ //and will be treated as unchanged object, and it will be out of sync
85
+ //this leads to skipUpdateIfSame failing after just 1 unchanged update
86
+ : jsonClone(newValue) as ValueType
81
87
  });
82
88
 
83
89
  const setValue = useCallback((newState: ValueType) => new Promise<ValueType>(resolve => {
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export * from './controls/canvas/DrawPad';
4
4
  export * from './controls/centered';
5
5
  export * from './controls/ColorPickerDialog';
6
6
  export * from './controls/date';
7
+ export * from './controls/diagram-picker';
7
8
  export * from './controls/divider';
8
9
  export * from './controls/dropdown';
9
10
  export * from './controls/error-boundary';
@@ -86,6 +86,18 @@ export const useCommonStyles = makeStyles({
86
86
  display: 'none !important'
87
87
  }
88
88
  },
89
+ hintLabel: {
90
+ color: tokens.colorNeutralForeground3,
91
+ fontSize: tokens.fontSizeBase200,
92
+ fontWeight: tokens.fontWeightRegular,
93
+ lineHeight: tokens.lineHeightBase200
94
+ },
95
+ validationLabel: {
96
+ color: tokens.colorPaletteRedForeground1,
97
+ fontSize: tokens.fontSizeBase200,
98
+ fontWeight: tokens.fontWeightRegular,
99
+ lineHeight: tokens.lineHeightBase200
100
+ }
89
101
  });
90
102
 
91
103
  export const commonSizes = {