playbook_ui 14.16.0.pre.alpha.PBNTR881advancedtablefullscreen6884 → 14.16.0.pre.alpha.PLAY1929bracketlayout6927

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +0 -70
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +1 -87
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +1 -14
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -2
  7. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +34 -34
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -2
  9. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +16 -0
  10. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.html.erb +0 -11
  11. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.jsx +0 -7
  12. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_inline_styles.scss +28 -24
  13. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +3 -4
  14. data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +2 -3
  15. data/app/pb_kits/playbook/pb_form/pb_form_validation.js +1 -1
  16. data/app/pb_kits/playbook/pb_layout/_layout.scss +57 -0
  17. data/app/pb_kits/playbook/pb_layout/_layout.tsx +16 -7
  18. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.jsx +190 -0
  19. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.md +5 -0
  20. data/app/pb_kits/playbook/pb_layout/docs/example.yml +1 -0
  21. data/app/pb_kits/playbook/pb_layout/docs/index.js +1 -0
  22. data/app/pb_kits/playbook/pb_layout/layout.test.js +4 -0
  23. data/app/pb_kits/playbook/pb_layout/subcomponents/_game.tsx +89 -0
  24. data/app/pb_kits/playbook/pb_layout/subcomponents/_round.tsx +57 -0
  25. data/app/pb_kits/playbook/pb_lightbox/hooks/useVisibility.js +1 -1
  26. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -1
  27. data/app/pb_kits/playbook/pb_tooltip/index.js +183 -56
  28. data/app/pb_kits/playbook/pb_typeahead/index.ts +2 -2
  29. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -1
  30. data/app/pb_kits/playbook/utilities/object.test.js +149 -1
  31. data/app/pb_kits/playbook/utilities/object.ts +124 -42
  32. data/dist/chunks/{_typeahead-N-EFroAX.js → _typeahead-Djo6qCne.js} +3 -3
  33. data/dist/chunks/_weekday_stacked-BGGESD-t.js +45 -0
  34. data/dist/chunks/lib-BGzBzFZX.js +29 -0
  35. data/dist/chunks/{pb_form_validation-DMajaRt3.js → pb_form_validation-BvNy9Bd6.js} +1 -1
  36. data/dist/chunks/vendor.js +1 -1
  37. data/dist/playbook-doc.js +1 -1
  38. data/dist/playbook-rails-react-bindings.js +1 -1
  39. data/dist/playbook-rails.js +1 -1
  40. data/dist/playbook.css +1 -1
  41. data/lib/playbook/version.rb +1 -1
  42. metadata +10 -9
  43. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +0 -90
  44. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.md +0 -3
  45. data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +0 -282
  46. data/dist/chunks/_weekday_stacked-jxFuYoYX.js +0 -45
  47. data/dist/chunks/lib-Co5y3V4K.js +0 -29
@@ -10,6 +10,8 @@ $list-header-height: $space_lg;
10
10
  $list-footer-height: $space_lg;
11
11
  $list-border-radius: $border_rad_lighter;
12
12
  $card-border-radius: $border_rad_lightest;
13
+ $bracket-connector-width: 45px;
14
+ $bracket-border-width: 4px;
13
15
 
14
16
 
15
17
  [class^=pb_layout_kit] {
@@ -168,6 +170,61 @@ $card-border-radius: $border_rad_lightest;
168
170
  }
169
171
  }
170
172
 
173
+ &[class*=_bracket]{
174
+ display: flex;
175
+ overflow-x: scroll;
176
+
177
+ div.layout_round {
178
+ display: flex;
179
+ flex-direction: column;
180
+ justify-content: space-around;
181
+ flex-grow: 1;
182
+ }
183
+
184
+ .connector_container {
185
+ display: flex;
186
+ flex-direction: column;
187
+ justify-content: space-around;
188
+ }
189
+ .right_connector {
190
+ border-top: $bracket-border-width solid $border_light;
191
+ width: $bracket-connector-width;
192
+ margin-left: $bracket-connector-width;
193
+ }
194
+
195
+ .layout_round .layout_game {
196
+ position: relative;
197
+ }
198
+
199
+ .half_box {
200
+ content: '';
201
+ position: absolute;
202
+ top: calc(50% - $bracket-border-width / 2);
203
+ height: calc(100% + $bracket-border-width);
204
+ width: $bracket-connector-width;
205
+ right: -$bracket-connector-width;
206
+ border-top-right-radius: $border_radius_lg;
207
+ border-bottom-right-radius: $border_radius_lg;
208
+ border-top: $bracket-border-width solid $border_light;
209
+ border-bottom: $bracket-border-width solid $border_light;
210
+ border-right: $bracket-border-width solid $border_light;
211
+ }
212
+
213
+ .layout_round_label {
214
+ display: none;
215
+ }
216
+
217
+ @media (max-width: $screen-md-max) {
218
+ flex-direction: column;
219
+ .layout_round_label {
220
+ display: block;
221
+ }
222
+ .layout_round .layout_game::after,
223
+ .connector_container {
224
+ display: none;
225
+ }
226
+ }
227
+ }
171
228
 
172
229
  &[class*=_sidebar]{
173
230
  $layout_sizes: (
@@ -4,6 +4,9 @@ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../uti
4
4
 
5
5
  import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
6
6
 
7
+ import { Round, RoundLabel } from "./subcomponents/_round";
8
+ import Game from "./subcomponents/_game";
9
+
7
10
  type LayoutPropTypes = {
8
11
  aria?: {[key: string]: string},
9
12
  children?: React.ReactChild[] | React.ReactChild,
@@ -18,7 +21,7 @@ type LayoutPropTypes = {
18
21
  size?: "xs" | "sm" | "md" | "base" | "lg" | "xl",
19
22
  variant?: "light" | "dark" | "gradient",
20
23
  transparent?: boolean,
21
- layout?: "sidebar" | "collection" | "kanban" | "content" | "masonry",
24
+ layout?: "sidebar" | "collection" | "kanban" | "content" | "masonry" | "bracket",
22
25
  } & GlobalProps
23
26
 
24
27
  type LayoutSideProps = {
@@ -140,7 +143,7 @@ const Layout = (props: LayoutPropTypes) => {
140
143
  const htmlProps = buildHtmlProps(htmlOptions)
141
144
 
142
145
  const layoutCss =
143
- layout == 'collection'
146
+ (layout == 'collection' || layout == 'bracket')
144
147
  ? `pb_layout_kit_${layout}`
145
148
  : layout == 'kanban'
146
149
  ? `pb_layout_kit_${layout}${responsiveClass}`
@@ -151,11 +154,9 @@ const Layout = (props: LayoutPropTypes) => {
151
154
  })
152
155
 
153
156
  const layoutCollapseCss =
154
- layout == 'collection'
157
+ (layout == 'collection' || layout == 'kanban' || layout == 'bracket')
155
158
  ? ''
156
- : layout == 'kanban'
157
- ? ''
158
- : buildCss('layout', position, 'collapse', collapse)
159
+ : buildCss('layout', position, 'collapse', collapse)
159
160
 
160
161
  const layoutChildren = React.Children.toArray(children)
161
162
 
@@ -175,6 +176,11 @@ const Layout = (props: LayoutPropTypes) => {
175
176
  (child: React.ReactElement & {type: {displayName: string}}) => child.type?.displayName !== 'Side'
176
177
  )
177
178
 
179
+ const numberOfRounds = Array.isArray(nonSideChildren) ? nonSideChildren.filter((child: any) => child.type?.name === 'Round').length : 0
180
+ const bracketChildren = nonSideChildren.map(child =>
181
+ React.isValidElement(child) ? React.cloneElement(child, { numberOfRounds }) : child
182
+ )
183
+
178
184
  const filteredProps = {...props}
179
185
  delete filteredProps?.position
180
186
 
@@ -196,7 +202,7 @@ const Layout = (props: LayoutPropTypes) => {
196
202
  style={dynamicInlineProps}
197
203
  >
198
204
  {subComponentTags('Side')}
199
- {nonSideChildren}
205
+ {layout === 'bracket' ? bracketChildren : nonSideChildren}
200
206
  </div>
201
207
  )
202
208
  }
@@ -206,5 +212,8 @@ Layout.Body = Body
206
212
  Layout.Item = Item
207
213
  Layout.Header = Header
208
214
  Layout.Footer = Footer
215
+ Layout.Round = Round
216
+ Layout.Game = Game
217
+ Layout.RoundLabel = RoundLabel
209
218
 
210
219
  export default Layout
@@ -0,0 +1,190 @@
1
+ import React from 'react'
2
+
3
+ import Layout from '../../pb_layout/_layout'
4
+ import Flex from '../../pb_flex/_flex'
5
+ import Body from '../../pb_body/_body'
6
+ import Caption from '../../pb_caption/_caption'
7
+ import SectionSeparator from '../../pb_section_separator/_section_separator'
8
+
9
+ const LayoutBracket = () => {
10
+ return (
11
+ <div>
12
+ <Layout
13
+ layout="bracket"
14
+ >
15
+ <Layout.RoundLabel>
16
+ <Caption>Wild Card</Caption>
17
+ <SectionSeparator marginY="sm"/>
18
+ </Layout.RoundLabel>
19
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
20
+ <Layout.Game>
21
+ <Flex justify="between">
22
+ <Body>Packers</Body>
23
+ <Body>10</Body>
24
+ </Flex>
25
+ <Flex justify="between">
26
+ <Body><strong>Eagles</strong></Body>
27
+ <Body>22</Body>
28
+ </Flex>
29
+ </Layout.Game>
30
+ <Layout.Game>
31
+ <Flex justify="between">
32
+ <Body>Vikings</Body>
33
+ <Body>9</Body>
34
+ </Flex>
35
+ <Flex justify="between">
36
+ <Body><strong>Rams</strong></Body>
37
+ <Body>27</Body>
38
+ </Flex>
39
+ </Layout.Game>
40
+ <Layout.Game>
41
+ <Flex justify="between">
42
+ <Body><strong>Lions</strong></Body>
43
+ </Flex>
44
+ <Flex justify="between">
45
+ <Body>BYE</Body>
46
+ </Flex>
47
+ </Layout.Game>
48
+ <Layout.Game>
49
+ <Flex justify="between">
50
+ <Body><strong>Commanders</strong></Body>
51
+ <Body>23</Body>
52
+ </Flex>
53
+ <Flex justify="between">
54
+ <Body>Buccaneers</Body>
55
+ <Body>20</Body>
56
+ </Flex>
57
+ </Layout.Game>
58
+ <Layout.Game>
59
+ <Flex justify="between">
60
+ <Body><strong>Chiefs</strong></Body>
61
+ </Flex>
62
+ <Flex justify="between">
63
+ <Body>BYE</Body>
64
+ </Flex>
65
+ </Layout.Game>
66
+ <Layout.Game>
67
+ <Flex justify="between">
68
+ <Body>Chargers</Body>
69
+ <Body>12</Body>
70
+ </Flex>
71
+ <Flex justify="between">
72
+ <Body><strong>Texans</strong></Body>
73
+ <Body>32</Body>
74
+ </Flex>
75
+ </Layout.Game>
76
+ <Layout.Game>
77
+ <Flex justify="between">
78
+ <Body>Broncos</Body>
79
+ <Body>7</Body>
80
+ </Flex>
81
+ <Flex justify="between">
82
+ <Body><strong>Bills</strong></Body>
83
+ <Body>31</Body>
84
+ </Flex>
85
+ </Layout.Game>
86
+ <Layout.Game>
87
+ <Flex justify="between">
88
+ <Body>Steelers</Body>
89
+ <Body>14</Body>
90
+ </Flex>
91
+ <Flex justify="between">
92
+ <Body><strong>Ravens</strong></Body>
93
+ <Body>28</Body>
94
+ </Flex>
95
+ </Layout.Game>
96
+ </Layout.Round>
97
+ <Layout.RoundLabel>
98
+ <Caption>Divisional</Caption>
99
+ <SectionSeparator marginY="sm"/>
100
+ </Layout.RoundLabel>
101
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
102
+ <Layout.Game>
103
+ <Flex justify="between">
104
+ <Body>Rams</Body>
105
+ <Body>22</Body>
106
+ </Flex>
107
+ <Flex justify="between">
108
+ <Body><strong>Eagles</strong></Body>
109
+ <Body>28</Body>
110
+ </Flex>
111
+ </Layout.Game>
112
+ <Layout.Game>
113
+ <Flex justify="between">
114
+ <Body><strong>Commanders</strong></Body>
115
+ <Body>45</Body>
116
+ </Flex>
117
+ <Flex justify="between">
118
+ <Body>Lions</Body>
119
+ <Body>31</Body>
120
+ </Flex>
121
+ </Layout.Game>
122
+ <Layout.Game>
123
+ <Flex justify="between">
124
+ <Body>Texans</Body>
125
+ <Body>14</Body>
126
+ </Flex>
127
+ <Flex justify="between">
128
+ <Body><strong>Chiefs</strong></Body>
129
+ <Body>23</Body>
130
+ </Flex>
131
+ </Layout.Game>
132
+ <Layout.Game>
133
+ <Flex justify="between">
134
+ <Body>Ravens</Body>
135
+ <Body>25</Body>
136
+ </Flex>
137
+ <Flex justify="between">
138
+ <Body><strong>Bills</strong></Body>
139
+ <Body>27</Body>
140
+ </Flex>
141
+ </Layout.Game>
142
+ </Layout.Round>
143
+ <Layout.RoundLabel>
144
+ <Caption>Conference</Caption>
145
+ <SectionSeparator marginY="sm"/>
146
+ </Layout.RoundLabel>
147
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
148
+ <Layout.Game>
149
+ <Flex justify="between">
150
+ <Body>Commanders</Body>
151
+ <Body>23</Body>
152
+ </Flex>
153
+ <Flex justify="between">
154
+ <Body><strong>Eagles</strong></Body>
155
+ <Body>55</Body>
156
+ </Flex>
157
+ </Layout.Game>
158
+ <Layout.Game>
159
+ <Flex justify="between">
160
+ <Body>Bills</Body>
161
+ <Body>29</Body>
162
+ </Flex>
163
+ <Flex justify="between">
164
+ <Body><strong>Chiefs</strong></Body>
165
+ <Body>32</Body>
166
+ </Flex>
167
+ </Layout.Game>
168
+ </Layout.Round>
169
+ <Layout.RoundLabel>
170
+ <Caption>Super Bowl</Caption>
171
+ <SectionSeparator marginY="sm"/>
172
+ </Layout.RoundLabel>
173
+ <Layout.Round>
174
+ <Layout.Game>
175
+ <Flex justify="between">
176
+ <Body>Chiefs</Body>
177
+ <Body>22</Body>
178
+ </Flex>
179
+ <Flex justify="between">
180
+ <Body><strong>Eagles</strong></Body>
181
+ <Body>40</Body>
182
+ </Flex>
183
+ </Layout.Game>
184
+ </Layout.Round>
185
+ </Layout>
186
+ </div>
187
+ )
188
+ }
189
+
190
+ export default LayoutBracket
@@ -0,0 +1,5 @@
1
+ Use `<Layout.RoundLabel>`, `<Layout.Round>`, and `<Layout.Game>` to make a bracket layout.
2
+
3
+ On mobile devices, `<Layout.RoundLabel>` will display (on desktop these components are hidden) and the bracket will be in one column.
4
+
5
+ Ensure that each `<Layout.Game>` maintains a consistent height for the bracket lines to lay out properly.
@@ -18,4 +18,5 @@ examples:
18
18
  - layout_kanban: Kanban Layout
19
19
  - layout_content: Content Layout
20
20
  - layout_masonry: Masonry Layout
21
+ - layout_bracket: Bracket Layout
21
22
 
@@ -7,4 +7,5 @@ export { default as LayoutKanbanResponsive } from './_layout_kanban_responsive.j
7
7
  export { default as LayoutCollectionDetail } from './_layout_collection_detail.jsx'
8
8
  export { default as LayoutContent } from './_layout_content.jsx'
9
9
  export { default as LayoutMasonry } from './_layout_masonry.jsx'
10
+ export { default as LayoutBracket } from './_layout_bracket.jsx'
10
11
 
@@ -82,6 +82,10 @@ test("render all layout variants", () => {
82
82
  layout: "masonry",
83
83
  expected: "pb_layout_kit_masonry_size_md_left_light",
84
84
  },
85
+ {
86
+ layout: "bracket",
87
+ expected: "pb_layout_kit_bracket",
88
+ },
85
89
  ]
86
90
 
87
91
  testValues.forEach(({ layout, expected }) => {
@@ -0,0 +1,89 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import { GlobalProps, globalProps, globalInlineProps } from '../../utilities/globalProps'
5
+
6
+ import Card from '../../pb_card/_card'
7
+ import SectionSeparator from '../../pb_section_separator/_section_separator'
8
+
9
+ type LayoutGameProps = {
10
+ children: React.ReactNode[] | React.ReactNode,
11
+ className?: string,
12
+ numberOfRounds: number,
13
+ numberOfGames: number,
14
+ isOdd: boolean,
15
+ } & GlobalProps
16
+
17
+ // Game component (modeled after Item)
18
+ const Game = (props: LayoutGameProps) => {
19
+ const { children, className, numberOfRounds, numberOfGames, isOdd } = props
20
+ const dynamicInlineProps = globalInlineProps(props)
21
+
22
+ const isMultiple = Array.isArray(children)
23
+ const numberOfChildren = isMultiple ? children.length : 0
24
+
25
+ let ratio = 0
26
+ let exponent
27
+ if (numberOfGames > 1) {
28
+ exponent = (numberOfRounds) - Math.log2(numberOfGames) - 1
29
+ ratio = 2 ** exponent
30
+ }
31
+
32
+ if (numberOfChildren === 2) {
33
+ const [firstChild, secondChild] = React.Children.toArray(children)
34
+
35
+ if (React.isValidElement(firstChild) && React.isValidElement(secondChild)) {
36
+ return (
37
+ <div
38
+ className={classnames('layout_game', globalProps(props), className)}
39
+ style={dynamicInlineProps}
40
+ >
41
+ <Card
42
+ marginY="xs"
43
+ padding="none"
44
+ shadow="deep"
45
+ >
46
+ <Card.Body padding="xs">{firstChild}</Card.Body>
47
+ <SectionSeparator />
48
+ <Card.Body padding="xs">{secondChild}</Card.Body>
49
+ </Card>
50
+ {isOdd && numberOfGames > 1 &&
51
+ <div
52
+ className="half_box"
53
+ style={{ height: `calc(${ratio} * 100% + 4px)` }}
54
+ />
55
+ }
56
+ </div>
57
+ )
58
+ }
59
+ }
60
+
61
+ return (
62
+ <div
63
+ className={classnames('layout_game', globalProps(props), className)}
64
+ style={dynamicInlineProps}
65
+ >
66
+ {((!isMultiple && children) || numberOfChildren >= 1 )? (
67
+ children
68
+ ) : (
69
+ <Card
70
+ marginY="xs"
71
+ padding="none"
72
+ shadow="deep"
73
+ >
74
+ <Card.Body padding="xs">To be determined...</Card.Body>
75
+ <SectionSeparator />
76
+ <Card.Body padding="xs">To be determined...</Card.Body>
77
+ </Card>
78
+ )}
79
+ {isOdd && numberOfGames > 1 &&
80
+ <div
81
+ className="half_box"
82
+ style={{ height: `calc(${ratio} * 100% + 4px)` }}
83
+ />
84
+ }
85
+ </div>
86
+ )
87
+ }
88
+
89
+ export default Game
@@ -0,0 +1,57 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import { GlobalProps, globalProps, globalInlineProps } from '../../utilities/globalProps'
5
+
6
+ type LayoutRoundLabelProps = {
7
+ children: React.ReactNode[] | React.ReactNode,
8
+ className?: string,
9
+ } & GlobalProps
10
+
11
+ export const RoundLabel = (props: LayoutRoundLabelProps) => {
12
+ const { children, className } = props
13
+ const dynamicInlineProps = globalInlineProps(props)
14
+ return (
15
+ <div
16
+ className={classnames('layout_round_label', className)}
17
+ style={dynamicInlineProps}
18
+ >
19
+ {children}
20
+ </div>
21
+ )
22
+ }
23
+
24
+ type LayoutRoundProps = {
25
+ children: React.ReactNode[] | React.ReactNode,
26
+ className?: string,
27
+ numberOfRounds: number,
28
+ } & GlobalProps
29
+
30
+ export const Round = (props: LayoutRoundProps) => {
31
+ const { children, className, numberOfRounds } = props
32
+ const dynamicInlineProps = globalInlineProps(props)
33
+ const numberOfChildren = Array.isArray(children) ? children.length : 0
34
+
35
+ const childrenWithProps = Array.isArray(children) ? children.map((child, index) =>
36
+ React.isValidElement(child) ? React.cloneElement(child, { numberOfRounds, numberOfGames: numberOfChildren, isOdd: index % 2 === 0 }) : child
37
+ ) : children
38
+
39
+ const rightConnectors = Array.from({ length: numberOfChildren / 2 }, (_, index) => (
40
+ <div
41
+ className="right_connector"
42
+ key={`right_connector_${index}`}
43
+ />
44
+ ))
45
+
46
+ return (
47
+ <>
48
+ <div
49
+ className={classnames('layout_round', globalProps(props), className)}
50
+ style={dynamicInlineProps}
51
+ >
52
+ {childrenWithProps}
53
+ </div>
54
+ <div className="connector_container">{rightConnectors}</div>
55
+ </>
56
+ )
57
+ }
@@ -1,4 +1,4 @@
1
- import { debounce } from 'lodash'
1
+ import { debounce } from "../../utilities/object"
2
2
  import { useCallback, useMemo, useState } from 'react'
3
3
 
4
4
  export default function useVisibility(initialState = false) {
@@ -7,11 +7,12 @@ import {
7
7
  buildDataProps,
8
8
  buildHtmlProps,
9
9
  } from "../utilities/props";
10
+ import { cloneDeep } from "../utilities/object";
11
+
10
12
  import Icon from "../pb_icon/_icon";
11
13
  import FormPill from "../pb_form_pill/_form_pill";
12
14
  import Body from "../pb_body/_body";
13
15
  import Caption from "../pb_caption/_caption";
14
- import { cloneDeep } from "lodash";
15
16
  import MultiLevelSelectOptions from "./multi_level_select_options";
16
17
  import MultiLevelSelectContext from "./context";
17
18