@trackunit/react-form-components 0.0.297 → 0.0.301

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/index.cjs.js CHANGED
@@ -12,6 +12,7 @@ var ReactSelect = require('react-select');
12
12
  var ReactAsyncCreatableSelect = require('react-select/async-creatable');
13
13
  var ReactCreatableSelect = require('react-select/creatable');
14
14
  var ReactAsyncSelect = require('react-select/async');
15
+ var reactUse = require('react-use');
15
16
  var dateFns = require('date-fns');
16
17
  var parsePhoneNumberFromString = require('libphonenumber-js');
17
18
 
@@ -930,7 +931,9 @@ const cvaActionContainer = cssClassVarianceUtilities.cvaMerge(["flex", "items-ce
930
931
  * @param {ActionButtonProps} props - The props for the ActionButton component
931
932
  * @returns {JSX.Element} ActionButton component
932
933
  */
933
- const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className, }) => {
934
+ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, key, className }) => {
935
+ const [, copyToClipboard] = reactUse.useCopyToClipboard();
936
+ const elementKey = React.useMemo(() => key !== null && key !== void 0 ? key : `ActionButton-${uuid.v4()}`, [key]);
934
937
  const getIconName = () => {
935
938
  switch (type) {
936
939
  case "PHONE_NUMBER":
@@ -938,11 +941,14 @@ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className,
938
941
  case "WEB_ADDRESS":
939
942
  return "ArrowTopRightOnSquare";
940
943
  case "EMAIL":
941
- default:
942
944
  return "Envelope";
945
+ case "COPY":
946
+ default:
947
+ return "ClipboardDocument";
943
948
  }
944
949
  };
945
950
  const ButtonAction = () => {
951
+ var _a, _b;
946
952
  switch (type) {
947
953
  case "EMAIL":
948
954
  return window.open(`mailto:${value}`);
@@ -952,11 +958,17 @@ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className,
952
958
  }
953
959
  return null;
954
960
  case "PHONE_NUMBER":
955
- default:
956
961
  return window.open(`tel:${value}`);
962
+ case "COPY":
963
+ return copyToClipboard((_b = (_a = value === null || value === void 0 ? void 0 : value.current) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "");
964
+ default:
965
+ return null;
957
966
  }
958
967
  };
959
- return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className }), children: jsxRuntime.jsx(reactComponents.IconButton, { disabled: disabled, dataTestId: dataTestId || "testIconButtonId", size: "small", variant: "secondary", icon: jsxRuntime.jsx(reactComponents.Icon, { size: "small", name: getIconName() }), onClick: ButtonAction, className: cvaActionButton({ size: iconSize }) }) }));
968
+ if (ButtonAction === null) {
969
+ return null;
970
+ }
971
+ return (jsxRuntime.jsx("div", { className: cvaActionContainer({ className }), children: jsxRuntime.jsx(reactComponents.IconButton, { disabled: disabled, dataTestId: dataTestId || "testIconButtonId", size: "small", variant: "secondary", icon: jsxRuntime.jsx(reactComponents.Icon, { size: "small", name: getIconName() }), onClick: ButtonAction, className: cvaActionButton({ size: iconSize }) }) }, elementKey));
960
972
  };
961
973
 
962
974
  const cvaInputBase = cssClassVarianceUtilities.cvaMerge([
@@ -1057,9 +1069,11 @@ const cvaInputSuffix = cssClassVarianceUtilities.cvaMerge(["flex", "justify-cent
1057
1069
  * This is a base used by our other input components such as TextInput, NumberInput, PasswordInput, etc.
1058
1070
  */
1059
1071
  const BaseInput = React__namespace.forwardRef((_a, ref) => {
1060
- var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "type", "inputClassName", "addonBeforeClassName"]);
1072
+ var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, showDefaultActions = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "showDefaultActions", "type", "inputClassName", "addonBeforeClassName"]);
1061
1073
  const isReadOnlyWithPlaceholder = React.useMemo(() => !!rest.readOnly && !!rest.placeholder && !rest.value, [rest.readOnly, rest.placeholder, rest.value]);
1062
1074
  const renderAsDisabled = rest.disabled || rest.readOnly;
1075
+ const innerRef = React__namespace.useRef(null);
1076
+ React__namespace.useImperativeHandle(ref, () => innerRef.current, []);
1063
1077
  return (jsxRuntime.jsxs("div", { className: cvaInput({
1064
1078
  disabled: renderAsDisabled,
1065
1079
  invalid: isInvalid,
@@ -1067,9 +1081,9 @@ const BaseInput = React__namespace.forwardRef((_a, ref) => {
1067
1081
  className,
1068
1082
  }), "data-testid": dataTestId && `${dataTestId}-container`, children: [addonBefore && addonBefore !== undefined ? (jsxRuntime.jsx("div", { className: cvaInputAddonBefore({ className: addonBeforeClassName }), "data-testid": dataTestId && `${dataTestId}-addonBefore`, children: addonBefore })) : null, prefix && addonBefore !== prefix ? (jsxRuntime.jsx("div", { className: cvaInputPrefix({
1069
1083
  disabled: renderAsDisabled,
1070
- }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsxRuntime.jsx("input", Object.assign({ ref: ref, "data-testid": dataTestId, className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsxRuntime.jsx("div", { className: cvaInputSuffix({
1084
+ }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsxRuntime.jsx("input", Object.assign({ ref: innerRef, "data-testid": dataTestId, className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsxRuntime.jsx("div", { className: cvaInputSuffix({
1071
1085
  disabled: renderAsDisabled,
1072
- }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsxRuntime.jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
1086
+ }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, rest.readOnly === true && showDefaultActions ? (jsxRuntime.jsx(ActionButton, { type: "COPY", value: innerRef }, "default-copy-action")) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsxRuntime.jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
1073
1087
  });
1074
1088
 
1075
1089
  /**
@@ -2116,7 +2130,7 @@ const TimeRangeField = (_a) => {
2116
2130
  var { className, dataTestId, onChange, isInvalid, errorMessage, label, tip, disabled, children, helpText, id } = _a, rest = __rest(_a, ["className", "dataTestId", "onChange", "isInvalid", "errorMessage", "label", "tip", "disabled", "children", "helpText", "id"]);
2117
2131
  const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
2118
2132
  const htmlFor = id ? id : "timeRangeField-" + uuid.v4();
2119
- return (jsxRuntime.jsx(FormGroup, { htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: disabled, children: jsxRuntime.jsx(TimeRange, Object.assign({ className: className, onChange: onChange, disabled: disabled, dataTestId: dataTestId, isInvalid: renderAsInvalid, children: children }, rest)) }));
2133
+ return (jsxRuntime.jsx(FormGroup, { htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: disabled, children: jsxRuntime.jsx(TimeRange, Object.assign({ className: className, onChange: onChange, disabled: disabled, dataTestId: dataTestId, isInvalid: renderAsInvalid }, rest, { children: children })) }));
2120
2134
  };
2121
2135
 
2122
2136
  const cvaToggleWrapper = cssClassVarianceUtilities.cvaMerge(["flex", "gap-2", "items-center"]);
package/index.esm.js CHANGED
@@ -10,6 +10,7 @@ export { default as ValueType } from 'react-select';
10
10
  import ReactAsyncCreatableSelect from 'react-select/async-creatable';
11
11
  import ReactCreatableSelect from 'react-select/creatable';
12
12
  import ReactAsyncSelect from 'react-select/async';
13
+ import { useCopyToClipboard } from 'react-use';
13
14
  import { format } from 'date-fns';
14
15
  import parsePhoneNumberFromString, { isSupportedCountry, getCountries, getCountryCallingCode, isValidPhoneNumber, parsePhoneNumberFromString as parsePhoneNumberFromString$1 } from 'libphonenumber-js';
15
16
 
@@ -900,7 +901,9 @@ const cvaActionContainer = cvaMerge(["flex", "items-center", "m-1"]);
900
901
  * @param {ActionButtonProps} props - The props for the ActionButton component
901
902
  * @returns {JSX.Element} ActionButton component
902
903
  */
903
- const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className, }) => {
904
+ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, key, className }) => {
905
+ const [, copyToClipboard] = useCopyToClipboard();
906
+ const elementKey = useMemo(() => key !== null && key !== void 0 ? key : `ActionButton-${v4()}`, [key]);
904
907
  const getIconName = () => {
905
908
  switch (type) {
906
909
  case "PHONE_NUMBER":
@@ -908,11 +911,14 @@ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className,
908
911
  case "WEB_ADDRESS":
909
912
  return "ArrowTopRightOnSquare";
910
913
  case "EMAIL":
911
- default:
912
914
  return "Envelope";
915
+ case "COPY":
916
+ default:
917
+ return "ClipboardDocument";
913
918
  }
914
919
  };
915
920
  const ButtonAction = () => {
921
+ var _a, _b;
916
922
  switch (type) {
917
923
  case "EMAIL":
918
924
  return window.open(`mailto:${value}`);
@@ -922,11 +928,17 @@ const ActionButton = ({ type, value, dataTestId, iconSize, disabled, className,
922
928
  }
923
929
  return null;
924
930
  case "PHONE_NUMBER":
925
- default:
926
931
  return window.open(`tel:${value}`);
932
+ case "COPY":
933
+ return copyToClipboard((_b = (_a = value === null || value === void 0 ? void 0 : value.current) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "");
934
+ default:
935
+ return null;
927
936
  }
928
937
  };
929
- return (jsx("div", { className: cvaActionContainer({ className }), children: jsx(IconButton, { disabled: disabled, dataTestId: dataTestId || "testIconButtonId", size: "small", variant: "secondary", icon: jsx(Icon, { size: "small", name: getIconName() }), onClick: ButtonAction, className: cvaActionButton({ size: iconSize }) }) }));
938
+ if (ButtonAction === null) {
939
+ return null;
940
+ }
941
+ return (jsx("div", { className: cvaActionContainer({ className }), children: jsx(IconButton, { disabled: disabled, dataTestId: dataTestId || "testIconButtonId", size: "small", variant: "secondary", icon: jsx(Icon, { size: "small", name: getIconName() }), onClick: ButtonAction, className: cvaActionButton({ size: iconSize }) }) }, elementKey));
930
942
  };
931
943
 
932
944
  const cvaInputBase = cvaMerge([
@@ -1027,9 +1039,11 @@ const cvaInputSuffix = cvaMerge(["flex", "justify-center", "items-center", "text
1027
1039
  * This is a base used by our other input components such as TextInput, NumberInput, PasswordInput, etc.
1028
1040
  */
1029
1041
  const BaseInput = React.forwardRef((_a, ref) => {
1030
- var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "type", "inputClassName", "addonBeforeClassName"]);
1042
+ var { className, isInvalid, dataTestId, prefix, suffix, addonBefore, addonAfter, actions, fieldSize = "medium", nonInteractive = false, showDefaultActions = false, type, inputClassName, addonBeforeClassName } = _a, rest = __rest(_a, ["className", "isInvalid", "dataTestId", "prefix", "suffix", "addonBefore", "addonAfter", "actions", "fieldSize", "nonInteractive", "showDefaultActions", "type", "inputClassName", "addonBeforeClassName"]);
1031
1043
  const isReadOnlyWithPlaceholder = useMemo(() => !!rest.readOnly && !!rest.placeholder && !rest.value, [rest.readOnly, rest.placeholder, rest.value]);
1032
1044
  const renderAsDisabled = rest.disabled || rest.readOnly;
1045
+ const innerRef = React.useRef(null);
1046
+ React.useImperativeHandle(ref, () => innerRef.current, []);
1033
1047
  return (jsxs("div", { className: cvaInput({
1034
1048
  disabled: renderAsDisabled,
1035
1049
  invalid: isInvalid,
@@ -1037,9 +1051,9 @@ const BaseInput = React.forwardRef((_a, ref) => {
1037
1051
  className,
1038
1052
  }), "data-testid": dataTestId && `${dataTestId}-container`, children: [addonBefore && addonBefore !== undefined ? (jsx("div", { className: cvaInputAddonBefore({ className: addonBeforeClassName }), "data-testid": dataTestId && `${dataTestId}-addonBefore`, children: addonBefore })) : null, prefix && addonBefore !== prefix ? (jsx("div", { className: cvaInputPrefix({
1039
1053
  disabled: renderAsDisabled,
1040
- }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsx("input", Object.assign({ ref: ref, "data-testid": dataTestId, className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsx("div", { className: cvaInputSuffix({
1054
+ }), "data-testid": dataTestId && `${dataTestId}-prefix`, children: prefix })) : null, jsx("input", Object.assign({ ref: innerRef, "data-testid": dataTestId, className: cvaInputField({ size: fieldSize, disabled: renderAsDisabled, className: inputClassName }), type: isReadOnlyWithPlaceholder ? "text" : type }, rest, { readOnly: rest.readOnly || nonInteractive })), suffix && addonBefore !== suffix ? (jsx("div", { className: cvaInputSuffix({
1041
1055
  disabled: renderAsDisabled,
1042
- }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
1056
+ }), "data-testid": dataTestId && `${dataTestId}-suffix`, children: suffix })) : null, rest.readOnly === true && showDefaultActions ? (jsx(ActionButton, { type: "COPY", value: innerRef }, "default-copy-action")) : null, actions && addonBefore !== actions ? actions : null, addonAfter && addonAfter !== undefined && addonBefore !== addonAfter ? (jsx("div", { className: cvaInputAddonAfter(), "data-testid": dataTestId && `${dataTestId}-addonAfter`, children: addonAfter })) : null] }));
1043
1057
  });
1044
1058
 
1045
1059
  /**
@@ -2086,7 +2100,7 @@ const TimeRangeField = (_a) => {
2086
2100
  var { className, dataTestId, onChange, isInvalid, errorMessage, label, tip, disabled, children, helpText, id } = _a, rest = __rest(_a, ["className", "dataTestId", "onChange", "isInvalid", "errorMessage", "label", "tip", "disabled", "children", "helpText", "id"]);
2087
2101
  const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
2088
2102
  const htmlFor = id ? id : "timeRangeField-" + v4();
2089
- return (jsx(FormGroup, { htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: disabled, children: jsx(TimeRange, Object.assign({ className: className, onChange: onChange, disabled: disabled, dataTestId: dataTestId, isInvalid: renderAsInvalid, children: children }, rest)) }));
2103
+ return (jsx(FormGroup, { htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: disabled, children: jsx(TimeRange, Object.assign({ className: className, onChange: onChange, disabled: disabled, dataTestId: dataTestId, isInvalid: renderAsInvalid }, rest, { children: children })) }));
2090
2104
  };
2091
2105
 
2092
2106
  const cvaToggleWrapper = cvaMerge(["flex", "gap-2", "items-center"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "0.0.297",
3
+ "version": "0.0.301",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -11,6 +11,7 @@
11
11
  "@trackunit/ui-icons": "*",
12
12
  "react": "^18.2.0",
13
13
  "uuid": "^9.0.1",
14
+ "react-use": "^17.4.0",
14
15
  "date-fns": "^2.30.0",
15
16
  "react-select": "^5.8.0",
16
17
  "libphonenumber-js": "1.10.36",
@@ -1,26 +1,51 @@
1
1
  /// <reference types="react" />
2
2
  import { ButtonCommonProps, CommonProps } from "@trackunit/react-components";
3
- type ActionType = "PHONE_NUMBER" | "WEB_ADDRESS" | "EMAIL";
3
+ type ActionType = "PHONE_NUMBER" | "WEB_ADDRESS" | "EMAIL" | "COPY";
4
4
  type FieldSize = "small" | "medium";
5
- interface ActionButtonProps extends ButtonCommonProps, CommonProps {
5
+ interface AbstractActionButtonProps extends ButtonCommonProps, CommonProps {
6
6
  /**
7
7
  * The type of action performed when clicking the button.
8
8
  */
9
9
  type: ActionType;
10
+ /**
11
+ * A key to be passed into the button.
12
+ */
13
+ key?: string;
10
14
  /**
11
15
  * The value to be passed into the button.
12
16
  */
13
- value?: string | null;
17
+ value?: string | React.RefObject<HTMLInputElement> | null;
14
18
  /**
15
19
  * The size of the icon.
16
20
  */
17
21
  iconSize?: FieldSize;
18
22
  }
23
+ interface GenericActionButtonProps extends AbstractActionButtonProps {
24
+ /**
25
+ * The type of action performed when clicking the button.
26
+ */
27
+ type: "PHONE_NUMBER" | "WEB_ADDRESS" | "EMAIL";
28
+ /**
29
+ * The value to be passed into the button.
30
+ */
31
+ value?: string | null;
32
+ }
33
+ interface CopyActionButtonProps extends AbstractActionButtonProps {
34
+ /**
35
+ * The type of action performed when clicking the button.
36
+ */
37
+ type: "COPY";
38
+ /**
39
+ * The value to be passed into the button.
40
+ */
41
+ value?: React.RefObject<HTMLInputElement>;
42
+ }
43
+ type ActionButtonProps = CopyActionButtonProps | GenericActionButtonProps;
19
44
  /**
20
45
  * The ActionButton component is a wrapper over IconButton to perform an action when the onClick event is triggered.
21
46
  *
22
47
  * @param {ActionButtonProps} props - The props for the ActionButton component
23
48
  * @returns {JSX.Element} ActionButton component
24
49
  */
25
- export declare const ActionButton: ({ type, value, dataTestId, iconSize, disabled, className, }: ActionButtonProps) => JSX.Element;
50
+ export declare const ActionButton: ({ type, value, dataTestId, iconSize, disabled, key, className }: ActionButtonProps) => JSX.Element | null;
26
51
  export {};
@@ -57,6 +57,14 @@ export interface BaseInputProps extends FilteredInputProps, CommonProps {
57
57
  * Custom css classes for the addon before element.
58
58
  */
59
59
  addonBeforeClassName?: string;
60
+ /**
61
+ * If true the default actions are shown.
62
+ */
63
+ showDefaultActions?: boolean;
64
+ /**
65
+ * If true the input is readonly.
66
+ */
67
+ readonly?: boolean;
60
68
  }
61
69
  /**
62
70
  * A base input component that can be used for text inputs, password inputs, etc.