playbook_ui 12.2.0 → 12.3.0.pre.alpha.patchtest1
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/_playbook.scss +3 -0
- data/app/pb_kits/playbook/data/menu.yml +1 -0
- data/app/pb_kits/playbook/index.js +3 -2
- data/app/pb_kits/playbook/pb_button/_button.scss +0 -5
- data/app/pb_kits/playbook/pb_button/_button.tsx +4 -0
- data/app/pb_kits/playbook/pb_button/_button_mixins.scss +39 -4
- data/app/pb_kits/playbook/pb_button/button.rb +2 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_accessibility.jsx +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_block_content.jsx +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +4 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_form.jsx +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_full_width.jsx +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.html.erb +2 -2
- data/app/pb_kits/playbook/pb_button/docs/_button_icon_options.jsx +4 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_link.html.erb +3 -3
- data/app/pb_kits/playbook/pb_button/docs/_button_link.jsx +6 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_loading.html.erb +3 -3
- data/app/pb_kits/playbook/pb_button/docs/_button_loading.jsx +6 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_options.jsx +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_size.html.erb +3 -3
- data/app/pb_kits/playbook/pb_button/docs/_button_size.jsx +6 -0
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +26 -19
- data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.scss +24 -0
- data/app/pb_kits/playbook/pb_form_group/_form_group.scss +10 -2
- data/app/pb_kits/playbook/pb_map/_map.scss +8 -0
- data/app/pb_kits/playbook/pb_map/_map.tsx +40 -0
- data/app/pb_kits/playbook/pb_map/docs/_map_default.jsx +52 -0
- data/app/pb_kits/playbook/pb_map/docs/_map_default.md +13 -0
- data/app/pb_kits/playbook/pb_map/docs/_map_with_plugin.jsx +64 -0
- data/app/pb_kits/playbook/pb_map/docs/_map_with_plugin.md +8 -0
- data/app/pb_kits/playbook/pb_map/docs/example.yml +7 -0
- data/app/pb_kits/playbook/pb_map/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_map/map.test.jsx +17 -0
- data/app/pb_kits/playbook/pb_progress_simple/{_progress_simple.jsx → _progress_simple.tsx} +7 -5
- data/app/pb_kits/playbook/pb_progress_simple/progress_simple.test.js +120 -0
- data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +4 -9
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.jsx +11 -2
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +0 -2
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +95 -0
- data/app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.jsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/components/Control.jsx +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +19 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.jsx +39 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.md +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -0
- data/app/pb_kits/playbook/playbook-doc.js +2 -0
- data/app/pb_kits/playbook/tokens/_colors.scss +3 -1
- data/app/pb_kits/playbook/utilities/_focus.scss +12 -0
- data/lib/playbook/version.rb +2 -2
- metadata +20 -5
@@ -0,0 +1,52 @@
|
|
1
|
+
import React, { useRef, useEffect } from 'react'
|
2
|
+
import { Map } from '../../'
|
3
|
+
|
4
|
+
import maplibregl from 'maplibre-gl'
|
5
|
+
|
6
|
+
const MapDefault = () => {
|
7
|
+
|
8
|
+
const mapContainerRef = useRef(null)
|
9
|
+
|
10
|
+
useEffect(() => {
|
11
|
+
if (!maplibregl.supported()) {
|
12
|
+
alert('Your browser does not support MapLibre GL');
|
13
|
+
} else {
|
14
|
+
const map = new maplibregl.Map({
|
15
|
+
container: mapContainerRef.current,
|
16
|
+
style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
17
|
+
center: [-75.379143, 39.831200],
|
18
|
+
zoom: 13,
|
19
|
+
})
|
20
|
+
//set marker/pin
|
21
|
+
/* eslint-disable-next-line */
|
22
|
+
const marker = new maplibregl.Marker({
|
23
|
+
color: "#0056CF",
|
24
|
+
}).setLngLat([-75.379143, 39.831200])
|
25
|
+
.setPopup(new maplibregl.Popup({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
|
26
|
+
.addTo(map);
|
27
|
+
|
28
|
+
//add zoom controls
|
29
|
+
map.addControl(new maplibregl.NavigationControl({showCompass: false}))
|
30
|
+
|
31
|
+
// disable map zoom when using scroll
|
32
|
+
map.scrollZoom.disable();
|
33
|
+
|
34
|
+
}
|
35
|
+
}, [])
|
36
|
+
return (
|
37
|
+
<Map>
|
38
|
+
<div
|
39
|
+
ref={mapContainerRef}
|
40
|
+
style={{
|
41
|
+
position: 'absolute',
|
42
|
+
left: 0,
|
43
|
+
right: 0,
|
44
|
+
top: 0,
|
45
|
+
bottom: 0,
|
46
|
+
}}
|
47
|
+
/>
|
48
|
+
</Map>
|
49
|
+
)
|
50
|
+
}
|
51
|
+
|
52
|
+
export default MapDefault
|
@@ -0,0 +1,13 @@
|
|
1
|
+
This kit provides a wrapping class to place around the MapLibre library. Complete docs for using the library can be found [here](https://maplibre.org/maplibre-gl-js-docs/api/).
|
2
|
+
|
3
|
+
Basic setup to start using MapLibre:
|
4
|
+
- Install the npm package using `yarn add maplibre-gl`
|
5
|
+
- Include a link to the CSS file as a CDN in your stylesheet using the following syntax:
|
6
|
+
`@import url("https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css");`
|
7
|
+
or include it as a link in the <head> tag `<link href='https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css' rel='stylesheet' />`
|
8
|
+
- To use Maplibre, you must also set a height on the containing div.
|
9
|
+
- You can now use MapLibre within the Map Kit as shown in this example.
|
10
|
+
|
11
|
+
__Notes__ :
|
12
|
+
- The MapLibre Marker allows us to pass it a HEX value as a color prop. In these doc examples we are using our primary color for the Marker.
|
13
|
+
- `scrollZoom` has been disabled in these doc examples for page usability
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import React, { useRef, useEffect } from 'react'
|
2
|
+
import { Map } from '../../'
|
3
|
+
import maplibregl from 'maplibre-gl'
|
4
|
+
import MapboxDraw from "@mapbox/mapbox-gl-draw";
|
5
|
+
|
6
|
+
const MapWithPlugin = () => {
|
7
|
+
|
8
|
+
const mapContainerRef = useRef(null)
|
9
|
+
|
10
|
+
useEffect(() => {
|
11
|
+
if (!maplibregl.supported()) {
|
12
|
+
alert('Your browser does not support MapLibre GL');
|
13
|
+
} else {
|
14
|
+
const map = new maplibregl.Map({
|
15
|
+
container: mapContainerRef.current,
|
16
|
+
style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
17
|
+
center: [-75.379143, 39.831200],
|
18
|
+
zoom: 13,
|
19
|
+
})
|
20
|
+
//set marker/pin
|
21
|
+
/* eslint-disable-next-line */
|
22
|
+
const marker = new maplibregl.Marker({
|
23
|
+
color: "#0056CF",
|
24
|
+
}).setLngLat([-75.379143, 39.831200])
|
25
|
+
.setPopup(new maplibregl.Popup({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
|
26
|
+
.addTo(map);
|
27
|
+
|
28
|
+
//add zoom controls
|
29
|
+
map.addControl(new maplibregl.NavigationControl({showCompass: false}))
|
30
|
+
|
31
|
+
// disable map zoom when using scroll
|
32
|
+
map.scrollZoom.disable();
|
33
|
+
|
34
|
+
//Add polygon draw button using map-box-gl-draw plugin
|
35
|
+
var draw = new MapboxDraw({
|
36
|
+
displayControlsDefault: false,
|
37
|
+
controls: {
|
38
|
+
polygon: true,
|
39
|
+
trash: true
|
40
|
+
}
|
41
|
+
});
|
42
|
+
map.addControl(draw);
|
43
|
+
}
|
44
|
+
}, [])
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
return (
|
49
|
+
<Map>
|
50
|
+
<div
|
51
|
+
ref={mapContainerRef}
|
52
|
+
style={{
|
53
|
+
position: 'absolute',
|
54
|
+
left: 0,
|
55
|
+
right: 0,
|
56
|
+
top: 0,
|
57
|
+
bottom: 0,
|
58
|
+
}}
|
59
|
+
/>
|
60
|
+
</Map>
|
61
|
+
)
|
62
|
+
}
|
63
|
+
|
64
|
+
export default MapWithPlugin
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Various plugins are available for use with MapLibre, one of which is the [mapbox-gl-draw](https://github.com/mapbox/mapbox-gl-draw). This plugin is recommended by MapLibre if you need to add the functionality of drawing polygons on the map.
|
2
|
+
|
3
|
+
To test this tool:
|
4
|
+
- Click the "draw box" icon to activate the polygon tool
|
5
|
+
- Click on a spot on the map to start drawing
|
6
|
+
- Continue clicking to create new points, defining the boundaries of the polygon
|
7
|
+
- Press enter or re-click the first point to finish the polygon
|
8
|
+
- Once drawn, polygons can be selected on click and then moved, by dragging-and-dropping the entire shape; resized, by dragging-and-dropping any boundary point(s); or deleted, by clicking the "trash" button.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { renderKit } from '../utilities/test-utils'
|
2
|
+
|
3
|
+
import { Map } from '../'
|
4
|
+
|
5
|
+
/* See these resources for more testing info:
|
6
|
+
- https://github.com/testing-library/jest-dom#usage for useage and examples
|
7
|
+
- https://jestjs.io/docs/en/using-matchers
|
8
|
+
*/
|
9
|
+
|
10
|
+
test('generated scaffold test - update me', () => {
|
11
|
+
const props = {
|
12
|
+
data: { testid: 'default' }
|
13
|
+
}
|
14
|
+
|
15
|
+
const kit = renderKit(Map , props)
|
16
|
+
expect(kit).toBeInTheDocument()
|
17
|
+
})
|
@@ -1,16 +1,15 @@
|
|
1
|
-
/* @flow */
|
2
1
|
import React from 'react'
|
3
2
|
import classnames from 'classnames'
|
4
|
-
import { buildCss } from '../utilities/props'
|
3
|
+
import { buildCss, buildDataProps } from '../utilities/props'
|
5
4
|
import { globalProps } from '../utilities/globalProps'
|
6
5
|
|
7
6
|
type ProgressSimpleProps = {
|
8
7
|
align?: "left" | "center" | "right",
|
9
|
-
className?: string |
|
8
|
+
className?: string | string[],
|
10
9
|
dark?: boolean,
|
11
10
|
data?: string,
|
12
11
|
id?: string,
|
13
|
-
max?:
|
12
|
+
max?: number,
|
14
13
|
muted: boolean,
|
15
14
|
percent: string,
|
16
15
|
value: number,
|
@@ -23,6 +22,7 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
|
|
23
22
|
align,
|
24
23
|
className,
|
25
24
|
dark = false,
|
25
|
+
data ={},
|
26
26
|
max,
|
27
27
|
muted = false,
|
28
28
|
percent = '',
|
@@ -34,6 +34,7 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
|
|
34
34
|
width: width,
|
35
35
|
}
|
36
36
|
|
37
|
+
const dataProps = buildDataProps(data)
|
37
38
|
const variantStyle = variant == 'default' ? '' : variant
|
38
39
|
|
39
40
|
const valueStyles = {
|
@@ -52,7 +53,8 @@ const ProgressSimple = (props: ProgressSimpleProps) => {
|
|
52
53
|
)
|
53
54
|
|
54
55
|
return (
|
55
|
-
<div
|
56
|
+
<div {...dataProps}
|
57
|
+
className={wrapperClass}>
|
56
58
|
<div
|
57
59
|
className={kitClass}
|
58
60
|
data-value={value}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { render, screen, cleanup } from '../utilities/test-utils'
|
3
|
+
|
4
|
+
import ProgressSimple from './_progress_simple'
|
5
|
+
|
6
|
+
const testId = "progress-simple-test"
|
7
|
+
|
8
|
+
test('renders default class name and percentage', () => {
|
9
|
+
render(
|
10
|
+
<div>
|
11
|
+
<ProgressSimple
|
12
|
+
data={{ testid: testId }}
|
13
|
+
percent={45}
|
14
|
+
/>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
)
|
18
|
+
|
19
|
+
const kit = screen.getByTestId(testId)
|
20
|
+
const progress = kit.querySelector(".progress_simple_value")
|
21
|
+
|
22
|
+
expect(kit).toHaveClass('pb_progress_simple_wrapper')
|
23
|
+
expect(progress).toHaveStyle("width: 45%")
|
24
|
+
|
25
|
+
})
|
26
|
+
|
27
|
+
test('renders values', () => {
|
28
|
+
render(
|
29
|
+
<div>
|
30
|
+
<ProgressSimple
|
31
|
+
data={{ testid: testId }}
|
32
|
+
max='10'
|
33
|
+
value='2'
|
34
|
+
/>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
)
|
38
|
+
|
39
|
+
const kit = screen.getByTestId(testId)
|
40
|
+
const progress = kit.querySelector(".progress_simple_value")
|
41
|
+
expect(progress).toHaveStyle("width: 20%")
|
42
|
+
})
|
43
|
+
|
44
|
+
test('renders progress bar width', () => {
|
45
|
+
render(
|
46
|
+
<div>
|
47
|
+
<ProgressSimple
|
48
|
+
data={{ testid: testId }}
|
49
|
+
percentage={40}
|
50
|
+
width="100px"
|
51
|
+
/>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
)
|
55
|
+
|
56
|
+
const kit = screen.getByTestId(testId)
|
57
|
+
const progress = kit.querySelector(".pb_progress_simple_kit")
|
58
|
+
expect(progress).toHaveStyle("width: 100px")
|
59
|
+
})
|
60
|
+
|
61
|
+
test('renders color variants', () => {
|
62
|
+
[
|
63
|
+
"positive",
|
64
|
+
"negative",
|
65
|
+
"warning"
|
66
|
+
].forEach((colorVariant) => {
|
67
|
+
|
68
|
+
render(
|
69
|
+
<div>
|
70
|
+
<ProgressSimple
|
71
|
+
data={{ testid: testId }}
|
72
|
+
percentage={40}
|
73
|
+
variant={colorVariant}
|
74
|
+
/>
|
75
|
+
</div>
|
76
|
+
)
|
77
|
+
|
78
|
+
const kit = screen.getByTestId(testId)
|
79
|
+
const progress = kit.querySelector(`.pb_progress_simple_kit_${colorVariant}`)
|
80
|
+
expect(progress).toBeInTheDocument()
|
81
|
+
|
82
|
+
cleanup()
|
83
|
+
})
|
84
|
+
})
|
85
|
+
|
86
|
+
test('renders muted prop', () => {
|
87
|
+
render(
|
88
|
+
<div>
|
89
|
+
<ProgressSimple
|
90
|
+
data={{ testid: testId }}
|
91
|
+
muted
|
92
|
+
percentage={40}
|
93
|
+
/>
|
94
|
+
</div>
|
95
|
+
)
|
96
|
+
|
97
|
+
const kit = screen.getByTestId(testId)
|
98
|
+
const progress = kit.querySelector('.pb_progress_simple_kit_muted')
|
99
|
+
expect(progress).toBeInTheDocument()
|
100
|
+
})
|
101
|
+
|
102
|
+
test('renders align prop', () => {
|
103
|
+
[
|
104
|
+
"left",
|
105
|
+
"center",
|
106
|
+
"right"
|
107
|
+
].forEach((alignProp) => {
|
108
|
+
render(
|
109
|
+
<ProgressSimple
|
110
|
+
align={alignProp}
|
111
|
+
data={{ testid: testId }}
|
112
|
+
percentage={45}
|
113
|
+
/>
|
114
|
+
)
|
115
|
+
const kit = screen.getByTestId(testId)
|
116
|
+
expect(kit).toHaveClass(`pb_progress_simple_wrapper_${alignProp}`)
|
117
|
+
|
118
|
+
cleanup()
|
119
|
+
})
|
120
|
+
})
|
@@ -19,12 +19,11 @@ $pb_selectable_card_border: 2px;
|
|
19
19
|
display: inherit;
|
20
20
|
flex-direction: inherit;
|
21
21
|
padding: 1px;
|
22
|
-
transition-property: all;
|
23
|
-
transition-duration: $transition_short;
|
24
|
-
transition-timing-function: $easeIn;
|
25
22
|
}
|
26
23
|
|
27
24
|
@include pb_card;
|
25
|
+
transition-property: none;
|
26
|
+
transition-duration: 0s;
|
28
27
|
background-color: $white;
|
29
28
|
padding: $space_sm;
|
30
29
|
margin-bottom: $space_sm;
|
@@ -55,9 +54,6 @@ $pb_selectable_card_border: 2px;
|
|
55
54
|
top: -($pb_selectable_card_indicator_size/2);
|
56
55
|
right: -($pb_selectable_card_indicator_size/2);
|
57
56
|
opacity: 0;
|
58
|
-
transition-property: opacity;
|
59
|
-
transition-duration: $transition_short;
|
60
|
-
transition-timing-function: $easeIn;
|
61
57
|
}
|
62
58
|
}
|
63
59
|
|
@@ -77,6 +73,8 @@ $pb_selectable_card_border: 2px;
|
|
77
73
|
|
78
74
|
position: relative;
|
79
75
|
@include pb_card_selected;
|
76
|
+
transition-property: none;
|
77
|
+
transition-duration: 0s;
|
80
78
|
|
81
79
|
.pb_selectable_card_circle {
|
82
80
|
opacity: $opacity_10;
|
@@ -127,9 +125,6 @@ $pb_selectable_card_border: 2px;
|
|
127
125
|
|
128
126
|
.separator {
|
129
127
|
align-self: stretch;
|
130
|
-
transition-property: all;
|
131
|
-
transition-duration: $transition_short;
|
132
|
-
transition-timing-function: $easeIn;
|
133
128
|
width: 1px;
|
134
129
|
margin-right: 1px;
|
135
130
|
margin-top: -1px;
|
@@ -18,7 +18,7 @@ import Option from './components/Option'
|
|
18
18
|
import Placeholder from './components/Placeholder'
|
19
19
|
import ValueContainer from './components/ValueContainer'
|
20
20
|
|
21
|
-
import { noop } from '../utilities/props'
|
21
|
+
import { noop, buildDataProps } from '../utilities/props'
|
22
22
|
|
23
23
|
/**
|
24
24
|
* @typedef {object} Props
|
@@ -32,6 +32,8 @@ type TypeaheadProps = {
|
|
32
32
|
components?: object,
|
33
33
|
createable?: boolean,
|
34
34
|
dark?: boolean,
|
35
|
+
data?: object,
|
36
|
+
error?: string,
|
35
37
|
id?: string,
|
36
38
|
label?: string,
|
37
39
|
loadOptions?: string,
|
@@ -49,6 +51,8 @@ const Typeahead = ({
|
|
49
51
|
async,
|
50
52
|
components = {},
|
51
53
|
createable,
|
54
|
+
error = "",
|
55
|
+
data = {},
|
52
56
|
getOptionLabel,
|
53
57
|
getOptionValue,
|
54
58
|
id,
|
@@ -106,13 +110,18 @@ const Typeahead = ({
|
|
106
110
|
}
|
107
111
|
}
|
108
112
|
|
113
|
+
const dataProps = buildDataProps(data)
|
114
|
+
|
109
115
|
const classes = `pb_typeahead_kit react-select ${globalProps(props)}`
|
110
116
|
const inlineClass = selectProps.inline ? 'inline' : null
|
111
117
|
|
112
118
|
return (
|
113
|
-
<div
|
119
|
+
<div {...dataProps}
|
120
|
+
className={classnames(classes, inlineClass)}
|
121
|
+
>
|
114
122
|
<Tag
|
115
123
|
classNamePrefix="typeahead-kit-select"
|
124
|
+
error={error}
|
116
125
|
onChange={handleOnChange}
|
117
126
|
{...selectProps}
|
118
127
|
/>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { render, screen } from '../utilities/test-utils'
|
3
|
+
import Typeahead from './_typeahead'
|
4
|
+
|
5
|
+
const options = [
|
6
|
+
{ label: 'Orange', value: '#FFA500' },
|
7
|
+
{ label: 'Red', value: '#FF0000' },
|
8
|
+
{ label: 'Green', value: '#00FF00' },
|
9
|
+
{ label: 'Blue', value: '#0000FF' },
|
10
|
+
]
|
11
|
+
|
12
|
+
test('typeahead classname + label renders as expected', () => {
|
13
|
+
render(
|
14
|
+
<Typeahead
|
15
|
+
data={{ testid: 'typeahead-test' }}
|
16
|
+
defaultValue={[options[0]]}
|
17
|
+
label="Colors"
|
18
|
+
options={options}
|
19
|
+
/>
|
20
|
+
)
|
21
|
+
|
22
|
+
const kit = screen.getByTestId('typeahead-test')
|
23
|
+
const label = kit.querySelector(".pb_caption_kit_md.pb_text_input_kit_label")
|
24
|
+
expect(kit).toHaveClass("pb_typeahead_kit")
|
25
|
+
expect(label).toHaveTextContent("Colors")
|
26
|
+
})
|
27
|
+
|
28
|
+
test('to be error variant', () => {
|
29
|
+
render(
|
30
|
+
<Typeahead
|
31
|
+
data={{ testid: 'error-test' }}
|
32
|
+
error='Please make a valid selection'
|
33
|
+
options={options}
|
34
|
+
/>
|
35
|
+
)
|
36
|
+
|
37
|
+
const kit = screen.getByTestId("error-test")
|
38
|
+
const error = kit.querySelector(".pb_body_kit_negative")
|
39
|
+
expect(error).toBeInTheDocument()
|
40
|
+
})
|
41
|
+
|
42
|
+
test('should be inline variant', () => {
|
43
|
+
render(
|
44
|
+
<Typeahead
|
45
|
+
data={{ testid: 'inline-test' }}
|
46
|
+
inline
|
47
|
+
options={options}
|
48
|
+
/>
|
49
|
+
)
|
50
|
+
|
51
|
+
const kit = screen.getByTestId('inline-test')
|
52
|
+
expect(kit).toHaveClass("inline")
|
53
|
+
})
|
54
|
+
|
55
|
+
test('typeahead with pills', () => {
|
56
|
+
render(
|
57
|
+
<Typeahead
|
58
|
+
data={{ testid: 'pills-test' }}
|
59
|
+
defaultValue={[options[0]]}
|
60
|
+
isMulti
|
61
|
+
options={options}
|
62
|
+
/>
|
63
|
+
)
|
64
|
+
|
65
|
+
const kit = screen.getByTestId('pills-test')
|
66
|
+
const pill = kit.querySelector(".pb_form_pill_kit_primary")
|
67
|
+
expect(pill).toBeInTheDocument()
|
68
|
+
})
|
69
|
+
|
70
|
+
test('typeahead multi select with badges and small pills', () => {
|
71
|
+
render(
|
72
|
+
<>
|
73
|
+
<Typeahead
|
74
|
+
data={{ testid: 'badge-test' }}
|
75
|
+
defaultValue={[options[0]]}
|
76
|
+
isMulti
|
77
|
+
multiKit="badge"
|
78
|
+
options={options}
|
79
|
+
/>
|
80
|
+
|
81
|
+
<Typeahead
|
82
|
+
data={{ testid: 'small-pill-test' }}
|
83
|
+
defaultValue={[options[0]]}
|
84
|
+
isMulti
|
85
|
+
multiKit="smallPill"
|
86
|
+
options={options}
|
87
|
+
/>
|
88
|
+
</>
|
89
|
+
)
|
90
|
+
|
91
|
+
const kit = screen.getByTestId('small-pill-test')
|
92
|
+
const badge = kit.querySelector(".pb_form_pill_kit_primary.mr_xs.small")
|
93
|
+
expect(badge).toBeInTheDocument()
|
94
|
+
})
|
95
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<%
|
2
|
+
options = [
|
3
|
+
{ label: 'Windows', value: '#FFA500' },
|
4
|
+
{ label: 'Siding', value: '#FF0000' },
|
5
|
+
{ label: 'Doors', value: '#00FF00' },
|
6
|
+
{ label: 'Roofs', value: '#0000FF' },
|
7
|
+
]
|
8
|
+
|
9
|
+
%>
|
10
|
+
|
11
|
+
<%= pb_rails("typeahead", props: { id: "typeahead-error-example", options: options, error: "Please make a valid selection", label: "Products", name: :foo, is_multi: false }) %>
|
12
|
+
|
13
|
+
<!-- This section is an example of the available JavaScript event hooks -->
|
14
|
+
<%= javascript_tag defer: "defer" do %>
|
15
|
+
document.addEventListener("pb-typeahead-kit-typeahead-error-example-result-option-select", function(event) {
|
16
|
+
console.log('Option selected')
|
17
|
+
console.dir(event.detail)
|
18
|
+
})
|
19
|
+
<% end %>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
// @flow
|
2
|
+
|
3
|
+
import React, { useState, useEffect } from 'react'
|
4
|
+
|
5
|
+
import Typeahead from '../_typeahead'
|
6
|
+
|
7
|
+
const options = [
|
8
|
+
{ label: 'Orange', value: '#FFA500' },
|
9
|
+
{ label: 'Red', value: '#FF0000' },
|
10
|
+
{ label: 'Green', value: '#00FF00' },
|
11
|
+
{ label: 'Blue', value: '#0000FF' },
|
12
|
+
]
|
13
|
+
|
14
|
+
const TypeaheadErrorState = (props) => {
|
15
|
+
const [errorState, setErrorState] = useState("Please make a valid selection");
|
16
|
+
const [searchValue, setSearchValue] = useState(null);
|
17
|
+
|
18
|
+
const handleOnChange = (value) => setSearchValue(value)
|
19
|
+
|
20
|
+
useEffect(() => {
|
21
|
+
if(searchValue) {
|
22
|
+
setErrorState("")
|
23
|
+
} else {
|
24
|
+
setErrorState("Please make a valid selection")
|
25
|
+
}
|
26
|
+
}, [searchValue])
|
27
|
+
|
28
|
+
return (
|
29
|
+
<Typeahead
|
30
|
+
error={errorState}
|
31
|
+
label="Colors"
|
32
|
+
onChange={handleOnChange}
|
33
|
+
options={options}
|
34
|
+
{...props}
|
35
|
+
/>
|
36
|
+
)
|
37
|
+
}
|
38
|
+
|
39
|
+
export default TypeaheadErrorState
|
@@ -0,0 +1 @@
|
|
1
|
+
Typeahead w/ Error shows that an option must be selected or the selected option is invalid (i.e., when used in a form it signals a user to fix an error).
|
@@ -8,6 +8,7 @@ examples:
|
|
8
8
|
- typeahead_with_pills_async_users: With Pills (Async Data w/ Users)
|
9
9
|
- typeahead_inline: Inline
|
10
10
|
- typeahead_multi_kit: Multi Kit Options
|
11
|
+
- typeahead_error_state: Error State
|
11
12
|
|
12
13
|
react:
|
13
14
|
- typeahead_default: Default
|
@@ -20,3 +21,4 @@ examples:
|
|
20
21
|
- typeahead_multi_kit: Multi Kit Options
|
21
22
|
- typeahead_createable: Createable
|
22
23
|
- typeahead_async_createable: Createable (+ Async Data)
|
24
|
+
- typeahead_error_state: Error State
|
@@ -8,3 +8,4 @@ export { default as TypeaheadInline } from './_typeahead_inline.jsx'
|
|
8
8
|
export { default as TypeaheadMultiKit } from './_typeahead_multi_kit.jsx'
|
9
9
|
export { default as TypeaheadCreateable } from './_typeahead_createable.jsx'
|
10
10
|
export { default as TypeaheadAsyncCreateable } from './_typeahead_async_createable.jsx'
|
11
|
+
export { default as TypeaheadErrorState } from './_typeahead_error_state.jsx'
|
@@ -5,6 +5,8 @@ module Playbook
|
|
5
5
|
class Typeahead < Playbook::KitBase
|
6
6
|
prop :async, type: Playbook::Props::Boolean, default: false
|
7
7
|
prop :default_options, type: Playbook::Props::HashArray, default: []
|
8
|
+
prop :error, type: Playbook::Props::String,
|
9
|
+
default: ""
|
8
10
|
prop :get_option_label
|
9
11
|
prop :get_option_value
|
10
12
|
prop :id
|
@@ -57,6 +59,7 @@ module Playbook
|
|
57
59
|
base_options = {
|
58
60
|
dark: dark,
|
59
61
|
defaultValue: default_options,
|
62
|
+
error: error,
|
60
63
|
id: id,
|
61
64
|
inline: inline,
|
62
65
|
isMulti: is_multi,
|
@@ -55,6 +55,7 @@ import * as Lightbox from 'pb_lightbox/docs'
|
|
55
55
|
import * as LineGraphDocs from 'pb_line_graph/docs'
|
56
56
|
import * as List from 'pb_list/docs'
|
57
57
|
import * as LoadingInline from 'pb_loading_inline/docs'
|
58
|
+
import * as Map from 'pb_map/docs'
|
58
59
|
import * as Message from 'pb_message/docs'
|
59
60
|
import * as MultipleUsers from 'pb_multiple_users/docs'
|
60
61
|
import * as MultipleUsersStacked from 'pb_multiple_users_stacked/docs'
|
@@ -152,6 +153,7 @@ WebpackerReact.setup({
|
|
152
153
|
...LineGraphDocs,
|
153
154
|
...List,
|
154
155
|
...LoadingInline,
|
156
|
+
...Map,
|
155
157
|
...Message,
|
156
158
|
...MultipleUsers,
|
157
159
|
...MultipleUsersStacked,
|
@@ -96,11 +96,13 @@ $hover_colors: (
|
|
96
96
|
);
|
97
97
|
|
98
98
|
/* Focus colors -----------------------*/
|
99
|
+
$focus_color: $primary;
|
99
100
|
$focus_input_light: rgba($active_light, $opacity_5);
|
100
101
|
$focus_input_dark: rgba(#144075, $opacity_5);
|
101
102
|
$focus_input_colors: (
|
102
103
|
focus_input_light: $focus_input_light,
|
103
|
-
focus_input_dark: $focus_input_dark
|
104
|
+
focus_input_dark: $focus_input_dark,
|
105
|
+
focus_color: $focus_color
|
104
106
|
);
|
105
107
|
|
106
108
|
/* Border colors ----------------------*/
|