@trackunit/react-form-components 1.7.5 → 1.7.10

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
@@ -2051,8 +2051,13 @@ const cvaSelectMenu = cssClassVarianceUtilities.cvaMerge(["relative", "p-1", "gr
2051
2051
  * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
2052
2052
  * @returns {ReactElement} SingleSelectMenuItem
2053
2053
  */
2054
- const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
2055
- return (jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, prefix: icon, selected: selected, suffix: selected ? jsxRuntime.jsx(reactComponents.Icon, { className: "block text-blue-600", name: "Check", size: "medium" }) : undefined }));
2054
+ const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
2055
+ return (jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: react.isValidElement(optionPrefix)
2056
+ ? react.cloneElement(optionPrefix, {
2057
+ className: "mr-1 flex items-center",
2058
+ size: "medium",
2059
+ })
2060
+ : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsxRuntime.jsx(reactComponents.Icon, { className: "block text-blue-600", name: "Check", size: "medium" }) : undefined }));
2056
2061
  };
2057
2062
  /**
2058
2063
  * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
@@ -2060,11 +2065,16 @@ const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTes
2060
2065
  * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
2061
2066
  * @returns {ReactElement} multi select menu item
2062
2067
  */
2063
- const MultiSelectMenuItem = ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
2068
+ const MultiSelectMenuItem = ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
2064
2069
  return (jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: e => {
2065
2070
  e.stopPropagation();
2066
2071
  onClick && onClick(e);
2067
- }, optionLabelDescription: optionLabelDescription, prefix: jsxRuntime.jsx(Checkbox, { checked: selected, disabled: disabled, onChange: () => null, onClick: e => {
2072
+ }, optionLabelDescription: optionLabelDescription, optionPrefix: react.isValidElement(optionPrefix)
2073
+ ? react.cloneElement(optionPrefix, {
2074
+ className: "mr-1 flex items-center",
2075
+ size: "medium",
2076
+ })
2077
+ : optionPrefix, prefix: jsxRuntime.jsx(Checkbox, { checked: selected, className: "gap-x-0", disabled: disabled, onChange: () => null, onClick: e => {
2068
2078
  e.stopPropagation();
2069
2079
  }, readOnly: false }), selected: selected }));
2070
2080
  };
@@ -2081,7 +2091,7 @@ const TagWithWidth = ({ onWidthKnown, children, ...rest }) => {
2081
2091
  react.useLayoutEffect(() => {
2082
2092
  onWidthKnown && onWidthKnown({ width: ref.current?.offsetWidth || 0 });
2083
2093
  }, [ref, onWidthKnown]);
2084
- return (jsxRuntime.jsx(reactComponents.Tag, { ref: ref, ...rest, children: children }));
2094
+ return (jsxRuntime.jsx(reactComponents.Tag, { ref: ref, ...rest, icon: react.isValidElement(rest.icon) ? react.cloneElement(rest.icon, { size: "small" }) : rest.icon, children: children }));
2085
2095
  };
2086
2096
 
2087
2097
  /**
@@ -2130,7 +2140,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2130
2140
  ...acc,
2131
2141
  elements: [
2132
2142
  ...acc.elements,
2133
- jsxRuntime.jsx(TagWithWidth, { color: "white", disabled: disabled, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxRuntime.jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", acc.counter] }) }, item.text + index),
2143
+ jsxRuntime.jsx(TagWithWidth, { color: "white", disabled: disabled, icon: item.Icon, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxRuntime.jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", acc.counter] }) }, item.text + index),
2134
2144
  ],
2135
2145
  };
2136
2146
  }
@@ -2143,7 +2153,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2143
2153
  ...acc,
2144
2154
  elements: [
2145
2155
  ...acc.elements,
2146
- jsxRuntime.jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
2156
+ jsxRuntime.jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white", dataTestId: `${item.text}-tag`, disabled: disabled, icon: item.Icon, onClose: e => {
2147
2157
  e.stopPropagation();
2148
2158
  item.onClick();
2149
2159
  }, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index),
@@ -2177,7 +2187,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2177
2187
  * @param {ReactNode} prefix a prefix element
2178
2188
  * @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
2179
2189
  */
2180
- const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, }) => {
2190
+ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, getOptionPrefix, }) => {
2181
2191
  const [t] = useTranslation();
2182
2192
  // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
2183
2193
  const customComponents = react.useMemo(() => {
@@ -2194,6 +2204,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2194
2204
  const searchInput = props && props.children && props.children[1];
2195
2205
  return (jsxRuntime.jsx(ReactSelect.components.ValueContainer, { ...props, isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsxRuntime.jsx(TagsContainer, { disabled: disabled, items: tags
2196
2206
  ? tags.map(({ props: tagProps }) => {
2207
+ const optionPrefix = tagProps.data && getOptionPrefix ? getOptionPrefix(tagProps.data) : null;
2197
2208
  return {
2198
2209
  text: tagProps.children,
2199
2210
  onClick: disabled
@@ -2203,6 +2214,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2203
2214
  tagProps.removeProps.onClick && tagProps.removeProps.onClick(e);
2204
2215
  },
2205
2216
  disabled: disabled,
2217
+ Icon: optionPrefix,
2206
2218
  };
2207
2219
  })
2208
2220
  : [], postFix: searchInput, width: "100%" })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [tags
@@ -2244,7 +2256,8 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2244
2256
  }) }));
2245
2257
  },
2246
2258
  SingleValue: props => {
2247
- return (jsxRuntime.jsx(ReactSelect.components.SingleValue, { ...props, className: props.isDisabled ? "text-slate-700" : "", children: jsxRuntime.jsxs("div", { "data-testid": dataTestId + "-singleValue", children: [props.children, getOptionLabelDescription && getOptionLabelDescription(props.data) ? (jsxRuntime.jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", getOptionLabelDescription(props.data), ")"] })) : null] }) }));
2259
+ const optionPrefix = getOptionPrefix ? getOptionPrefix(props.data) : null;
2260
+ return (jsxRuntime.jsx(ReactSelect.components.SingleValue, { ...props, className: props.isDisabled ? "text-slate-700" : "", children: jsxRuntime.jsxs("div", { className: "flex items-center gap-1", "data-testid": dataTestId + "-singleValue", children: [optionPrefix !== null ? optionPrefix : null, props.children, getOptionLabelDescription && getOptionLabelDescription(props.data) ? (jsxRuntime.jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", getOptionLabelDescription(props.data), ")"] })) : null] }) }));
2248
2261
  },
2249
2262
  Menu: props => {
2250
2263
  return (jsxRuntime.jsx(ReactSelect.components.Menu, { ...props, className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) }));
@@ -2277,22 +2290,23 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2277
2290
  ...props.innerProps,
2278
2291
  role: "option",
2279
2292
  onClick: () => { },
2280
- }, children: props.isMulti ? (jsxRuntime.jsx(MultiSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data) })) : (jsxRuntime.jsx(SingleSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data) })) }));
2293
+ }, children: props.isMulti ? (jsxRuntime.jsx(MultiSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) : (jsxRuntime.jsx(SingleSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) }));
2281
2294
  },
2282
2295
  ...componentsProps,
2283
2296
  };
2284
2297
  }, [
2285
2298
  componentsProps,
2286
- disabled,
2287
- fieldSize,
2288
- getOptionLabelDescription,
2289
- hasError,
2290
2299
  maxSelectedDisplayCount,
2291
- prefix,
2292
- readOnly,
2300
+ disabled,
2293
2301
  setMenuIsEnabled,
2294
- t,
2302
+ readOnly,
2295
2303
  dataTestId,
2304
+ t,
2305
+ prefix,
2306
+ hasError,
2307
+ getOptionLabelDescription,
2308
+ fieldSize,
2309
+ getOptionPrefix,
2296
2310
  ]);
2297
2311
  return customComponents;
2298
2312
  };
@@ -2405,7 +2419,7 @@ const useCustomStyles = ({ refContainer, maxSelectedDisplayCount, styles, disabl
2405
2419
  * @param {SelectProps} props - The props for the Select component
2406
2420
  * @returns {UseSelectProps} Select component
2407
2421
  */
2408
- const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, fieldSize = "medium", ...props }) => {
2422
+ const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, getOptionPrefix, fieldSize = "medium", ...props }) => {
2409
2423
  const refContainer = react.useRef(document.createElement("div"));
2410
2424
  const { customStyles } = useCustomStyles({
2411
2425
  refContainer,
@@ -2427,6 +2441,7 @@ const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMen
2427
2441
  hasError,
2428
2442
  fieldSize,
2429
2443
  getOptionLabelDescription,
2444
+ getOptionPrefix,
2430
2445
  });
2431
2446
  const menuPlacement = "auto";
2432
2447
  const openMenuHandler = async () => {
package/index.esm.js CHANGED
@@ -4,7 +4,7 @@ import { IconButton, Icon, Tooltip, useGeometry, useIsTextTruncated, Text, Headi
4
4
  import { useCopyToClipboard } from 'usehooks-ts';
5
5
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
6
6
  import { themeSpacing } from '@trackunit/ui-design-tokens';
7
- import { forwardRef, useRef, useImperativeHandle, useMemo, useState, useCallback, useEffect, cloneElement, createContext, useContext, useLayoutEffect } from 'react';
7
+ import { forwardRef, useRef, useImperativeHandle, useMemo, useState, useCallback, useEffect, cloneElement, createContext, useContext, isValidElement, useLayoutEffect } from 'react';
8
8
  import { titleCase } from 'string-ts';
9
9
  import { uuidv4, nonNullable } from '@trackunit/shared-utils';
10
10
  import { Temporal } from '@js-temporal/polyfill';
@@ -2050,8 +2050,13 @@ const cvaSelectMenu = cvaMerge(["relative", "p-1", "grid", "gap-1"]);
2050
2050
  * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
2051
2051
  * @returns {ReactElement} SingleSelectMenuItem
2052
2052
  */
2053
- const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
2054
- return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { className: "block text-blue-600", name: "Check", size: "medium" }) : undefined }));
2053
+ const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
2054
+ return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
2055
+ ? cloneElement(optionPrefix, {
2056
+ className: "mr-1 flex items-center",
2057
+ size: "medium",
2058
+ })
2059
+ : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { className: "block text-blue-600", name: "Check", size: "medium" }) : undefined }));
2055
2060
  };
2056
2061
  /**
2057
2062
  * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
@@ -2059,11 +2064,16 @@ const SingleSelectMenuItem = ({ label, icon, onClick, selected, focused, dataTes
2059
2064
  * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
2060
2065
  * @returns {ReactElement} multi select menu item
2061
2066
  */
2062
- const MultiSelectMenuItem = ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }) => {
2067
+ const MultiSelectMenuItem = ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }) => {
2063
2068
  return (jsx(MenuItem, { dataTestId: dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: e => {
2064
2069
  e.stopPropagation();
2065
2070
  onClick && onClick(e);
2066
- }, optionLabelDescription: optionLabelDescription, prefix: jsx(Checkbox, { checked: selected, disabled: disabled, onChange: () => null, onClick: e => {
2071
+ }, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
2072
+ ? cloneElement(optionPrefix, {
2073
+ className: "mr-1 flex items-center",
2074
+ size: "medium",
2075
+ })
2076
+ : optionPrefix, prefix: jsx(Checkbox, { checked: selected, className: "gap-x-0", disabled: disabled, onChange: () => null, onClick: e => {
2067
2077
  e.stopPropagation();
2068
2078
  }, readOnly: false }), selected: selected }));
2069
2079
  };
@@ -2080,7 +2090,7 @@ const TagWithWidth = ({ onWidthKnown, children, ...rest }) => {
2080
2090
  useLayoutEffect(() => {
2081
2091
  onWidthKnown && onWidthKnown({ width: ref.current?.offsetWidth || 0 });
2082
2092
  }, [ref, onWidthKnown]);
2083
- return (jsx(Tag, { ref: ref, ...rest, children: children }));
2093
+ return (jsx(Tag, { ref: ref, ...rest, icon: isValidElement(rest.icon) ? cloneElement(rest.icon, { size: "small" }) : rest.icon, children: children }));
2084
2094
  };
2085
2095
 
2086
2096
  /**
@@ -2129,7 +2139,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2129
2139
  ...acc,
2130
2140
  elements: [
2131
2141
  ...acc.elements,
2132
- jsx(TagWithWidth, { color: "white", disabled: disabled, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", acc.counter] }) }, item.text + index),
2142
+ jsx(TagWithWidth, { color: "white", disabled: disabled, icon: item.Icon, onWidthKnown: ({ width: reportedWidth }) => setCounterWidth(reportedWidth), children: jsxs("div", { className: cvaSelectCounter(), "data-testid": "select-counter", children: ["+", acc.counter] }) }, item.text + index),
2133
2143
  ],
2134
2144
  };
2135
2145
  }
@@ -2142,7 +2152,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2142
2152
  ...acc,
2143
2153
  elements: [
2144
2154
  ...acc.elements,
2145
- jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white", dataTestId: `${item.text}-tag`, disabled: disabled, onClose: e => {
2155
+ jsx(TagWithWidth, { className: "inline-flex shrink-0", color: item.disabled ? "neutral" : "white", dataTestId: `${item.text}-tag`, disabled: disabled, icon: item.Icon, onClose: e => {
2146
2156
  e.stopPropagation();
2147
2157
  item.onClick();
2148
2158
  }, onWidthKnown: onWidthKnownHandler, children: item.text }, item.text + index),
@@ -2176,7 +2186,7 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 6, postFix, disabled
2176
2186
  * @param {ReactNode} prefix a prefix element
2177
2187
  * @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
2178
2188
  */
2179
- const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, }) => {
2189
+ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, getOptionPrefix, }) => {
2180
2190
  const [t] = useTranslation();
2181
2191
  // perhaps it should not be wrap in memo (causing some issues with opening and closing on mobiles)
2182
2192
  const customComponents = useMemo(() => {
@@ -2193,6 +2203,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2193
2203
  const searchInput = props && props.children && props.children[1];
2194
2204
  return (jsx(components.ValueContainer, { ...props, isDisabled: props.selectProps.isDisabled, children: maxSelectedDisplayCount === undefined ? (jsx(TagsContainer, { disabled: disabled, items: tags
2195
2205
  ? tags.map(({ props: tagProps }) => {
2206
+ const optionPrefix = tagProps.data && getOptionPrefix ? getOptionPrefix(tagProps.data) : null;
2196
2207
  return {
2197
2208
  text: tagProps.children,
2198
2209
  onClick: disabled
@@ -2202,6 +2213,7 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2202
2213
  tagProps.removeProps.onClick && tagProps.removeProps.onClick(e);
2203
2214
  },
2204
2215
  disabled: disabled,
2216
+ Icon: optionPrefix,
2205
2217
  };
2206
2218
  })
2207
2219
  : [], postFix: searchInput, width: "100%" })) : (jsxs(Fragment, { children: [tags
@@ -2243,7 +2255,8 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2243
2255
  }) }));
2244
2256
  },
2245
2257
  SingleValue: props => {
2246
- return (jsx(components.SingleValue, { ...props, className: props.isDisabled ? "text-slate-700" : "", children: jsxs("div", { "data-testid": dataTestId + "-singleValue", children: [props.children, getOptionLabelDescription && getOptionLabelDescription(props.data) ? (jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", getOptionLabelDescription(props.data), ")"] })) : null] }) }));
2258
+ const optionPrefix = getOptionPrefix ? getOptionPrefix(props.data) : null;
2259
+ return (jsx(components.SingleValue, { ...props, className: props.isDisabled ? "text-slate-700" : "", children: jsxs("div", { className: "flex items-center gap-1", "data-testid": dataTestId + "-singleValue", children: [optionPrefix !== null ? optionPrefix : null, props.children, getOptionLabelDescription && getOptionLabelDescription(props.data) ? (jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", getOptionLabelDescription(props.data), ")"] })) : null] }) }));
2247
2260
  },
2248
2261
  Menu: props => {
2249
2262
  return (jsx(components.Menu, { ...props, className: cvaSelectMenuList({ menuIsOpen: props.selectProps.menuIsOpen }) }));
@@ -2276,22 +2289,23 @@ const useCustomComponents = ({ componentsProps, disabled, readOnly, setMenuIsEna
2276
2289
  ...props.innerProps,
2277
2290
  role: "option",
2278
2291
  onClick: () => { },
2279
- }, children: props.isMulti ? (jsx(MultiSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data) })) : (jsx(SingleSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data) })) }));
2292
+ }, children: props.isMulti ? (jsx(MultiSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) : (jsx(SingleSelectMenuItem, { ...componentProps, dataTestId: typeof props.label === "string" ? props.label : undefined, disabled: disabled || props.isDisabled, fieldSize: fieldSize, optionLabelDescription: getOptionLabelDescription?.(props.data), optionPrefix: getOptionPrefix?.(props.data) })) }));
2280
2293
  },
2281
2294
  ...componentsProps,
2282
2295
  };
2283
2296
  }, [
2284
2297
  componentsProps,
2285
- disabled,
2286
- fieldSize,
2287
- getOptionLabelDescription,
2288
- hasError,
2289
2298
  maxSelectedDisplayCount,
2290
- prefix,
2291
- readOnly,
2299
+ disabled,
2292
2300
  setMenuIsEnabled,
2293
- t,
2301
+ readOnly,
2294
2302
  dataTestId,
2303
+ t,
2304
+ prefix,
2305
+ hasError,
2306
+ getOptionLabelDescription,
2307
+ fieldSize,
2308
+ getOptionPrefix,
2295
2309
  ]);
2296
2310
  return customComponents;
2297
2311
  };
@@ -2404,7 +2418,7 @@ const useCustomStyles = ({ refContainer, maxSelectedDisplayCount, styles, disabl
2404
2418
  * @param {SelectProps} props - The props for the Select component
2405
2419
  * @returns {UseSelectProps} Select component
2406
2420
  */
2407
- const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, fieldSize = "medium", ...props }) => {
2421
+ const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMenuHeight = 200, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix = "", onMenuOpen, onMenuClose, maxSelectedDisplayCount = undefined, isClearable = false, isSearchable = true, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, getOptionPrefix, fieldSize = "medium", ...props }) => {
2408
2422
  const refContainer = useRef(document.createElement("div"));
2409
2423
  const { customStyles } = useCustomStyles({
2410
2424
  refContainer,
@@ -2426,6 +2440,7 @@ const useSelect = ({ id, className, dataTestId = "select", prefix, async, maxMen
2426
2440
  hasError,
2427
2441
  fieldSize,
2428
2442
  getOptionLabelDescription,
2443
+ getOptionPrefix,
2429
2444
  });
2430
2445
  const menuPlacement = "auto";
2431
2446
  const openMenuHandler = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "1.7.5",
3
+ "version": "1.7.10",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -16,14 +16,14 @@
16
16
  "zod": "^3.23.8",
17
17
  "react-hook-form": "7.62.0",
18
18
  "tailwind-merge": "^2.0.0",
19
- "@trackunit/css-class-variance-utilities": "1.6.27",
20
- "@trackunit/react-components": "1.7.36",
21
- "@trackunit/ui-icons": "1.6.26",
22
- "@trackunit/shared-utils": "1.8.27",
23
- "@trackunit/ui-design-tokens": "1.6.28",
24
- "@trackunit/i18n-library-translation": "1.6.30",
19
+ "@trackunit/css-class-variance-utilities": "1.6.30",
20
+ "@trackunit/react-components": "1.7.41",
21
+ "@trackunit/ui-icons": "1.6.29",
22
+ "@trackunit/shared-utils": "1.8.30",
23
+ "@trackunit/ui-design-tokens": "1.6.31",
24
+ "@trackunit/i18n-library-translation": "1.6.33",
25
25
  "string-ts": "^2.0.0",
26
- "@trackunit/react-test-setup": "1.3.27",
26
+ "@trackunit/react-test-setup": "1.3.30",
27
27
  "@js-temporal/polyfill": "^0.5.1"
28
28
  },
29
29
  "module": "./index.esm.js",
@@ -1,5 +1,5 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
- import { MouseEventHandler, ReactElement } from "react";
2
+ import { MouseEventHandler, ReactElement, ReactNode } from "react";
3
3
  import { FormComponentSizes } from "../../../types";
4
4
  interface SelectMenuItemProps extends CommonProps {
5
5
  /**
@@ -29,6 +29,11 @@ interface SelectMenuItemProps extends CommonProps {
29
29
  * Such as a description or a hint for the option
30
30
  */
31
31
  optionLabelDescription?: string;
32
+ /**
33
+ * A React element to render before the label value itself
34
+ * This is typically used to render an icon.
35
+ */
36
+ optionPrefix?: ReactNode;
32
37
  /**
33
38
  * The size of the selected item
34
39
  */
@@ -47,12 +52,12 @@ export interface SingleSelectMenuItemProps extends SelectMenuItemProps {
47
52
  * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
48
53
  * @returns {ReactElement} SingleSelectMenuItem
49
54
  */
50
- export declare const SingleSelectMenuItem: ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }: SingleSelectMenuItemProps) => import("react/jsx-runtime").JSX.Element;
55
+ export declare const SingleSelectMenuItem: ({ label, icon, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }: SingleSelectMenuItemProps) => import("react/jsx-runtime").JSX.Element;
51
56
  /**
52
57
  * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
53
58
  *
54
59
  * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
55
60
  * @returns {ReactElement} multi select menu item
56
61
  */
57
- export declare const MultiSelectMenuItem: ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, fieldSize, }: SelectMenuItemProps) => import("react/jsx-runtime").JSX.Element;
62
+ export declare const MultiSelectMenuItem: ({ label, onClick, selected, focused, dataTestId, disabled, optionLabelDescription, optionPrefix, fieldSize, }: SelectMenuItemProps) => import("react/jsx-runtime").JSX.Element;
58
63
  export {};
@@ -1,4 +1,4 @@
1
- import { ReactElement } from "react";
1
+ import { ReactElement, ReactNode } from "react";
2
2
  interface TagsContainerItem {
3
3
  /**
4
4
  * A text value to be passed to tags inside container
@@ -12,6 +12,7 @@ interface TagsContainerItem {
12
12
  * A flag to set tags to readonly mode (without close button)
13
13
  */
14
14
  disabled: boolean;
15
+ Icon?: ReactNode;
15
16
  }
16
17
  interface TagsContainerProps {
17
18
  /**
@@ -17,7 +17,7 @@ import { FormComponentSizes } from "../../types";
17
17
  * @param {ReactNode} prefix a prefix element
18
18
  * @returns {Partial<SelectComponents<Option, boolean, GroupBase<Option>>> | undefined} components object to override react-select default components
19
19
  */
20
- export declare const useCustomComponents: <Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, }: {
20
+ export declare const useCustomComponents: <Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>({ componentsProps, disabled, readOnly, setMenuIsEnabled, dataTestId, maxSelectedDisplayCount, prefix, hasError, fieldSize, getOptionLabelDescription, getOptionPrefix, }: {
21
21
  componentsProps: Partial<SelectComponents<Option, IsMulti, Group>> | undefined;
22
22
  disabled: boolean;
23
23
  readOnly: boolean;
@@ -28,4 +28,5 @@ export declare const useCustomComponents: <Option, IsMulti extends boolean = fal
28
28
  hasError?: boolean;
29
29
  fieldSize?: FormComponentSizes;
30
30
  getOptionLabelDescription?: (option: Option) => string | undefined;
31
+ getOptionPrefix?: (option: Option) => ReactNode;
31
32
  }) => Partial<SelectComponents<Option, IsMulti, Group>>;
@@ -122,6 +122,12 @@ export type SelectProps<Option, IsAsync extends boolean, IsMulti extends boolean
122
122
  * @memberof SelectProps
123
123
  */
124
124
  getOptionLabelDescription?: (option: Option) => string | undefined;
125
+ /**
126
+ * This callback returns
127
+ *
128
+ * @memberof SelectProps
129
+ */
130
+ getOptionPrefix?: (option: Option) => ReactNode;
125
131
  /**
126
132
  * The size of the select component.
127
133
  * Large = 40px, Medium = 32px, Small = 28px.
@@ -144,5 +150,5 @@ interface UseSelectProps<Option, IsMulti extends boolean = false, Group extends
144
150
  * @param {SelectProps} props - The props for the Select component
145
151
  * @returns {UseSelectProps} Select component
146
152
  */
147
- export declare const useSelect: <Option, IsAsync extends boolean = false, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>({ id, className, dataTestId, prefix, async, maxMenuHeight, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix, onMenuOpen, onMenuClose, maxSelectedDisplayCount, isClearable, isSearchable, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, fieldSize, ...props }: SelectProps<Option, IsAsync, IsMulti, Group>) => UseSelectProps<Option, IsMulti, Group>;
153
+ export declare const useSelect: <Option, IsAsync extends boolean = false, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>({ id, className, dataTestId, prefix, async, maxMenuHeight, label, hasError, disabled, isMulti, components, value, options, onChange, isLoading, classNamePrefix, onMenuOpen, onMenuClose, maxSelectedDisplayCount, isClearable, isSearchable, onMenuScrollToBottom, styles, filterOption, onInputChange, getOptionLabelDescription, getOptionPrefix, fieldSize, ...props }: SelectProps<Option, IsAsync, IsMulti, Group>) => UseSelectProps<Option, IsMulti, Group>;
148
154
  export {};