/*! Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ import { CardContent } from '@material-ui/core'; import { FormField, NORTHSTAR_COLORS, Text, Theme, makeStyles } from 'aws-northstar'; import { getDataEqualityHash } from '$common/utils'; import { v4 as uuid } from 'uuid'; import Card from '@material-ui/core/Card'; import CardHeader from '@material-ui/core/CardHeader'; import Grid, { GridProps } from '@material-ui/core/Grid'; import React, { ReactNode, useMemo } from 'react'; import useFieldApi from '@data-driven-forms/react-form-renderer/use-field-api'; export interface CardSelectOption { value: string; title?: string | ReactNode; subtitle?: string | ReactNode; icon?: string | ReactNode; content?: ReactNode; } export const DEFAULT_GRID_CONTAINER_PROPS: GridProps = { spacing: 2, direction: 'row', alignItems: 'stretch', // @ts-ignore justifyContent: 'flex-start', } export const DEFAULT_GRID_ITEM_PROPS: GridProps = { sm: 12, md: 6, lg: 4, xl: 3, } export interface CardSelectProps { /** * The name of the control used in HTML forms. * */ name: string; /** * Allows you to indicate that the control is to be focused as soon as the load event triggers, * allowing the user to just start typing without having to manually focus the input. * Don't use this option in pages that allow for the field to be scrolled out of the viewport. * */ autofocus?: boolean; /** * Id of the internal input.
* Use in conjunction with Form Field to relate a label element "for" attribute to this control for better web accessibility. * See example in FormField for more details. * */ controlId?: string; /** * Adds an aria-label on the native input. * */ label?: string; /** * Adds aria-labelledby on the native input.
* Use this only with form fields that contain multiple controls under the same label.
* Define a custom id inside the label.
* Refer to that label from every single control under that label using this property. * */ ariaLabelledby?: string; /** * Adds aria-describedby on the native input.
* Use this only with form fields that contain multiple controls under the same label.
* Define custom ids inside the description, hint and error text.
* Refer to these from every single control under that label using this property.
* Refer to any other hint/description text that you provide. * */ ariaDescribedby?: string; /** * Adds aria-required on the native input * */ ariaRequired?: boolean; /** * Items to displays for selections */ options: CardSelectOption[]; gridContainer?: GridProps; gridItem?: GridProps; isReadOnly?: boolean; } const useStyles = makeStyles(() => ({ card: { flex: 'auto', height: '100%', margin: 'auto', '&:hover': { cursor: 'pointer', }, }, avatar: { backgroundColor: 'white', }, })); export const CardSelect: React.FC = ({ gridContainer: _gridContainerProps, gridItem: _gridItemProps, ...props }) => { const { label, description, helperText, input, validateOnMount, stretch, showError, renderReload, onReloadClick, createNewLinkHref, createNewLink, secondaryControl, meta: { error, submitFailed }, isReadOnly, } = useFieldApi(props); const styles = useStyles(); const gridContainerProps = useMemo(() => { return { ...DEFAULT_GRID_CONTAINER_PROPS, ..._gridContainerProps, } }, [getDataEqualityHash(_gridContainerProps)]); const gridItemrProps = useMemo(() => { return { ...DEFAULT_GRID_ITEM_PROPS, ..._gridItemProps, } }, [getDataEqualityHash(_gridItemProps)]); const controlId = input.name || uuid(); const errorText = ((validateOnMount || submitFailed || showError) && error) || ''; return ( {props.options.map((option) => ( { input.onChange({ target: { value: option.value } }); } } > {option.content && ( {typeof option.content === 'string' ? {option.content} : option.content} )} ))} ); };