diff --git a/README.md b/README.md index 6574765..e72fb49 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,6 @@ E.g: Login ``` -##### innerRef - -Type: `function` - -Callback that gets passed a ref to inner DOM node (or component if the `is` prop is set to a React component type). - ##### clearfix Type: `boolean` diff --git a/package.json b/package.json index 863e57f..34f5cfa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui-box", - "version": "3.3.0", + "version": "4.0.0-0", "description": "Blazing Fast React UI Primitive", "contributors": [ "Jeroen Ransijn (https://twitter.com/jeroen_ransijn)", @@ -14,10 +14,10 @@ ], "repository": "segmentio/ui-box", "license": "MIT", - "main": "dist/index.js", - "typings": "dist/index.d.ts", + "main": "dist/src/index.js", + "typings": "dist/src/index.d.ts", "files": [ - "dist" + "dist/src" ], "sideEffects": false, "scripts": { @@ -27,7 +27,7 @@ "build": "tsc", "build-storybook": "build-storybook -s .storybook/static -o .out", "release": "np", - "benchmark": "echo ui-box && react-benchmark tools/benchmarks/box.js", + "benchmark": "echo ui-box && react-benchmark dist/tools/benchmarks/box.js", "size": "size-limit", "coverage": "nyc report --reporter=html" }, @@ -150,7 +150,7 @@ "size-limit": [ { "webpack": false, - "path": "dist/index.js", + "path": "dist/src/index.js", "limit": "5 KB", "running": false, "gzip": false diff --git a/src/box.tsx b/src/box.tsx index 3e4d331..f201931 100644 --- a/src/box.tsx +++ b/src/box.tsx @@ -1,18 +1,18 @@ -import React from 'react' +import React, { forwardRef } from 'react' import PropTypes from 'prop-types' -import {BoxComponent} from './types/box-types' +import {BoxComponent, ForwardRefBoxComponent} from './types/box-types' import {propTypes} from './enhancers' import enhanceProps from './enhance-props' import {extractAnchorProps, getUseSafeHref} from './utils/safeHref' -const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, ...props }) => { +const Box: ForwardRefBoxComponent = ({ is = 'div', children, allowUnsafeHref, ...props }, ref) => { // Convert the CSS props to class names (and inject the styles) const {className, enhancedProps: parsedProps} = enhanceProps(props) parsedProps.className = className - if (innerRef) { - parsedProps.ref = innerRef + if (ref) { + parsedProps.ref = ref } /** @@ -32,19 +32,17 @@ const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, .. Box.displayName = 'Box' -Box.propTypes = { +const BoxWithRef = forwardRef(Box) as BoxComponent + +BoxWithRef.propTypes = { ...propTypes, - innerRef: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.shape({ current: PropTypes.element }) - ]), - is: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.elementType]) + is: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.elementType]), + allowUnsafeHref: PropTypes.bool } -Box.defaultProps = { - innerRef: null, +BoxWithRef.defaultProps = { is: 'div', boxSizing: 'border-box' } -export default Box +export default BoxWithRef diff --git a/src/types/box-types.ts b/src/types/box-types.ts index ed7cf67..5eb2eb8 100644 --- a/src/types/box-types.ts +++ b/src/types/box-types.ts @@ -29,7 +29,7 @@ export type RefType = T extends keyof DomNodes * Remove box props from object `T` if they're present * @template T Object */ -type WithoutBoxProps = Without +type WithoutBoxProps = Without /** * Grab components passed to the `is` prop and return their props @@ -53,7 +53,7 @@ export type BoxProps = InheritedProps & * Callback that gets passed a ref to inner DOM node (or component if the * `is` prop is set to a React component type). */ - innerRef?: React.Ref> + ref?: React.Ref> /** * Allows the high level value of safeHref to be overwritten on an individual component basis @@ -61,6 +61,12 @@ export type BoxProps = InheritedProps & allowUnsafeHref?: boolean } +export interface ForwardRefBoxComponent { + (props: BoxProps, ref?: React.Ref>): React.ReactElement | null + propTypes?: React.FunctionComponent['propTypes'] + displayName?: React.FunctionComponent['displayName'] +} + export interface BoxComponent { (props: BoxProps): React.ReactElement | null propTypes?: React.FunctionComponent['propTypes'] diff --git a/test/box.tsx b/test/box.tsx index 122666a..17eeff8 100644 --- a/test/box.tsx +++ b/test/box.tsx @@ -57,16 +57,16 @@ test('is prop allows changing the component type', t => { t.true(component.is(TestComponent)) }) -test('innerRef prop gets passed the ref', t => { +test('ref gets forwarded', t => { const node = {domNode: true} - const innerRef = sinon.spy() - render.create(, { + const ref = sinon.spy() + render.create(, { createNodeMock() { return node } }) - t.true(innerRef.calledOnce) - t.is(innerRef.args[0][0], node) + t.true(ref.calledOnce) + t.is(ref.args[0][0], node) }) test('renders children', t => { diff --git a/tools/story.tsx b/tools/story.tsx index 06abee0..059cf98 100644 --- a/tools/story.tsx +++ b/tools/story.tsx @@ -180,14 +180,14 @@ storiesOf('Box', module) boxSizing: border-box )) - .add('innerRef', () => ( + .add('ref', () => ( - innerRef + ref )) - .add('innerRef as React ref', () => ( + .add('ref as React ref', () => ( - React ref + React ref )) .add('props pass through', () => ( diff --git a/tsconfig.json b/tsconfig.json index ec28fd3..5ba8e22 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,6 +27,7 @@ "esModuleInterop": true }, "include": [ - "src" + "src", + "tools" ] }