@planningcenter/tapestry-react 2.6.0-rc.0 → 2.6.0-rc.10

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 (77) 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/components/CheckboxCell.js +1 -1
  5. package/dist/cjs/DataTable/hooks/useCollapsibleRows.js +2 -2
  6. package/dist/cjs/DragDrop/DragDrop.js +7 -0
  7. package/dist/cjs/Dropdown/Dropdown.js +5 -3
  8. package/dist/cjs/Dropdown/Link.js +2 -4
  9. package/dist/cjs/Input/InputLabel.js +40 -63
  10. package/dist/cjs/Modal/Modal.js +18 -8
  11. package/dist/cjs/Popover/Popover.js +10 -2
  12. package/dist/cjs/Portal/Portal.js +11 -1
  13. package/dist/cjs/Scrim/Scrim.js +16 -4
  14. package/dist/cjs/ThemeProvider/ThemeProvider.js +24 -6
  15. package/dist/cjs/ThemeProvider/styles.js +1 -4
  16. package/dist/cjs/TimeField/TimeField.js +1 -1
  17. package/dist/cjs/Tooltip/Tooltip.js +17 -17
  18. package/dist/cjs/index.d.js +70 -25
  19. package/dist/cjs/system/split-styles.js +2 -2
  20. package/dist/esm/Button/Button.js +8 -1
  21. package/dist/esm/Button/Button.test.js +67 -9
  22. package/dist/esm/DataTable/components/BodyRow.js +2 -2
  23. package/dist/esm/DataTable/components/CheckboxCell.js +1 -1
  24. package/dist/esm/DataTable/hooks/useCollapsibleRows.js +1 -1
  25. package/dist/esm/DragDrop/DragDrop.js +5 -0
  26. package/dist/esm/Dropdown/Dropdown.js +6 -4
  27. package/dist/esm/Dropdown/Link.js +1 -2
  28. package/dist/esm/Input/InputLabel.js +40 -63
  29. package/dist/esm/Modal/Modal.js +16 -8
  30. package/dist/esm/Popover/Popover.js +8 -2
  31. package/dist/esm/Portal/Portal.js +10 -0
  32. package/dist/esm/Scrim/Scrim.js +15 -4
  33. package/dist/esm/ThemeProvider/ThemeProvider.js +21 -6
  34. package/dist/esm/ThemeProvider/styles.js +1 -4
  35. package/dist/esm/TimeField/TimeField.js +1 -1
  36. package/dist/esm/Tooltip/Tooltip.js +18 -18
  37. package/dist/esm/index.d.js +39 -6
  38. package/dist/esm/system/split-styles.js +1 -1
  39. package/dist/types/Button/Button.d.ts +4 -0
  40. package/dist/types/Divider/Divider.d.ts +2 -2
  41. package/dist/types/Portal/Portal.d.ts +3 -0
  42. package/dist/types/Spinner/Spinner.d.ts +3 -1
  43. package/dist/types/ThemeProvider/ThemeProvider.d.ts +4 -2
  44. package/dist/types/index.d.ts +74 -5
  45. package/package.json +3 -3
  46. package/src/Button/Button.test.tsx +30 -0
  47. package/src/Button/Button.tsx +14 -1
  48. package/src/DataTable/DataTable.js +1 -1
  49. package/src/DataTable/components/BodyRow.js +1 -1
  50. package/src/DataTable/components/BodyRows.js +4 -1
  51. package/src/DataTable/components/CheckboxCell.js +1 -2
  52. package/src/DataTable/hooks/useCollapsibleRows.js +1 -1
  53. package/src/Divider/Divider.tsx +2 -2
  54. package/src/DragDrop/DragDrop.js +5 -0
  55. package/src/Dropdown/Dropdown.js +7 -4
  56. package/src/Dropdown/Dropdown.mdx +3 -3
  57. package/src/Dropdown/Link.js +1 -7
  58. package/src/Icon/Icon.mdx +45 -47
  59. package/src/Input/InputLabel.js +39 -36
  60. package/src/Input/InputLabel.mdx +1 -0
  61. package/src/Modal/Modal.js +16 -6
  62. package/src/Modal/Modal.mdx +2 -1
  63. package/src/Popover/Popover.mdx +1 -0
  64. package/src/Popover/Popover.tsx +8 -2
  65. package/src/Portal/Portal.tsx +14 -0
  66. package/src/RangeSlider/RangeSlider.mdx +10 -12
  67. package/src/Scrim/Scrim.mdx +1 -0
  68. package/src/Scrim/Scrim.tsx +11 -6
  69. package/src/Sidebar/Sidebar.mdx +0 -1
  70. package/src/Spinner/Spinner.tsx +2 -1
  71. package/src/ThemeProvider/ThemeProvider.tsx +22 -10
  72. package/src/ThemeProvider/styles.ts +23 -12
  73. package/src/TimeField/TimeField.js +1 -1
  74. package/src/Tooltip/Tooltip.js +20 -18
  75. package/src/index.d.ts +74 -5
  76. package/src/system/split-styles.js +4 -2
  77. package/src/.DS_Store +0 -0
@@ -11,18 +11,16 @@ render(() => {
11
11
  const [volume, setVolume] = React.useState(50)
12
12
  const muted = volume === 0
13
13
  return (
14
- <ThemeProvider theme={{ icons }}>
15
- <StackView axis="horizontal" alignment="center" width="25%" spacing={1}>
16
- <Icon>
17
- <Icon.Path name="services.volume0" />
18
- <Icon.Path name="services.volume1" visible={muted} />
19
- <Icon.Path name="services.volume2" visible={!muted} />
20
- <Icon.Path name="services.volume3" visible={!muted && volume > 50} />
21
- </Icon>
22
- <RangeSlider value={volume} onChange={setVolume} />
23
- <Text>{volume}</Text>
24
- </StackView>
25
- </ThemeProvider>
14
+ <StackView axis="horizontal" alignment="center" width="25%" spacing={1}>
15
+ <Icon>
16
+ <Icon.Path name="services.volume0" />
17
+ <Icon.Path name="services.volume1" visible={muted} />
18
+ <Icon.Path name="services.volume2" visible={!muted} />
19
+ <Icon.Path name="services.volume3" visible={!muted && volume > 50} />
20
+ </Icon>
21
+ <RangeSlider value={volume} onChange={setVolume} />
22
+ <Text>{volume}</Text>
23
+ </StackView>
26
24
  )
27
25
  })
28
26
  ```
@@ -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
@@ -3,6 +3,7 @@ import { keyframes } from '@emotion/react'
3
3
 
4
4
  import { Box } from '../Box'
5
5
  import { useThemeProps } from '../system'
6
+ import { StyleProps } from '../index'
6
7
 
7
8
  const rotate = keyframes({
8
9
  '100%': { transform: 'rotate(360deg)' },
@@ -37,7 +38,7 @@ export type SpinnerProps = {
37
38
  * Secondary color of spinner.
38
39
  */
39
40
  trackColor?: string
40
- }
41
+ } & StyleProps & React.HTMLAttributes<HTMLElement>
41
42
 
42
43
  export function Spinner({
43
44
  center,
@@ -3,6 +3,7 @@ import { ThemeProvider as EmotionThemeProvider } from '@emotion/react'
3
3
  import { CacheProvider } from '@emotion/react'
4
4
  import createCache from '@emotion/cache'
5
5
  import { merge } from 'lodash'
6
+ import { Box, BoxProps } from '../Box'
6
7
 
7
8
  import defaultTheme from '../system/default-theme'
8
9
  import { flattenPalette } from '../system'
@@ -16,6 +17,10 @@ export const cache = createCache({
16
17
  key: 'tapestry-react',
17
18
  })
18
19
 
20
+ function mergeIntoNewObject(...merges: object[]) {
21
+ return merge({}, ...merges)
22
+ }
23
+
19
24
  export const themeStorage = {
20
25
  get: () => window.localStorage.getItem(STORAGE_KEY),
21
26
  set: (value) => window.localStorage.setItem(STORAGE_KEY, value),
@@ -38,28 +43,31 @@ function mergeThemes(a: Theme = {}, b: Theme = {}) {
38
43
  button: {
39
44
  ...a.button,
40
45
  ...b.button,
41
- themes: merge(a.button?.themes || {}, b.button?.themes || {}),
46
+ themes: mergeIntoNewObject(a.button?.themes || {}, b.button?.themes || {}),
42
47
  },
43
- colors: merge(
48
+ colors: mergeIntoNewObject(
44
49
  flattenPalette(a.colors || {}),
45
50
  flattenPalette(b.colors || {})
46
51
  ),
47
52
  spinner: {
48
53
  ...a.spinner,
49
54
  ...b.spinner,
50
- sizes: merge(a.spinner?.sizes || {}, b.spinner?.sizes || {}),
51
- thickness: merge(a.spinner?.thickness || {}, b.spinner?.thickness || {}),
55
+ sizes: mergeIntoNewObject(a.spinner?.sizes || {}, b.spinner?.sizes || {}),
56
+ thickness: mergeIntoNewObject(a.spinner?.thickness || {}, b.spinner?.thickness || {}),
52
57
  },
53
58
  }
54
59
  }
55
60
 
61
+ type Props = {
62
+ theme?: Theme
63
+ children: React.ReactNode
64
+ } & BoxProps
65
+
56
66
  export function ThemeProvider({
57
67
  theme = emptyTheme,
58
68
  children,
59
- }: {
60
- theme?: Theme
61
- children: React.ReactNode
62
- }) {
69
+ ...boxProps
70
+ }: Props) {
63
71
  const [mergedTheme, setMergedTheme] = useState(() =>
64
72
  mergeThemes(defaultTheme, theme)
65
73
  )
@@ -76,9 +84,13 @@ export function ThemeProvider({
76
84
  return (
77
85
  <CacheProvider value={cache}>
78
86
  <EmotionThemeProvider theme={mergedTheme}>
79
- <div {...{ [`${getThemeDataAttribute(mergedTheme.id)}`]: true }}>
87
+ <Box
88
+ className="tapestry-react-reset"
89
+ {...boxProps}
90
+ {...{ [`${getThemeDataAttribute(mergedTheme.id)}`]: true }}
91
+ >
80
92
  {children}
81
- </div>
93
+ </Box>
82
94
  </EmotionThemeProvider>
83
95
  </CacheProvider>
84
96
  )
@@ -39,23 +39,37 @@ ${getRootStyles(null, defaultColorProperties)}
39
39
 
40
40
  .tapestry-react-reset {
41
41
  appearance: none;
42
+ background-color: transparent;
43
+ border-width: 0px;
44
+ border-style: solid;
45
+ border-color: transparent;
46
+ box-sizing: border-box;
47
+ color: inherit;
42
48
  box-sizing: border-box;
49
+ flex-grow: 0;
50
+ flex-shrink: 0;
51
+ flex-basis: auto;
43
52
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
44
53
  font-weight: 400;
45
- text-decoration: none;
46
- flex: 0 0 auto;
54
+ margin-top: 0;
55
+ margin-right: 0;
56
+ margin-bottom: 0;
57
+ margin-left: 0;
47
58
  min-width: 0px;
48
59
  min-height: 0px;
49
- padding: 0px;
50
- margin: 0px;
51
- border: 0px solid transparent;
52
- background-color: transparent;
53
- color: inherit;
60
+ padding-top: 0;
61
+ padding-right: 0;
62
+ padding-bottom: 0;
63
+ padding-left: 0;
64
+ text-decoration: none;
54
65
  }
55
66
 
56
67
  .tapestry-react-reset::-moz-focus-inner {
57
- padding: 0px;
58
- border: 0px;
68
+ padding-top: 0;
69
+ padding-right: 0;
70
+ padding-bottom: 0;
71
+ padding-left: 0;
72
+ border: none;
59
73
  }
60
74
 
61
75
  .tapestry-react-reset:focus:not(.focus-visible) {
@@ -70,9 +84,6 @@ ${getRootStyles(null, defaultColorProperties)}
70
84
  // so we can have more control over when styles are injected since multiple
71
85
  // Providers can be used on a page
72
86
  function ensureStyleElement(themeId) {
73
- // we use our own global style implementation in place of Emotion Global
74
- // so we can have more control over when styles are injected since multiple
75
- // Providers can be used on a page
76
87
  if (
77
88
  typeof window !== 'undefined' &&
78
89
  !document.getElementById(`tapestry-react-style-${themeId}`)
@@ -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
@@ -3,6 +3,7 @@ import React, {
3
3
  Children,
4
4
  cloneElement,
5
5
  forwardRef,
6
+ useRef,
6
7
  useState,
7
8
  useCallback,
8
9
  useImperativeHandle,
@@ -124,8 +125,8 @@ function Tooltip(props: Props, ref) {
124
125
  let isPageInView = true
125
126
  let isFocused = false
126
127
  let isMouseDown = false
127
- let openTimeoutId = null
128
- let closeTimeoutId = null
128
+ let openTimeoutId = useRef(null)
129
+ let closeTimeoutId = useRef(null)
129
130
 
130
131
  // prevents tooltips showing when focused and navigating back to a page after leaving
131
132
  const cleanupPageViewChange = useCallback(
@@ -137,21 +138,21 @@ function Tooltip(props: Props, ref) {
137
138
  emitter.on('CLOSE_OPEN_TOOLTIPS', close)
138
139
  return () => {
139
140
  emitter.off('CLOSE_OPEN_TOOLTIPS', close)
140
- clearTimeout(openTimeoutId)
141
- clearTimeout(closeTimeoutId)
141
+ clearTimeout(openTimeoutId.current)
142
+ clearTimeout(closeTimeoutId.current)
142
143
  cleanupPageViewChange()
143
144
  }
144
145
  }, [])
145
146
 
146
147
  const open = () => {
147
- clearTimeout(closeTimeoutId)
148
- closeTimeoutId = null
148
+ clearTimeout(closeTimeoutId.current)
149
+ closeTimeoutId.current = null
149
150
  setIsPopoverOpen(true)
150
151
  }
151
152
 
152
153
  const close = () => {
153
- clearTimeout(openTimeoutId)
154
- openTimeoutId = null
154
+ clearTimeout(openTimeoutId.current)
155
+ openTimeoutId.current = null
155
156
  setIsPopoverOpen(false)
156
157
  }
157
158
 
@@ -179,24 +180,25 @@ function Tooltip(props: Props, ref) {
179
180
 
180
181
  const createOpenTimeout = useCallback(() => {
181
182
  clearGlobalTimeout()
182
- if (openTimeoutId === null) {
183
- clearTimeout(closeTimeoutId)
184
- closeTimeoutId = null
183
+ if (openTimeoutId.current === null) {
184
+ clearTimeout(closeTimeoutId.current)
185
+ closeTimeoutId.current = null
185
186
  if (isPopoverOpen === false) {
186
187
  emitter.emit('CLOSE_OPEN_TOOLTIPS')
187
- openTimeoutId = setTimeout(() => open(), instantDelay ? 0 : openDelay)
188
+ openTimeoutId.current = setTimeout(
189
+ () => open(),
190
+ instantDelay ? 0 : openDelay
191
+ )
188
192
  }
189
193
  }
190
194
  })
191
195
 
192
196
  const createCloseTimeout = useCallback(() => {
193
197
  startGlobalTimeout()
194
- if (closeTimeoutId === null) {
195
- clearTimeout(openTimeoutId)
196
- openTimeoutId = null
197
- closeTimeoutId = setTimeout(() => {
198
- close()
199
- }, closeDelay)
198
+ if (closeTimeoutId.current === null) {
199
+ clearTimeout(openTimeoutId.current)
200
+ openTimeoutId.current = null
201
+ closeTimeoutId.current = setTimeout(() => close(), closeDelay)
200
202
  }
201
203
  })
202
204
 
package/src/index.d.ts CHANGED
@@ -259,6 +259,10 @@ export type CommonProps = React.RefAttributes<any> &
259
259
  React.HTMLAttributes<any> &
260
260
  any
261
261
 
262
+ export type CommonComponent = React.FC<CommonProps>
263
+ export type CommonPropsWith<T extends object> = Omit<CommonProps, keyof T> & T
264
+ export type CommonComponentWith<T extends object> = React.FC<CommonPropsWith<T>>
265
+
262
266
  export const designSystem: any
263
267
  export const hooks: any
264
268
  export const server: any
@@ -267,7 +271,6 @@ export const utils: any
267
271
  export const Avatar: React.FC<CommonProps>
268
272
  export const Badge: React.FC<CommonProps>
269
273
  export const Calendar: React.FC<CommonProps>
270
- export const Checkbox: React.FC<CommonProps>
271
274
  export const CheckboxCard: React.FC<CommonProps>
272
275
  export const CheckboxGroup: React.FC<CommonProps>
273
276
  export const ChurchCenterStatus: React.FC<CommonProps>
@@ -289,11 +292,19 @@ export const Highlight: React.FC<CommonProps>
289
292
  export const Icon: React.FC<CommonProps>
290
293
  export const Link: React.FC<CommonProps>
291
294
  export const LinkList: React.FC<CommonProps>
292
- export const List: React.FC<CommonProps>
293
295
  export const Logo: React.FC<CommonProps>
294
296
  export const Menu: React.FC<CommonProps>
295
297
  export const Modal: React.FC<CommonProps>
296
298
  export const NumberField: React.FC<CommonProps>
299
+ export const PageActions: CommonComponent
300
+ export const PageBody: CommonComponent
301
+ export const PageButton: CommonComponent
302
+ export const PageDropdown: CommonComponent
303
+ export const PageHeader: CommonComponent
304
+ export const PageTab: CommonComponent
305
+ export const PageTabList: CommonComponent
306
+ export const PageTitle: CommonComponent
307
+ export const PageToolbar: CommonComponent
297
308
  export const PagerView: React.FC<CommonProps>
298
309
  export const Pagination: React.FC<CommonProps>
299
310
  export const Progress: React.FC<CommonProps>
@@ -304,9 +315,7 @@ export const Section: React.FC<CommonProps>
304
315
  export const HeadingUppercase: React.FC<CommonProps>
305
316
  export const SegmentedControl: React.FC<CommonProps>
306
317
  export const SegmentedTabs: React.FC<CommonProps>
307
- export const Select: React.FC<CommonProps>
308
318
  export const Sidebar: React.FC<CommonProps>
309
- export const Sortable: React.FC<CommonProps>
310
319
  export const StepperField: React.FC<CommonProps>
311
320
  export const StepperProgress: React.FC<CommonProps>
312
321
  export const Summary: React.FC<CommonProps>
@@ -320,6 +329,67 @@ export const Tooltip: React.FC<CommonProps>
320
329
  export const VariantProvider: React.FC<CommonProps>
321
330
  export const Wizard: React.FC<CommonProps>
322
331
 
332
+ // ============
333
+ // Manual Types
334
+ // ===========
335
+ // These are components written in JS, where we can provide very small (one prop at a time) useful
336
+ // typings for consumers.
337
+ // ============
338
+
339
+ type HTMLInputWrapperComponent = CommonComponentWith<{
340
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
341
+ }>
342
+
343
+ // ========
344
+ // Checkbox
345
+ // ========
346
+
347
+ export const Checkbox: HTMLInputWrapperComponent
348
+
349
+ // =====
350
+ // Input
351
+ // =====
352
+
353
+ export const Input: HTMLInputWrapperComponent & {
354
+ Inline: HTMLInputWrapperComponent
355
+ Input: HTMLInputWrapperComponent
356
+ InputBox: CommonComponent
357
+ InputField: HTMLInputWrapperComponent
358
+ InputLabel: CommonComponent
359
+ }
360
+
361
+ // ====
362
+ // List
363
+ // ====
364
+
365
+ export const List: CommonComponent & { Item: CommonComponent }
366
+
367
+ // ======
368
+ // Select
369
+ // ======
370
+
371
+ export const Select: CommonComponent & {
372
+ Inline: CommonComponent
373
+ Option: CommonComponent
374
+ OptionGroup: CommonComponent
375
+ Value: CommonComponent
376
+ toggleValue: (...args: unknown) => unknown
377
+ }
378
+
379
+ // ========
380
+ // Sortable
381
+ // ========
382
+
383
+ export const Sortable: CommonComponent & {
384
+ SortableManager: CommonComponent
385
+ SortableList: CommonComponent
386
+ SortableItem: CommonComponent
387
+ }
388
+
389
+ // =====================
390
+ // Typescript Components
391
+ // =====================
392
+
323
393
  export * from './Alert'
324
394
  export * from './Box'
325
395
  export * from './Button'
@@ -328,7 +398,6 @@ export * from './Divider'
328
398
  export * from './FilterLayout'
329
399
  export * from './GridView'
330
400
  export * from './Group'
331
- export * from './Input'
332
401
  export * from './Popover'
333
402
  export * from './Portal'
334
403
  export * from './Scrim'
@@ -1,7 +1,7 @@
1
1
  import { stylePropNames, pseudoPropNames } from './style-names'
2
2
  import { parsePluginStyles } from './parse-styles'
3
3
 
4
- export default function ({
4
+ export default function SplitStyles({
5
5
  className,
6
6
  mediaQueries = {},
7
7
  plugin,
@@ -26,7 +26,9 @@ export default function ({
26
26
  }
27
27
  return {
28
28
  ...restProps,
29
- className: className ? `tapestry-react-reset ${className}` : `tapestry-react-reset`,
29
+ className: className
30
+ ? `tapestry-react-reset ${className}`
31
+ : `tapestry-react-reset`,
30
32
  css: (theme) => {
31
33
  const propStyles = {}
32
34
  for (const prop in styleProps) {
package/src/.DS_Store DELETED
Binary file