@trackunit/react-form-components 1.0.19 → 1.0.23

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
@@ -581,8 +581,7 @@ const IndeterminateIcon = ({ className }) => (jsxRuntime.jsx("svg", { className:
581
581
  const Checkbox = React__namespace.forwardRef(({ className, dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ...rest }, ref) => {
582
582
  const icon = indeterminate ? (jsxRuntime.jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsxRuntime.jsx(CheckIcon, { className: cvaCheckboxIcon() }));
583
583
  const internalRef = React__namespace.useRef(null);
584
- const labelRef = React__namespace.useRef(null);
585
- const textIsCutOff = reactComponents.useIsTextCutOff(labelRef);
584
+ const { isTextTruncated: isLabelCutOff, ref: labelRef } = reactComponents.useIsTextTruncated();
586
585
  const isReadonly = disabled || readOnly;
587
586
  const onKeyPress = e => {
588
587
  if ("Space" === e.code) {
@@ -598,7 +597,7 @@ const Checkbox = React__namespace.forwardRef(({ className, dataTestId = "checkbo
598
597
  disabled: isReadonly,
599
598
  invalid: isReadonly ? false : isInvalid,
600
599
  state: indeterminate ? "indeterminate" : checked ? "selected" : "deselected",
601
- }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon }), jsxRuntime.jsx(reactComponents.Tooltip, { className: "w-full", disabled: !textIsCutOff, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
600
+ }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon }), jsxRuntime.jsx(reactComponents.Tooltip, { className: "w-full", disabled: !isLabelCutOff, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
602
601
  invalid: isReadonly ? false : isInvalid,
603
602
  disabled: isReadonly,
604
603
  }), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix] }));
@@ -1485,20 +1484,18 @@ RadioGroup.displayName = "RadioGroup";
1485
1484
  const RadioItem = ({ label, value, dataTestId, className, description, suffix, ...rest }) => {
1486
1485
  const groupCtx = React.useContext(RadioGroupContext);
1487
1486
  const isChecked = groupCtx?.value === value;
1488
- const labelRef = React.useRef(null);
1489
- const descriptionRef = React.useRef(null);
1490
- const labelTextIsCutOff = reactComponents.useIsTextCutOff(labelRef);
1491
- const descriptionTextIsCutOff = reactComponents.useIsTextCutOff(descriptionRef);
1487
+ const { ref: labelRef, isTextTruncated: isLabelTruncated } = reactComponents.useIsTextTruncated();
1488
+ const { ref: descriptionRef, isTextTruncated: isDescriptionTruncated } = reactComponents.useIsTextTruncated();
1492
1489
  const descriptionId = description ? `${groupCtx?.id}-${value}-description` : undefined;
1493
1490
  const inputId = `${groupCtx?.id}-${value}`;
1494
1491
  return (jsxRuntime.jsxs("label", { className: cvaRadioItemWrapper({ className }), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, htmlFor: inputId, children: [jsxRuntime.jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
1495
1492
  checked: isChecked,
1496
1493
  disabled: groupCtx?.disabled,
1497
1494
  invalid: groupCtx?.isInvalid,
1498
- }), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaLabelTooltip(), dataTestId: dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !labelTextIsCutOff, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
1495
+ }), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaLabelTooltip(), dataTestId: dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !isLabelTruncated, label: label, placement: "top", children: jsxRuntime.jsx("span", { className: cvaLabel({
1499
1496
  invalid: groupCtx?.isInvalid,
1500
1497
  disabled: groupCtx?.disabled,
1501
- }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix ? (jsxRuntime.jsx("div", { className: cvaSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaDescriptionTooltip(), dataTestId: dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !descriptionTextIsCutOff, label: description, placement: "top", children: jsxRuntime.jsx("span", { className: cvaRadioItemDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
1498
+ }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix ? (jsxRuntime.jsx("div", { className: cvaSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsxRuntime.jsx(reactComponents.Tooltip, { className: cvaDescriptionTooltip(), dataTestId: dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsxRuntime.jsx("span", { className: cvaRadioItemDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
1502
1499
  };
1503
1500
 
1504
1501
  const cvaTimeRange = cssClassVarianceUtilities.cvaMerge([
@@ -1934,7 +1931,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled
1934
1931
  * @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
1935
1932
  * @param {boolean} disabled decide to override disabled variant
1936
1933
  * @param {boolean} menuIsOpen menu is open state
1937
- * @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
1934
+ * @param {MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
1938
1935
  * @param {string} dataTestId a test id
1939
1936
  * @param {number} maxSelectedDisplayCount a number of max display count
1940
1937
  * @param {JSX.Element} dropdownIcon an custom dropdown icon
@@ -1945,7 +1942,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled
1945
1942
  const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon, prefix, hasError, getOptionLabelDescription, }) => {
1946
1943
  const [t] = useTranslation();
1947
1944
  // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
1948
- const customComponents = React__namespace.useMemo(() => {
1945
+ const customComponents = React.useMemo(() => {
1949
1946
  return {
1950
1947
  ValueContainer: props => {
1951
1948
  if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
@@ -1994,7 +1991,12 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEna
1994
1991
  if (disabled) {
1995
1992
  return null;
1996
1993
  }
1997
- return (jsxRuntime.jsx(ReactSelect.components.ClearIndicator, { ...props, children: jsxRuntime.jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId ? `${dataTestId}-XMarkIcon` : null, onClick: props.clearValue, children: jsxRuntime.jsx(reactComponents.Icon, { ariaLabel: t("clearIndicator.icon.tooltip.clearAll"), name: "XCircle", size: "medium" }) }) }));
1994
+ return (jsxRuntime.jsx(ReactSelect.components.ClearIndicator, { ...props, innerProps: {
1995
+ ...props.innerProps,
1996
+ onMouseDown: e => {
1997
+ e.preventDefault();
1998
+ },
1999
+ }, children: jsxRuntime.jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId ? `${dataTestId}-XMarkIcon` : null, onClick: props.clearValue, children: jsxRuntime.jsx(reactComponents.Icon, { ariaLabel: t("clearIndicator.icon.tooltip.clearAll"), name: "XCircle", size: "medium" }) }) }));
1998
2000
  },
1999
2001
  Control: props => {
2000
2002
  return (jsxRuntime.jsx(ReactSelect.components.Control, { ...props, className: cvaSelectControl({
package/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useNamespaceTranslation, registerTranslations, NamespaceTrans } from '@trackunit/i18n-library-translation';
3
- import { IconButton, Icon, Tooltip, useIsTextCutOff, Heading, Text, Spinner, MenuItem, Tag, useIsFirstRender } from '@trackunit/react-components';
3
+ import { IconButton, Icon, Tooltip, useIsTextTruncated, Heading, Text, Spinner, MenuItem, Tag, useIsFirstRender } from '@trackunit/react-components';
4
4
  import { useCopyToClipboard } from 'usehooks-ts';
5
5
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
6
6
  import * as React from 'react';
@@ -562,8 +562,7 @@ const IndeterminateIcon = ({ className }) => (jsx("svg", { className: className,
562
562
  const Checkbox = React.forwardRef(({ className, dataTestId = "checkbox", onChange, checked = false, disabled = false, isInvalid = false, readOnly, indeterminate = false, suffix, label, tabIndex = 0, stopPropagation, ...rest }, ref) => {
563
563
  const icon = indeterminate ? (jsx(IndeterminateIcon, { className: cvaCheckboxIcon() })) : (checked && jsx(CheckIcon, { className: cvaCheckboxIcon() }));
564
564
  const internalRef = React.useRef(null);
565
- const labelRef = React.useRef(null);
566
- const textIsCutOff = useIsTextCutOff(labelRef);
565
+ const { isTextTruncated: isLabelCutOff, ref: labelRef } = useIsTextTruncated();
567
566
  const isReadonly = disabled || readOnly;
568
567
  const onKeyPress = e => {
569
568
  if ("Space" === e.code) {
@@ -579,7 +578,7 @@ const Checkbox = React.forwardRef(({ className, dataTestId = "checkbox", onChang
579
578
  disabled: isReadonly,
580
579
  invalid: isReadonly ? false : isInvalid,
581
580
  state: indeterminate ? "indeterminate" : checked ? "selected" : "deselected",
582
- }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon }), jsx(Tooltip, { className: "w-full", disabled: !textIsCutOff, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
581
+ }), id: uuid, tabIndex: isReadonly ? -1 : tabIndex, children: icon }), jsx(Tooltip, { className: "w-full", disabled: !isLabelCutOff, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
583
582
  invalid: isReadonly ? false : isInvalid,
584
583
  disabled: isReadonly,
585
584
  }), id: `checkbox-label-${label}`, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix] }));
@@ -1466,20 +1465,18 @@ RadioGroup.displayName = "RadioGroup";
1466
1465
  const RadioItem = ({ label, value, dataTestId, className, description, suffix, ...rest }) => {
1467
1466
  const groupCtx = useContext(RadioGroupContext);
1468
1467
  const isChecked = groupCtx?.value === value;
1469
- const labelRef = useRef(null);
1470
- const descriptionRef = useRef(null);
1471
- const labelTextIsCutOff = useIsTextCutOff(labelRef);
1472
- const descriptionTextIsCutOff = useIsTextCutOff(descriptionRef);
1468
+ const { ref: labelRef, isTextTruncated: isLabelTruncated } = useIsTextTruncated();
1469
+ const { ref: descriptionRef, isTextTruncated: isDescriptionTruncated } = useIsTextTruncated();
1473
1470
  const descriptionId = description ? `${groupCtx?.id}-${value}-description` : undefined;
1474
1471
  const inputId = `${groupCtx?.id}-${value}`;
1475
1472
  return (jsxs("label", { className: cvaRadioItemWrapper({ className }), "data-testid": dataTestId ? `${dataTestId}-Wrapper` : undefined, htmlFor: inputId, children: [jsx("input", { "aria-describedby": descriptionId, checked: isChecked, className: cvaRadioItem({
1476
1473
  checked: isChecked,
1477
1474
  disabled: groupCtx?.disabled,
1478
1475
  invalid: groupCtx?.isInvalid,
1479
- }), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), jsx(Tooltip, { className: cvaLabelTooltip(), dataTestId: dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !labelTextIsCutOff, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
1476
+ }), "data-testid": dataTestId, id: inputId, onChange: groupCtx?.onChange, type: "radio", value: value, ...rest }), jsx(Tooltip, { className: cvaLabelTooltip(), dataTestId: dataTestId ? `${dataTestId}-Label-Tooltip` : undefined, disabled: !isLabelTruncated, label: label, placement: "top", children: jsx("span", { className: cvaLabel({
1480
1477
  invalid: groupCtx?.isInvalid,
1481
1478
  disabled: groupCtx?.disabled,
1482
- }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix ? (jsx("div", { className: cvaSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaDescriptionTooltip(), dataTestId: dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !descriptionTextIsCutOff, label: description, placement: "top", children: jsx("span", { className: cvaRadioItemDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
1479
+ }), "data-testid": dataTestId ? `${dataTestId}-Label` : undefined, ref: labelRef, children: label }) }, "tooltip-" + rest.name), suffix ? (jsx("div", { className: cvaSuffixContainer(), "data-testid": dataTestId ? `${dataTestId}-suffix-container` : undefined, children: suffix })) : null, description ? (jsx(Tooltip, { className: cvaDescriptionTooltip(), dataTestId: dataTestId ? `${dataTestId}-Description-Tooltip` : undefined, disabled: !isDescriptionTruncated, label: description, placement: "top", children: jsx("span", { className: cvaRadioItemDescription({ disabled: groupCtx?.disabled }), "data-testid": dataTestId ? `${dataTestId}-Description` : undefined, id: descriptionId, ref: descriptionRef, children: description }) }, "description-tooltip-" + rest.name)) : null] }));
1483
1480
  };
1484
1481
 
1485
1482
  const cvaTimeRange = cvaMerge([
@@ -1915,7 +1912,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled
1915
1912
  * @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
1916
1913
  * @param {boolean} disabled decide to override disabled variant
1917
1914
  * @param {boolean} menuIsOpen menu is open state
1918
- * @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
1915
+ * @param {MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
1919
1916
  * @param {string} dataTestId a test id
1920
1917
  * @param {number} maxSelectedDisplayCount a number of max display count
1921
1918
  * @param {JSX.Element} dropdownIcon an custom dropdown icon
@@ -1926,7 +1923,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix, disabled
1926
1923
  const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEnabled, dataTestId, maxSelectedDisplayCount, dropdownIcon, prefix, hasError, getOptionLabelDescription, }) => {
1927
1924
  const [t] = useTranslation();
1928
1925
  // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
1929
- const customComponents = React.useMemo(() => {
1926
+ const customComponents = useMemo(() => {
1930
1927
  return {
1931
1928
  ValueContainer: props => {
1932
1929
  if (props.isMulti && Array.isArray(props.children) && props.children.length > 0) {
@@ -1975,7 +1972,12 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, refMenuIsEna
1975
1972
  if (disabled) {
1976
1973
  return null;
1977
1974
  }
1978
- return (jsx(components.ClearIndicator, { ...props, children: jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId ? `${dataTestId}-XMarkIcon` : null, onClick: props.clearValue, children: jsx(Icon, { ariaLabel: t("clearIndicator.icon.tooltip.clearAll"), name: "XCircle", size: "medium" }) }) }));
1975
+ return (jsx(components.ClearIndicator, { ...props, innerProps: {
1976
+ ...props.innerProps,
1977
+ onMouseDown: e => {
1978
+ e.preventDefault();
1979
+ },
1980
+ }, children: jsx("div", { className: cvaSelectXIcon(), "data-testid": dataTestId ? `${dataTestId}-XMarkIcon` : null, onClick: props.clearValue, children: jsx(Icon, { ariaLabel: t("clearIndicator.icon.tooltip.clearAll"), name: "XCircle", size: "medium" }) }) }));
1979
1981
  },
1980
1982
  Control: props => {
1981
1983
  return (jsx(components.Control, { ...props, className: cvaSelectControl({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "1.0.19",
3
+ "version": "1.0.23",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -17,11 +17,11 @@
17
17
  "zod": "3.22.4",
18
18
  "react-hook-form": "7.53.1",
19
19
  "tailwind-merge": "^2.0.0",
20
- "@trackunit/css-class-variance-utilities": "^1.0.1",
21
- "@trackunit/react-components": "^1.1.1",
22
- "@trackunit/ui-icons": "^1.0.4",
23
- "@trackunit/shared-utils": "^1.0.3",
24
- "@trackunit/i18n-library-translation": "^1.0.8"
20
+ "@trackunit/css-class-variance-utilities": "^1.0.2",
21
+ "@trackunit/react-components": "^1.1.5",
22
+ "@trackunit/ui-icons": "^1.0.5",
23
+ "@trackunit/shared-utils": "^1.1.1",
24
+ "@trackunit/i18n-library-translation": "^1.0.11"
25
25
  },
26
26
  "module": "./index.esm.js",
27
27
  "main": "./index.cjs.js",
@@ -1,4 +1,4 @@
1
- import * as React from "react";
1
+ import { MutableRefObject } from "react";
2
2
  import { GroupBase } from "react-select";
3
3
  import { SelectComponents } from "react-select/dist/declarations/src/components";
4
4
  /**
@@ -10,7 +10,7 @@ import { SelectComponents } from "react-select/dist/declarations/src/components"
10
10
  * @param {Partial<SelectComponents<Option, IsMulti, Group>> | undefined} componentsProps a custom component prop that you can to override defaults
11
11
  * @param {boolean} disabled decide to override disabled variant
12
12
  * @param {boolean} menuIsOpen menu is open state
13
- * @param {React.MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
13
+ * @param {MutableRefObject<boolean>} refMenuIsEnabled a flag to block menu from open
14
14
  * @param {string} dataTestId a test id
15
15
  * @param {number} maxSelectedDisplayCount a number of max display count
16
16
  * @param {JSX.Element} dropdownIcon an custom dropdown icon
@@ -22,7 +22,7 @@ export declare const useCustomComponents: <Option, IsMulti extends boolean = fal
22
22
  componentsProps: Partial<SelectComponents<Option, IsMulti, Group>> | undefined;
23
23
  disabled: boolean;
24
24
  readOnly: boolean;
25
- refMenuIsEnabled: React.MutableRefObject<boolean>;
25
+ refMenuIsEnabled: MutableRefObject<boolean>;
26
26
  dataTestId: string;
27
27
  maxSelectedDisplayCount: number | undefined;
28
28
  dropdownIcon?: JSX.Element;
@@ -12,9 +12,9 @@ import { BaseOptionType } from "./FormFieldSelectAdapter";
12
12
  */
13
13
  export declare const CreatableSelectField: import("react").ForwardRefExoticComponent<import("dist/libs/react/components/src").CommonProps & {
14
14
  label: string | React.ReactNode;
15
- tip?: string | React.ReactNode;
16
- helpText?: (string | null) | undefined;
17
- helpAddon?: string | React.ReactNode;
15
+ tip?: import("react").ReactNode;
16
+ helpText?: string | null | undefined;
17
+ helpAddon?: import("react").ReactNode;
18
18
  isInvalid?: boolean | undefined;
19
19
  } & import("dist/libs/shared/utils/src").MappedOmit<import("../Select/useSelect").SelectProps<BaseOptionType, false, false, import("react-select").GroupBase<BaseOptionType>>, "label" | "onBlur" | "onChange" | "options" | "value" | "defaultValue"> & {
20
20
  onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
@@ -11,9 +11,9 @@ import { BaseOptionType } from "./FormFieldSelectAdapter";
11
11
  */
12
12
  export declare const SelectField: import("react").ForwardRefExoticComponent<import("dist/libs/react/components/src").CommonProps & {
13
13
  label: string | React.ReactNode;
14
- tip?: string | React.ReactNode;
15
- helpText?: (string | null) | undefined;
16
- helpAddon?: string | React.ReactNode;
14
+ tip?: import("react").ReactNode;
15
+ helpText?: string | null | undefined;
16
+ helpAddon?: import("react").ReactNode;
17
17
  isInvalid?: boolean | undefined;
18
18
  } & import("dist/libs/shared/utils/src").MappedOmit<import("../Select/useSelect").SelectProps<BaseOptionType, false, false, import("react-select").GroupBase<BaseOptionType>>, "label" | "onBlur" | "onChange" | "options" | "value" | "defaultValue"> & {
19
19
  onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;