diff --git a/packages/big-design/src/components/Fieldset/Fieldset.tsx b/packages/big-design/src/components/Fieldset/Fieldset.tsx index e1c825060..9807ac0a7 100644 --- a/packages/big-design/src/components/Fieldset/Fieldset.tsx +++ b/packages/big-design/src/components/Fieldset/Fieldset.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { memo, useMemo } from 'react'; import { warning } from '../../utils/warning'; @@ -11,44 +11,46 @@ export interface FieldsetProps extends React.FieldsetHTMLAttributes = ({ className, legend, description, children, style, ...props }) => { - const renderedLegend = useMemo(() => { - if (typeof legend === 'string') { - return {legend}; - } - - if (React.isValidElement(legend) && legend.type === FieldsetLegend) { - return legend; - } - - if (!legend) { - return null; - } - - warning('legend must be either a string or a FieldsetLegend component.'); - }, [legend]); - - const renderedDescription = useMemo(() => { - if (typeof description === 'string') { - return {description}; - } - - if (React.isValidElement(description) && description.type === FieldsetDescription) { - return description; - } - - if (!description) { - return null; - } - - warning('description must be either a string or a FieldsetDescription component.'); - }, [description]); - - return ( - - {renderedLegend} - {renderedDescription} - {children} - - ); -}; +export const Fieldset: React.FC = memo( + ({ className, legend, description, children, style, ...props }) => { + const renderedLegend = useMemo(() => { + if (typeof legend === 'string') { + return {legend}; + } + + if (React.isValidElement(legend) && legend.type === FieldsetLegend) { + return legend; + } + + if (!legend) { + return null; + } + + warning('legend must be either a string or a FieldsetLegend component.'); + }, [legend]); + + const renderedDescription = useMemo(() => { + if (typeof description === 'string') { + return {description}; + } + + if (React.isValidElement(description) && description.type === FieldsetDescription) { + return description; + } + + if (!description) { + return null; + } + + warning('description must be either a string or a FieldsetDescription component.'); + }, [description]); + + return ( + + {renderedLegend} + {renderedDescription} + {children} + + ); + }, +); diff --git a/packages/big-design/src/components/Form/spec.tsx b/packages/big-design/src/components/Form/spec.tsx index a0b1a4f23..ec4dd5bab 100644 --- a/packages/big-design/src/components/Form/spec.tsx +++ b/packages/big-design/src/components/Form/spec.tsx @@ -2,6 +2,7 @@ import { fireEvent, render } from '@test/utils'; import 'jest-styled-components'; import React from 'react'; +import { Fieldset } from '../Fieldset'; import { Input } from '../Input'; import { Form } from './index'; @@ -27,7 +28,6 @@ test('calls onSubmit', () => { test('exposes expected statics', () => { expect(Form.Error).toBeDefined(); - expect(Form.Fieldset).toBeDefined(); expect(Form.Label).toBeDefined(); expect(Form.Group).toBeDefined(); }); @@ -35,7 +35,7 @@ test('exposes expected statics', () => { test('simple form render', () => { const { container } = render(
- @@ -54,7 +54,7 @@ test('simple form render', () => { placeholder="Placeholder text" /> - +
, ); diff --git a/packages/big-design/src/components/index.ts b/packages/big-design/src/components/index.ts index ece802b51..962fdbe89 100644 --- a/packages/big-design/src/components/index.ts +++ b/packages/big-design/src/components/index.ts @@ -5,6 +5,7 @@ export * from './Checkbox'; export * from './Chip'; export * from './Dropdown'; export * from './Flex'; +export * from './Fieldset'; export * from './Form'; export * from './GlobalStyles'; export * from './Grid'; diff --git a/packages/big-design/src/utils/warning/spec.ts b/packages/big-design/src/utils/warning/spec.ts index f5d386d52..008b88e0e 100644 --- a/packages/big-design/src/utils/warning/spec.ts +++ b/packages/big-design/src/utils/warning/spec.ts @@ -1,6 +1,6 @@ import { warning } from './warning'; -const consoleError = jest.spyOn(console, 'error').mockImplementation(jest.fn); +const consoleError = jest.spyOn(console, 'warn').mockImplementation(jest.fn); jest.mock('./warning', () => ({ ...jest.requireActual('./warning'), diff --git a/packages/big-design/src/utils/warning/warning.ts b/packages/big-design/src/utils/warning/warning.ts index 45bbca78d..f86a8b96c 100644 --- a/packages/big-design/src/utils/warning/warning.ts +++ b/packages/big-design/src/utils/warning/warning.ts @@ -1,54 +1,30 @@ -// Ported version of Facebook's warning module: -// https://github.com/BerkeleyTrue/warning/blob/master/warning.js +// Ported from tiny-warning: +// https://github.com/alexreardon/tiny-warning/blob/master/src/index.js // -------------------------------------------- // Since we don't care about whether or not there is a condition passed // we modified the original to account for that. -export let warning = (_format: string) => {}; // tslint:disable-line +const isProduction: boolean = process.env.NODE_ENV === 'production'; -if (process.env.NODE_ENV !== 'production') { - const printWarning = (format: string, ...args: any[]) => { - // @ts-ignore - const len = arguments.length; +export const warning = (message: string): void => { + // don't do anything in production + // wrapping in production check for better dead code elimination + if (!isProduction) { + // Condition not passed + const text: string = `Warning: ${message}`; - args = new Array(len > 1 ? len - 1 : 0); - - for (let key = 1; key < len; key++) { - // @ts-ignore - args[key - 1] = arguments[key]; - } - - let argIndex = 0; - - const message = - 'Warning: ' + - format.replace(/%s/g, () => { - return args[argIndex++]; - }); + // check console for IE9 support which provides console + // only with open devtools if (typeof console !== 'undefined') { - console.error(message); // tslint:disable-line - } - try { - throw new Error(message); - } catch (x) {} // tslint:disable-line - }; - - warning = (format: string, ...args: any[]) => { - // @ts-ignore - const len = arguments.length; - - args = new Array(len > 2 ? len - 2 : 0); - - for (let key = 2; key < len; key++) { - // @ts-ignore - args[key - 2] = arguments[key]; + console.warn(text); // tslint:disable-line no-console } - if (format === undefined) { - throw new Error('`warning(format, ...args)` requires a warning ' + 'message argument'); - } - - // @ts-ignore - printWarning.apply(null, [format].concat(args)); - }; -} + // Throwing an error and catching it immediately + // to improve debugging + // A consumer can use 'pause on caught exceptions' + // https://github.com/facebook/react/issues/4216 + try { + throw Error(text); + } catch (x) {} // tslint:disable-line no-empty + } +}; diff --git a/packages/docs/PropTables/FormPropTable.tsx b/packages/docs/PropTables/FormPropTable.tsx index 4390fccef..177ea8a3d 100644 --- a/packages/docs/PropTables/FormPropTable.tsx +++ b/packages/docs/PropTables/FormPropTable.tsx @@ -24,18 +24,18 @@ const formProps: Prop[] = [ const formFieldsetProps: Prop[] = [ { name: 'description', - types: 'ReactChild', - description: 'Pass in a description to display in the fieldset.', + types: ['string', 'FieldsetDescription'], + description: 'Pass in a description to display in the fieldset. Will render nothing if not the correct type.', }, { name: 'legend', - types: 'ReactChild', - description: 'Pass in a legend to display in the fieldset.', + types: ['string', 'FieldsetLegend'], + description: 'Pass in a legend to display in the fieldset. Will render nothing if not the correct type.', }, ]; export const FormFieldsetPropTable: React.FC = props => ( - + ); export const FormLabelPropTable: React.FC<{ id?: string }> = ({ id }) => ( diff --git a/packages/docs/pages/Form/FormPage.tsx b/packages/docs/pages/Form/FormPage.tsx index eeaf32299..522ea1be1 100644 --- a/packages/docs/pages/Form/FormPage.tsx +++ b/packages/docs/pages/Form/FormPage.tsx @@ -2,6 +2,7 @@ import { Box, Button, Checkbox, + Fieldset, Form, H0, H1, @@ -60,9 +61,9 @@ export default () => (

API

- +

Input Types

@@ -126,13 +127,13 @@ export default () => ( - +
}> null} /> - +
{/* jsx-to-string:end */} diff --git a/packages/docs/pages/Radio/RadioPage.tsx b/packages/docs/pages/Radio/RadioPage.tsx index 7cb42c697..35b58161a 100644 --- a/packages/docs/pages/Radio/RadioPage.tsx +++ b/packages/docs/pages/Radio/RadioPage.tsx @@ -1,4 +1,4 @@ -import { Form, H0, H1, Link, Radio, Text } from '@bigcommerce/big-design'; +import { Fieldset, Form, H0, H1, Link, Radio, Text } from '@bigcommerce/big-design'; import React from 'react'; import { Code, CodePreview } from '../../components'; @@ -46,7 +46,7 @@ export default () => (

Grouping

- In order to group radio controls, use the Form.Fieldset component to separate the controls. + In order to group radio controls, use the Fieldset component to separate the controls. @@ -60,18 +60,18 @@ export default () => ( return (
- +
- - +
+
- +
); }}