playbook_ui 12.5.0.pre.alpha.filter1 → 12.5.0.pre.alpha.phonerails1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|