Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/react-bindings/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
...require('@stardust-ui/internal-tooling/jest'),
name: 'react-bindings',
moduleNameMapper: require('lerna-alias').jest(),
}
35 changes: 35 additions & 0 deletions packages/react-bindings/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@stardust-ui/react-bindings",
"description": "A set of components and hooks to build components libraries and UI kits.",
"version": "0.39.0",
"author": "Oleksandr Fediashov <a@fedyashov.com>",
"bugs": "https://github.com/stardust-ui/react/issues",
"dependencies": {
"@babel/runtime": "^7.1.2"
},
"devDependencies": {
"@stardust-ui/internal-tooling": "^0.39.0",
"lerna-alias": "^3.0.3-0"
},
"files": [
"dist"
],
"homepage": "https://github.com/stardust-ui/react/tree/master/packages/react-bindings",
"jsnext:main": "dist/es/index.js",
"license": "MIT",
"main": "dist/commonjs/index.js",
"module": "dist/es/index.js",
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0"
},
"publishConfig": {
"access": "public"
},
"repository": "stardust-ui/react.git",
"scripts": {
"build": "cross-env TS_NODE_PROJECT=../../tsconfig.json gulp bundle:package:no-umd --package react-bindings"
},
"sideEffects": false,
"types": "dist/es/index.d.ts"
}
2 changes: 2 additions & 0 deletions packages/react-bindings/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as getElementType } from './utils/getElementType'
export { default as getUnhandledProps } from './utils/getUnhandledProps'
17 changes: 17 additions & 0 deletions packages/react-bindings/src/utils/getElementType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from 'react'

/**
* Returns a createElement() type based on the props of the Component.
* Useful for calculating what type a component should render as.
*
* @param {object} props A ReactElement props object
* @returns {string|function} A ReactElement type
*/
function getElementType<P extends Record<string, any>>(props: P): React.ElementType {
// ----------------------------------------
// use defaultProp or 'div'

return props.as || 'div'
}

export default getElementType
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/**
* Returns an object consisting of props beyond the scope of the Component.
* Useful for getting and spreading unknown props from the user.
* @param {function} Component A function or ReactClass.
*
* @param {string[]} handledProps An array with names of props
* @param {object} props A ReactElement props object
* @returns {{}} A shallow copy of the prop object
*/
const getUnhandledProps = (Component, props) => {
const { handledProps = [] } = Component

return Object.keys(props).reduce((acc, prop) => {
function getUnhandledProps<P extends Record<string, any>>(
handledProps: (keyof P)[],
props: P,
): Partial<P> {
return Object.keys(props).reduce<Partial<P>>((acc, prop) => {
if (handledProps.indexOf(prop) === -1) acc[prop] = props[prop]

return acc
Expand Down
11 changes: 11 additions & 0 deletions packages/react-bindings/test/utils/getElementType-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { getElementType } from '@stardust-ui/react-bindings'

describe('getElementType', () => {
test('takes a value from "as" prop', () => {
expect(getElementType({ as: 'span' })).toBe('span')
})

test('defaults to "div"', () => {
expect(getElementType({})).toBe('div')
})
})
15 changes: 15 additions & 0 deletions packages/react-bindings/test/utils/getUnhandledProps-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { getUnhandledProps } from '@stardust-ui/react-bindings'

describe('getUnhandledProps', () => {
test('leaves props that are not defined in handledProps', () => {
expect(getUnhandledProps([], { 'data-leave-this': 'it is unhandled' })).toHaveProperty(
'data-leave-this',
)
})

test('removes props defined in handledProps', () => {
expect(
getUnhandledProps(['data-remove-me'], { 'data-remove-me': 'it is handled' }),
).not.toHaveProperty('data-remove-me')
})
})
11 changes: 11 additions & 0 deletions packages/react-bindings/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../build/tsconfig.common",
"compilerOptions": {
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"noUnusedParameters": true,
"strictNullChecks": true
},
"include": ["src", "test"]
}
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"dependencies": {
"@babel/runtime": "^7.1.2",
"@stardust-ui/accessibility": "^0.39.0",
"@stardust-ui/react-bindings": "^0.39.0",
"@stardust-ui/react-component-event-listener": "^0.39.0",
"@stardust-ui/react-component-nesting-registry": "^0.39.0",
"@stardust-ui/react-component-ref": "^0.39.0",
Expand Down
1 change: 0 additions & 1 deletion packages/react/src/lib/UIComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class UIComponent<P, S = {}> extends React.Component<P, S> {
return renderComponent(
{
className: this.childClass.className,
defaultProps: this.childClass.defaultProps,
displayName: this.childClass.displayName,
handledProps: this.childClass.handledProps,
props: this.props,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getElementType, getUnhandledProps } from '@stardust-ui/react-bindings'
import { Ref } from '@stardust-ui/react-component-ref'
import * as React from 'react'
import * as PropTypes from 'prop-types'
Expand All @@ -6,8 +7,6 @@ import * as _ from 'lodash'
import { getNextElement, focusAsync } from './focusUtilities'

import { AutoFocusZoneProps } from './AutoFocusZone.types'
import getUnhandledProps from '../../getUnhandledProps'
import getElementType from '../../getElementType'
import callable from '../../callable'

/** AutoFocusZone is used to focus inner element on mount. */
Expand All @@ -19,19 +18,16 @@ export default class AutoFocusZone extends React.Component<AutoFocusZoneProps> {
firstFocusableSelector: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
}

static handledProps = _.keys(AutoFocusZone.propTypes)
static handledProps = _.keys(AutoFocusZone.propTypes) as any
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💣

_.keys() and Object.keys() returns string[] in TS:

image

So type cast is required is there as typings for getUnhandledProps() are more strict.


componentDidMount(): void {
this.findElementAndFocusAsync()
}

render(): JSX.Element {
const unhandledProps = getUnhandledProps(
{ handledProps: AutoFocusZone.handledProps },
this.props,
)
const unhandledProps = getUnhandledProps(AutoFocusZone.handledProps, this.props)

const ElementType = getElementType({}, this.props) as React.ComponentClass<AutoFocusZoneProps>
const ElementType = getElementType(this.props)

return (
<Ref innerRef={this.root}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getElementType, getUnhandledProps } from '@stardust-ui/react-bindings'
import { EventListener } from '@stardust-ui/react-component-event-listener'
import * as React from 'react'
import * as ReactDOM from 'react-dom'
Expand All @@ -15,8 +16,6 @@ import {
} from './focusUtilities'

import { FocusTrapZoneProps } from './FocusTrapZone.types'
import getUnhandledProps from '../../getUnhandledProps'
import getElementType from '../../getElementType'

/** FocusTrapZone is used to trap the focus in any html element placed in body
* and hide other elements outside of Focus Trap Zone from accessibility tree.
Expand Down Expand Up @@ -130,11 +129,8 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
ariaLabelledBy,
disabled = false,
} = this.props
const unhandledProps = getUnhandledProps(
{ handledProps: [..._.keys(FocusTrapZone.propTypes)] },
this.props,
)
const ElementType = getElementType({ defaultProps: FocusTrapZone.defaultProps }, this.props)
const unhandledProps = getUnhandledProps(_.keys(FocusTrapZone.propTypes) as any, this.props)
const ElementType = getElementType(this.props)

const bumperProps = {
style: {
Expand Down
10 changes: 3 additions & 7 deletions packages/react/src/lib/accessibility/FocusZone/FocusZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
FocusZoneTabbableElements,
IS_FOCUSABLE_ATTRIBUTE,
} from '@stardust-ui/accessibility'
import { getElementType, getUnhandledProps } from '@stardust-ui/react-bindings'
import * as React from 'react'
import cx from 'classnames'
import * as _ from 'lodash'
Expand All @@ -24,8 +25,6 @@ import {
getParent,
FOCUSZONE_ID_ATTRIBUTE,
} from './focusUtilities'
import getUnhandledProps from '../../getUnhandledProps'
import getElementType from '../../getElementType'

const TABINDEX = 'tabindex'
const LARGE_DISTANCE_FROM_CENTER = 999999999
Expand Down Expand Up @@ -208,11 +207,8 @@ export default class FocusZone extends React.Component<FocusZoneProps> implement
render() {
const { className } = this.props

const ElementType = getElementType({ defaultProps: FocusZone.defaultProps }, this.props)
const unhandledProps = getUnhandledProps(
{ handledProps: [..._.keys(FocusZone.propTypes)] },
this.props,
)
const ElementType = getElementType(this.props)
const unhandledProps = getUnhandledProps(_.keys(FocusZone.propTypes) as any, this.props)

// Note, right before rendering/reconciling proceeds, we need to record if focus
// was in the zone before the update. This helper will track this and, if focus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ const createComponent = <P extends ObjectOf<any> = any>({
return renderComponent(
{
className,
defaultProps,
displayName,
handledProps: _.keys(propTypes).concat(handledProps),
props,
Expand Down
26 changes: 0 additions & 26 deletions packages/react/src/lib/getElementType.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions packages/react/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ export { default as getOrGenerateIdFromShorthand } from './getOrGenerateIdFromSh
export * from './factories'
export { default as callable } from './callable'
export { default as constants } from './constants'
export { default as getElementType } from './getElementType'
export { default as getUnhandledProps } from './getUnhandledProps'
export { default as mergeThemes } from './mergeThemes'
export { default as mergeProviderContexts } from './mergeProviderContexts'

Expand Down
9 changes: 3 additions & 6 deletions packages/react/src/lib/renderComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import {
FocusZoneDefinition,
Accessibility,
} from '@stardust-ui/accessibility'
import { getElementType, getUnhandledProps } from '@stardust-ui/react-bindings'
import cx from 'classnames'
import * as React from 'react'
import * as _ from 'lodash'

import callable from './callable'
import getElementType from './getElementType'
import getUnhandledProps from './getUnhandledProps'
import logProviderMissingWarning from './providerMissingHandler'
import {
ComponentStyleFunctionParam,
Expand Down Expand Up @@ -46,7 +45,6 @@ export type RenderComponentCallback<P> = (config: RenderResultConfig<P>) => any

export interface RenderConfig<P> {
className?: string
defaultProps?: { [key: string]: any }
displayName: string
handledProps: string[]
props: PropsWithVarsAndStyles
Expand Down Expand Up @@ -160,7 +158,6 @@ const renderComponent = <P extends {}>(
): React.ReactElement<P> => {
const {
className,
defaultProps,
displayName,
handledProps,
props,
Expand All @@ -177,7 +174,7 @@ const renderComponent = <P extends {}>(
const { disableAnimations = false, renderer = null, rtl = false, theme = emptyTheme } =
context || {}

const ElementType = getElementType({ defaultProps }, props) as React.ReactType<P>
const ElementType = getElementType(props) as React.ReactType<P>
const stateAndProps = { ...state, ...props }

// Resolve variables for this component, allow props.variables to override
Expand Down Expand Up @@ -205,7 +202,7 @@ const renderComponent = <P extends {}>(
rtl,
)

const unhandledProps = getUnhandledProps({ handledProps }, props)
const unhandledProps = getUnhandledProps(handledProps, props)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was strange to pass handledProps in object when we can just pass them.


const styleParam: ComponentStyleFunctionParam = {
displayName,
Expand Down
26 changes: 0 additions & 26 deletions packages/react/test/specs/lib/getUnhandledProps-test.tsx

This file was deleted.