playbook_ui 4.14.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/data/menu.yml +2 -0
  4. data/app/pb_kits/playbook/index.js +4 -1
  5. data/app/pb_kits/playbook/packs/examples.js +2 -0
  6. data/app/pb_kits/playbook/packs/kits/pb_progress_step.js +2 -0
  7. data/app/pb_kits/playbook/pb_button/_button.jsx +9 -1
  8. data/app/pb_kits/playbook/pb_contact/_contact.jsx +1 -0
  9. data/app/pb_kits/playbook/pb_contact/contact.rb +2 -0
  10. data/app/pb_kits/playbook/pb_contact/docs/_contact_default.html.erb +5 -0
  11. data/app/pb_kits/playbook/pb_contact/docs/_contact_default.jsx +4 -0
  12. data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.html.erb +6 -0
  13. data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.jsx +5 -0
  14. data/app/pb_kits/playbook/pb_date_year_stacked/_date_year_stacked.jsx +2 -2
  15. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.jsx +56 -0
  16. data/app/pb_kits/playbook/pb_filter/Filter/FilterBackground.jsx +26 -0
  17. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.jsx +58 -0
  18. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.jsx +46 -0
  19. data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.jsx +37 -0
  20. data/app/pb_kits/playbook/pb_filter/Filter/ResultsCount.jsx +34 -0
  21. data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.jsx +85 -0
  22. data/app/pb_kits/playbook/pb_filter/Filter/index.jsx +26 -0
  23. data/app/pb_kits/playbook/pb_filter/_filter.jsx +1 -222
  24. data/app/pb_kits/playbook/pb_filter/_filter.scss +16 -13
  25. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +34 -41
  26. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx +13 -9
  27. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_background.html.erb +69 -74
  28. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_background.jsx +12 -9
  29. data/app/pb_kits/playbook/pb_filter/docs/_filter_only.html.erb +28 -35
  30. data/app/pb_kits/playbook/pb_filter/docs/_filter_only.jsx +5 -6
  31. data/app/pb_kits/playbook/pb_filter/docs/_filter_single.html.erb +35 -41
  32. data/app/pb_kits/playbook/pb_filter/docs/_filter_single.jsx +12 -10
  33. data/app/pb_kits/playbook/pb_filter/docs/_sort_only.html.erb +12 -18
  34. data/app/pb_kits/playbook/pb_filter/docs/_sort_only.jsx +14 -44
  35. data/app/pb_kits/playbook/pb_filter/templates/_default.html.erb +1 -1
  36. data/app/pb_kits/playbook/pb_layout/_layout.jsx +66 -14
  37. data/app/pb_kits/playbook/pb_layout/docs/_layout_colors.jsx +63 -0
  38. data/app/pb_kits/playbook/pb_layout/docs/_layout_sizes.jsx +87 -0
  39. data/app/pb_kits/playbook/pb_layout/docs/_layout_sizes_dark.jsx +92 -0
  40. data/app/pb_kits/playbook/pb_layout/docs/_layout_transparent.jsx +24 -0
  41. data/app/pb_kits/playbook/pb_layout/docs/example.yml +4 -1
  42. data/app/pb_kits/playbook/pb_layout/docs/index.js +4 -1
  43. data/app/pb_kits/playbook/pb_online_status/_online_status.jsx +31 -14
  44. data/app/pb_kits/playbook/pb_online_status/docs/_online_status_default.jsx +19 -0
  45. data/app/pb_kits/playbook/pb_online_status/docs/example.yml +3 -3
  46. data/app/pb_kits/playbook/pb_online_status/docs/index.js +1 -0
  47. data/app/pb_kits/playbook/pb_popover/_popover.jsx +2 -2
  48. data/app/pb_kits/playbook/pb_popover/docs/example.yml +0 -2
  49. data/app/pb_kits/playbook/pb_popover/docs/index.js +0 -1
  50. data/app/pb_kits/playbook/pb_progress_step/_progress_step.html.erb +6 -0
  51. data/app/pb_kits/playbook/pb_progress_step/_progress_step.jsx +35 -0
  52. data/app/pb_kits/playbook/pb_progress_step/_progress_step.scss +388 -0
  53. data/app/pb_kits/playbook/pb_progress_step/_progress_step_item.html.erb +23 -0
  54. data/app/pb_kits/playbook/pb_progress_step/_progress_step_item.jsx +44 -0
  55. data/app/pb_kits/playbook/pb_progress_step/docs/_description.md +1 -0
  56. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_dark.html.erb +8 -0
  57. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_dark.jsx +18 -0
  58. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_default.html.erb +33 -0
  59. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_default.jsx +39 -0
  60. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_vertical.html.erb +33 -0
  61. data/app/pb_kits/playbook/pb_progress_step/docs/_progress_step_vertical.jsx +40 -0
  62. data/app/pb_kits/playbook/pb_progress_step/docs/example.yml +12 -0
  63. data/app/pb_kits/playbook/pb_progress_step/docs/index.js +3 -0
  64. data/app/pb_kits/playbook/pb_progress_step/progress_step.rb +33 -0
  65. data/app/pb_kits/playbook/pb_progress_step/progress_step_item.rb +19 -0
  66. data/app/pb_kits/playbook/pb_stat_change/docs/_stat_change_default.html.erb +1 -1
  67. data/app/pb_kits/playbook/pb_stat_change/docs/_stat_change_default.jsx +1 -1
  68. data/app/pb_kits/playbook/pb_stat_change/stat_change.rb +1 -1
  69. data/app/pb_kits/playbook/pb_timestamp/_timestamp.jsx +39 -14
  70. data/app/pb_kits/playbook/pb_timestamp/docs/_timestamp_default.jsx +8 -0
  71. data/app/pb_kits/playbook/pb_timestamp/docs/example.yml +3 -3
  72. data/app/pb_kits/playbook/pb_timestamp/docs/index.js +1 -0
  73. data/app/pb_kits/playbook/pb_title_detail/_title_detail.jsx +47 -14
  74. data/app/pb_kits/playbook/pb_title_detail/docs/_title_detail_default.jsx +26 -0
  75. data/app/pb_kits/playbook/pb_title_detail/docs/example.yml +3 -3
  76. data/app/pb_kits/playbook/pb_title_detail/docs/index.js +1 -0
  77. data/app/pb_kits/playbook/pb_tooltip/_tooltip.html.erb +10 -0
  78. data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +105 -0
  79. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_default.html.erb +10 -0
  80. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_white.html.erb +9 -0
  81. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +5 -0
  82. data/app/pb_kits/playbook/pb_tooltip/index.js +80 -0
  83. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +34 -0
  84. data/app/pb_kits/playbook/tokens/_colors.scss +4 -0
  85. data/app/pb_kits/playbook/vendor.js +3 -0
  86. data/lib/playbook/version.rb +1 -1
  87. metadata +41 -6
  88. data/app/pb_kits/playbook/pb_layout/_body.jsx +0 -26
  89. data/app/pb_kits/playbook/pb_layout/_sidebar.jsx +0 -26
  90. data/app/pb_kits/playbook/pb_layout/docs/_layout_default.jsx +0 -14
  91. data/app/pb_kits/playbook/pb_popover/docs/_popover_with_button.html.erb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e529c840f659aace42862d67f6579c6fa9f1fc952960381374b8b005ff41b95
4
- data.tar.gz: 53c5c3676212e699d5c232fc6d4bc59ea3ab10a97335d08e7dc0e4e139a8859f
3
+ metadata.gz: 8d06b43573e33c771eb3617100802fa3e8ad15bf58f7037c233725df32d4e447
4
+ data.tar.gz: 005256edb667970f313898e57ede8d2f50cbe9222fd99007a318808e075f3e23
5
5
  SHA512:
6
- metadata.gz: 92e483f7ec5633610f6180f3d1cf8740f9fae2d128c9db1a17ae8ac55a352a19f358ad32104236f8dcbe9ccd370f40a57c3a63b2b7587a200c95f8d00500dc76
7
- data.tar.gz: 4707de050cf746dd9d82db1cc36cdc1bdf03a8a2653510e2785b324491ddbb1c462faea3053d4ba0d4e65c99f20bf609db0e76a16a3e851518ad58797af6c283
6
+ metadata.gz: 33b0a8f35f696aed191bae44c33aa4686864ba89ac73473b88cd749e30d6cc792a7d4fedff7b413857b7ddd3c22959b68df5b34884c0ffe92e6ec319b0af8c2d
7
+ data.tar.gz: 1070e81eb6faefd83fe85fa725534a8d5ad2ee16f17fb1b9b920433d045a75e09040a85ac64f33c3789d89de1b4dbb332355950f0289914a9acd65a6b8dc19e7
@@ -50,6 +50,7 @@
50
50
  @import 'pb_popover/popover';
51
51
  @import 'pb_progress_pills/progress_pills';
52
52
  @import 'pb_progress_simple/progress_simple';
53
+ @import 'pb_progress_step/progress_step';
53
54
  @import 'pb_radio/radio';
54
55
  @import 'pb_section_separator/section_separator';
55
56
  @import 'pb_select/select';
@@ -67,6 +68,7 @@
67
68
  @import 'pb_title_count/title_count';
68
69
  @import 'pb_title_detail/title_detail';
69
70
  @import 'pb_toggle/toggle';
71
+ @import 'pb_tooltip/tooltip';
70
72
  @import 'pb_typeahead/typeahead';
71
73
  @import 'pb_user/user';
72
74
  @import 'pb_user_badge/user_badge';
@@ -48,11 +48,13 @@ kits:
48
48
  - popover
49
49
  - progress_pills
50
50
  - progress_simple
51
+ - progress_step
51
52
  - section_separator
52
53
  - source
53
54
  - star_rating
54
55
  - stat_change
55
56
  - table
57
+ - tooltip
56
58
  - typography:
57
59
  - body
58
60
  - caption
@@ -52,6 +52,7 @@ export PersonContact from './pb_person_contact/_person_contact.jsx'
52
52
  export Pill from './pb_pill/_pill.jsx'
53
53
  export ProgressPills from './pb_progress_pills/_progress_pills.jsx'
54
54
  export ProgressSimple from './pb_progress_simple/_progress_simple.jsx'
55
+ export ProgressStep from './pb_progress_step/_progress_step.jsx'
55
56
  export Radio from './pb_radio/_radio.jsx'
56
57
  export SectionSeparator from './pb_section_separator/_section_separator.jsx'
57
58
  export Select from './pb_select/_select.jsx'
@@ -66,10 +67,11 @@ export Textarea from './pb_textarea/_textarea.jsx'
66
67
  export TextInput from './pb_text_input/_text_input.jsx'
67
68
  export Time from './pb_time/_time.jsx'
68
69
  export TimeStacked from './pb_time_stacked/_time_stacked.jsx'
69
- export TimeStamp from './pb_timestamp/_timestamp.jsx'
70
+ export Timestamp from './pb_timestamp/_timestamp.jsx'
70
71
  export TimeRangeInline from './pb_time_range_inline/_time_range_inline.jsx'
71
72
  export Title from './pb_title/_title.jsx'
72
73
  export TitleCount from './pb_title_count/_title_count.jsx'
74
+ export TitleDetail from './pb_title_detail/_title_detail.jsx'
73
75
  export Toggle from './pb_toggle/_toggle.jsx'
74
76
  export User from './pb_user/_user.jsx'
75
77
  export UserBadge from './pb_user_badge/_user_badge.jsx'
@@ -86,3 +88,4 @@ export pbChart from './plugins/pb_chart.js'
86
88
  export PbTypeahead from './pb_typeahead'
87
89
  export PbPopover from './pb_popover'
88
90
  export PbTable from './pb_table'
91
+ export PbTooltip from './pb_tooltip'
@@ -63,6 +63,7 @@ import * as PersonContact from 'pb_person_contact/docs'
63
63
  import * as Pill from 'pb_pill/docs'
64
64
  import * as ProgressPills from 'pb_progress_pills/docs'
65
65
  import * as ProgressSimple from 'pb_progress_simple/docs'
66
+ import * as ProgressStep from 'pb_progress_step/docs'
66
67
  import * as Radio from 'pb_radio/docs'
67
68
  import * as SectionSeparator from 'pb_section_separator/docs'
68
69
  import * as Select from 'pb_select/docs'
@@ -137,6 +138,7 @@ WebpackerReact.setup({
137
138
  ...Pill,
138
139
  ...ProgressPills,
139
140
  ...ProgressSimple,
141
+ ...ProgressStep,
140
142
  ...Radio,
141
143
  ...SectionSeparator,
142
144
  ...Select,
@@ -0,0 +1,2 @@
1
+ import '../../pb_progress_step/_progress_step.jsx'
2
+
@@ -3,6 +3,8 @@
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
5
 
6
+ import Icon from '../pb_icon/_icon.jsx'
7
+
6
8
  type EventHandler = (SyntheticInputEvent<HTMLInputElement>) => void
7
9
  type ButtonPropTypes = {
8
10
  aria?: {
@@ -83,7 +85,13 @@ const Button = (props: ButtonPropTypes) => {
83
85
  const buttonAria = buttonAriaProps(props)
84
86
  const css = classnames(buttonClassName(props), className)
85
87
  const loadingIcon = (
86
- <i className="pb_icon_kit far fa-spinner fa-fw fa-pulse loading-icon" />
88
+ <div className="loading-icon">
89
+ <Icon
90
+ fixedWidth
91
+ icon="spinner"
92
+ pulse
93
+ />
94
+ </div>
87
95
  )
88
96
 
89
97
  const content = (
@@ -9,6 +9,7 @@ const contactTypeMap = {
9
9
  'cell': 'mobile',
10
10
  'home': 'phone',
11
11
  'work': 'phone-office',
12
+ 'work-cell': 'phone-laptop',
12
13
  'email': 'envelope',
13
14
  'wrong number': 'slash-phone',
14
15
  }
@@ -28,6 +28,8 @@ module Playbook
28
28
  "phone-office"
29
29
  when "email"
30
30
  "envelope"
31
+ when "work-cell"
32
+ "phone-laptop"
31
33
  when "wrong-phone"
32
34
  "phone-slash"
33
35
  else # "unknown" || "other"
@@ -16,3 +16,8 @@
16
16
  contact_type: "wrong number",
17
17
  contact_value: "3245627482",
18
18
  }) %>
19
+
20
+ <%= pb_rails("contact", props: {
21
+ contact_type: "work-cell",
22
+ contact_value: "349-185-9988",
23
+ }) %>
@@ -19,6 +19,10 @@ const ContactDefault = () => {
19
19
  contactType="work"
20
20
  contactValue="3245627482"
21
21
  />
22
+ <Contact
23
+ contactType="work-cell"
24
+ contactValue="3245627482"
25
+ />
22
26
  </div>
23
27
  )
24
28
  }
@@ -14,3 +14,9 @@
14
14
  contact_value: "3245627482",
15
15
  contact_detail: "Work",
16
16
  }) %>
17
+
18
+ <%= pb_rails("contact", props: {
19
+ contact_type: "work-cell",
20
+ contact_value: "3245627482",
21
+ contact_detail: "Work-Cell",
22
+ }) %>
@@ -18,6 +18,11 @@ const ContactDefault = () => {
18
18
  contactType="work"
19
19
  contactValue="3245627482"
20
20
  />
21
+ <Contact
22
+ contactDetail="Work-Cell"
23
+ contactType="work-cell"
24
+ contactValue="3245627482"
25
+ />
21
26
  </div>
22
27
  )
23
28
  }
@@ -12,7 +12,7 @@ import {
12
12
  } from '../'
13
13
 
14
14
  type DateYearStackedProps = {
15
- align?: 'center' | 'right',
15
+ align?: 'left' | 'center' | 'right',
16
16
  className?: String | Array<String>,
17
17
  dark?: Boolean,
18
18
  data?: String,
@@ -21,7 +21,7 @@ type DateYearStackedProps = {
21
21
  }
22
22
 
23
23
  const DateYearStacked = ({
24
- align,
24
+ align = 'left',
25
25
  className,
26
26
  dark = false,
27
27
  date,
@@ -0,0 +1,56 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { isEmpty, map, omitBy } from 'lodash'
5
+ import { Caption, Title } from '../../'
6
+
7
+ export type FilterDescription = {
8
+ [key: string]: ?string | boolean,
9
+ }
10
+
11
+ export type CurrentFiltersProps = {
12
+ filters: FilterDescription,
13
+ }
14
+
15
+ const hiddenFilters = (value) => isEmpty(value) && value !== true
16
+
17
+ const CurrentFilters = ({ filters }: CurrentFiltersProps) => {
18
+ const displayableFilters = omitBy(filters, hiddenFilters)
19
+
20
+ return (
21
+ <div className="maskContainer">
22
+ <If condition={!isEmpty(filters)}>
23
+ <div className="filters">
24
+ <div className="left_gradient" />
25
+ {map(displayableFilters, (value, name) => (
26
+ <div
27
+ className="filter"
28
+ key={`filter-${name}`}
29
+ >
30
+ <Choose>
31
+ <When condition={value === true}>
32
+ <Title
33
+ size={4}
34
+ tag="h4"
35
+ text={name}
36
+ />
37
+ </When>
38
+ <Otherwise>
39
+ <Caption text={name} />
40
+ <Title
41
+ size={4}
42
+ tag="h4"
43
+ text={value}
44
+ />
45
+ </Otherwise>
46
+ </Choose>
47
+ </div>
48
+ ))}
49
+ <div className="right_gradient" />
50
+ </div>
51
+ </If>
52
+ </div>
53
+ )
54
+ }
55
+
56
+ export default CurrentFilters
@@ -0,0 +1,26 @@
1
+ /* @flow */
2
+
3
+ import React, { Node } from 'react'
4
+ import { Card } from '../../'
5
+
6
+ type FilterBackgroundProps = {
7
+ background: boolean,
8
+ className: string,
9
+ children: Node,
10
+ }
11
+ const FilterBackground = ({ background = true, className, children }: FilterBackgroundProps) => (
12
+ <div className={`pb_filter_kit ${className}`}>
13
+ <Choose>
14
+ <When condition={background}>
15
+ <Card padding="none">
16
+ {children}
17
+ </Card>
18
+ </When>
19
+ <Otherwise>
20
+ {children}
21
+ </Otherwise>
22
+ </Choose>
23
+ </div>
24
+ )
25
+
26
+ export default FilterBackground
@@ -0,0 +1,58 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { Caption, Flex, SectionSeparator } from '../../'
5
+
6
+ import CurrentFilters, { FilterDescription } from './CurrentFilters'
7
+ import FilterBackground, { FilterBackgroundProps } from './FilterBackground'
8
+ import FiltersPopover from './FiltersPopover'
9
+ import ResultsCount from './ResultsCount'
10
+ import SortMenu, { SortingChangeCallback, SortOptions, SortValue } from './SortMenu'
11
+
12
+ export type FilterDoubleProps = {
13
+ children: Node,
14
+ filters?: FilterDescription,
15
+ onSortChange: SortingChangeCallback,
16
+ results?: number,
17
+ sortOptions: SortOptions,
18
+ sortValue?: SortValue,
19
+ } & FilterBackgroundProps
20
+
21
+ const FilterDouble = ({ onSortChange, sortOptions, sortValue, filters, results, children, ...bgProps }: FilterDoubleProps) => (
22
+ <FilterBackground {...bgProps}>
23
+ <Flex
24
+ orientation="row"
25
+ vertical="center"
26
+ >
27
+ <FiltersPopover>
28
+ {children}
29
+ </FiltersPopover>
30
+ <CurrentFilters filters={filters} />
31
+ </Flex>
32
+ <SectionSeparator />
33
+ <Flex
34
+ className="filter-bottom"
35
+ orientation="row"
36
+ spacing="between"
37
+ vertical="center"
38
+ >
39
+ <ResultsCount
40
+ results={results}
41
+ title
42
+ />
43
+ <Flex
44
+ orientation="row"
45
+ vertical="center"
46
+ >
47
+ <Caption text="sort by:" />
48
+ <SortMenu
49
+ onChange={onSortChange}
50
+ options={sortOptions}
51
+ value={sortValue}
52
+ />
53
+ </Flex>
54
+ </Flex>
55
+ </FilterBackground>
56
+ )
57
+
58
+ export default FilterDouble
@@ -0,0 +1,46 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { isEmpty } from 'lodash'
5
+ import { Flex } from '../../'
6
+
7
+ import CurrentFilters, { FilterDescription } from './CurrentFilters'
8
+ import FilterBackground, { FilterBackgroundProps } from './FilterBackground'
9
+ import FiltersPopover from './FiltersPopover'
10
+ import ResultsCount from './ResultsCount'
11
+ import SortMenu, { SortingChangeCallback, SortOptions, SortValue } from './SortMenu'
12
+
13
+ export type FilterSingleProps = {
14
+ children?: Node,
15
+ filters?: FilterDescription,
16
+ onSortChange?: SortingChangeCallback,
17
+ results?: number,
18
+ sortOptions?: SortOptions,
19
+ sortValue?: SortValue,
20
+ } & FilterBackgroundProps
21
+
22
+ const FilterSingle = ({ onSortChange, sortOptions, sortValue, filters, results, children, ...bgProps }: FilterSingleProps) => (
23
+ <FilterBackground {...bgProps}>
24
+ <Flex
25
+ orientation="row"
26
+ vertical="center"
27
+ >
28
+ <If condition={children}>
29
+ <FiltersPopover>
30
+ {children}
31
+ </FiltersPopover>
32
+ <CurrentFilters filters={filters} />
33
+ </If>
34
+ <ResultsCount results={results} />
35
+ <If condition={!isEmpty(sortOptions)}>
36
+ <SortMenu
37
+ onChange={onSortChange}
38
+ options={sortOptions}
39
+ value={sortValue}
40
+ />
41
+ </If>
42
+ </Flex>
43
+ </FilterBackground>
44
+ )
45
+
46
+ export default FilterSingle
@@ -0,0 +1,37 @@
1
+ /* @flow */
2
+
3
+ import React, { Node, useState } from 'react'
4
+ import { CircleIconButton, PbReactPopover } from '../../'
5
+
6
+ const FiltersPopoverProps = { children: Node }
7
+ const FiltersPopover = ({ children }: FiltersPopoverProps) => {
8
+ const [hide, updateHide] = useState(true)
9
+ const toggle = () => updateHide(!hide)
10
+
11
+ const filterButton = (
12
+ <CircleIconButton
13
+ icon="filter"
14
+ id="filter"
15
+ onClick={toggle}
16
+ text="filter"
17
+ variant="secondary"
18
+ />
19
+ )
20
+
21
+ return (
22
+ <PbReactPopover
23
+ closeOnClick="outside"
24
+ offset
25
+ placement="bottom"
26
+ reference={filterButton}
27
+ shouldClosePopover={updateHide}
28
+ show={!hide}
29
+ >
30
+ <div className="pb-form">
31
+ {children}
32
+ </div>
33
+ </PbReactPopover>
34
+ )
35
+ }
36
+
37
+ export default FiltersPopover
@@ -0,0 +1,34 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { Caption, TitleCount } from '../../'
5
+
6
+ const resultsText = (results: number): string => results == 1 ? 'Result' : 'Results'
7
+
8
+ type ResultsCountProps = {
9
+ results?: ?number,
10
+ title?: boolean,
11
+ }
12
+ const ResultsCount = ({ results, title }: ResultsCountProps) => (
13
+ <Choose>
14
+ <When condition={results && title}>
15
+ <TitleCount
16
+ align="center"
17
+ count={results}
18
+ title={`${resultsText(results)}:`}
19
+ />
20
+ </When>
21
+ <When condition={results}>
22
+ <Caption
23
+ className="filter-results"
24
+ size="xs"
25
+ text={`${results} ${resultsText(results)}`}
26
+ />
27
+ </When>
28
+ <Otherwise>
29
+ <div />
30
+ </Otherwise>
31
+ </Choose>
32
+ )
33
+
34
+ export default ResultsCount
@@ -0,0 +1,85 @@
1
+ /* @flow */
2
+
3
+ import React, { useState } from 'react'
4
+ import { find, map, partial } from 'lodash'
5
+ import { Button, Icon, List, ListItem, PbReactPopover } from '../../'
6
+
7
+ export type Direction = 'asc' | 'desc'
8
+ export type SortOptions = { [name: string]: string }
9
+ export type SortValue = { name: string, dir: Direction }
10
+ export type SortingChangeCallback = (SortValue[]) => void
11
+
12
+ const nextValue = (value: SortValue[], name: string): Direction => {
13
+ const current = find(value, { name })
14
+ return {
15
+ name,
16
+ dir: current && current.dir == 'asc' ? 'desc' : 'asc',
17
+ }
18
+ }
19
+
20
+ const directionIcon = (dir: Direction) => (
21
+ dir == 'asc' ? 'sort-amount-up' : 'sort-amount-down'
22
+ )
23
+
24
+ const renderOptions = (options: SortOptions, value: SortValue[], handleChange: (SortValue) => void) => (
25
+ map(options, (label, name) => {
26
+ const next = nextValue(value, name)
27
+ return (
28
+ <ListItem key={`option-${next.name}-${next.dir}`}>
29
+ <Button
30
+ icon={directionIcon(next.dir)}
31
+ onClick={partial(handleChange, next)}
32
+ text={` ${label}`}
33
+ variant="link"
34
+ />
35
+ </ListItem>
36
+ )
37
+ })
38
+ )
39
+
40
+ export type SortMenuProps = {
41
+ value?: SortValue[],
42
+ options: SortOptions,
43
+ onChange: SortingChangeCallback,
44
+ }
45
+ const SortMenu = ({ options, value, onChange }: SortMenuProps) => {
46
+ const [hide, updateHide] = useState(true)
47
+ const toggle = () => updateHide(!hide)
48
+ const handleChange = (value: SortValue) => {
49
+ updateHide(true)
50
+ onChange([value])
51
+ }
52
+
53
+ const sortButton = (
54
+ <Button
55
+ id="sort-button"
56
+ onClick={toggle}
57
+ variant="link"
58
+ >
59
+ {map(value, ({ dir, name }) => (
60
+ <span key={`current-sort-${name}-${dir}`}>
61
+ <Icon icon={directionIcon(dir)} />
62
+ {` ${options[name]}`}
63
+ </span>
64
+ ))}
65
+ </Button>
66
+ )
67
+
68
+ return (
69
+ <PbReactPopover
70
+ className="pb_filter_sort_menu"
71
+ closeOnClick="outside"
72
+ offset
73
+ placement="bottom"
74
+ reference={sortButton}
75
+ shouldClosePopover={updateHide}
76
+ show={!hide}
77
+ >
78
+ <List>
79
+ {renderOptions(options, value, handleChange)}
80
+ </List>
81
+ </PbReactPopover>
82
+ )
83
+ }
84
+
85
+ export default SortMenu
@@ -0,0 +1,26 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+
5
+ import FilterSingle, { FilterSingleProps } from './FilterSingle'
6
+ import FilterDouble, { FilterDoubleProps } from './FilterDouble'
7
+
8
+ type FilterProps = FilterSingleProps | FilterDoubleProps & {
9
+ double?: boolean,
10
+ }
11
+
12
+ const Filter = ({
13
+ double = false,
14
+ ...templateProps
15
+ }: FilterProps) => (
16
+ <Choose>
17
+ <When condition={double}>
18
+ <FilterDouble {...templateProps} />
19
+ </When>
20
+ <Otherwise>
21
+ <FilterSingle {...templateProps} />
22
+ </Otherwise>
23
+ </Choose>
24
+ )
25
+
26
+ export default Filter