playbook_ui 12.5.0.pre.alpha.filter1 → 12.5.0.pre.alpha.phonerails1
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.jsx +76 -0
- data/app/pb_kits/playbook/pb_filter/Filter/{FilterBackground.tsx → FilterBackground.jsx} +14 -12
- data/app/pb_kits/playbook/pb_filter/Filter/{FilterDouble.tsx → FilterDouble.jsx} +8 -7
- data/app/pb_kits/playbook/pb_filter/Filter/{FilterSingle.tsx → FilterSingle.jsx} +25 -25
- data/app/pb_kits/playbook/pb_filter/Filter/{FiltersPopover.tsx → FiltersPopover.jsx} +11 -13
- data/app/pb_kits/playbook/pb_filter/Filter/{ResultsCount.tsx → ResultsCount.jsx} +14 -39
- data/app/pb_kits/playbook/pb_filter/Filter/{SortMenu.tsx → SortMenu.jsx} +6 -6
- data/app/pb_kits/playbook/pb_filter/Filter/{index.tsx → index.jsx} +10 -17
- data/app/pb_kits/playbook/pb_filter/{_filter.tsx → _filter.jsx} +2 -0
- data/app/pb_kits/playbook/pb_list/_list.tsx +2 -2
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +61 -47
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_initial_country.html.erb +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.html.erb +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.html.erb +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -1
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.html.erb +1 -15
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +32 -33
- data/lib/playbook/version.rb +2 -2
- metadata +14 -11
- data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e827c4077969ef2258c6c650173ef5c8227d81aca0a0201c19ae0e136de1decb
|
4
|
+
data.tar.gz: aec0d42668e214f8a32b4220704c76af66a2b55a43fbeb0efb28eb6832c45d9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed4ab9a7d46404031c54b2c4e22731d4260d00d2db11af3b280b03f92df607f1afd8a6f3b68d6b52aa6e8866605c5c7fa85c4598a4323b2dfbc6a9d5490ff196
|
7
|
+
data.tar.gz: 23d61876cc9d04ea7b378b9ecc896b5d4f0a8d04b336a2b3f0fbf81c24189cc8ac86cc2f0eb65b3760d2da51c9699798a8dbe38c20a98744c3076b6f450706ab
|
@@ -0,0 +1,76 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React from 'react'
|
4
|
+
import { isEmpty, map, omitBy } from 'lodash'
|
5
|
+
|
6
|
+
import Body from '../../pb_body/_body'
|
7
|
+
import Caption from '../../pb_caption/_caption'
|
8
|
+
import Title from '../../pb_title/_title'
|
9
|
+
|
10
|
+
export type FilterDescription = {
|
11
|
+
[key: string]: ?string | boolean,
|
12
|
+
}
|
13
|
+
|
14
|
+
export type CurrentFiltersProps = {
|
15
|
+
dark: boolean,
|
16
|
+
filters: FilterDescription,
|
17
|
+
}
|
18
|
+
|
19
|
+
const hiddenFilters = (value) => isEmpty(value) && value !== true
|
20
|
+
|
21
|
+
const CurrentFilters = ({ dark, filters }: CurrentFiltersProps) => {
|
22
|
+
const displayableFilters = omitBy(filters, hiddenFilters)
|
23
|
+
|
24
|
+
return (
|
25
|
+
<div className="maskContainer">
|
26
|
+
<If condition={isEmpty(filters)}>
|
27
|
+
<div className="filters">
|
28
|
+
<Body
|
29
|
+
color="light"
|
30
|
+
paddingLeft="xs"
|
31
|
+
size={4}
|
32
|
+
tag="h4"
|
33
|
+
text="No Filter Selected"
|
34
|
+
/>
|
35
|
+
</div>
|
36
|
+
</If>
|
37
|
+
<If condition={!isEmpty(filters)}>
|
38
|
+
<div className="filters">
|
39
|
+
<div className="left_gradient" />
|
40
|
+
{map(displayableFilters, (value, name) => (
|
41
|
+
<div
|
42
|
+
className="filter"
|
43
|
+
key={`filter-${name}`}
|
44
|
+
>
|
45
|
+
<Choose>
|
46
|
+
<When condition={value === true}>
|
47
|
+
<Title
|
48
|
+
dark={dark}
|
49
|
+
size={4}
|
50
|
+
tag="h4"
|
51
|
+
text={name}
|
52
|
+
/>
|
53
|
+
</When>
|
54
|
+
<Otherwise>
|
55
|
+
<Caption
|
56
|
+
dark={dark}
|
57
|
+
text={name}
|
58
|
+
/>
|
59
|
+
<Title
|
60
|
+
dark={dark}
|
61
|
+
size={4}
|
62
|
+
tag="h4"
|
63
|
+
text={value}
|
64
|
+
/>
|
65
|
+
</Otherwise>
|
66
|
+
</Choose>
|
67
|
+
</div>
|
68
|
+
))}
|
69
|
+
<div className="right_gradient" />
|
70
|
+
</div>
|
71
|
+
</If>
|
72
|
+
</div>
|
73
|
+
)
|
74
|
+
}
|
75
|
+
|
76
|
+
export default CurrentFilters
|
@@ -1,33 +1,35 @@
|
|
1
|
-
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React, { Node } from 'react'
|
2
4
|
import classnames from 'classnames'
|
3
5
|
|
4
|
-
import {
|
6
|
+
import { globalProps } from '../../utilities/globalProps'
|
5
7
|
|
6
8
|
import Card from '../../pb_card/_card'
|
7
9
|
|
8
|
-
|
10
|
+
type FilterBackgroundProps = {
|
9
11
|
background: boolean,
|
10
12
|
className: string,
|
11
|
-
children
|
13
|
+
children: Node,
|
12
14
|
dark: boolean,
|
13
|
-
}
|
15
|
+
}
|
14
16
|
|
15
|
-
const FilterBackground = (props: FilterBackgroundProps)
|
17
|
+
const FilterBackground = (props: FilterBackgroundProps) => {
|
16
18
|
const { background = true, className, children, dark } = props
|
17
19
|
|
18
20
|
return (
|
19
21
|
<div className={classnames(`pb_filter_kit ${className}`, globalProps(props))}>
|
20
|
-
|
22
|
+
<Choose>
|
23
|
+
<When condition={background}>
|
21
24
|
<Card
|
22
25
|
dark={dark}
|
23
26
|
padding="none"
|
24
27
|
>
|
25
28
|
{children}
|
26
|
-
</Card>
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
29
|
+
</Card>
|
30
|
+
</When>
|
31
|
+
<Otherwise>{children}</Otherwise>
|
32
|
+
</Choose>
|
31
33
|
</div>
|
32
34
|
)
|
33
35
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
|
3
5
|
import CurrentFilters, { FilterDescription } from './CurrentFilters'
|
@@ -13,14 +15,13 @@ import SortMenu, {
|
|
13
15
|
import Caption from '../../pb_caption/_caption'
|
14
16
|
import Flex from '../../pb_flex/_flex'
|
15
17
|
import SectionSeparator from '../../pb_section_separator/_section_separator'
|
16
|
-
|
17
18
|
export type FilterDoubleProps = {
|
18
|
-
children
|
19
|
+
children: Node,
|
19
20
|
filters?: FilterDescription,
|
20
|
-
onSortChange
|
21
|
+
onSortChange: SortingChangeCallback,
|
21
22
|
results?: number,
|
22
|
-
sortOptions
|
23
|
-
sortValue?: SortValue
|
23
|
+
sortOptions: SortOptions,
|
24
|
+
sortValue?: SortValue,
|
24
25
|
} & FilterBackgroundProps
|
25
26
|
|
26
27
|
const FilterDouble = ({
|
@@ -34,7 +35,7 @@ const FilterDouble = ({
|
|
34
35
|
minWidth,
|
35
36
|
placement,
|
36
37
|
...bgProps
|
37
|
-
}: FilterDoubleProps)
|
38
|
+
}: FilterDoubleProps) => (
|
38
39
|
<FilterBackground
|
39
40
|
dark={dark}
|
40
41
|
{...bgProps}
|
@@ -48,7 +49,7 @@ const FilterDouble = ({
|
|
48
49
|
minWidth={minWidth}
|
49
50
|
placement={placement}
|
50
51
|
>
|
51
|
-
|
52
|
+
{children}
|
52
53
|
</FiltersPopover>
|
53
54
|
<CurrentFilters
|
54
55
|
dark={dark}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import { isEmpty } from 'lodash'
|
3
5
|
|
@@ -14,12 +16,12 @@ import SortMenu, {
|
|
14
16
|
} from './SortMenu'
|
15
17
|
|
16
18
|
export type FilterSingleProps = {
|
17
|
-
children?:
|
19
|
+
children?: Node,
|
18
20
|
filters?: FilterDescription,
|
19
21
|
onSortChange?: SortingChangeCallback,
|
20
22
|
results?: number,
|
21
23
|
sortOptions?: SortOptions,
|
22
|
-
sortValue?: SortValue
|
24
|
+
sortValue?: SortValue,
|
23
25
|
} & FilterBackgroundProps
|
24
26
|
|
25
27
|
const FilterSingle = ({
|
@@ -33,7 +35,7 @@ const FilterSingle = ({
|
|
33
35
|
minWidth,
|
34
36
|
placement,
|
35
37
|
...bgProps
|
36
|
-
}: FilterSingleProps)
|
38
|
+
}: FilterSingleProps) => {
|
37
39
|
return (
|
38
40
|
<FilterBackground
|
39
41
|
dark={dark}
|
@@ -44,33 +46,31 @@ const FilterSingle = ({
|
|
44
46
|
paddingRight="lg"
|
45
47
|
vertical="center"
|
46
48
|
>
|
47
|
-
{
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
>
|
49
|
+
<If condition={children}>
|
50
|
+
<FiltersPopover
|
51
|
+
dark={dark}
|
52
|
+
minWidth={minWidth}
|
53
|
+
placement={placement}
|
54
|
+
>
|
54
55
|
{children}
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
56
|
+
</FiltersPopover>
|
57
|
+
<CurrentFilters
|
58
|
+
dark={dark}
|
59
|
+
filters={filters}
|
60
|
+
/>
|
61
|
+
</If>
|
62
62
|
<ResultsCount
|
63
63
|
dark={dark}
|
64
64
|
results={results}
|
65
65
|
/>
|
66
|
-
{
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
66
|
+
<If condition={!isEmpty(sortOptions)}>
|
67
|
+
<SortMenu
|
68
|
+
dark={dark}
|
69
|
+
onChange={onSortChange}
|
70
|
+
options={sortOptions}
|
71
|
+
value={sortValue}
|
72
|
+
/>
|
73
|
+
</If>
|
74
74
|
</Flex>
|
75
75
|
</FilterBackground>
|
76
76
|
)
|
@@ -1,15 +1,12 @@
|
|
1
|
-
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React, { Node, useState } from 'react'
|
2
4
|
|
3
5
|
import CircleIconButton from '../../pb_circle_icon_button/_circle_icon_button'
|
4
6
|
import PbReactPopover from '../../pb_popover/_popover'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
dark?: boolean,
|
9
|
-
minWidth?: string,
|
10
|
-
placement?: "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "right-start" | "right-end" | "left-start" | "left-end",
|
11
|
-
}
|
12
|
-
const FiltersPopover = ({ children, dark, minWidth, placement = "bottom-start" }: FiltersPopoverProps): React.ReactElement => {
|
8
|
+
const FiltersPopoverProps = { children: Node }
|
9
|
+
const FiltersPopover = ({ children, dark, minWidth, placement = "bottom-start" }: FiltersPopoverProps) => {
|
13
10
|
const [hide, updateHide] = useState(true)
|
14
11
|
const toggle = () => updateHide(!hide)
|
15
12
|
|
@@ -19,6 +16,7 @@ const FiltersPopover = ({ children, dark, minWidth, placement = "bottom-start" }
|
|
19
16
|
icon="filter"
|
20
17
|
id="filter"
|
21
18
|
onClick={toggle}
|
19
|
+
text="filter"
|
22
20
|
variant="secondary"
|
23
21
|
/>
|
24
22
|
)
|
@@ -32,11 +30,11 @@ const FiltersPopover = ({ children, dark, minWidth, placement = "bottom-start" }
|
|
32
30
|
shouldClosePopover={updateHide}
|
33
31
|
show={!hide}
|
34
32
|
>
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
<div className="pb-form">
|
34
|
+
{typeof children === 'function'
|
35
|
+
? children({ closePopover: () => (updateHide(true)) })
|
36
|
+
: children}
|
37
|
+
</div>
|
40
38
|
</PbReactPopover>
|
41
39
|
)
|
42
40
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
|
3
5
|
import Caption from '../../pb_caption/_caption'
|
@@ -7,58 +9,31 @@ const resultsText = (results: number): string => results == 1 ? 'Result' : 'Resu
|
|
7
9
|
|
8
10
|
type ResultsCountProps = {
|
9
11
|
dark?: boolean,
|
10
|
-
results?: number
|
12
|
+
results?: ?number,
|
11
13
|
title?: boolean,
|
12
14
|
}
|
13
|
-
const ResultsCount = ({ dark, results, title }: ResultsCountProps)
|
14
|
-
|
15
|
-
|
16
|
-
return (
|
15
|
+
const ResultsCount = ({ dark, results, title }: ResultsCountProps) => (
|
16
|
+
<Choose>
|
17
|
+
<When condition={results && title}>
|
17
18
|
<TitleCount
|
18
19
|
align="center"
|
19
20
|
count={results}
|
20
21
|
dark={dark}
|
21
22
|
title={`${resultsText(results)}:`}
|
22
23
|
/>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
const justResults = () => {
|
27
|
-
return (
|
24
|
+
</When>
|
25
|
+
<When condition={results}>
|
28
26
|
<Caption
|
29
27
|
className="filter-results"
|
30
28
|
dark={dark}
|
31
29
|
size="xs"
|
32
30
|
text={`${results} ${resultsText(results)}`}
|
33
31
|
/>
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
<>
|
41
|
-
{resultTitle()}
|
42
|
-
</>
|
43
|
-
)
|
44
|
-
} else if (results) {
|
45
|
-
return (
|
46
|
-
<>
|
47
|
-
{justResults()}
|
48
|
-
</>
|
49
|
-
)
|
50
|
-
} else {
|
51
|
-
return (
|
52
|
-
<div />
|
53
|
-
)
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
return (
|
58
|
-
<>
|
59
|
-
{displayResultsCount()}
|
60
|
-
</>
|
61
|
-
)
|
62
|
-
}
|
32
|
+
</When>
|
33
|
+
<Otherwise>
|
34
|
+
<div />
|
35
|
+
</Otherwise>
|
36
|
+
</Choose>
|
37
|
+
)
|
63
38
|
|
64
39
|
export default ResultsCount
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React, { useState } from 'react'
|
2
4
|
import { find, map, partial } from 'lodash'
|
3
5
|
|
@@ -10,9 +12,9 @@ import PbReactPopover from '../../pb_popover/_popover'
|
|
10
12
|
export type Direction = 'asc' | 'desc'
|
11
13
|
export type SortOptions = { [name: string]: string }
|
12
14
|
export type SortValue = { name: string, dir: Direction }
|
13
|
-
export type SortingChangeCallback = (
|
15
|
+
export type SortingChangeCallback = (SortValue[]) => void
|
14
16
|
|
15
|
-
const nextValue = (value: SortValue[], name: string):
|
17
|
+
const nextValue = (value: SortValue[], name: string): Direction => {
|
16
18
|
const current = find(value, { name })
|
17
19
|
return {
|
18
20
|
name,
|
@@ -24,13 +26,12 @@ const directionIcon = (dir: Direction) => (
|
|
24
26
|
dir == 'asc' ? 'sort-amount-up' : 'sort-amount-down'
|
25
27
|
)
|
26
28
|
|
27
|
-
const renderOptions = (options: SortOptions, value: SortValue[], handleChange: (
|
29
|
+
const renderOptions = (options: SortOptions, value: SortValue[], handleChange: (SortValue) => void) => (
|
28
30
|
map(options, (label, name) => {
|
29
31
|
const next = nextValue(value, name)
|
30
32
|
return (
|
31
33
|
<ListItem key={`option-${next.name}-${next.dir}`}>
|
32
34
|
<Button
|
33
|
-
htmlType={undefined}
|
34
35
|
onClick={partial(handleChange, next)}
|
35
36
|
text={` ${label}`}
|
36
37
|
variant="link"
|
@@ -46,7 +47,7 @@ export type SortMenuProps = {
|
|
46
47
|
options: SortOptions,
|
47
48
|
value?: SortValue[],
|
48
49
|
}
|
49
|
-
const SortMenu = ({ dark, options, value, onChange }: SortMenuProps)
|
50
|
+
const SortMenu = ({ dark, options, value, onChange }: SortMenuProps) => {
|
50
51
|
const [hide, updateHide] = useState(true)
|
51
52
|
const toggle = () => updateHide(!hide)
|
52
53
|
const handleChange = (value: SortValue) => {
|
@@ -57,7 +58,6 @@ const SortMenu = ({ dark, options, value, onChange }: SortMenuProps): React.Reac
|
|
57
58
|
const sortButton = (
|
58
59
|
<Button
|
59
60
|
dark={dark}
|
60
|
-
htmlType={undefined}
|
61
61
|
id="sort-button"
|
62
62
|
onClick={toggle}
|
63
63
|
paddingRight="none"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import FilterSingle, { FilterSingleProps } from './FilterSingle'
|
3
5
|
import FilterDouble, { FilterDoubleProps } from './FilterDouble'
|
@@ -8,25 +10,16 @@ type FilterProps =
|
|
8
10
|
double?: boolean,
|
9
11
|
})
|
10
12
|
|
11
|
-
const Filter = ({
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
const displayFilter = () => {
|
16
|
-
if (double === true) {
|
17
|
-
return (
|
13
|
+
const Filter = ({ double = false, ...templateProps }: FilterProps) => {
|
14
|
+
return (
|
15
|
+
<Choose>
|
16
|
+
<When condition={double}>
|
18
17
|
<FilterDouble {...templateProps} />
|
19
|
-
|
20
|
-
|
21
|
-
return (
|
18
|
+
</When>
|
19
|
+
<Otherwise>
|
22
20
|
<FilterSingle {...templateProps} />
|
23
|
-
|
24
|
-
|
25
|
-
}
|
26
|
-
return (
|
27
|
-
<>
|
28
|
-
{displayFilter()}
|
29
|
-
</>
|
21
|
+
</Otherwise>
|
22
|
+
</Choose>
|
30
23
|
)
|
31
24
|
}
|
32
25
|
|
@@ -11,14 +11,14 @@ type ListProps = {
|
|
11
11
|
dark?: boolean;
|
12
12
|
data?: object;
|
13
13
|
id?: string;
|
14
|
-
layout
|
14
|
+
layout: "" | "left" | "right";
|
15
15
|
ordered?: boolean;
|
16
16
|
role?: string;
|
17
17
|
tabIndex?: number;
|
18
18
|
text?: string;
|
19
19
|
size?: string;
|
20
20
|
variant?: string;
|
21
|
-
xpadding
|
21
|
+
xpadding: boolean;
|
22
22
|
};
|
23
23
|
|
24
24
|
const List = (props: ListProps) => {
|
@@ -1,32 +1,32 @@
|
|
1
1
|
/* @flow */
|
2
|
-
import React, { useEffect, useRef, useState } from
|
3
|
-
import classnames from
|
4
|
-
import { buildAriaProps, buildCss, buildDataProps } from
|
5
|
-
import { globalProps } from
|
6
|
-
import intlTelInput from
|
7
|
-
import
|
8
|
-
import TextInput from
|
2
|
+
import React, { useEffect, useRef, useState } from "react"
|
3
|
+
import classnames from "classnames"
|
4
|
+
import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props"
|
5
|
+
import { globalProps } from "../utilities/globalProps"
|
6
|
+
import intlTelInput from "intl-tel-input"
|
7
|
+
import "intl-tel-input/build/css/intlTelInput.css"
|
8
|
+
import TextInput from "../pb_text_input/_text_input"
|
9
9
|
|
10
10
|
declare global {
|
11
11
|
interface Window {
|
12
|
-
intlTelInputGlobals: any
|
12
|
+
intlTelInputGlobals: any
|
13
13
|
}
|
14
14
|
}
|
15
15
|
|
16
16
|
type PhoneNumberInputProps = {
|
17
|
-
aria?: { [key: string]: string }
|
18
|
-
className?: string
|
19
|
-
data?: { [key: string]: string }
|
20
|
-
disabled?: boolean
|
21
|
-
id?: string
|
22
|
-
initialCountry?: string
|
23
|
-
isValid?: (valid: boolean) => void
|
24
|
-
label?: string
|
25
|
-
name?: string
|
26
|
-
onChange?: (e: React.FormEvent<HTMLInputElement>) => void
|
27
|
-
onlyCountries: string[]
|
28
|
-
preferredCountries?: string[]
|
29
|
-
value?: string
|
17
|
+
aria?: { [key: string]: string }
|
18
|
+
className?: string
|
19
|
+
data?: { [key: string]: string }
|
20
|
+
disabled?: boolean
|
21
|
+
id?: string
|
22
|
+
initialCountry?: string
|
23
|
+
isValid?: (valid: boolean) => void
|
24
|
+
label?: string
|
25
|
+
name?: string
|
26
|
+
onChange?: (e: React.FormEvent<HTMLInputElement>) => void
|
27
|
+
onlyCountries: string[]
|
28
|
+
preferredCountries?: string[]
|
29
|
+
value?: string
|
30
30
|
}
|
31
31
|
|
32
32
|
enum ValidationError {
|
@@ -35,17 +35,20 @@ enum ValidationError {
|
|
35
35
|
}
|
36
36
|
|
37
37
|
const formatToGlobalCountryName = (countryName: string) => {
|
38
|
-
return countryName.split(
|
38
|
+
return countryName.split("(")[0].trim()
|
39
39
|
}
|
40
40
|
|
41
41
|
const formatAllCountries = () => {
|
42
42
|
let countryData = window.intlTelInputGlobals.getCountryData()
|
43
|
+
|
43
44
|
for (let i = 0; i < countryData.length; i++) {
|
44
45
|
let country = countryData[i]
|
45
46
|
country.name = formatToGlobalCountryName(country.name)
|
46
47
|
}
|
47
48
|
}
|
48
49
|
|
50
|
+
formatAllCountries()
|
51
|
+
|
49
52
|
const containOnlyNumbers = (value: string) => {
|
50
53
|
return /^(\++)*(\d+)$/.test(value)
|
51
54
|
}
|
@@ -56,25 +59,33 @@ const PhoneNumberInput = (props: PhoneNumberInputProps) => {
|
|
56
59
|
className,
|
57
60
|
data = {},
|
58
61
|
disabled = false,
|
59
|
-
id =
|
60
|
-
initialCountry =
|
61
|
-
isValid = () => {
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
id = "",
|
63
|
+
initialCountry = "",
|
64
|
+
isValid = () => {
|
65
|
+
void 0
|
66
|
+
},
|
67
|
+
label = "",
|
68
|
+
name = "",
|
69
|
+
onChange = () => {
|
70
|
+
void 0
|
71
|
+
},
|
65
72
|
onlyCountries = [],
|
66
73
|
preferredCountries = [],
|
67
|
-
value =
|
74
|
+
value = "",
|
68
75
|
} = props
|
69
76
|
|
70
77
|
const ariaProps = buildAriaProps(aria)
|
71
78
|
const dataProps = buildDataProps(data)
|
72
|
-
const classes = classnames(
|
79
|
+
const classes = classnames(
|
80
|
+
buildCss("pb_phone_number_input"),
|
81
|
+
globalProps(props),
|
82
|
+
className
|
83
|
+
)
|
73
84
|
|
74
85
|
const inputRef = useRef<HTMLInputElement>()
|
75
86
|
const [inputValue, setInputValue] = useState(value)
|
76
87
|
const [itiInit, setItiInit] = useState<any>()
|
77
|
-
const [error, setError] = useState(
|
88
|
+
const [error, setError] = useState("")
|
78
89
|
|
79
90
|
const validateTooLongNumber = (itiInit: any) => {
|
80
91
|
const error = itiInit.getValidationError()
|
@@ -83,7 +94,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps) => {
|
|
83
94
|
const countryName = itiInit.getSelectedCountryData().name
|
84
95
|
setError(`Invalid ${countryName} phone number (too long)`)
|
85
96
|
} else {
|
86
|
-
setError(
|
97
|
+
setError("")
|
87
98
|
}
|
88
99
|
}
|
89
100
|
|
@@ -98,7 +109,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps) => {
|
|
98
109
|
|
99
110
|
const validateOnlyNumbers = () => {
|
100
111
|
if (inputValue && !containOnlyNumbers(inputValue)) {
|
101
|
-
setError(
|
112
|
+
setError("Invalid phone number. Enter numbers only.")
|
102
113
|
}
|
103
114
|
}
|
104
115
|
|
@@ -114,29 +125,32 @@ const PhoneNumberInput = (props: PhoneNumberInputProps) => {
|
|
114
125
|
isValid(itiInit.isValidNumber())
|
115
126
|
}
|
116
127
|
|
128
|
+
// Separating Concerns as React Docs Recommend
|
129
|
+
// This also Fixes things for our react_component rendering on the Rails Side
|
117
130
|
useEffect(() => {
|
118
131
|
formatAllCountries()
|
132
|
+
}, [])
|
119
133
|
|
134
|
+
useEffect(() => {
|
120
135
|
const telInputInit = new intlTelInput(inputRef.current, {
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
136
|
+
utilsScript:
|
137
|
+
"https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/utils.js",
|
138
|
+
separateDialCode: true,
|
139
|
+
preferredCountries,
|
140
|
+
allowDropdown: !disabled,
|
141
|
+
initialCountry,
|
142
|
+
onlyCountries,
|
143
|
+
})
|
144
|
+
|
145
|
+
inputRef.current.addEventListener("countrychange", () =>
|
146
|
+
validateTooLongNumber(telInputInit)
|
128
147
|
)
|
129
|
-
|
130
|
-
inputRef.current.addEventListener("countrychange", () => validateTooLongNumber(telInputInit))
|
148
|
+
|
131
149
|
setItiInit(telInputInit)
|
132
150
|
}, [])
|
133
151
|
|
134
152
|
return (
|
135
|
-
<div
|
136
|
-
{...ariaProps}
|
137
|
-
{...dataProps}
|
138
|
-
className={classes}
|
139
|
-
>
|
153
|
+
<div {...ariaProps} {...dataProps} className={classes}>
|
140
154
|
<TextInput
|
141
155
|
disabled={disabled}
|
142
156
|
error={error}
|
@@ -7,4 +7,7 @@ examples:
|
|
7
7
|
- phone_number_input_only_countries: Limited Countries
|
8
8
|
|
9
9
|
rails:
|
10
|
-
- phone_number_input_default: Default
|
10
|
+
- phone_number_input_default: Default
|
11
|
+
- phone_number_input_preferred_countries: Preferred Countries
|
12
|
+
- phone_number_input_initial_country: Initial Country
|
13
|
+
- phone_number_input_only_countries: Limited Countries
|
@@ -1,15 +1 @@
|
|
1
|
-
<%= react_component("PhoneNumberInput", object.phone_number_input_options) %>
|
2
|
-
|
3
|
-
<script>
|
4
|
-
const formatToGlobalCountryName = () => {
|
5
|
-
return countryName.split('(')[0].trim()
|
6
|
-
}
|
7
|
-
|
8
|
-
const formatAllCountries = () => {
|
9
|
-
let countryData = window.intlTelInputGlobals.getCountryData()
|
10
|
-
for (let i = 0; i < countryData.length; i++) {
|
11
|
-
let country = countryData[i]
|
12
|
-
country.name = formatToGlobalCountryName(country.name)
|
13
|
-
}
|
14
|
-
}
|
15
|
-
</script>
|
1
|
+
<%= react_component("PhoneNumberInput", object.phone_number_input_options) %>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import React, { useEffect } from "react";
|
2
2
|
import ReactDOM from "react-dom";
|
3
|
+
|
3
4
|
import {
|
4
5
|
Popper,
|
5
6
|
Manager as PopperManager,
|
@@ -22,7 +23,7 @@ type PbPopoverProps = {
|
|
22
23
|
aria?: { [key: string]: string };
|
23
24
|
className?: string;
|
24
25
|
closeOnClick?: "outside" | "inside" | "any";
|
25
|
-
data?:
|
26
|
+
data?: object;
|
26
27
|
id?: string;
|
27
28
|
offset?: boolean;
|
28
29
|
reference: PopperReference & any;
|
@@ -99,31 +100,31 @@ const Popover = (props: PbPopoverProps) => {
|
|
99
100
|
|
100
101
|
return (
|
101
102
|
<Popper
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
modifiers={popoverModifiers({ modifiers, offset })}
|
104
|
+
placement={placement}
|
105
|
+
referenceElement={referenceElement}
|
105
106
|
>
|
106
107
|
{({ placement, ref, style }) => {
|
107
108
|
return (
|
108
109
|
<div
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
110
|
+
{...ariaProps}
|
111
|
+
{...dataProps}
|
112
|
+
className={classes}
|
113
|
+
data-placement={placement}
|
114
|
+
id={id}
|
115
|
+
ref={ref}
|
116
|
+
style={Object.assign({}, style, zIndexStyle)}
|
116
117
|
>
|
117
118
|
<div
|
118
|
-
|
119
|
+
className={classnames(`${buildCss("pb_popover_tooltip")} show`)}
|
119
120
|
>
|
120
121
|
<div
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
122
|
+
className={classnames(
|
123
|
+
"pb_popover_body",
|
124
|
+
popoverSpacing,
|
125
|
+
overflowHandling
|
126
|
+
)}
|
127
|
+
style={widthHeightStyles()}
|
127
128
|
>
|
128
129
|
{children}
|
129
130
|
</div>
|
@@ -191,17 +192,17 @@ const PbReactPopover = (props: PbPopoverProps) => {
|
|
191
192
|
|
192
193
|
const popoverComponent = (
|
193
194
|
<Popover
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
195
|
+
className={className}
|
196
|
+
maxHeight={maxHeight}
|
197
|
+
maxWidth={maxWidth}
|
198
|
+
minHeight={minHeight}
|
199
|
+
minWidth={minWidth}
|
200
|
+
modifiers={modifiers}
|
201
|
+
offset={offset}
|
202
|
+
placement={placement}
|
203
|
+
referenceElement={referenceElement}
|
204
|
+
zIndex={zIndex}
|
205
|
+
{...props}
|
205
206
|
>
|
206
207
|
{children}
|
207
208
|
</Popover>
|
@@ -213,9 +214,7 @@ const PbReactPopover = (props: PbPopoverProps) => {
|
|
213
214
|
{reference && !referenceElement && (
|
214
215
|
<PopperReference>
|
215
216
|
{({ ref }) => (
|
216
|
-
<span
|
217
|
-
className="pb_popover_reference_wrapper"
|
218
|
-
ref={ref}>
|
217
|
+
<span className="pb_popover_reference_wrapper" ref={ref}>
|
219
218
|
<reference.type {...reference.props} />
|
220
219
|
</span>
|
221
220
|
)}
|
@@ -237,4 +236,4 @@ const PbReactPopover = (props: PbPopoverProps) => {
|
|
237
236
|
);
|
238
237
|
};
|
239
238
|
|
240
|
-
export default PbReactPopover;
|
239
|
+
export default PbReactPopover;
|
data/lib/playbook/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: playbook_ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.5.0.pre.alpha.
|
4
|
+
version: 12.5.0.pre.alpha.phonerails1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Power UX
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-03-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -910,16 +910,16 @@ files:
|
|
910
910
|
- app/pb_kits/playbook/pb_file_upload/docs/example.yml
|
911
911
|
- app/pb_kits/playbook/pb_file_upload/docs/index.js
|
912
912
|
- app/pb_kits/playbook/pb_file_upload/fileupload.test.js
|
913
|
-
- app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.
|
914
|
-
- app/pb_kits/playbook/pb_filter/Filter/FilterBackground.
|
915
|
-
- app/pb_kits/playbook/pb_filter/Filter/FilterDouble.
|
916
|
-
- app/pb_kits/playbook/pb_filter/Filter/FilterSingle.
|
917
|
-
- app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.
|
918
|
-
- app/pb_kits/playbook/pb_filter/Filter/ResultsCount.
|
919
|
-
- app/pb_kits/playbook/pb_filter/Filter/SortMenu.
|
920
|
-
- app/pb_kits/playbook/pb_filter/Filter/index.
|
913
|
+
- app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.jsx
|
914
|
+
- app/pb_kits/playbook/pb_filter/Filter/FilterBackground.jsx
|
915
|
+
- app/pb_kits/playbook/pb_filter/Filter/FilterDouble.jsx
|
916
|
+
- app/pb_kits/playbook/pb_filter/Filter/FilterSingle.jsx
|
917
|
+
- app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.jsx
|
918
|
+
- app/pb_kits/playbook/pb_filter/Filter/ResultsCount.jsx
|
919
|
+
- app/pb_kits/playbook/pb_filter/Filter/SortMenu.jsx
|
920
|
+
- app/pb_kits/playbook/pb_filter/Filter/index.jsx
|
921
|
+
- app/pb_kits/playbook/pb_filter/_filter.jsx
|
921
922
|
- app/pb_kits/playbook/pb_filter/_filter.scss
|
922
|
-
- app/pb_kits/playbook/pb_filter/_filter.tsx
|
923
923
|
- app/pb_kits/playbook/pb_filter/docs/_description.md
|
924
924
|
- app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb
|
925
925
|
- app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx
|
@@ -1561,10 +1561,13 @@ files:
|
|
1561
1561
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.html.erb
|
1562
1562
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.jsx
|
1563
1563
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.md
|
1564
|
+
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_initial_country.html.erb
|
1564
1565
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_initial_country.jsx
|
1565
1566
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_initial_country.md
|
1567
|
+
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.html.erb
|
1566
1568
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx
|
1567
1569
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.md
|
1570
|
+
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.html.erb
|
1568
1571
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.jsx
|
1569
1572
|
- app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.md
|
1570
1573
|
- app/pb_kits/playbook/pb_phone_number_input/docs/example.yml
|
@@ -1,72 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { isEmpty, map, omitBy } from 'lodash'
|
3
|
-
|
4
|
-
import Body from '../../pb_body/_body'
|
5
|
-
import Caption from '../../pb_caption/_caption'
|
6
|
-
import Title from '../../pb_title/_title'
|
7
|
-
|
8
|
-
export type FilterDescription = {
|
9
|
-
[key: string]: string | null | boolean,
|
10
|
-
}
|
11
|
-
|
12
|
-
export type CurrentFiltersProps = {
|
13
|
-
dark: boolean,
|
14
|
-
filters: FilterDescription,
|
15
|
-
}
|
16
|
-
|
17
|
-
const hiddenFilters = (value: any) => isEmpty(value) && value !== true
|
18
|
-
|
19
|
-
const CurrentFilters = ({ dark, filters }: CurrentFiltersProps): React.ReactElement => {
|
20
|
-
const displayableFilters = omitBy(filters, hiddenFilters)
|
21
|
-
|
22
|
-
return (
|
23
|
-
<div className="maskContainer">
|
24
|
-
{ isEmpty(filters) &&
|
25
|
-
<div className="filters">
|
26
|
-
<Body
|
27
|
-
color="light"
|
28
|
-
paddingLeft="xs"
|
29
|
-
size={4}
|
30
|
-
tag="h4"
|
31
|
-
text="No Filter Selected"
|
32
|
-
/>
|
33
|
-
</div>
|
34
|
-
}
|
35
|
-
{ !isEmpty(filters) &&
|
36
|
-
<div className="filters">
|
37
|
-
<div className="left_gradient" />
|
38
|
-
{map(displayableFilters, (value, name) => (
|
39
|
-
<div
|
40
|
-
className="filter"
|
41
|
-
key={`filter-${name}`}
|
42
|
-
>
|
43
|
-
{ value === true ?
|
44
|
-
<Title
|
45
|
-
dark={dark}
|
46
|
-
size={4}
|
47
|
-
tag="h4"
|
48
|
-
text={name}
|
49
|
-
/> :
|
50
|
-
<div>
|
51
|
-
<Caption
|
52
|
-
dark={dark}
|
53
|
-
text={name}
|
54
|
-
/>
|
55
|
-
<Title
|
56
|
-
dark={dark}
|
57
|
-
size={4}
|
58
|
-
tag="h4"
|
59
|
-
text={value}
|
60
|
-
/>
|
61
|
-
</div>
|
62
|
-
}
|
63
|
-
</div>
|
64
|
-
))}
|
65
|
-
<div className="right_gradient" />
|
66
|
-
</div>
|
67
|
-
}
|
68
|
-
</div>
|
69
|
-
)
|
70
|
-
}
|
71
|
-
|
72
|
-
export default CurrentFilters
|