@planningcenter/tapestry-react 2.6.0-rc.9 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cjs/Button/Button.js +8 -1
  2. package/dist/cjs/Button/Button.test.js +51 -8
  3. package/dist/cjs/DataTable/components/BodyRow.js +2 -2
  4. package/dist/cjs/DataTable/hooks/useCollapsibleRows.js +2 -2
  5. package/dist/cjs/Dropdown/Dropdown.js +5 -3
  6. package/dist/cjs/Dropdown/Dropdown.test.js +3 -3
  7. package/dist/cjs/Dropdown/Link.js +2 -4
  8. package/dist/cjs/Input/InputLabel.js +40 -63
  9. package/dist/cjs/Modal/Modal.js +15 -7
  10. package/dist/cjs/Modal/Modal.test.js +2 -2
  11. package/dist/cjs/Popover/Popover.js +10 -2
  12. package/dist/cjs/Scrim/Scrim.js +16 -4
  13. package/dist/cjs/Table/Table.js +5 -3
  14. package/dist/cjs/ThemeProvider/ThemeProvider.js +2 -2
  15. package/dist/cjs/TimeField/TimeField.js +1 -1
  16. package/dist/cjs/Tooltip/Tooltip.js +27 -23
  17. package/dist/cjs/system/utils.js +2 -2
  18. package/dist/cjs/utils.js +3 -3
  19. package/dist/esm/Button/Button.js +8 -1
  20. package/dist/esm/Button/Button.test.js +67 -9
  21. package/dist/esm/DataTable/components/BodyRow.js +2 -2
  22. package/dist/esm/DataTable/hooks/useCollapsibleRows.js +1 -1
  23. package/dist/esm/Dropdown/Dropdown.js +6 -4
  24. package/dist/esm/Dropdown/Dropdown.test.js +1 -1
  25. package/dist/esm/Dropdown/Link.js +1 -2
  26. package/dist/esm/Input/InputLabel.js +40 -63
  27. package/dist/esm/Modal/Modal.js +13 -7
  28. package/dist/esm/Modal/Modal.test.js +1 -1
  29. package/dist/esm/Popover/Popover.js +8 -2
  30. package/dist/esm/Scrim/Scrim.js +15 -4
  31. package/dist/esm/Table/Table.js +2 -1
  32. package/dist/esm/ThemeProvider/ThemeProvider.js +1 -1
  33. package/dist/esm/TimeField/TimeField.js +1 -1
  34. package/dist/esm/Tooltip/Tooltip.js +29 -24
  35. package/dist/esm/system/utils.js +1 -1
  36. package/dist/esm/utils.js +1 -1
  37. package/dist/types/Button/Button.d.ts +4 -0
  38. package/dist/types/ThemeProvider/ThemeProvider.d.ts +3 -3
  39. package/dist/types/index.d.ts +1 -1
  40. package/package.json +4 -4
  41. package/src/Button/Button.test.tsx +30 -0
  42. package/src/Button/Button.tsx +14 -1
  43. package/src/DataTable/DataTable.js +1 -1
  44. package/src/DataTable/components/BodyRow.js +1 -1
  45. package/src/DataTable/hooks/useCollapsibleRows.js +1 -1
  46. package/src/Dropdown/Dropdown.js +7 -4
  47. package/src/Dropdown/Dropdown.mdx +3 -3
  48. package/src/Dropdown/Dropdown.test.tsx +1 -1
  49. package/src/Dropdown/Link.js +1 -7
  50. package/src/Input/InputLabel.js +39 -36
  51. package/src/Input/InputLabel.mdx +1 -0
  52. package/src/Modal/Modal.js +12 -4
  53. package/src/Modal/Modal.mdx +2 -1
  54. package/src/Modal/Modal.test.tsx +1 -1
  55. package/src/Popover/Popover.mdx +1 -0
  56. package/src/Popover/Popover.tsx +8 -2
  57. package/src/Scrim/Scrim.mdx +1 -0
  58. package/src/Scrim/Scrim.tsx +11 -6
  59. package/src/Sidebar/Sidebar.mdx +0 -1
  60. package/src/Table/Table.js +2 -1
  61. package/src/ThemeProvider/ThemeProvider.tsx +7 -6
  62. package/src/TimeField/TimeField.js +1 -1
  63. package/src/Tooltip/Tooltip.js +19 -21
  64. package/src/index.d.ts +1 -1
  65. package/src/system/utils.js +1 -1
  66. package/src/utils.js +1 -1
package/dist/esm/utils.js CHANGED
@@ -6,7 +6,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
6
6
 
7
7
  import { Children, cloneElement } from 'react';
8
8
  import { tabbable } from 'tabbable';
9
- import { kebabCase } from 'lodash';
9
+ import kebabCase from 'lodash/kebabCase';
10
10
  /**
11
11
  * Returns true if user platform is an iOS device
12
12
  * https://stackoverflow.com/a/9039885/1461204
@@ -60,6 +60,10 @@ declare type ButtonProps = {
60
60
  * Where the browser should navigate to when pressed. If you need any element here other than `<a>`, remember to use the `as` prop.
61
61
  */
62
62
  to?: string;
63
+ /**
64
+ * Where the browser should navigate to when pressed. If you need any element here other than `<a>`, remember to use the `as` prop.
65
+ */
66
+ href?: string;
63
67
  /**
64
68
  * Wraps button in a [`<Tooltip />`](./tooltip). Accepts any valid Tooltip props.
65
69
  */
@@ -8,11 +8,11 @@ export declare const themeStorage: {
8
8
  set: (value: any) => void;
9
9
  };
10
10
  export declare const themeInitializerScript: string;
11
- export declare function ThemeProvider({ theme, children, ...boxProps }: {
11
+ declare type Props = {
12
12
  theme?: Theme;
13
13
  children: React.ReactNode;
14
- boxProps?: BoxProps;
15
- }): JSX.Element;
14
+ } & BoxProps;
15
+ export declare function ThemeProvider({ theme, children, ...boxProps }: Props): JSX.Element;
16
16
  export declare namespace ThemeProvider {
17
17
  var cache: import("@emotion/utils").EmotionCache;
18
18
  var setRootStyles: (themeId: any, styles: any) => void;
@@ -350,7 +350,7 @@ export const Checkbox: HTMLInputWrapperComponent
350
350
  // Input
351
351
  // =====
352
352
 
353
- export const Input: CommonComponent & {
353
+ export const Input: HTMLInputWrapperComponent & {
354
354
  Inline: HTMLInputWrapperComponent
355
355
  Input: HTMLInputWrapperComponent
356
356
  InputBox: CommonComponent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/tapestry-react",
3
- "version": "2.6.0-rc.9",
3
+ "version": "2.6.0",
4
4
  "description": "A collection of flexible React components to help you build resilient, accessible user interfaces quickly and effectively.",
5
5
  "author": "Front End Systems Engineering <frontend@pco.bz>",
6
6
  "main": "dist/cjs/index.js",
@@ -76,7 +76,7 @@
76
76
  "husky": "^4.3.8",
77
77
  "is-ci-cli": "^2.2.0",
78
78
  "jest": "^26.6.3",
79
- "jest-canvas-mock": "2.3.1",
79
+ "jest-canvas-mock": "^2.5.0",
80
80
  "jest-watch-typeahead": "0.6.1",
81
81
  "react": "^17.0.1",
82
82
  "react-dom": "^17.0.1",
@@ -88,7 +88,7 @@
88
88
  "typescript": "^4.1.5"
89
89
  },
90
90
  "dependencies": {
91
- "@planningcenter/icons": "^14.11.0",
91
+ "@planningcenter/icons": "^14.12.0",
92
92
  "@planningcenter/react-beautiful-dnd": "^13.2.1",
93
93
  "@popmotion/popcorn": "^0.4.4",
94
94
  "@popperjs/core": "^2.11.6",
@@ -106,6 +106,6 @@
106
106
  "stylefire": "^7.0.3",
107
107
  "tabbable": "^6.0.0",
108
108
  "tiny-spring": "^1.0.0",
109
- "zustand": "^4.1.1"
109
+ "zustand": "^4.3.7"
110
110
  }
111
111
  }
@@ -2,12 +2,42 @@ import React from 'react'
2
2
  import { render, fireEvent } from '@testing-library/react'
3
3
  import { Button } from './Button'
4
4
 
5
+ it(`should render as <button> with type="button" by default`, () => {
6
+ const { container } = render(<Button />)
7
+ const button = container.querySelector('button')
8
+ expect(button.getAttribute('type')).toEqual('button')
9
+ })
10
+
11
+ it(`should render as <button> with type="submit"`, () => {
12
+ const { container } = render(<Button type='submit' />)
13
+ const button = container.querySelector('button')
14
+ expect(button.getAttribute('type')).toEqual('submit')
15
+ })
16
+
5
17
  it(`should render title`, () => {
6
18
  const title = 'Hello'
7
19
  const { getByText } = render(<Button title={title} />)
8
20
  getByText(title)
9
21
  })
10
22
 
23
+ it(`should render <a> without a type if "to" is provided`, () => {
24
+ const { container } = render(<Button to='#' />)
25
+ const button = container.querySelector('a')
26
+ expect(button.getAttribute('type')).toBeNull()
27
+ })
28
+
29
+ it(`should render <a> without a type if "href" is provided`, () => {
30
+ const { container } = render(<Button href='#' />)
31
+ const button = container.querySelector('a')
32
+ expect(button.getAttribute('type')).toBeNull()
33
+ })
34
+
35
+ it(`should render <a> with "href" if "to" is specifed`, () => {
36
+ const { container } = render(<Button to='#' />)
37
+ const button = container.querySelector('a')
38
+ expect(button.getAttribute('href')).toEqual('#')
39
+ })
40
+
11
41
  it(`should render href and external link values`, () => {
12
42
  const title = 'Hello'
13
43
  const { getByText } = render(
@@ -86,6 +86,11 @@ type ButtonProps = {
86
86
  */
87
87
  to?: string
88
88
 
89
+ /**
90
+ * Where the browser should navigate to when pressed. If you need any element here other than `<a>`, remember to use the `as` prop.
91
+ */
92
+ href?: string
93
+
89
94
  /**
90
95
  * Wraps button in a [`<Tooltip />`](./tooltip). Accepts any valid Tooltip props.
91
96
  */
@@ -287,6 +292,14 @@ export function Button({
287
292
  restProps['href'] = to
288
293
  }
289
294
 
295
+ // remove `type` if either `to` or `href` is specified
296
+ if (to || (restProps as any).href) {
297
+ buttonProps = {
298
+ ...buttonProps,
299
+ type: null,
300
+ }
301
+ }
302
+
290
303
  // apply stroke defaults and higher z-index when hovering to show outline in group properly
291
304
  if (variant === 'outline') {
292
305
  buttonProps = {
@@ -342,7 +355,7 @@ export function Button({
342
355
  }
343
356
 
344
357
  if (
345
- type &&
358
+ buttonProps.type &&
346
359
  (restProps as any).as &&
347
360
  (restProps as any).as !== "button"
348
361
  ) {
@@ -242,7 +242,7 @@ export type Props = {
242
242
  onColumnSort?: Function,
243
243
 
244
244
  /**
245
- * `(rowData: any, rowIndex: number) => void`
245
+ * `(rowData: any, rowIndex: number, event: React.SyntheticEvent) => void`
246
246
  *
247
247
  * Callback when a row has been clicked.
248
248
  */
@@ -19,7 +19,7 @@ function BodyRow({
19
19
  } = useKeyboardShortcuts(keyboardShortcuts, { rowData, rowIndex })
20
20
  const props = {
21
21
  ref: innerRef,
22
- onClick: onRowClick && (() => onRowClick(rowData, rowIndex)),
22
+ onClick: (event) => onRowClick && onRowClick(rowData, rowIndex, event),
23
23
  onMouseEnter: bindKeyboardShortcuts,
24
24
  onMouseLeave: unbindKeyboardShortcuts,
25
25
  style: {
@@ -1,6 +1,6 @@
1
1
  import { createContext, useCallback, useContext, useEffect } from 'react'
2
2
  import useConstant from '../../hooks/useConstant'
3
- import create from 'zustand'
3
+ import { create } from 'zustand'
4
4
 
5
5
  import { range } from '../../utils'
6
6
 
@@ -9,7 +9,7 @@ import Popover from '../Popover'
9
9
  import { cloneChildren, generateId } from '../utils'
10
10
 
11
11
  import Item, { ITEM_DISPLAY_NAME } from './Item'
12
- import Link, { LINK_DISPLAY_NAME, LINK_DATA } from './Link'
12
+ import Link, { LINK_DISPLAY_NAME } from './Link'
13
13
 
14
14
  type Props = {
15
15
  children?: React.ReactNode,
@@ -125,7 +125,7 @@ class Dropdown extends Component<Props> {
125
125
  this.closePopover()
126
126
  this.popover.focusAnchor()
127
127
  }
128
- if (data === LINK_DATA) {
128
+ if (node.tagName === 'A' && event.type !== 'click') {
129
129
  node.click()
130
130
  } else if (this.props.onSelect) {
131
131
  this.props.onSelect(data)
@@ -215,18 +215,21 @@ class Dropdown extends Component<Props> {
215
215
  'aria-haspopup': true,
216
216
  'aria-expanded': isPopoverOpen,
217
217
  [arrowIconOnly ? 'icon' : 'iconRight']: {
218
- name: isPopoverOpen ? 'general.upCaret' : 'general.downCaret',
218
+ name: isPopoverOpen
219
+ ? 'general.upCaret'
220
+ : 'general.downCaret',
219
221
  size: 'sm',
220
222
  },
221
223
  title: arrowIconOnly ? 'arrow down' : restProps.title,
222
224
  tabIndex: 0,
223
225
  cursor: 'pointer',
224
226
  onBlur: requestBlur,
225
- onClick: () => {
227
+ onClick: (event) => {
226
228
  this.togglePopover()
227
229
  if (!isPopoverOpen) {
228
230
  this.popover.focusAnchor()
229
231
  }
232
+ onClick && onClick(event)
230
233
  },
231
234
  onKeyDown: (event) => {
232
235
  anchorProps.onKeyDown(event)
@@ -26,10 +26,10 @@ render(
26
26
  render(
27
27
  <Dropdown title="Links" size="sm" variant="outline">
28
28
  <Dropdown.Link to="http://planning.center" external>
29
- Planning Center
29
+ Planning Center (external)
30
30
  </Dropdown.Link>
31
- <Dropdown.Link to="https://reactjs.org" external>
32
- React Docs
31
+ <Dropdown.Link to="/button">
32
+ Tapestry React Button
33
33
  </Dropdown.Link>
34
34
  </Dropdown>
35
35
  )
@@ -2,7 +2,7 @@ import React, { useState } from 'react'
2
2
  import { fireEvent, render, screen } from '@testing-library/react'
3
3
  import userEvent from '@testing-library/user-event'
4
4
  import '@testing-library/jest-dom/extend-expect'
5
- import { noop } from 'lodash'
5
+ import noop from 'lodash/noop'
6
6
  import { Box, Button, Text, ThemeProvider } from '..'
7
7
  import Dropdown from './Dropdown'
8
8
 
@@ -4,7 +4,6 @@ import { ItemListItem } from '../ItemList'
4
4
  import Menu from '../Menu'
5
5
 
6
6
  export const LINK_DISPLAY_NAME = 'Dropdown.Link'
7
- export const LINK_DATA = 'link'
8
7
 
9
8
  class Link extends Component {
10
9
  // Graphql wasn't picking up the correct displayName when this was
@@ -17,12 +16,7 @@ class Link extends Component {
17
16
  restProps.target = '_blank'
18
17
  }
19
18
  return (
20
- <ItemListItem
21
- data={LINK_DATA}
22
- text={text}
23
- disabled={disabled}
24
- index={index}
25
- >
19
+ <ItemListItem data="link" text={text} disabled={disabled} index={index}>
26
20
  {({ id, highlight, highlighted, clearHighlight, select }) => (
27
21
  <Menu.Item
28
22
  as="a"
@@ -1,8 +1,9 @@
1
1
  // @flow
2
- import React, { Component } from 'react'
2
+ import React, { useCallback, useRef, useEffect } from 'react'
3
3
 
4
4
  import { getColor } from '../system'
5
5
  import Text from '../Text'
6
+ import { useThemeProps } from '../system'
6
7
 
7
8
  import { inputs, inputLabels } from './utils'
8
9
 
@@ -10,54 +11,56 @@ export type InputLabelProps = {
10
11
  /**
11
12
  * The `id` of the input to control. Compatible with all Tapestry-React form components.
12
13
  */
13
- controls: string,
14
+ controls?: string,
14
15
 
15
16
  /**
16
17
  * The current state of the label. Should match corresponding `Input`'s state prop.
17
18
  */
18
- state: 'warning' | 'error' | 'success',
19
+ state?: 'warning' | 'error' | 'success',
19
20
  }
20
21
 
21
- class InputLabel extends Component<InputLabelProps> {
22
- componentDidMount() {
23
- this.input = inputs[this.props.controls]
24
- inputLabels[this.props.controls] = true
25
- }
22
+ function InputLabel({ controls, state, ...restProps }: InputLabelProps) {
23
+ const { ...themeProps } = useThemeProps('inputLabel', restProps)
26
24
 
27
- componentWillUnmount() {
28
- delete inputLabels[this.props.controls]
29
- }
25
+ const input = useRef(null)
30
26
 
31
- focusInput = () => {
32
- this.input && this.input.focus()
27
+ if (controls) {
28
+ themeProps.id = `${controls}-label`
33
29
  }
34
-
35
- handleMouseOver = () => {
36
- this.input && this.input.setState({ isHovered: true })
30
+ if (state) {
31
+ themeProps.color = getColor(state)
37
32
  }
38
33
 
39
- handleMouseOut = () => {
40
- this.input && this.input.setState({ isHovered: false })
41
- }
34
+ useEffect(() => {
35
+ input.current = inputs[controls]
36
+ inputLabels[controls] = true
42
37
 
43
- render() {
44
- const { controls, state, ...restProps } = this.props
45
- if (controls) {
46
- restProps.id = `${controls}-label`
47
- }
48
- if (state) {
49
- restProps.color = getColor(state)
38
+ return () => {
39
+ delete inputLabels[controls]
50
40
  }
51
- return (
52
- <Text
53
- as="label"
54
- onMouseOver={this.handleMouseOver}
55
- onMouseOut={this.handleMouseOut}
56
- onClick={this.focusInput}
57
- {...restProps}
58
- />
59
- )
60
- }
41
+ }, [])
42
+
43
+ const focusInput = useCallback(() => {
44
+ input.current && input.current.focus()
45
+ }, [input])
46
+
47
+ const handleMouseOver = useCallback(() => {
48
+ input.current && input.current.setState({ isHovered: true })
49
+ }, [input])
50
+
51
+ const handleMouseOut = useCallback(() => {
52
+ input.current && input.current.setState({ isHovered: false })
53
+ }, [input])
54
+
55
+ return (
56
+ <Text
57
+ as="label"
58
+ onMouseOver={handleMouseOver}
59
+ onMouseOut={handleMouseOut}
60
+ onClick={focusInput}
61
+ {...themeProps}
62
+ />
63
+ )
61
64
  }
62
65
 
63
66
  InputLabel.displayName = 'Input.InputLabel'
@@ -4,6 +4,7 @@ category: Forms
4
4
  summary: Provides accessibility as well as usability improvements for mouse users by allowing the user to click the <InputLabel/> component to focus the respective control. This mimics the browsers native label tag, but allows use with custom components like <Select/>.
5
5
  propsSummary: Accepts [Text](/text) props.
6
6
  parent: Input
7
+ themeKey: inputLabel
7
8
  ---
8
9
 
9
10
  ```jsx live
@@ -5,6 +5,7 @@ import Box from '../Box'
5
5
  import Scrim from '../Scrim'
6
6
  import { useDocumentEvent } from '../hooks'
7
7
  import { trapFocus } from '../utils'
8
+ import { useThemeProps } from '../system'
8
9
 
9
10
  export type ModalProps = {
10
11
  children?: any,
@@ -23,6 +24,11 @@ export type ModalProps = {
23
24
  * Determines whether the modal is open or not.
24
25
  */
25
26
  open: boolean,
27
+
28
+ /**
29
+ * Props passed to the internal [`<Scrim/>`](/scrim) component.
30
+ */
31
+ scrimProps?: object,
26
32
  }
27
33
 
28
34
  function Modal({
@@ -32,6 +38,7 @@ function Modal({
32
38
  open,
33
39
  ...restProps
34
40
  }: ModalProps) {
41
+ const { scrimProps = {}, ...themeProps } = useThemeProps('modal', restProps)
35
42
  const modalRef = useRef(null)
36
43
 
37
44
  useLayoutEffect(() => {
@@ -58,16 +65,17 @@ function Modal({
58
65
  onRequestClose()
59
66
  }
60
67
  }}
68
+ {...scrimProps}
61
69
  >
62
70
  <Box
71
+ backgroundColor="surface"
63
72
  innerRef={modalRef}
64
- width="100%"
73
+ margin={4}
65
74
  maxWidth={60}
66
75
  padding={2}
67
- margin={4}
68
- backgroundColor="surface"
69
76
  radius={3}
70
- {...restProps}
77
+ width="100%"
78
+ {...themeProps}
71
79
  >
72
80
  {children}
73
81
  </Box>
@@ -2,6 +2,7 @@
2
2
  title: Modal
3
3
  category: Overlays
4
4
  propsSummary: Accepts [Box](/box) props.
5
+ themeKey: modal
5
6
  ---
6
7
 
7
8
  ```jsx live
@@ -16,7 +17,7 @@ function MyModal(props) {
16
17
  return () => setLazyComponent(null)
17
18
  }, [props.open])
18
19
  return (
19
- <Modal id="modal" closeOnOutsideClick height={200} {...props}>
20
+ <Modal id="modal" closeOnOutsideClick height={25} {...props}>
20
21
  <StackView spacing={2}>
21
22
  {lazyComponent || <Text>Loading lazy component...</Text>}
22
23
  <Select
@@ -5,7 +5,7 @@ import '@testing-library/jest-dom/extend-expect'
5
5
  import Dropdown from '../Dropdown'
6
6
  import Select from '../Select'
7
7
  import { Button, Heading, Modal, ThemeProvider } from '../'
8
- import { noop } from 'lodash'
8
+ import noop from 'lodash/noop'
9
9
 
10
10
  describe('Modal', () => {
11
11
  const TestModal = () => {
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Popover
3
3
  category: Overlays
4
+ themeKey: popover
4
5
  ---
5
6
 
6
7
  ```jsx live
@@ -7,6 +7,8 @@ import { lockScroll } from '../utils'
7
7
 
8
8
  import rewireTabOrder from './rewireTabOrder'
9
9
  import { getFixedParent, getModifiers } from './utils'
10
+ import { useThemeProps } from '../system'
11
+ import { useTheme } from '@emotion/react'
10
12
 
11
13
  type anchorCallbackProps = {
12
14
  innerRef(node: HTMLElement): void
@@ -116,6 +118,10 @@ export const Popover = React.forwardRef(
116
118
  }: PopoverProps,
117
119
  ref
118
120
  ) => {
121
+ const { zIndex = 10000, ...themeProps } = useThemeProps(
122
+ 'popover',
123
+ restProps
124
+ )
119
125
  const anchorRef = React.useRef(null)
120
126
  const popperRef = React.useRef(null)
121
127
  const unlockScroll = React.useRef(null)
@@ -253,8 +259,8 @@ export const Popover = React.forwardRef(
253
259
  }
254
260
  },
255
261
  // ideally this should be pulled out to something like ThemeProvider for predictable z indices
256
- style: { zIndex: 10000 },
257
- ...restProps,
262
+ style: { zIndex },
263
+ ...themeProps,
258
264
  })
259
265
  : null}
260
266
  </Portal>
@@ -3,6 +3,7 @@ title: Scrim
3
3
  category: Overlays
4
4
  summary: Scrims are used to display focused content like alerts, modals, or media previews.
5
5
  propsSummary: Accepts [StackView](/stackview) props.
6
+ themeKey: scrim
6
7
  ---
7
8
 
8
9
  ```jsx live
@@ -1,33 +1,38 @@
1
1
  import * as React from 'react'
2
2
 
3
3
  import StackView from '../StackView'
4
+ import { useThemeProps } from '../system'
4
5
 
5
6
  type ScrimProps = {
6
7
  /** Gain access to the internal ref. */
7
- ref?: any,
8
- children?: any,
8
+ ref?: any
9
+ children?: any
9
10
  }
10
11
 
11
- const Scrim = React.forwardRef(function (props: ScrimProps, _ref: any) {
12
+ const Scrim = React.forwardRef(function (
13
+ { ref, ...restProps }: ScrimProps,
14
+ _ref: any
15
+ ) {
12
16
  React.useLayoutEffect(() => {
13
17
  document.body.style.overflow = 'hidden'
14
18
  return () => {
15
19
  document.body.style.overflow = ''
16
20
  }
17
21
  }, [])
22
+ const { zIndex = 10000, ...themeProps } = useThemeProps('scrim', restProps)
18
23
  return (
19
24
  <StackView
20
- innerRef={props.ref}
25
+ innerRef={ref}
21
26
  position="fixed"
22
27
  top={0}
23
28
  right={0}
24
29
  bottom={0}
25
30
  left={0}
26
- zIndex={10000}
31
+ zIndex={zIndex}
27
32
  overflow="auto"
28
33
  // @ts-ignore
29
34
  backgroundColor="hsla(0,0%,0%,0.4)"
30
- {...props}
35
+ {...themeProps}
31
36
  />
32
37
  )
33
38
  })
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  title: Sidebar
3
3
  category: General
4
- propsSummary: Accepts [StackView](/stackview) props.
5
4
  ---
6
5
 
7
6
  ```jsx live
@@ -1,7 +1,8 @@
1
1
  // @flow
2
2
  import React, { PureComponent, Children, Fragment } from 'react'
3
3
  import { Global } from '@emotion/react'
4
- import { camelCase, snakeCase } from 'lodash'
4
+ import camelCase from 'lodash/camelCase'
5
+ import snakeCase from 'lodash/snakeCase'
5
6
 
6
7
  import type { PaginationProps } from '../Pagination/Pagination'
7
8
 
@@ -2,7 +2,7 @@ import React, { useLayoutEffect, useState } from 'react'
2
2
  import { ThemeProvider as EmotionThemeProvider } from '@emotion/react'
3
3
  import { CacheProvider } from '@emotion/react'
4
4
  import createCache from '@emotion/cache'
5
- import { merge } from 'lodash'
5
+ import merge from 'lodash/merge'
6
6
  import { Box, BoxProps } from '../Box'
7
7
 
8
8
  import defaultTheme from '../system/default-theme'
@@ -58,15 +58,16 @@ function mergeThemes(a: Theme = {}, b: Theme = {}) {
58
58
  }
59
59
  }
60
60
 
61
+ type Props = {
62
+ theme?: Theme
63
+ children: React.ReactNode
64
+ } & BoxProps
65
+
61
66
  export function ThemeProvider({
62
67
  theme = emptyTheme,
63
68
  children,
64
69
  ...boxProps
65
- }: {
66
- theme?: Theme
67
- children: React.ReactNode
68
- boxProps?: BoxProps
69
- }) {
70
+ }: Props) {
70
71
  const [mergedTheme, setMergedTheme] = useState(() =>
71
72
  mergeThemes(defaultTheme, theme)
72
73
  )
@@ -230,7 +230,7 @@ class TimeField extends Component<Props> {
230
230
  highlightOnInteraction
231
231
  value={this.state.meridiem}
232
232
  grow={0}
233
- width={3}
233
+ width="2em"
234
234
  textAlign="center"
235
235
  aria-label="AM/PM"
236
236
  onChange={noop} // prevent React warnings