diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.js b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx similarity index 95% rename from packages/ibm-products/src/components/APIKeyModal/APIKeyModal.js rename to packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx index fbbd0a67b8..e2b7029a71 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.js +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx @@ -1,5 +1,5 @@ // -// Copyright IBM Corp. 2021, 2021 +// Copyright IBM Corp. 2021, 2024 // // This source code is licensed under the Apache-2.0 license found in the // LICENSE file in the root directory of this source tree. @@ -27,16 +27,17 @@ import { usePortalTarget } from '../../global/js/hooks/usePortalTarget'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; import { isRequiredIf } from '../../global/js/utils/props-helper'; import uuidv4 from '../../global/js/utils/uuidv4'; +import { APIKeyModalProps } from './APIKeyModal.types'; const componentName = 'APIKeyModal'; // Default values for props const defaults = { apiKeyName: '', - customSteps: Object.freeze([]), + customSteps: [], }; -export let APIKeyModal = forwardRef( +export let APIKeyModal: React.FC = forwardRef( ( { // The component props, in alphabetical order (for consistency). @@ -87,13 +88,13 @@ export let APIKeyModal = forwardRef( // Collect any other property values passed in. ...rest }, - ref + ref: React.Ref ) => { - const [title, setTitle] = useState(null); + const [title, setTitle] = useState(null); const [copyError, setCopyError] = useState(false); const [name, setName] = useState(apiKeyName); const [currentStep, setCurrentStep] = useState(0); - const copyRef = useRef(); + const copyRef = useRef(); const apiKeyInputId = useRef(uuidv4()); const nameInputId = useRef(uuidv4()); const renderPortalUse = usePortalTarget(portalTargetIn); @@ -118,8 +119,8 @@ export let APIKeyModal = forwardRef( if (loading) { return true; } - if (hasSteps && 'valid' in customSteps[currentStep]) { - return !customSteps[currentStep].valid; + if (hasSteps && 'valid' in (customSteps?.[currentStep] || [])) { + return !customSteps[currentStep]?.valid; } if (!hasSteps && nameRequired && !name) { return true; @@ -153,7 +154,7 @@ export let APIKeyModal = forwardRef( } else if (apiKeyLoaded) { setTitle(generateSuccessTitle); } else if (hasSteps) { - setTitle(customSteps[currentStep].title); + setTitle(customSteps[currentStep]?.title); } else { setTitle(generateTitle); } @@ -176,7 +177,7 @@ export let APIKeyModal = forwardRef( const onCloseHandler = () => { setName(''); setCurrentStep(0); - onClose(); + onClose?.(); }; const submitHandler = async (e) => { @@ -195,9 +196,9 @@ export let APIKeyModal = forwardRef( } } } else if (editing) { - onRequestEdit(name); + onRequestEdit?.(name); } else { - onRequestGenerate(name); + onRequestGenerate?.(name); } }; @@ -226,7 +227,7 @@ export let APIKeyModal = forwardRef( /> {hasSteps && !apiKeyLoaded ? ( - customSteps[currentStep].content + customSteps[currentStep]?.content ) : ( <> {body &&

{body}

} @@ -248,7 +249,7 @@ export let APIKeyModal = forwardRef( /> )} {(editing || (!apiKeyLoaded && nameRequired)) && ( -
+ ; + /** + * designates if the modal is in the edit mode + */ + editing?: boolean; + /** + * designates if an error has occurred in a request + */ + error?: boolean; + /** + * text to display if an error has occurred + */ + errorText?: string; + /** + * default primary button text for modal in assumed default mode create or generate. + * in create mode this is the button text prior to supplying an api key, which then + * uses copyButtonText + */ + generateButtonText?: string; + /** + * content to display if generate request was successful + */ + generateSuccessBody?: ReactNode; + /** + * title for a successful key generation + */ + generateSuccessTitle?: string; + /** + * default title for the modal in generate key mode + */ + generateTitle?: string; + /** + * designates if the api input has the visibility toggle enabled + */ + hasAPIKeyVisibilityToggle?: boolean; + /** + * designates if user is able to download the api key + */ + hasDownloadLink?: boolean; + /** + * label text that's displayed when hovering over visibility toggler to hide key + */ + hideAPIKeyLabel?: string; + /** + * designates if the modal is in a loading state via a request or some other in progress operation + */ + loading?: boolean; + /** + * text that displays while modal is in the loading state + */ + loadingText?: string; + /** + * general label text for modal + */ + modalLabel?: string; + /** + * helper text for name input + */ + nameHelperText?: string; + /** + * label for api key name input + */ + nameLabel?: string; + /** + * placeholder text for api key name input + */ + namePlaceholder?: string; + /** + * designates if a name is required or not for key generation. NOTE- if using custom steps set this to false since you will be using your own validation + */ + nameRequired?: boolean; + /** + * handler for on modal close + */ + onClose?(): void; + /** + * Optional callback if you want to use your own copy function instead of the build in one + * onCopy(apiKey) + */ + onCopy?(apiKey: string): void; + /** + * handler for api key edit + */ + onRequestEdit?(apiKeyName: string): void; + /** + * handler for api key generation + */ + onRequestGenerate?(apiKeyName: string): void; + /** + * designates if modal is open or closed + */ + open: boolean; + /** + * The DOM node the tearsheet should be rendered within. Defaults to document.body. + */ + portalTarget: ReactNode; + /** + * label text that's displayed when hovering over visibility toggler to show key + */ + showAPIKeyLabel?: string; +} + +type CustomStepConditionalProps = { + /** + * if you need more options for key creation beyond just the name use custom steps to obtain whatever data is required. + */ + customSteps?: Array<{ + valid?: boolean; + content?: ReactNode; + title?: string; + }>; + /** + * text that displays in the secondary button when using custom steps to indicate to the user that there is a previous step + */ + previousStepButtonText: string; + /** + * text that displays in the primary button when using custom steps to indicate to the user that there is a next step + */ + nextStepButtonText: string; +}; + +type EditingConditionalProps = { + /** + * designates if the modal is in the edit mode + */ + editing?: boolean; + /** + * text for the edit button + */ + editButtonText: string; + /** + * designates if the edit request was successful + */ + editSuccess: boolean; + /** + * title for a successful edit + */ + editSuccessTitle: string; +}; + +type HasDownloadLinkProps = { + /** + * designates if user is able to download the api key + */ + hasDownloadLink?: boolean; + /** + * the content that appears that indicates the key is downloadable + */ + downloadBodyText: string; + /** + * designates the name of downloadable json file with the key. if not specified will default to 'apikey' + */ + downloadFileName: string; + /** + * designates the file type for the downloadable key + */ + downloadFileType: 'txt' | 'json'; + /** + * anchor text for the download link + */ + downloadLinkText: string; +}; + +export type APIKeyModalProps = APIKeyModalCommonProps & + CustomStepConditionalProps & + EditingConditionalProps & + HasDownloadLinkProps; diff --git a/packages/ibm-products/src/custom-typings/index.d.ts b/packages/ibm-products/src/custom-typings/index.d.ts new file mode 100644 index 0000000000..18e07bccfb --- /dev/null +++ b/packages/ibm-products/src/custom-typings/index.d.ts @@ -0,0 +1,196 @@ +declare module '@carbon/react' { + export { + Accordion, + AccordionItem, + ActionableNotification, + AspectRatio, + Breadcrumb, + Button, + ButtonKind, + ButtonProps, + ButtonSet, + Checkbox, + CheckboxGroup, + ClassPrefix, + ClickableTile, + CodeSnippet, + CodeSnippetSkeleton, + Column, + ColumnDefaultProps, + ComboBox, + ComboButton, + ComposedModal, + ContainedList, + ContainedListItem, + ContainedListItem, + Content, + ContentSwitcher, + ContextMenu, + Copy, + CopyButton, + CopyButtonProps, + DangerButton, + DataTable, + DataTable, + DataTable, + DataTableCustomRowData, + DataTableCustomRowProps, + DataTableCustomSelectionProps, + DataTableHeader, + DataTableRow, + DataTableSkeleton, + DatePicker, + DatePickerInput, + DefinitionTooltip, + DenormalizedRow, + Dropdown, + DropdownProps, + ErrorBoundary, + ExpandableSearch, + FileUploader, + FileUploaderDropContainer, + FileUploaderDropContainerProps, + FileUploaderItem, + FileUploaderItemProps, + FileUploaderProps, + FilterableMultiSelect, + FilterableMultiSelectProps, + FlexGrid, + FluidForm, + Form, + FormGroup, + FormItem, + FormLabel, + FormProps, + ForwardRefReturn, + Grid, + GridDefaultProps, + Header, + HeaderGlobalAction, + HeaderGlobalBar, + HeaderName, + HeaderName, + HeaderNavigation, + Heading, + IconButton, + IconTab, + IdPrefix, + InlineLoading, + InlineNotification, + Layer, + Layer, + Link, + LinkProps, + ListBoxBaseItemType, + ListItem, + Loading, + LoadingProps, + Menu, + MenuButton, + MenuItem, + MenuItemDivider, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalWrapper, + MultiSelect, + MultiSelectProps, + Notification, + NumberInput, + NumberInputOnChangeDataVariant, + OnChangeData, + OrderedList, + OverflowMenu, + OverflowMenuItem, + Pagination, + PaginationNav, + PasswordInput, + Popover, + PrimaryButton, + ProgressBar, + ProgressBar, + ProgressIndicator, + ProgressIndicator, + ProgressIndicatorSkeleton, + ProgressStep, + RadioButton, + RadioButtonGroup, + RadioTile, + Row, + Search, + SearchSkeleton, + SecondaryButton, + Select, + SelectItem, + SelectItemGroup, + SideNav, + SideNavItems, + SideNavLink, + SkeletonIcon, + SkeletonIconProps, + SkeletonPlaceholder, + SkeletonPlaceholderProps, + SkeletonText, + SkeletonTextProps, + SkipToContent, + Slider, + Stack, + StructuredList, + StructuredListSkeleton, + Switch, + Tab, + Tab, + TabContent, + TabList, + TabPanel, + TabPanels, + Table, + Table, + TableBody, + TableBody, + TableCell, + TableCell, + TableContainer, + TableExpandHeader, + TableExpandRow, + TableExpandedRow, + TableHead, + TableHead, + TableHeader, + TableHeader, + TableRow, + TableRow, + TableSelectAll, + TableSelectAllProps, + TableSelectRow, + TableToolbarSearch, + Tabs, + Tabs, + TabsSkeleton, + Tag, + TextArea, + TextAreaProps, + TextInput, + TextInput, + TextInputProps, + Theme, + Tile, + TileGroup, + TimePicker, + TimePickerSelect, + ToastNotification, + Toggle, + Toggletip, + ToggletipActions, + ToggletipButton, + ToggletipContent, + ToggletipLabel, + Tooltip, + TreeNode, + TreeView, + UIShell, + UnorderedList, + TagTypeName, + } from '@carbon/react'; +}