playbook_ui 12.4.0 → 12.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/index.js +4 -1
  3. data/app/pb_kits/playbook/pb_button/_button.tsx +2 -2
  4. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +37 -33
  5. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +55 -0
  6. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.test.js +41 -0
  7. data/app/pb_kits/playbook/pb_map/_map.scss +114 -2
  8. data/app/pb_kits/playbook/pb_map/_map.tsx +42 -2
  9. data/app/pb_kits/playbook/pb_map/docs/_map_default.jsx +47 -24
  10. data/app/pb_kits/playbook/pb_map/docs/_map_default.md +5 -5
  11. data/app/pb_kits/playbook/pb_map/docs/_map_with_plugin.jsx +20 -17
  12. data/app/pb_kits/playbook/pb_map/docs/example.yml +0 -1
  13. data/app/pb_kits/playbook/pb_map/pbMapTheme.ts +23 -0
  14. data/app/pb_kits/playbook/pb_message/{_message.jsx → _message.tsx} +35 -35
  15. data/app/pb_kits/playbook/pb_message/message.test.js +63 -0
  16. data/app/pb_kits/playbook/pb_passphrase/{_passphrase.jsx → _passphrase.tsx} +56 -56
  17. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.html.erb +3 -0
  18. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -0
  19. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.html.erb +15 -0
  20. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +43 -0
  21. data/app/pb_kits/playbook/pb_popover/_popover.tsx +3 -3
  22. data/app/pb_kits/playbook/pb_selectable_list/_selectable_list.scss +1 -1
  23. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +4 -0
  24. data/app/pb_kits/playbook/playbook-rails-react-bindings.js +2 -0
  25. data/lib/playbook/version.rb +2 -2
  26. metadata +11 -5
  27. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.jsx +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c9cb603d0564380dc76fd27efdc587607430f9e349d5288672a6f44ae9cdd7e
4
- data.tar.gz: b677f2dfb9bfe0bfc848018c3a84be1f94af01e87372ff4ba0dbf78a50c0857c
3
+ metadata.gz: 92319a3771d2aa0a3198e988dc95b91e977ee532db2884cd6197912cb045caae
4
+ data.tar.gz: caaa026385dd1d94a65175ba00ef818caab6a901c5bb0da90cd24920158e885f
5
5
  SHA512:
6
- metadata.gz: 5671ee0b58e71684f090dcac6d15c2297d19c071b7f58082badd065319fdf91e27a3884779a8e3c021101515a40c7a9b2c0c07c880b632894faafb23a16322ac
7
- data.tar.gz: ea93cf50049661329f814c893e245ceff4d3be4c4bd5ce9264624eafea84d0a82a833d50cebb6e233d90e5e124c60372d68f5516c4ba4269992325b4178e5b86
6
+ metadata.gz: 7469df006da7d11b70de500123a4d260db2a2c8c0b79ee80766dde6a760eaa81c71b59880aad14ee48a7d9ee91b2c6237e766b8c046a19b088b61830b0e5f2b6
7
+ data.tar.gz: 7e0f3a0e05f403da3b31e8b21ab01ee92fb4139a5223af663a62f9672ff381009a75cd1a9f30ea57289e28ffda043f23cab7364eae1e54973e9f4922d8884f28
@@ -123,4 +123,7 @@ export { default as PbTable } from './pb_table'
123
123
  export { default as PbTextarea } from './pb_textarea'
124
124
  export { default as PbTooltip } from './pb_tooltip'
125
125
  export { default as PbTypeahead } from './pb_typeahead'
126
- export { default as dialogHelper } from './pb_dialog/dialogHelper'
126
+ export { default as dialogHelper } from './pb_dialog/dialogHelper'
127
+
128
+ //Theming
129
+ export {default as mapTheme} from './pb_map/pbMapTheme'
@@ -27,9 +27,9 @@ type ButtonPropTypes = {
27
27
  size?: 'sm' | 'md' | 'lg',
28
28
  text?: string,
29
29
  type?: 'inline' | null,
30
- htmlType: 'submit' | 'reset' | 'button' | undefined,
30
+ htmlType?: 'submit' | 'reset' | 'button' | undefined,
31
31
  value?: string | null,
32
- variant: 'primary' | 'secondary' | 'link',
32
+ variant?: 'primary' | 'secondary' | 'link',
33
33
  wrapperClass?: string,
34
34
  } & GlobalProps
35
35
 
@@ -14,7 +14,7 @@ type DatePickerProps = {
14
14
  aria?: {[key: string]: string},
15
15
  className?: string,
16
16
  dark?: boolean,
17
- data?: object,
17
+ data?: { [key: string]: string },
18
18
  defaultDate?: string,
19
19
  disableDate?: number[],
20
20
  disableInput?: boolean,
@@ -27,8 +27,8 @@ type DatePickerProps = {
27
27
  hideLabel?: boolean,
28
28
  id?: string,
29
29
  inLine?: boolean,
30
- inputAria?: object,
31
- inputData?: object,
30
+ inputAria?: {[key: string]: string},
31
+ inputData?: {[key: string]: string},
32
32
  inputOnChange?: (arg: string) => void,
33
33
  inputValue?: any,
34
34
  label?: string,
@@ -47,7 +47,7 @@ type DatePickerProps = {
47
47
  yearRange?: number[],
48
48
  } & GlobalProps
49
49
 
50
- const DatePicker = (props: DatePickerProps) => {
50
+ const DatePicker = (props: DatePickerProps): React.ReactElement => {
51
51
  if (props.plugins) deprecatedProps('Date Picker', ['plugins'])
52
52
 
53
53
  const {
@@ -67,7 +67,7 @@ const DatePicker = (props: DatePickerProps) => {
67
67
  hideIcon = false,
68
68
  hideLabel = false,
69
69
  id,
70
- inLine = true,
70
+ inLine = false,
71
71
  inputAria,
72
72
  inputData,
73
73
  inputOnChange,
@@ -77,7 +77,7 @@ const DatePicker = (props: DatePickerProps) => {
77
77
  minDate,
78
78
  mode = 'single',
79
79
  name,
80
- onChange = () => {},
80
+ onChange = () => { void 0 },
81
81
  pickerId,
82
82
  placeholder = 'Select Date',
83
83
  plugins = false,
@@ -163,36 +163,40 @@ const DatePicker = (props: DatePickerProps) => {
163
163
  value={inputValue}
164
164
  />
165
165
 
166
- {!hideIcon &&
166
+ { !hideIcon &&
167
167
  <div
168
- className={iconWrapperClass()}
169
- id={`cal-icon-${pickerId}`}
170
- >
171
- <Icon
172
- className="cal_icon"
173
- icon="calendar-alt"
174
- />
175
- </div>
176
- }
177
-
178
-
179
- { hideIcon && inLine ? <><div
180
- className={iconWrapperClass()}
181
- id={`${pickerId}-icon-plus`}
182
- >
168
+ className={iconWrapperClass()}
169
+ id={`cal-icon-${pickerId}`}
170
+ >
183
171
  <Icon
184
- className="date-picker-plus-icon"
185
- icon="plus" />
186
- </div><div
187
- className={iconWrapperClass()}
188
- id={`${pickerId}-angle-down`}
189
- >
190
- <Icon
191
- className="angle_down_icon"
192
- icon="angle-down" />
193
- </div></> : null}
194
-
172
+ className="cal_icon"
173
+ icon="calendar-alt"
174
+ />
175
+ </div>
176
+ }
195
177
 
178
+ { hideIcon && inLine ?
179
+ <div>
180
+ <div
181
+ className={iconWrapperClass()}
182
+ id={`${pickerId}-icon-plus`}
183
+ >
184
+ <Icon
185
+ className="date-picker-plus-icon"
186
+ icon="plus"
187
+ />
188
+ </div>
189
+ <div
190
+ className={iconWrapperClass()}
191
+ id={`${pickerId}-angle-down`}
192
+ >
193
+ <Icon
194
+ className="angle_down_icon"
195
+ icon="angle-down"
196
+ />
197
+ </div>
198
+ </div>
199
+ : null }
196
200
  </div>
197
201
  </div>
198
202
  )
@@ -0,0 +1,55 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
5
+ import { globalProps } from '../utilities/globalProps'
6
+
7
+ import Body from '../pb_body/_body'
8
+ import Icon from '../pb_icon/_icon'
9
+
10
+ type LoadingInlineProps = {
11
+ align?: "left" | "center" | "right",
12
+ aria?: { [key: string]: string },
13
+ className?: string,
14
+ data?: { [key: string]: string },
15
+ id?: string,
16
+ }
17
+
18
+ const LoadingInline = (props: LoadingInlineProps) => {
19
+ const {
20
+ align = 'left',
21
+ aria = {},
22
+ className,
23
+ data = {},
24
+ id,
25
+ } = props
26
+
27
+ const ariaProps = buildAriaProps(aria)
28
+ const dataProps = buildDataProps(data)
29
+ const classes = classnames(
30
+ buildCss(`pb_loading_inline_kit_${align}`),
31
+ globalProps(props),
32
+ className
33
+ )
34
+
35
+ return (
36
+ <div
37
+ {...ariaProps}
38
+ {...dataProps}
39
+ className={classes}
40
+ id={id}
41
+ >
42
+ <Body color="light">
43
+ <Icon
44
+ aria={{ label: 'loading icon' }}
45
+ fixedWidth
46
+ icon="spinner"
47
+ pulse
48
+ />
49
+ {' Loading'}
50
+ </Body>
51
+ </div>
52
+ )
53
+ }
54
+
55
+ export default LoadingInline
@@ -0,0 +1,41 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+ import LoadingInline from './_loading_inline'
4
+
5
+ const testId = "loadingInline"
6
+
7
+ test('should render custom class and data', () => {
8
+ render(
9
+ <LoadingInline
10
+ className='custom-class'
11
+ data={{ testid: testId }}
12
+ />
13
+ )
14
+
15
+ const kit = screen.getByTestId(testId)
16
+ expect(kit).toHaveClass('custom-class')
17
+ })
18
+
19
+ test('should render id', () => {
20
+ render(
21
+ <LoadingInline
22
+ data={{ testid: testId }}
23
+ id={testId}
24
+ />
25
+ )
26
+
27
+ const kit = screen.getByTestId(testId)
28
+ expect(kit).toHaveProperty('id', testId)
29
+ })
30
+
31
+ test('should render aria-label', () => {
32
+ render(
33
+ <LoadingInline
34
+ aria={{ label: testId }}
35
+ data={{ testid: testId }}
36
+ />
37
+ )
38
+
39
+ const kit = screen.getByTestId(testId)
40
+ expect(kit).toHaveAttribute('aria-label', testId)
41
+ })
@@ -1,8 +1,120 @@
1
1
  @import "../tokens/typography";
2
- @import "../tokens/colors";
2
+ @import "../tokens/colors";
3
3
  @import "../tokens/shadows";
4
+ @import "../tokens/border_radius";
4
5
 
5
- .pb_map {
6
+ [class*="pb_map"] {
6
7
  font-family: $font_family_base !important;
7
8
 
9
+ .maplibregl-ctrl-attrib-button {
10
+ &:focus {
11
+ box-shadow: unset;
12
+ }
13
+ &:focus-visible {
14
+ box-shadow: 0 0 0 1px $primary_action;
15
+ }
16
+ &:hover {
17
+ box-shadow: $shadow_deep;
18
+ }
19
+ }
20
+ .custom-nav-control {
21
+ position: absolute;
22
+ right: $space_xs + 2;
23
+ top: $space_xs + 2;
24
+ z-index: 2;
25
+
26
+ .custom-nav-control-zoom {
27
+ border-radius: $border_radius_md;
28
+ box-shadow: $shadow_deep;
29
+ background: $card_light;
30
+ .map-zoom-in-button {
31
+ border-bottom-left-radius: unset;
32
+ border-bottom-right-radius: unset;
33
+ border-bottom: transparent;
34
+ }
35
+ .map-zoom-out-button {
36
+ border-top-left-radius: unset;
37
+ border-top-right-radius: unset;
38
+ }
39
+ }
40
+
41
+ .map-zoom-in-button,
42
+ .map-zoom-out-button,
43
+ .map-flyto-button {
44
+ border: solid 1px $border_light;
45
+ cursor: pointer;
46
+ padding: $space_xs + 2;
47
+ text-align: center;
48
+ color: $text_lt_light;
49
+ background-color: $card_light;
50
+
51
+ display: flex;
52
+ justify-content: center;
53
+ align-items: center;
54
+
55
+ svg {
56
+ width: $space_xs + 4;
57
+ height: $space_sm;
58
+ display: flex;
59
+ }
60
+
61
+ &:hover {
62
+ background-color: darken($bg_light, 2%);
63
+ }
64
+
65
+ &:focus-visible {
66
+ border: solid 1px $primary_action;
67
+ box-shadow: unset;
68
+ }
69
+ }
70
+
71
+ .map-flyto-button {
72
+ border-radius: $border_radius_md;
73
+ margin-top: $space_xs;
74
+ box-shadow: $shadow_deep;
75
+ background-color: $card_light;
76
+ }
77
+ }
78
+
79
+ .maplibregl-popup-content {
80
+ padding: $space_sm;
81
+ background-color: $card_light;
82
+ box-shadow: $shadow_deeper;
83
+ }
84
+
85
+ &.dark {
86
+ .maplibregl-canvas {
87
+ filter: invert(100%) brightness(175%) contrast(80%) sepia(50%) saturate(2)
88
+ hue-rotate(185deg);
89
+ }
90
+
91
+ .pb_section_separator_kit_card_horizontal::after {
92
+ background: $border_dark;
93
+ }
94
+ .custom-nav-control-zoom {
95
+ border: solid 1px #0a0527;
96
+ background: $bg_dark;
97
+ }
98
+
99
+ .maplibregl-popup-content {
100
+ background-color: $bg_dark;
101
+ color: $text_dk_default;
102
+ }
103
+
104
+ .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip,
105
+ .maplibregl-popup-anchor-bottom .maplibregl-popup-tip {
106
+ border-top-color: $bg_dark;
107
+ }
108
+ .map-zoom-in-button,
109
+ .map-zoom-out-button,
110
+ .map-flyto-button {
111
+ color: $text_dk_default;
112
+ background-color: $bg_dark;
113
+ border-color: $border_dark;
114
+
115
+ &:hover {
116
+ background-color: #221e3d;
117
+ }
118
+ }
119
+ }
8
120
  }
@@ -1,8 +1,11 @@
1
1
  import React from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
4
- import { globalProps } from '../utilities/globalProps'
4
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
5
5
 
6
+ import Flex from "../pb_flex/_flex"
7
+ import Icon from '../pb_icon/_icon'
8
+ import Button from '../pb_button/_button'
6
9
 
7
10
  type MapProps = {
8
11
  aria?: { [key: string]: string },
@@ -10,7 +13,12 @@ type MapProps = {
10
13
  className?: string,
11
14
  data?: { [key: string]: string },
12
15
  id?: string,
13
- }
16
+ zoomBtns?: boolean,
17
+ flyTo?: boolean,
18
+ zoomInClick?: () => {},
19
+ zoomOutClick?: () => {},
20
+ flyToClick?: () => {},
21
+ } & GlobalProps
14
22
 
15
23
  const Map = (props: MapProps) => {
16
24
  const {
@@ -19,6 +27,11 @@ const Map = (props: MapProps) => {
19
27
  className,
20
28
  data = {},
21
29
  id,
30
+ zoomBtns = false,
31
+ flyTo = false,
32
+ zoomInClick,
33
+ zoomOutClick,
34
+ flyToClick
22
35
  } = props
23
36
 
24
37
  const ariaProps = buildAriaProps(aria)
@@ -32,6 +45,33 @@ const Map = (props: MapProps) => {
32
45
  className={classes}
33
46
  id={id}
34
47
  >
48
+ {
49
+ zoomBtns ? (
50
+ <Flex className="custom-nav-control" orientation='column'>
51
+ <div className="custom-nav-control-zoom">
52
+ <Button className='map-zoom-in-button'
53
+ onClick={zoomInClick}
54
+ >
55
+ <Icon icon="plus"/>
56
+ </Button>
57
+ <Button className='map-zoom-out-button'
58
+ onClick={zoomOutClick}
59
+ >
60
+ <Icon icon="minus"/>
61
+ </Button>
62
+ </div>
63
+ {
64
+ flyTo ? (
65
+ <Button className='map-flyto-button'
66
+ onClick={flyToClick}
67
+ >
68
+ <Icon icon="eye"/>
69
+ </Button>
70
+ ) : null
71
+ }
72
+ </Flex>
73
+ ) : null
74
+ }
35
75
  {children}
36
76
  </div>
37
77
  )
@@ -1,40 +1,63 @@
1
- import React, { useRef, useEffect } from 'react'
1
+ import React, { useRef, useEffect, useState } from 'react'
2
2
  import { Map } from '../../'
3
-
4
3
  import maplibregl from 'maplibre-gl'
4
+ import mapTheme from '../pbMapTheme'
5
5
 
6
- const MapDefault = () => {
6
+ const MapDefault = (props) => {
7
7
 
8
+ //set Map instance to access from outside useEffect
9
+ const [mapInstance, setMapInstance] = useState(null)
8
10
  const mapContainerRef = useRef(null)
9
11
 
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
- })
12
+ //Set default position
13
+ const defaultPosition = [-75.379143, 39.831200]
14
+
15
+ // linking Maplibre methods to PB custom zoom in, zoom out, and fly to buttons
16
+ const handleZoomIn = (map) => {map.zoomIn({...mapTheme.zoomConfig})}
17
+ const handleZoomOut = (map) => {map.zoomOut({...mapTheme.zoomConfig})}
18
+ const handleFlyTo = (map) => {map.flyTo({
19
+ center: defaultPosition,
20
+ ... mapTheme.flyToConfig
21
+ });}
22
+
23
+ //This function is called by the useEffect when map instance first loads
24
+ const loadMap = ( { target: map }) => {
20
25
  //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
+ new maplibregl.Marker({
27
+ color: mapTheme.marker,
28
+ }).setLngLat(defaultPosition)
29
+ .setPopup(new maplibregl.Popup({closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
26
30
  .addTo(map);
27
31
 
28
- //add zoom controls
29
- map.addControl(new maplibregl.NavigationControl({showCompass: false}))
30
-
31
32
  // disable map zoom when using scroll
32
33
  map.scrollZoom.disable();
34
+
35
+ //add attributioncontrols
36
+ map.addControl(new maplibregl.AttributionControl({
37
+ compact: true
38
+ }));
39
+
40
+ //set map instance
41
+ setMapInstance(map)
42
+ }
43
+
44
+ useEffect(() => {
45
+ new maplibregl.Map({
46
+ container: mapContainerRef.current,
47
+ center: defaultPosition,
48
+ ...mapTheme.mapConfig
49
+ }).on('load', loadMap)
33
50
 
34
- }
35
51
  }, [])
52
+
36
53
  return (
37
- <Map>
54
+ <Map flyTo
55
+ flyToClick={()=> {handleFlyTo(mapInstance)}}
56
+ zoomBtns
57
+ zoomInClick={() => {handleZoomIn(mapInstance)}}
58
+ zoomOutClick={()=> {handleZoomOut(mapInstance)}}
59
+ {...props}
60
+ >
38
61
  <div
39
62
  ref={mapContainerRef}
40
63
  style={{
@@ -44,7 +67,7 @@ return (
44
67
  top: 0,
45
68
  bottom: 0,
46
69
  }}
47
- />
70
+ />
48
71
  </Map>
49
72
  )
50
73
  }
@@ -2,12 +2,12 @@ This kit provides a wrapping class to place around the MapLibre library. Complet
2
2
 
3
3
  Basic setup to start using MapLibre:
4
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.
5
+ - To include the maplibre css, include a link to the CSS file as a CDN in your stylesheet using the following syntax: `@import url("https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css");`
6
+ 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' />`
9
7
  - You can now use MapLibre within the Map Kit as shown in this example.
10
8
 
11
9
  __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.
10
+ - To enable custom buttons, set `zoomBtns` and `flyTo` to true and pass in `zoomInClick`, `zoomOutClick` and `flyToClick` as shown in this doc example.
11
+ - Use `mapTheme.marker` to set the Marker color.
12
+ - To use Maplibre, you must also set a height and width to the containing div (.pb_map) and set position to 'relative'.
13
13
  - `scrollZoom` has been disabled in these doc examples for page usability
@@ -2,30 +2,26 @@ import React, { useRef, useEffect } from 'react'
2
2
  import { Map } from '../../'
3
3
  import maplibregl from 'maplibre-gl'
4
4
  import MapboxDraw from "@mapbox/mapbox-gl-draw";
5
+ import mapTheme from '../pbMapTheme'
5
6
 
6
- const MapWithPlugin = () => {
7
+ const MapWithPlugin = (props) => {
8
+ //set Map instance to access from outside useEffect
9
+ const mapContainerRef = useRef(null)
7
10
 
8
- const mapContainerRef = useRef(null)
11
+ //Set default position
12
+ const defaultPosition = [-75.379143, 39.831200]
9
13
 
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
- })
14
+ //This function should contain all maplibre related code
15
+ const loadMap = ( { target: map }) => {
20
16
  //set marker/pin
21
17
  /* eslint-disable-next-line */
22
18
  const marker = new maplibregl.Marker({
23
- color: "#0056CF",
24
- }).setLngLat([-75.379143, 39.831200])
19
+ color: mapTheme.marker,
20
+ }).setLngLat(defaultPosition)
25
21
  .setPopup(new maplibregl.Popup({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_4">Hello World!</h4>`)) // add popup
26
22
  .addTo(map);
27
23
 
28
- //add zoom controls
24
+ //add maplibre default zoom controls
29
25
  map.addControl(new maplibregl.NavigationControl({showCompass: false}))
30
26
 
31
27
  // disable map zoom when using scroll
@@ -40,13 +36,20 @@ const MapWithPlugin = () => {
40
36
  }
41
37
  });
42
38
  map.addControl(draw);
43
- }
39
+ }
40
+
41
+ useEffect(() => {
42
+ new maplibregl.Map({
43
+ container: mapContainerRef.current,
44
+ center: [-75.379143, 39.831200],
45
+ ...mapTheme.mapConfig
46
+ }).on('load', loadMap)
44
47
  }, [])
45
48
 
46
49
 
47
50
 
48
51
  return (
49
- <Map>
52
+ <Map {...props} >
50
53
  <div
51
54
  ref={mapContainerRef}
52
55
  style={{
@@ -4,4 +4,3 @@ examples:
4
4
  react:
5
5
  - map_default: Default
6
6
  - map_with_plugin: Map With Polygon Draw Plugin
7
-
@@ -0,0 +1,23 @@
1
+ import colors from '../tokens/exports/_colors.scss'
2
+
3
+ const mapTheme = {
4
+ marker : colors.primary_action,
5
+ maptiles: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
6
+ flyToConfig: {
7
+ zoom: 13,
8
+ bearing: 0,
9
+ curve: 1.42, // change the speed at which it zooms
10
+ easing: function (t: any) {
11
+ return t;
12
+ },
13
+ essential: true
14
+ },
15
+ zoomConfig: { duration:1000 },
16
+ mapConfig: {
17
+ style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
18
+ zoom: 13,
19
+ attributionControl: false,
20
+ }
21
+ }
22
+
23
+ export default mapTheme
@@ -13,11 +13,11 @@ import Timestamp from '../pb_timestamp/_timestamp'
13
13
  import Title from '../pb_title/_title'
14
14
 
15
15
  type MessageProps = {
16
- aria: object,
16
+ aria: { [key: string]: string },
17
17
  avatarName?: string,
18
- avatarStatus?: string,
18
+ avatarStatus?: "away" | "offline" | "online",
19
19
  avatarUrl?: string,
20
- children?: array<React.ReactNode> | React.ReactNode,
20
+ children?: React.ReactChild[] | React.ReactChild,
21
21
  className?: string,
22
22
  data?: object,
23
23
  id?: string,
@@ -61,53 +61,53 @@ const Message = (props: MessageProps) => {
61
61
 
62
62
  return (
63
63
  <div
64
- {...ariaProps}
65
- {...dataProps}
66
- className={classes}
67
- id={id}
64
+ {...ariaProps}
65
+ {...dataProps}
66
+ className={classes}
67
+ id={id}
68
68
  >
69
- <If condition={shouldDisplayAvatar}>
69
+ {shouldDisplayAvatar &&
70
70
  <Avatar
71
- imageUrl={avatarUrl}
72
- name={avatarName}
73
- size="xs"
74
- status={avatarStatus}
71
+ imageUrl={avatarUrl}
72
+ name={avatarName}
73
+ size="xs"
74
+ status={avatarStatus}
75
75
  />
76
- </If>
76
+ }
77
77
  <div className="content_wrapper">
78
78
  <Flex
79
- justify={alignTimestamp === 'left' ? 'none' : 'between'}
80
- orientation="row"
79
+ justify={alignTimestamp === 'left' ? 'none' : 'between'}
80
+ orientation="row"
81
81
  >
82
- <If condition={label}>
82
+ {label &&
83
83
  <Title
84
- className="message_title"
85
- size={4}
86
- text={label}
84
+ className="message_title"
85
+ size={4}
86
+ text={label}
87
87
  />
88
- </If>
88
+ }
89
89
  <Timestamp
90
- className={`pull-${alignTimestamp} ${timestampObject ? 'message_humanized_time' : null}`}
91
- text={timestamp}
92
- timezone={timezone}
90
+ className={`pull-${alignTimestamp} ${timestampObject ? 'message_humanized_time' : null}`}
91
+ text={timestamp}
92
+ timestamp={''}
93
+ timezone={timezone}
93
94
  />
94
- <If condition={timestampObject}>
95
+ {timestampObject &&
95
96
  <Timestamp
96
- className={`pull-${alignTimestamp} message_timestamp`}
97
- timestamp={timestampObject}
98
- timezone={timezone}
97
+ className={`pull-${alignTimestamp} message_timestamp`}
98
+ text={''}
99
+ timestamp={timestampObject}
100
+ timezone={timezone}
99
101
  />
100
- </If>
102
+ }
101
103
  </Flex>
102
- <If condition={message}>
104
+ {message &&
103
105
  <Body
104
- className="pb_message_body"
105
- text={message}
106
+ className="pb_message_body"
107
+ text={message}
106
108
  />
107
- </If>
108
- <If condition={children}>
109
- { children }
110
- </If>
109
+ }
110
+ {children}
111
111
  </div>
112
112
  </div>
113
113
  )
@@ -0,0 +1,63 @@
1
+ import React from 'react'
2
+ import { render, screen } from '../utilities/test-utils'
3
+ import Message from './_message'
4
+ import Image from './../pb_image/_image'
5
+
6
+ const testId = "message"
7
+
8
+ const MessageDefault = () => {
9
+ return (
10
+ <>
11
+ <Message
12
+ avatarName="Becca Jacobs"
13
+ avatarUrl="https://randomuser.me/api/portraits/women/50.jpg"
14
+ className='custom-class'
15
+ data={{ testid: testId }}
16
+ label="Lucille Sanchez"
17
+ message="Application for Kate Smith is waiting for your approval"
18
+ timestamp="2 days ago"
19
+ >
20
+ <Image
21
+ alt="picture of a misty forest"
22
+ size="md"
23
+ url="https://unsplash.it/500/400/?image=634"
24
+ />
25
+ </Message>
26
+ </>
27
+ )
28
+ }
29
+
30
+ test('should render message', () => {
31
+ render(<MessageDefault />)
32
+
33
+ const kit = screen.getByText('Application for Kate Smith is waiting for your approval')
34
+ expect(kit).toBeInTheDocument()
35
+ })
36
+
37
+ test('should render label', () => {
38
+ render(<MessageDefault />)
39
+
40
+ const kit = screen.getByText('Lucille Sanchez')
41
+ expect(kit).toBeInTheDocument()
42
+ })
43
+
44
+ test('should render timestamp', () => {
45
+ render(<MessageDefault />)
46
+
47
+ const kit = screen.getByText('2 days ago')
48
+ expect(kit).toBeInTheDocument()
49
+ })
50
+
51
+ test('should render custom class and data', () => {
52
+ render(<MessageDefault />)
53
+
54
+ const kit = screen.getByTestId(testId)
55
+ expect(kit).toHaveClass('custom-class')
56
+ })
57
+
58
+ test('should render a children', () => {
59
+ render(<MessageDefault />)
60
+
61
+ const kit = screen.getByAltText('picture of a misty forest')
62
+ expect(kit).toBeInTheDocument()
63
+ })
@@ -15,7 +15,7 @@ import PbReactPopover from '../pb_popover/_popover'
15
15
  import TextInput from '../pb_text_input/_text_input'
16
16
 
17
17
  type PassphraseProps = {
18
- aria?: object,
18
+ aria?: { [key: string]: string },
19
19
  confirmation?: boolean,
20
20
  className?: string,
21
21
  data?: object,
@@ -23,7 +23,7 @@ type PassphraseProps = {
23
23
  id?: string,
24
24
  inputProps?: {},
25
25
  label?: string,
26
- onChange: (String) => void,
26
+ onChange: (inputValue: String) => void,
27
27
  showTipsBelow?: "always" | "xs" | "sm" | "md" | "lg" | "xl",
28
28
  tips?: Array<string>,
29
29
  uncontrolled?: boolean,
@@ -40,7 +40,7 @@ const Passphrase = (props: PassphraseProps) => {
40
40
  id,
41
41
  inputProps = {},
42
42
  label = confirmation ? "Confirm Passphrase" : "Passphrase",
43
- onChange = () => {},
43
+ onChange = () => { },
44
44
  showTipsBelow = "always",
45
45
  tips = [],
46
46
  uncontrolled = false,
@@ -62,11 +62,11 @@ const Passphrase = (props: PassphraseProps) => {
62
62
  )
63
63
 
64
64
  const toggleShowPopover = () => setShowPopover(!showPopover)
65
- const handleShouldClosePopover = (shouldClosePopover) => {
65
+ const handleShouldClosePopover = (shouldClosePopover: boolean) => {
66
66
  setShowPopover(!shouldClosePopover)
67
67
  }
68
68
 
69
- const toggleShowPassphrase = (e) => {
69
+ const toggleShowPassphrase = (e: React.MouseEvent<HTMLElement>) => {
70
70
  e.preventDefault()
71
71
  setShowPassphrase(!showPassphrase)
72
72
  }
@@ -86,54 +86,54 @@ const Passphrase = (props: PassphraseProps) => {
86
86
 
87
87
  const popoverReference = (
88
88
  <CircleIconButton
89
- className={tipClass}
90
- dark={dark}
91
- icon="info-circle"
92
- onClick={toggleShowPopover}
93
- variant="link"
89
+ className={tipClass}
90
+ dark={dark}
91
+ icon="info-circle"
92
+ onClick={toggleShowPopover}
93
+ variant="link"
94
94
  />
95
95
  )
96
96
 
97
97
  return (
98
- <div
99
- {...ariaProps}
100
- {...dataProps}
101
- className={classes}
102
- id={id}
98
+ <div
99
+ {...ariaProps}
100
+ {...dataProps}
101
+ className={classes}
102
+ id={id}
103
103
  >
104
104
  <label>
105
105
  <Flex align="baseline">
106
- <Caption
107
- className="passphrase-label"
108
- text={label}
106
+ <Caption
107
+ className="passphrase-label"
108
+ text={label}
109
109
  />
110
- <If condition={tips.length > 0 && !confirmation}>
110
+ {tips.length > 0 && !confirmation &&
111
111
  <PbReactPopover
112
- className="passphrase-tips"
113
- closeOnClick="outside"
114
- placement="right"
115
- reference={popoverReference}
116
- shouldClosePopover={handleShouldClosePopover}
117
- show={showPopover}
112
+ className="passphrase-tips"
113
+ closeOnClick="outside"
114
+ placement="right"
115
+ reference={popoverReference}
116
+ shouldClosePopover={handleShouldClosePopover}
117
+ show={showPopover}
118
118
  >
119
- <Flex
120
- align="center"
121
- orientation="column"
119
+ <Flex
120
+ align="center"
121
+ orientation="column"
122
122
  >
123
- <Caption
124
- marginBottom="xs"
125
- text="Tips for a good passphrase"
123
+ <Caption
124
+ marginBottom="xs"
125
+ text="Tips for a good passphrase"
126
126
  />
127
127
  <div>
128
128
  {tips.map((tip, i) => (
129
- <Caption
130
- key={i}
131
- marginBottom="xs"
132
- size="xs"
129
+ <Caption
130
+ key={i}
131
+ marginBottom="xs"
132
+ size="xs"
133
133
  >
134
- <Icon
135
- icon="shield-check"
136
- marginRight="xs"
134
+ <Icon
135
+ icon="shield-check"
136
+ marginRight="xs"
137
137
  />
138
138
  {tip}
139
139
  </Caption>
@@ -141,34 +141,34 @@ const Passphrase = (props: PassphraseProps) => {
141
141
  </div>
142
142
  </Flex>
143
143
  </PbReactPopover>
144
- </If>
144
+ }
145
145
  </Flex>
146
146
  <div className="passphrase-text-input-wrapper">
147
147
  <TextInput
148
- className="passphrase-text-input"
149
- dark={dark}
150
- marginBottom="xs"
151
- onChange={handleChange}
152
- placeholder="Enter a passphrase..."
153
- type={showPassphrase ? "text" : "password"}
154
- value={displayValue}
155
- {...inputProps}
148
+ className="passphrase-text-input"
149
+ dark={dark}
150
+ marginBottom="xs"
151
+ onChange={handleChange}
152
+ placeholder="Enter a passphrase..."
153
+ type={showPassphrase ? "text" : "password"}
154
+ value={displayValue}
155
+ {...inputProps}
156
156
  />
157
- <span
158
- className="show-passphrase-icon"
159
- onClick={toggleShowPassphrase}
157
+ <span
158
+ className="show-passphrase-icon"
159
+ onClick={toggleShowPassphrase}
160
160
  >
161
161
  <Body
162
- className={showPassphrase ? "hide-icon" : ""}
163
- color="light"
164
- dark={dark}
162
+ className={showPassphrase ? "hide-icon" : ""}
163
+ color="light"
164
+ dark={dark}
165
165
  >
166
166
  <Icon icon="eye-slash" />
167
167
  </Body>
168
168
  <Body
169
- className={showPassphrase ? "" : "hide-icon"}
170
- color="light"
171
- dark={dark}
169
+ className={showPassphrase ? "" : "hide-icon"}
170
+ color="light"
171
+ dark={dark}
172
172
  >
173
173
  <Icon icon="eye" />
174
174
  </Body>
@@ -0,0 +1,3 @@
1
+ <%= pb_rails("phone_number_input", props: {
2
+ id: "hello"
3
+ }) %>
@@ -5,3 +5,6 @@ examples:
5
5
  - phone_number_input_preferred_countries: Preferred Countries
6
6
  - phone_number_input_initial_country: Initial Country
7
7
  - phone_number_input_only_countries: Limited Countries
8
+
9
+ rails:
10
+ - phone_number_input_default: Default
@@ -0,0 +1,15 @@
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>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbPhoneNumberInput
5
+ class PhoneNumberInput < Playbook::KitBase
6
+ prop :disabled, type: Playbook::Props::Boolean,
7
+ default: false
8
+ prop :initial_country, type: Playbook::Props::String,
9
+ default: ""
10
+ prop :is_valid
11
+ prop :label, type: Playbook::Props::String,
12
+ default: ""
13
+ prop :name, type: Playbook::Props::String,
14
+ default: ""
15
+ prop :onchange
16
+ prop :only_countries, type: Playbook::Props::Array,
17
+ default: []
18
+ prop :preferred_countries, type: Playbook::Props::Array,
19
+ default: []
20
+ prop :value, type: Playbook::Props::String,
21
+ default: ""
22
+
23
+ def classname
24
+ generate_classname("pb_phone_number_input")
25
+ end
26
+
27
+ def phone_number_input_options
28
+ {
29
+ id: id,
30
+ disabled: disabled,
31
+ initialCountry: initial_country,
32
+ isValid: is_valid,
33
+ label: label,
34
+ name: name,
35
+ onChange: onchange,
36
+ onlyCountries: only_countries,
37
+ preferredCountries: preferred_countries,
38
+ value: value,
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -28,9 +28,9 @@ type PbPopoverProps = {
28
28
  offset?: boolean;
29
29
  reference: PopperReference & any;
30
30
  show?: boolean;
31
- shouldClosePopover?: (arg0: boolean) => boolean | boolean;
32
- } & GlobalProps &
33
- PopperProps<any>;
31
+ shouldClosePopover?: (arg0: boolean) => void;
32
+ } & GlobalProps & Omit<PopperProps<any>, 'children'>
33
+ & { children?: React.ReactChild[] | React.ReactChild }
34
34
 
35
35
  // Prop enabled default modifiers here
36
36
  // https://popper.js.org/docs/v2/modifiers
@@ -8,7 +8,7 @@
8
8
  background-color: $bg_light;
9
9
  }
10
10
  &[class*=checked_item] {
11
- background-color: $bg_light;
11
+ background-color: $active_light;
12
12
  }
13
13
  }
14
14
  [class^=pb_radio_kit] {
@@ -183,6 +183,10 @@
183
183
  }
184
184
 
185
185
  .typeahead-kit-select__menu {
186
+ .typeahead-kit-select__menu-list {
187
+ padding: 0;
188
+ }
189
+
186
190
  .typeahead-kit-select__option {
187
191
  &.typeahead-kit-select__option--is-focused {
188
192
  background-color: $hover_light;
@@ -17,6 +17,7 @@ import Passphrase from './pb_passphrase/_passphrase'
17
17
  import RichTextEditor from './pb_rich_text_editor/_rich_text_editor'
18
18
  import TreemapChart from './pb_treemap_chart/_treemap_chart'
19
19
  import Typeahead from './pb_typeahead/_typeahead'
20
+ import PhoneNumberInput from './pb_phone_number_input/_phone_number_input'
20
21
 
21
22
  WebpackerReact.registerComponents({
22
23
  BarGraph,
@@ -33,6 +34,7 @@ WebpackerReact.registerComponents({
33
34
  TreemapChart,
34
35
  Typeahead,
35
36
  Gauge,
37
+ PhoneNumberInput
36
38
  })
37
39
 
38
40
  ujs.setup(
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- PREVIOUS_VERSION = "12.3.1"
5
- VERSION = "12.4.0"
4
+ PREVIOUS_VERSION = "12.4.0"
5
+ VERSION = "12.5.0"
6
6
  end
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.4.0
4
+ version: 12.5.0
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-02-20 00:00:00.000000000 Z
12
+ date: 2023-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -1379,8 +1379,8 @@ files:
1379
1379
  - app/pb_kits/playbook/pb_list/item.rb
1380
1380
  - app/pb_kits/playbook/pb_list/list.html.erb
1381
1381
  - app/pb_kits/playbook/pb_list/list.rb
1382
- - app/pb_kits/playbook/pb_loading_inline/_loading_inline.jsx
1383
1382
  - app/pb_kits/playbook/pb_loading_inline/_loading_inline.scss
1383
+ - app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx
1384
1384
  - app/pb_kits/playbook/pb_loading_inline/docs/_description.md
1385
1385
  - app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_light.html.erb
1386
1386
  - app/pb_kits/playbook/pb_loading_inline/docs/_loading_inline_light.jsx
@@ -1388,6 +1388,7 @@ files:
1388
1388
  - app/pb_kits/playbook/pb_loading_inline/docs/index.js
1389
1389
  - app/pb_kits/playbook/pb_loading_inline/loading_inline.html.erb
1390
1390
  - app/pb_kits/playbook/pb_loading_inline/loading_inline.rb
1391
+ - app/pb_kits/playbook/pb_loading_inline/loading_inline.test.js
1391
1392
  - app/pb_kits/playbook/pb_logistic/_logistic.jsx
1392
1393
  - app/pb_kits/playbook/pb_map/_map.scss
1393
1394
  - app/pb_kits/playbook/pb_map/_map.tsx
@@ -1398,8 +1399,9 @@ files:
1398
1399
  - app/pb_kits/playbook/pb_map/docs/example.yml
1399
1400
  - app/pb_kits/playbook/pb_map/docs/index.js
1400
1401
  - app/pb_kits/playbook/pb_map/map.test.jsx
1401
- - app/pb_kits/playbook/pb_message/_message.jsx
1402
+ - app/pb_kits/playbook/pb_map/pbMapTheme.ts
1402
1403
  - app/pb_kits/playbook/pb_message/_message.scss
1404
+ - app/pb_kits/playbook/pb_message/_message.tsx
1403
1405
  - app/pb_kits/playbook/pb_message/_message_mixins.scss
1404
1406
  - app/pb_kits/playbook/pb_message/docs/_description.md
1405
1407
  - app/pb_kits/playbook/pb_message/docs/_footer.md
@@ -1412,6 +1414,7 @@ files:
1412
1414
  - app/pb_kits/playbook/pb_message/docs/index.js
1413
1415
  - app/pb_kits/playbook/pb_message/message.html.erb
1414
1416
  - app/pb_kits/playbook/pb_message/message.rb
1417
+ - app/pb_kits/playbook/pb_message/message.test.js
1415
1418
  - app/pb_kits/playbook/pb_multiple_users/_multiple_users.jsx
1416
1419
  - app/pb_kits/playbook/pb_multiple_users/_multiple_users.scss
1417
1420
  - app/pb_kits/playbook/pb_multiple_users/docs/_description.md
@@ -1496,8 +1499,8 @@ files:
1496
1499
  - app/pb_kits/playbook/pb_pagination/docs/example.yml
1497
1500
  - app/pb_kits/playbook/pb_pagination/pagination.html.erb
1498
1501
  - app/pb_kits/playbook/pb_pagination/pagination.rb
1499
- - app/pb_kits/playbook/pb_passphrase/_passphrase.jsx
1500
1502
  - app/pb_kits/playbook/pb_passphrase/_passphrase.scss
1503
+ - app/pb_kits/playbook/pb_passphrase/_passphrase.tsx
1501
1504
  - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.html.erb
1502
1505
  - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.jsx
1503
1506
  - app/pb_kits/playbook/pb_passphrase/docs/_passphrase_breached.md
@@ -1555,6 +1558,7 @@ files:
1555
1558
  - app/pb_kits/playbook/pb_person_contact/person_contact.rb
1556
1559
  - app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss
1557
1560
  - app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx
1561
+ - app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.html.erb
1558
1562
  - app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.jsx
1559
1563
  - app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_default.md
1560
1564
  - app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_initial_country.jsx
@@ -1565,6 +1569,8 @@ files:
1565
1569
  - app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.md
1566
1570
  - app/pb_kits/playbook/pb_phone_number_input/docs/example.yml
1567
1571
  - app/pb_kits/playbook/pb_phone_number_input/docs/index.js
1572
+ - app/pb_kits/playbook/pb_phone_number_input/phone_number_input.html.erb
1573
+ - app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb
1568
1574
  - app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js
1569
1575
  - app/pb_kits/playbook/pb_phone_number_input/types.d.ts
1570
1576
  - app/pb_kits/playbook/pb_pill/_pill.scss
@@ -1,37 +0,0 @@
1
- /* @flow */
2
-
3
- import React from 'react'
4
- import classnames from 'classnames'
5
-
6
- import { globalProps } from '../utilities/globalProps'
7
-
8
- import Body from '../pb_body/_body'
9
- import Icon from '../pb_icon/_icon'
10
- type LoadingInlineProps = {
11
- align?: "left" | "center" | "right",
12
- className?: string,
13
- dark?: boolean,
14
- data?: string,
15
- id?: string,
16
- }
17
-
18
- const LoadingInline = (props: LoadingInlineProps) => {
19
- const { align = 'left' } = props
20
- return (
21
- <div
22
- className={classnames(`pb_loading_inline_kit_${align}`, globalProps(props))}
23
- >
24
- <Body color="light">
25
- <Icon
26
- aria={{ label: 'loading icon' }}
27
- fixedWidth
28
- icon="spinner"
29
- pulse
30
- />
31
- {' Loading'}
32
- </Body>
33
- </div>
34
- )
35
- }
36
-
37
- export default LoadingInline