@trackunit/react-form-components 2.1.61 → 2.1.62

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
@@ -1964,25 +1964,8 @@ const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange,
1964
1964
  };
1965
1965
  Checkbox.displayName = "Checkbox";
1966
1966
 
1967
- /**
1968
- * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
1969
- *
1970
- * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
1971
- * @returns {ReactElement} SingleSelectMenuItem
1972
- */
1973
- const SingleSelectMenuItem = ({ label, icon, onClick, selected = false, focused = false, disabled = false, "data-testid": dataTestId, optionLabelDescription, optionPrefix, optionContent, fieldSize = "medium", }) => {
1974
- return (jsxRuntime.jsx(reactComponents.MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: react.isValidElement(optionPrefix)
1975
- ? react.cloneElement(optionPrefix, {
1976
- className: "mr-1 flex items-center",
1977
- size: "medium",
1978
- })
1979
- : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsxRuntime.jsx(reactComponents.Icon, { color: "primary", name: "Check", size: fieldSize === "large" ? "medium" : "small" }) : undefined, children: optionContent }));
1980
- };
1981
1967
  /**
1982
1968
  * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
1983
- *
1984
- * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
1985
- * @returns {ReactElement} multi select menu item
1986
1969
  */
1987
1970
  const MultiSelectMenuItem = ({ label, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, optionContent, fieldSize, }) => {
1988
1971
  return (jsxRuntime.jsx(reactComponents.MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: e => {
@@ -1996,6 +1979,18 @@ const MultiSelectMenuItem = ({ label, onClick, selected, focused, "data-testid":
1996
1979
  : optionPrefix, prefix: jsxRuntime.jsx(Checkbox, { checked: selected, className: "gap-x-0", disabled: disabled, onChange: () => null, readOnly: false }), selected: selected, children: optionContent }));
1997
1980
  };
1998
1981
 
1982
+ /**
1983
+ * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
1984
+ */
1985
+ const SingleSelectMenuItem = ({ label, icon, onClick, selected = false, focused = false, disabled = false, "data-testid": dataTestId, optionLabelDescription, optionPrefix, optionContent, fieldSize = "medium", }) => {
1986
+ return (jsxRuntime.jsx(reactComponents.MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: react.isValidElement(optionPrefix)
1987
+ ? react.cloneElement(optionPrefix, {
1988
+ className: "mr-1 flex items-center",
1989
+ size: "medium",
1990
+ })
1991
+ : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsxRuntime.jsx(reactComponents.Icon, { color: "primary", name: "Check", size: fieldSize === "large" ? "medium" : "small" }) : undefined, children: optionContent }));
1992
+ };
1993
+
1999
1994
  /**
2000
1995
  * Custom hook to measure the geometry of multiple elements indexed by number.
2001
1996
  * Similar to useMeasure but handles multiple elements efficiently with a single ResizeObserver.
package/index.esm.js CHANGED
@@ -1963,25 +1963,8 @@ const Checkbox = ({ className, "data-testid": dataTestId = "checkbox", onChange,
1963
1963
  };
1964
1964
  Checkbox.displayName = "Checkbox";
1965
1965
 
1966
- /**
1967
- * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
1968
- *
1969
- * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
1970
- * @returns {ReactElement} SingleSelectMenuItem
1971
- */
1972
- const SingleSelectMenuItem = ({ label, icon, onClick, selected = false, focused = false, disabled = false, "data-testid": dataTestId, optionLabelDescription, optionPrefix, optionContent, fieldSize = "medium", }) => {
1973
- return (jsx(MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
1974
- ? cloneElement(optionPrefix, {
1975
- className: "mr-1 flex items-center",
1976
- size: "medium",
1977
- })
1978
- : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { color: "primary", name: "Check", size: fieldSize === "large" ? "medium" : "small" }) : undefined, children: optionContent }));
1979
- };
1980
1966
  /**
1981
1967
  * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
1982
- *
1983
- * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
1984
- * @returns {ReactElement} multi select menu item
1985
1968
  */
1986
1969
  const MultiSelectMenuItem = ({ label, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, optionContent, fieldSize, }) => {
1987
1970
  return (jsx(MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: e => {
@@ -1995,6 +1978,18 @@ const MultiSelectMenuItem = ({ label, onClick, selected, focused, "data-testid":
1995
1978
  : optionPrefix, prefix: jsx(Checkbox, { checked: selected, className: "gap-x-0", disabled: disabled, onChange: () => null, readOnly: false }), selected: selected, children: optionContent }));
1996
1979
  };
1997
1980
 
1981
+ /**
1982
+ * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
1983
+ */
1984
+ const SingleSelectMenuItem = ({ label, icon, onClick, selected = false, focused = false, disabled = false, "data-testid": dataTestId, optionLabelDescription, optionPrefix, optionContent, fieldSize = "medium", }) => {
1985
+ return (jsx(MenuItem, { "data-testid": dataTestId, disabled: disabled, fieldSize: fieldSize, focused: focused, label: label, onClick: onClick, optionLabelDescription: optionLabelDescription, optionPrefix: isValidElement(optionPrefix)
1986
+ ? cloneElement(optionPrefix, {
1987
+ className: "mr-1 flex items-center",
1988
+ size: "medium",
1989
+ })
1990
+ : optionPrefix, prefix: icon, selected: selected, suffix: selected ? jsx(Icon, { color: "primary", name: "Check", size: fieldSize === "large" ? "medium" : "small" }) : undefined, children: optionContent }));
1991
+ };
1992
+
1998
1993
  /**
1999
1994
  * Custom hook to measure the geometry of multiple elements indexed by number.
2000
1995
  * Similar to useMeasure but handles multiple elements efficiently with a single ResizeObserver.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/react/form-components/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["// Migration entry point for @nx/js:tsc build target.\n// Migrations are registered in ../migrations.json and resolved by NX at runtime.\nexport {};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-utils.js","sourceRoot":"","sources":["../../../../../../libs/react/form-components/migrations/utils/jsx-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger, type Tree, visitNotIgnoredFiles } from \"@nx/devkit\";\nimport { tsquery } from \"@phenomnomnominal/tsquery\";\nimport * as ts from \"typescript\";\n\nconst TSX_EXTENSIONS = [\".tsx\", \".jsx\"] as const;\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".jsx\"] as const;\n\nconst isTsxFile = (filePath: string): boolean => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));\nconst isTsFile = (filePath: string): boolean => TS_EXTENSIONS.some(ext => filePath.endsWith(ext));\n\nconst isUnderNodeModules = (filePath: string): boolean =>\n filePath.includes(\"/node_modules/\") || filePath.startsWith(\"node_modules/\");\n\nconst isUnderDist = (filePath: string): boolean =>\n filePath.includes(\"/dist/\") || filePath.startsWith(\"dist/\") || filePath.includes(\"/.nx/\");\n\n/**\n * Visits every `.tsx`/`.jsx` file under the workspace root and invokes the\n * callback with the file path and its current contents. Files that don't\n * include the marker substring are skipped, which makes large workspaces\n * cheap to scan.\n */\nexport const visitTsxFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsxFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Same as {@link visitTsxFiles} but also includes plain `.ts` files. Use this\n * when the codemod also rewrites non-JSX files such as helpers or hooks.\n */\nexport const visitTsFiles = (\n tree: Tree,\n marker: string,\n callback: (filePath: string, content: string) => string | null | undefined\n): number => {\n let touched = 0;\n visitNotIgnoredFiles(tree, \"/\", filePath => {\n if (!isTsFile(filePath)) return;\n if (isUnderNodeModules(filePath) || isUnderDist(filePath)) return;\n const content = tree.read(filePath, \"utf-8\");\n if (content === null) return;\n if (!content.includes(marker)) return;\n const updated = callback(filePath, content);\n if (updated !== null && updated !== undefined && updated !== content) {\n tree.write(filePath, updated);\n touched += 1;\n }\n });\n return touched;\n};\n\n/**\n * Mapping of imported component aliases to their original names for a given\n * package. For `import { IconButton as Btn } from \"@trackunit/react-components\"`\n * this returns `{ Btn: \"IconButton\" }`.\n *\n * Returns `null` when the file imports nothing from the package, which lets\n * callers short-circuit before parsing JSX.\n */\nexport const getImportedAliases = (sourceFile: ts.SourceFile, packageName: string): Record<string, string> | null => {\n const result: Record<string, string> = {};\n let found = false;\n\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt)) continue;\n const moduleSpecifier = stmt.moduleSpecifier;\n if (!ts.isStringLiteral(moduleSpecifier)) continue;\n if (moduleSpecifier.text !== packageName) continue;\n\n const namedBindings = stmt.importClause?.namedBindings;\n if (namedBindings === undefined || !ts.isNamedImports(namedBindings)) continue;\n\n for (const element of namedBindings.elements) {\n const localName = element.name.text;\n const importedName = element.propertyName?.text ?? localName;\n result[localName] = importedName;\n found = true;\n }\n }\n\n return found ? result : null;\n};\n\n/**\n * Returns the local alias used in this file for `originalName` when imported\n * from `packageName`, or `null` if the component is not imported.\n */\nexport const getLocalAliasFor = (\n sourceFile: ts.SourceFile,\n packageName: string,\n originalName: string\n): string | null => {\n const aliases = getImportedAliases(sourceFile, packageName);\n if (aliases === null) return null;\n for (const [local, original] of Object.entries(aliases)) {\n if (original === originalName) return local;\n }\n return null;\n};\n\nexport type JsxElementMatch = {\n /** The opening JSX element (the one carrying the attributes). */\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement;\n /** The full element including children, or the self-closing element. */\n element: ts.JsxElement | ts.JsxSelfClosingElement;\n};\n\n/**\n * Finds every JSX element whose tag name resolves to one of `tagNames`\n * (typically the local aliases returned by {@link getImportedAliases}).\n *\n * The result intentionally includes both opening and full elements so callers\n * can manipulate attributes (via `openingElement`) or wrap/replace the whole\n * element (via `element`).\n */\nexport const findJsxElements = (\n sourceFile: ts.SourceFile,\n tagNames: ReadonlyArray<string>\n): ReadonlyArray<JsxElementMatch> => {\n const matches: Array<JsxElementMatch> = [];\n const tagSet = new Set(tagNames);\n\n const visit = (node: ts.Node): void => {\n if (ts.isJsxSelfClosingElement(node)) {\n if (ts.isIdentifier(node.tagName) && tagSet.has(node.tagName.text)) {\n matches.push({ openingElement: node, element: node });\n }\n } else if (ts.isJsxElement(node)) {\n const opening = node.openingElement;\n if (ts.isIdentifier(opening.tagName) && tagSet.has(opening.tagName.text)) {\n matches.push({ openingElement: opening, element: node });\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return matches;\n};\n\n/**\n * Looks up a named JSX attribute on the opening element. Returns `null` when\n * the attribute is missing or part of a spread attribute (which we cannot\n * statically inspect).\n */\nexport const findJsxAttribute = (\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeName: string\n): ts.JsxAttribute | null => {\n for (const attr of openingElement.attributes.properties) {\n if (!ts.isJsxAttribute(attr)) continue;\n if (!ts.isIdentifier(attr.name)) continue;\n if (attr.name.text === attributeName) return attr;\n }\n return null;\n};\n\n/**\n * `true` when the element forwards a spread expression such as `{...rest}`,\n * which means we can't be sure which attributes are actually set.\n */\nexport const hasSpreadAttribute = (openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement): boolean => {\n return openingElement.attributes.properties.some(prop => ts.isJsxSpreadAttribute(prop));\n};\n\n/**\n * Parses the file as TSX so JSX is recognised. We do not need a full program\n * here; tsquery's `ast` helper produces a script-kind source file which loses\n * JSX context, so we go through `createSourceFile` directly.\n */\nexport const parseTsx = (content: string, fileName = \"file.tsx\"): ts.SourceFile =>\n ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n\n/** Re-exported for codemods that need direct AST queries. */\nexport { tsquery };\n\n/**\n * Helper for codemods to log a one-line summary at the end of a run. Migration\n * runners aggregate logs per migration, so this keeps output focused.\n */\nexport const logSummary = (migrationName: string, touched: number, manualReviewNeeded?: number): void => {\n if (touched === 0) {\n logger.info(` ${migrationName}: no files changed`);\n return;\n }\n const reviewSuffix =\n manualReviewNeeded !== undefined && manualReviewNeeded > 0\n ? ` (${manualReviewNeeded} location(s) need manual review)`\n : \"\";\n logger.info(` ${migrationName}: updated ${touched} file(s)${reviewSuffix}`);\n};\n\n/**\n * Inserts an attribute string immediately after the tag name (so the new\n * attribute appears first). Returns the resulting source content.\n *\n * The added attribute is rendered verbatim, so callers are responsible for\n * including the leading space (e.g. ` title=\"Close\"`).\n */\nexport const insertAttributeIntoOpeningTag = (\n content: string,\n openingElement: ts.JsxOpeningElement | ts.JsxSelfClosingElement,\n attributeText: string\n): string => {\n const tagName = openingElement.tagName;\n const insertPos = tagName.getEnd();\n return content.slice(0, insertPos) + ` ${attributeText}` + content.slice(insertPos);\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionbutton-add-title.js","sourceRoot":"","sources":["../../../../../../libs/react/form-components/migrations/v2-0-0/actionbutton-add-title.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Tree, logger } from \"@nx/devkit\";\nimport * as ts from \"typescript\";\nimport {\n findJsxAttribute,\n findJsxElements,\n getImportedAliases,\n hasSpreadAttribute,\n logSummary,\n parseTsx,\n visitTsxFiles,\n} from \"../utils/jsx-utils\";\n\nconst PACKAGE_NAME = \"@trackunit/react-form-components\";\nconst COMPONENT_NAME = \"ActionButton\";\n\nconst ACTION_TYPE_TO_TITLE: Record<string, string> = {\n COPY: \"Copy value\",\n EDIT: \"Edit value\",\n EMAIL: \"Send email\",\n PHONE_NUMBER: \"Call number\",\n WEB_ADDRESS: \"Open link\",\n};\n\nconst DEFAULT_TITLE = \"Action\";\n\nconst resolveTitleForType = (typeAttr: ts.JsxAttribute | null): string => {\n if (typeAttr === null) return DEFAULT_TITLE;\n const initializer = typeAttr.initializer;\n if (initializer === undefined) return DEFAULT_TITLE;\n if (ts.isStringLiteral(initializer)) {\n return ACTION_TYPE_TO_TITLE[initializer.text] ?? DEFAULT_TITLE;\n }\n return DEFAULT_TITLE;\n};\n\nconst transformActionButtonUsage = (filePath: string, content: string): string | null => {\n const sourceFile = parseTsx(content, filePath);\n\n const aliases = getImportedAliases(sourceFile, PACKAGE_NAME);\n if (aliases === null) return null;\n\n const localAlias = Object.entries(aliases).find(([, name]) => name === COMPONENT_NAME)?.[0];\n if (localAlias === undefined) return null;\n\n const matches = findJsxElements(sourceFile, [localAlias]);\n if (matches.length === 0) return null;\n\n type Edit = { offset: number; text: string };\n const edits: Array<Edit> = [];\n\n for (const { openingElement } of matches) {\n if (hasSpreadAttribute(openingElement)) continue;\n if (findJsxAttribute(openingElement, \"title\") !== null) continue;\n\n const typeAttr = findJsxAttribute(openingElement, \"type\");\n const title = resolveTitleForType(typeAttr);\n edits.push({\n offset: openingElement.tagName.getEnd(),\n text: ` title=\"${title}\"`,\n });\n }\n\n if (edits.length === 0) return null;\n\n edits.sort((a, b) => (a.offset === b.offset ? 0 : b.offset - a.offset));\n\n let updated = content;\n for (const { offset, text } of edits) {\n updated = updated.slice(0, offset) + text + updated.slice(offset);\n }\n return updated;\n};\n\n/**\n * Adds the now-required `title` prop to `<ActionButton>` usages that don't\n * already provide one. The default value is derived from the `type` prop when\n * possible (e.g. `COPY` → \"Copy value\"); consumers should replace the\n * placeholders with their own localized strings.\n */\nexport const actionButtonAddTitle = (tree: Tree): void => {\n const touched = visitTsxFiles(tree, \"ActionButton\", transformActionButtonUsage);\n logSummary(\"actionbutton-add-title\", touched);\n if (touched > 0) {\n logger.info(` Replace placeholder ActionButton titles with your own localized strings.`);\n }\n};\n\nexport default actionButtonAddTitle;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "2.1.61",
3
+ "version": "2.1.62",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "migrations": "./migrations.json",
@@ -0,0 +1,6 @@
1
+ import { ReactElement } from "react";
2
+ import { SelectMenuItemProps } from "./selectMenuItemTypes";
3
+ /**
4
+ * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
5
+ */
6
+ export declare const MultiSelectMenuItem: ({ label, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, optionContent, fieldSize, }: SelectMenuItemProps) => ReactElement;
@@ -1,68 +1,6 @@
1
- import { CommonProps } from "@trackunit/react-components";
2
- import { MouseEventHandler, ReactElement, ReactNode } from "react";
3
- import { FormComponentSizes } from "../../../../types";
4
- interface SelectMenuItemProps extends CommonProps {
5
- /**
6
- * A string to render as an item label.
7
- *
8
- */
9
- label: string;
10
- /**
11
- * A handler for click on element
12
- */
13
- onClick?: MouseEventHandler<HTMLDivElement>;
14
- /**
15
- * A boolean prop to set menu item to selected state
16
- */
17
- selected?: boolean;
18
- /**
19
- * A boolean prop to set menu item to focused state
20
- */
21
- focused?: boolean;
22
- /**
23
- * A boolean prop to set menu item to disabled state
24
- * used in disabled select options
25
- */
26
- disabled?: boolean;
27
- /**
28
- * A value to be displayed after the label value itself
29
- * Such as a description or a hint for the option
30
- */
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;
37
- /**
38
- * Rich content to render in place of the default label/description layout.
39
- * This keeps the surrounding menu item chrome while allowing custom content.
40
- */
41
- optionContent?: ReactNode;
42
- /**
43
- * The size of the selected item
44
- */
45
- fieldSize?: FormComponentSizes;
46
- }
47
- export interface SingleSelectMenuItemProps extends SelectMenuItemProps {
48
- /**
49
- * A React element to render before the text in the select.
50
- * This is typically used to render an icon.
51
- */
52
- icon?: ReactElement;
53
- }
1
+ import { ReactElement } from "react";
2
+ import { SingleSelectMenuItemProps } from "./selectMenuItemTypes";
54
3
  /**
55
4
  * A single select menu item is a basic wrapper around Menu item designed to be used as a single value render in Select list
56
- *
57
- * @param {SelectMenuItemProps} props - The props for the SingleSelectMenuItem
58
- * @returns {ReactElement} SingleSelectMenuItem
59
5
  */
60
6
  export declare const SingleSelectMenuItem: ({ label, icon, onClick, selected, focused, disabled, "data-testid": dataTestId, optionLabelDescription, optionPrefix, optionContent, fieldSize, }: SingleSelectMenuItemProps) => ReactElement;
61
- /**
62
- * A multi select menu item is a basic wrapper around Menu item designed to be used as a multi value render in Select list
63
- *
64
- * @param {SelectMenuItemProps} props - The props for the MultiSelectMenuItem
65
- * @returns {ReactElement} multi select menu item
66
- */
67
- export declare const MultiSelectMenuItem: ({ label, onClick, selected, focused, "data-testid": dataTestId, disabled, optionLabelDescription, optionPrefix, optionContent, fieldSize, }: SelectMenuItemProps) => ReactElement;
68
- export {};
@@ -0,0 +1,29 @@
1
+ import { CommonProps } from "@trackunit/react-components";
2
+ import { MouseEventHandler, ReactElement, ReactNode } from "react";
3
+ import { FormComponentSizes } from "../../../../types";
4
+ /** Props shared by select menu item renderers in BaseSelect. */
5
+ export interface SelectMenuItemProps extends CommonProps {
6
+ /** A string to render as an item label. */
7
+ label: string;
8
+ /** A handler for click on element */
9
+ onClick?: MouseEventHandler<HTMLDivElement>;
10
+ /** A boolean prop to set menu item to selected state */
11
+ selected?: boolean;
12
+ /** A boolean prop to set menu item to focused state */
13
+ focused?: boolean;
14
+ /** A boolean prop to set menu item to disabled state */
15
+ disabled?: boolean;
16
+ /** A value to be displayed after the label value itself */
17
+ optionLabelDescription?: string;
18
+ /** A React element to render before the label value itself */
19
+ optionPrefix?: ReactNode;
20
+ /** Rich content to render in place of the default label/description layout. */
21
+ optionContent?: ReactNode;
22
+ /** The size of the selected item */
23
+ fieldSize?: FormComponentSizes;
24
+ }
25
+ /** Props for a single-select menu item in BaseSelect. */
26
+ export interface SingleSelectMenuItemProps extends SelectMenuItemProps {
27
+ /** A React element to render before the text in the select. */
28
+ icon?: ReactElement;
29
+ }