import PropTypes from 'prop-types'; import { useBrand, overrideReconciler } from '@westpac/core'; import React, { useId, useMemo, ReactNode, CSSProperties, forwardRef } from 'react'; import { defaultInputGroup } from './overrides/inputGroup'; import { TextInputField } from './TextInputField'; import pkg from '../package.json'; import { sizeMap } from '@westpac/text-input'; // ============================== // Context and Consumer Hook // ============================== type Sizes = 'small' | 'medium' | 'large' | 'xlarge'; // ============================== // Component // ============================== interface TextWrapperProps { children?: ReactNode; css?: CSSProperties; size?: Sizes; readOnly?: boolean; disabled?: boolean; } const TextWrapper = ({ children, disabled, readOnly, size = 'medium', ...props }: TextWrapperProps) => { const { COLORS } = useBrand(); return ( {children} ); }; interface WrapperProps { children?: ReactNode; css?: CSSProperties; before?: boolean; after?: boolean; invalid?: boolean; ariaInvalid?: boolean; disabled?: boolean; readOnly?: boolean; size?: Sizes; } const Wrapper = ({ children, before, after, disabled, readOnly, size = 'medium', invalid, ariaInvalid, ...props }: WrapperProps) => { const { COLORS } = useBrand(); var s = sizeMap[size]; return (
button, > select, > input': { width: 'auto !important', margin: '-1px !important', }, '> *': { height: 'auto !important', ...(before ? { borderTopRightRadius: '0 !important', borderBottomRightRadius: '0 !important', } : {}), ...(after ? { borderTopLeftRadius: '0 !important', borderBottomLeftRadius: '0 !important', } : {}), }, ...(before ? { borderTopRightRadius: 0, borderBottomRightRadius: 0, borderRight: 'none' } : {}), ...(after ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0, borderLeft: 'none' } : {}), }} > {children}
); }; export interface InputGroupProps { /** * Define an id for internal elements */ instanceId?: string; /** * The name of the input field */ name?: string; /** * The placeholder of the input field */ placeholder?: string; /** * The label text for the input field */ label?: string; /** * InputGroup size */ size?: Sizes; /** * The look of the component */ look?: 'primary' | 'hero' | 'faint'; /** * Data driven */ data?: { before?: { inputType: 'text' | 'button' | 'select'; data?: unknown[] | string; onClick?: (...args: unknown[]) => unknown; }; after?: { inputType: 'text' | 'button' | 'select'; data?: unknown[] | string; onClick?: (...args: unknown[]) => unknown; }; }; /** * Invalid input mode */ invalid?: boolean; /** * Aria Invalid input mode */ ariaInvalid?: boolean; /** * Disabled input mode */ disabled?: boolean; /** * Read only mode */ readOnly?: boolean; /** * Element before input */ before?: ReactNode; /** * Element after the input */ after?: ReactNode; /** * InputGroup children */ children?: React.ReactNode; /** * The override API */ overrides?: { InputGroup?: { styles?: (...args: unknown[]) => unknown; component?: React.ElementType; attributes?: (...args: unknown[]) => unknown; }; Text?: { styles?: (...args: unknown[]) => unknown; component?: React.ElementType; attributes?: (...args: unknown[]) => unknown; }; TextInput?: { styles?: (...args: unknown[]) => unknown; component?: React.ElementType; attributes?: (...args: unknown[]) => unknown; }; Select?: { styles?: (...args: unknown[]) => unknown; component?: React.ElementType; attributes?: (...args: unknown[]) => unknown; }; Button?: { styles?: (...args: unknown[]) => unknown; component?: React.ElementType; attributes?: (...args: unknown[]) => unknown; }; }; } export const InputGroup = forwardRef( ( { instanceId, name, label, look, readOnly, size = 'medium', invalid = false, disabled = false, children, overrides: componentOverrides, placeholder, before, after, ariaInvalid, data, ...rest }, ref ) => { const { OVERRIDES: { [pkg.name]: tokenOverrides }, [pkg.name]: brandOverrides, } = useBrand(); const defaultOverrides = { InputGroup: defaultInputGroup, }; const _id = useId(); const id = useMemo(() => instanceId || `gel-input-group-${_id}`, [_id, instanceId]); const state = { id, name, label, size, look, invalid, disabled, readOnly, overrides: componentOverrides, placeholder, ariaInvalid, ...rest, }; const { InputGroup: { component: InputGroup, styles: inputGroupStyles, attributes: inputGroupAttributes, }, } = overrideReconciler(defaultOverrides, tokenOverrides, brandOverrides, componentOverrides); return ( {before && ( {typeof before === 'string' ? ( {before} ) : ( before )} )} {after && ( {typeof after === 'string' ? ( {after} ) : ( after )} )} ); } ); InputGroup.displayName = 'InputGroup'; TextWrapper.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit TypeScript types and run "yarn prop-types" | // ---------------------------------------------------------------------- children: PropTypes.node, disabled: PropTypes.bool, readOnly: PropTypes.bool, size: PropTypes.oneOf(['large', 'medium', 'small', 'xlarge']), }; Wrapper.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit TypeScript types and run "yarn prop-types" | // ---------------------------------------------------------------------- after: PropTypes.bool, ariaInvalid: PropTypes.bool, before: PropTypes.bool, children: PropTypes.node, disabled: PropTypes.bool, invalid: PropTypes.bool, readOnly: PropTypes.bool, size: PropTypes.oneOf(['large', 'medium', 'small', 'xlarge']), }; InputGroup.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit TypeScript types and run "yarn prop-types" | // ---------------------------------------------------------------------- /** * Element after the input */ after: PropTypes.node, /** * Aria Invalid input mode */ ariaInvalid: PropTypes.bool, /** * Element before input */ before: PropTypes.node, /** * InputGroup children */ children: PropTypes.node, /** * Data driven */ data: PropTypes.shape({ after: PropTypes.shape({ data: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), inputType: PropTypes.oneOf(['button', 'select', 'text']).isRequired, onClick: PropTypes.func, }), before: PropTypes.shape({ data: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), inputType: PropTypes.oneOf(['button', 'select', 'text']).isRequired, onClick: PropTypes.func, }), }), /** * Disabled input mode */ disabled: PropTypes.bool, /** * Define an id for internal elements */ instanceId: PropTypes.string, /** * Invalid input mode */ invalid: PropTypes.bool, /** * The label text for the input field */ label: PropTypes.string, /** * The look of the component */ look: PropTypes.oneOf(['faint', 'hero', 'primary']), /** * The name of the input field */ name: PropTypes.string, /** * The override API */ overrides: PropTypes.shape({ Button: PropTypes.shape({ attributes: PropTypes.func, component: PropTypes.elementType, styles: PropTypes.func, }), InputGroup: PropTypes.shape({ attributes: PropTypes.func, component: PropTypes.elementType, styles: PropTypes.func, }), Select: PropTypes.shape({ attributes: PropTypes.func, component: PropTypes.elementType, styles: PropTypes.func, }), Text: PropTypes.shape({ attributes: PropTypes.func, component: PropTypes.elementType, styles: PropTypes.func, }), TextInput: PropTypes.shape({ attributes: PropTypes.func, component: PropTypes.elementType, styles: PropTypes.func, }), }), /** * The placeholder of the input field */ placeholder: PropTypes.string, /** * Read only mode */ readOnly: PropTypes.bool, /** * InputGroup size */ size: PropTypes.oneOf(['large', 'medium', 'small', 'xlarge']), };