playbook_ui 9.10.0.pre.alpha1 → 9.12.0.pre.text.addon

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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.jsx +8 -19
  3. data/app/pb_kits/playbook/pb_button/button.rb +5 -3
  4. data/app/pb_kits/playbook/pb_button/docs/_button_accessibility.html.erb +1 -1
  5. data/app/pb_kits/playbook/pb_button/docs/_button_accessibility.jsx +1 -1
  6. data/app/pb_kits/playbook/pb_button/docs/_button_link.html.erb +3 -3
  7. data/app/pb_kits/playbook/pb_button/docs/_button_link.jsx +3 -0
  8. data/app/pb_kits/playbook/pb_button/docs/_button_loading.html.erb +3 -3
  9. data/app/pb_kits/playbook/pb_button/docs/_button_loading.jsx +3 -0
  10. data/app/pb_kits/playbook/pb_passphrase/useZxcvbn.js +3 -3
  11. data/app/pb_kits/playbook/pb_table/docs/_table_side_highlight.md +1 -1
  12. data/app/pb_kits/playbook/pb_text_input/_text_input.jsx +80 -31
  13. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +98 -0
  14. data/app/pb_kits/playbook/pb_text_input/add_on.html.erb +13 -0
  15. data/app/pb_kits/playbook/pb_text_input/add_on.rb +30 -0
  16. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_add_on.html.erb +24 -0
  17. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_add_on.jsx +82 -0
  18. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_custom.html.erb +1 -1
  19. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +2 -0
  20. data/app/pb_kits/playbook/pb_text_input/docs/index.js +1 -0
  21. data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +7 -16
  22. data/app/pb_kits/playbook/pb_text_input/text_input.rb +36 -2
  23. data/lib/playbook/props.rb +1 -0
  24. data/lib/playbook/props/nested_props.rb +23 -0
  25. data/lib/playbook/version.rb +1 -1
  26. metadata +24 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b36c79f834fafef501c48ece8fc72990708ab4323f3c172527d9a9a31bb9fa4
4
- data.tar.gz: ddc237d11376abb37c4e0d8630fbf06f4f2510dd0bdadefebc364bdf4b4e735a
3
+ metadata.gz: f94c4155e43cfcdf17c58b5afce6b032c570576aff59506dc1751cb4f0763010
4
+ data.tar.gz: 24b67df04fa47777d4c4f8ec6d43c648e61e7b1f2325c15acd4b125045d45012
5
5
  SHA512:
6
- metadata.gz: 71667f6a96f25e9fee0bd7d741b38c09eeced8c397c1126fafc1b3525b984d6a717e6332d2690818df67c0eb7da370429bbc50481f17c820256121d9972f48ae
7
- data.tar.gz: 953083fe2726a16fbbd33b7b550c1136230b6dec1043e0fd4f3c6ed47c52249c47b98a9da5e889cec15c05b11a42257f32cc1824d62e6109a8ad0009c1824f5e
6
+ metadata.gz: f5bd3d916766662441b2e5ca737747554866e2ee519669bdb557da95faccab27a5dcaf1f28b8fa1764cdf5b5687f9972739323e2b97e8aa1bc3516893eb1e4a1
7
+ data.tar.gz: c4ae6e848dbea60dcc6e6b990579223d65c10fb6fc1b30ceb22769e3d4c95d24338b4086cde2464743db270be9330fc4950cc3b801d0671894e8dac87f1a25e5
@@ -2,16 +2,14 @@
2
2
 
3
3
  import React from 'react'
4
4
  import classnames from 'classnames'
5
- import { buildDataProps } from '../utilities/props'
5
+ import { buildAriaProps, buildDataProps } from '../utilities/props'
6
6
  import { globalProps } from '../utilities/globalProps.js'
7
7
 
8
8
  import Icon from '../pb_icon/_icon.jsx'
9
9
 
10
10
  type EventHandler = (SyntheticInputEvent<HTMLInputElement>) => void
11
11
  type ButtonPropTypes = {
12
- aria?: {
13
- label: string,
14
- },
12
+ aria?: object,
15
13
  children?: array<React.ReactChild>,
16
14
  className?: string | array<string>,
17
15
  data?: object,
@@ -55,20 +53,9 @@ const buttonClassName = (props: ButtonPropTypes) => {
55
53
  return className
56
54
  }
57
55
 
58
- const buttonAriaProps = (props: ButtonPropTypes) => {
59
- const { aria } = props
60
- if (typeof aria !== 'object') return {}
61
- const { label } = aria
62
-
63
- const ariaProps = {}
64
-
65
- if (label !== null) ariaProps['aria-label'] = label
66
-
67
- return ariaProps
68
- }
69
-
70
56
  const Button = (props: ButtonPropTypes) => {
71
57
  const {
58
+ aria = {},
72
59
  children,
73
60
  className,
74
61
  data = {},
@@ -84,7 +71,7 @@ const Button = (props: ButtonPropTypes) => {
84
71
  value,
85
72
  } = props
86
73
 
87
- const buttonAria = buttonAriaProps(props)
74
+ const ariaProps = buildAriaProps(aria)
88
75
  const dataProps = buildDataProps(data)
89
76
  const css = classnames(
90
77
  buttonClassName(props),
@@ -114,11 +101,12 @@ const Button = (props: ButtonPropTypes) => {
114
101
  return (
115
102
  <If condition={link !== null}>
116
103
  <a
117
- {...buttonAria}
104
+ {...ariaProps}
118
105
  {...dataProps}
119
106
  className={css}
120
107
  href={link}
121
108
  id={id}
109
+ role="link"
122
110
  target={newWindow ? '_blank' : null}
123
111
  >
124
112
  <If condition={loading}>{loadingIcon}</If>
@@ -126,12 +114,13 @@ const Button = (props: ButtonPropTypes) => {
126
114
  </a>
127
115
  <Else />
128
116
  <button
129
- {...buttonAria}
117
+ {...ariaProps}
130
118
  {...dataProps}
131
119
  className={css}
132
120
  disabled={disabled}
133
121
  id={id}
134
122
  onClick={onClick}
123
+ role="button"
135
124
  type={htmlType}
136
125
  value={value}
137
126
  >
@@ -21,11 +21,12 @@ module Playbook
21
21
 
22
22
  def options
23
23
  {
24
- id: id,
25
- data: data,
24
+ aria: aria,
26
25
  class: classname,
26
+ data: data,
27
27
  disabled: disabled,
28
- aria: aria,
28
+ id: id,
29
+ role: "button",
29
30
  type: type,
30
31
  value: value,
31
32
  }.compact
@@ -34,6 +35,7 @@ module Playbook
34
35
  def link_options
35
36
  options.merge(
36
37
  href: link,
38
+ role: "link",
37
39
  target: new_window ? "_blank" : "_self"
38
40
  )
39
41
  end
@@ -1 +1 @@
1
- <%= pb_rails("button", props: { text: "Button with ARIA", aria: {label: "button"}, tag: "a", link: "http://google.com" }) %>
1
+ <%= pb_rails("button", props: { text: "Button with ARIA", aria: {label: "Go to Google"}, tag: "a", link: "http://google.com" }) %>
@@ -4,7 +4,7 @@ import { Button } from '../../'
4
4
  const ButtonAccessibility = (props) => (
5
5
  <div>
6
6
  <Button
7
- aria={{ label: 'button' }}
7
+ aria={{ label: 'Go to Google' }}
8
8
  link="https://google.com"
9
9
  tag="a"
10
10
  text="Button with ARIA"
@@ -1,3 +1,3 @@
1
- <%= pb_rails("button", props: { text: "A Tag Button", tag: "a", link: "http://google.com" }) %>
2
- <%= pb_rails("button", props: { text: "Open in new Window", new_window: true, link: "http://google.com" }) %>
3
- <%= pb_rails("button", props: { text: "A Tag Button Disabled", disabled: true, link: "http://google.com" }) %>
1
+ <%= pb_rails("button", props: { text: "A Tag Button", aria: { label: "Link to Google" }, tag: "a", link: "http://google.com" }) %>
2
+ <%= pb_rails("button", props: { text: "Open in new Window", aria: { label: "Link to Google in new window" }, new_window: true, link: "http://google.com" }) %>
3
+ <%= pb_rails("button", props: { text: "A Tag Button Disabled", aria: { label: "Disabled link to Google" }, disabled: true, link: "http://google.com" }) %>
@@ -4,12 +4,14 @@ import { Button } from '../../'
4
4
  const ButtonLink = (props) => (
5
5
  <div>
6
6
  <Button
7
+ aria={{ label: 'Link to Google' }}
7
8
  link="https://google.com"
8
9
  text="A Tag Button"
9
10
  {...props}
10
11
  />
11
12
  {' '}
12
13
  <Button
14
+ aria={{ label: 'Link to Google in new window' }}
13
15
  link="https://google.com"
14
16
  newWindow
15
17
  text="Open in New Window"
@@ -17,6 +19,7 @@ const ButtonLink = (props) => (
17
19
  />
18
20
  {' '}
19
21
  <Button
22
+ aria={{ label: 'Disabled link to Google' }}
20
23
  disabled
21
24
  link="https://google.com"
22
25
  text="A Tag Button Disabled"
@@ -1,3 +1,3 @@
1
- <%= pb_rails("button", props: { text: "Button Primary", loading: true }) %>
2
- <%= pb_rails("button", props: { text: "Button Primary", variant: "secondary", loading: true }) %>
3
- <%= pb_rails("button", props: { text: "Button Primary", variant: "link", loading: true }) %>
1
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", loading: true }) %>
2
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", variant: "secondary", loading: true }) %>
3
+ <%= pb_rails("button", props: { aria: { label: "Loading" }, text: "Button Primary", variant: "link", loading: true }) %>
@@ -4,12 +4,14 @@ import { Button } from '../../'
4
4
  const ButtonLoading = (props) => (
5
5
  <div>
6
6
  <Button
7
+ aria={{ label: 'Loading' }}
7
8
  loading
8
9
  text="Button Primary"
9
10
  {...props}
10
11
  />
11
12
  {' '}
12
13
  <Button
14
+ aria={{ label: 'Loading' }}
13
15
  loading
14
16
  text="Button Secondary"
15
17
  variant="secondary"
@@ -17,6 +19,7 @@ const ButtonLoading = (props) => (
17
19
  />
18
20
  {' '}
19
21
  <Button
22
+ aria={{ label: 'Loading' }}
20
23
  loading
21
24
  text="A Tag Button Disabled"
22
25
  variant="link"
@@ -15,9 +15,9 @@ export default function useZxcvbn(options) {
15
15
 
16
16
  useEffect(() => {
17
17
  if (confirmation) return
18
-
19
- setResult(calculator(passphrase))
20
- const str = result.score
18
+ const newResult = calculator(passphrase)
19
+ setResult(newResult)
20
+ const str = newResult.score
21
21
 
22
22
  const noPassphrase = passphrase.length <= 0
23
23
  const commonPassphrase = common || isPwned
@@ -1,3 +1,3 @@
1
- Side highlight can take product, status, and category colors. To view full list of colors, visit <a href="https://playbook.powerapp.cloud/utilities" target="_blank">token colors</a>.
1
+ Side highlight can take product, status, and category colors. To view full list of colors, visit <a href="https://playbook.powerapp.cloud/visual_guidelines" target="_blank">token colors</a>.
2
2
 
3
3
  Note: Only use category colors for categories. Do not mix it with product or status colors.
@@ -1,13 +1,10 @@
1
1
  /* @flow */
2
2
  import React, { forwardRef } from 'react'
3
3
  import classnames from 'classnames'
4
- import { Body, Caption } from '../'
4
+ import { Body, Caption, Card, Flex, Icon } from '../'
5
5
  import { globalProps } from '../utilities/globalProps.js'
6
6
 
7
- import {
8
- buildAriaProps,
9
- buildDataProps,
10
- } from '../utilities/props'
7
+ import { buildAriaProps, buildDataProps } from '../utilities/props'
11
8
 
12
9
  type TextInputProps = {
13
10
  aria?: object,
@@ -25,12 +22,14 @@ type TextInputProps = {
25
22
  type: string,
26
23
  value: string | number,
27
24
  children: Node,
25
+ addOn?: {
26
+ icon?: string,
27
+ alignment?: "right" | "left",
28
+ border?: boolean,
29
+ },
28
30
  }
29
31
 
30
- const TextInput = (
31
- props: TextInputProps,
32
- ref: React.ElementRef<"input">
33
- ) => {
32
+ const TextInput = (props: TextInputProps, ref: React.ElementRef<"input">) => {
34
33
  const {
35
34
  aria = {},
36
35
  className,
@@ -47,16 +46,78 @@ const TextInput = (
47
46
  type = 'text',
48
47
  value = '',
49
48
  children = null,
49
+ addOn = { icon: null, alignment: 'right', border: true },
50
50
  } = props
51
51
 
52
52
  const ariaProps = buildAriaProps(aria)
53
53
  const dataProps = buildDataProps(data)
54
+
55
+ const { alignment, border, icon } = addOn
56
+ const addOnAlignment = alignment === 'left' ? 'left' : 'right'
57
+ const borderToChange = addOnAlignment === 'left' ? 'right' : 'left'
58
+ const borderToggle = border === false ? 'off' : 'on'
59
+ const borderCss = `border_${borderToChange}_${borderToggle}`
60
+
61
+ const shouldShowAddOn = icon !== null
62
+ const addOnCss = shouldShowAddOn ? 'text_input_wrapper_add_on' : null
63
+ const addOnDarkModeCardCss = (shouldShowAddOn && dark) ? 'add-on-card-dark' : null
54
64
  const css = classnames([
55
65
  'pb_text_input_kit',
56
66
  error ? 'error' : null,
57
67
  globalProps(props),
58
68
  className,
59
69
  ])
70
+ const addOnIcon = (
71
+ <Icon
72
+ className="add-on-icon"
73
+ dark={dark}
74
+ fixedWidth={false}
75
+ icon={icon}
76
+ />
77
+ )
78
+ const textInput = (
79
+ <input
80
+ {...props}
81
+ className="text_input"
82
+ disabled={disabled}
83
+ id={id}
84
+ name={name}
85
+ onChange={onChange}
86
+ placeholder={placeholder}
87
+ ref={ref}
88
+ required={required}
89
+ type={type}
90
+ value={value}
91
+ />
92
+ )
93
+
94
+ const addOnInput = (
95
+ <React.Fragment>
96
+ <Flex
97
+ className={`add-on-${addOnAlignment} ${borderCss}`}
98
+ inline="flex-container"
99
+ vertical="center"
100
+ >
101
+ <If condition={addOnAlignment == 'left'}>
102
+ <Card
103
+ className={`${addOnDarkModeCardCss} add-on-card card-left-aligned`}
104
+ dark={dark}
105
+ >
106
+ {addOnIcon}
107
+ </Card>
108
+ {textInput}
109
+ <Else />
110
+ {textInput}
111
+ <Card
112
+ className={`${addOnDarkModeCardCss} add-on-card card-right-aligned`}
113
+ dark={dark}
114
+ >
115
+ {addOnIcon}
116
+ </Card>
117
+ </If>
118
+ </Flex>
119
+ </React.Fragment>
120
+ )
60
121
 
61
122
  return (
62
123
  <div
@@ -69,29 +130,17 @@ const TextInput = (
69
130
  dark={dark}
70
131
  text={label}
71
132
  />
72
- <div className="text_input_wrapper">
73
- <If condition={children}>
74
- {children}
75
- <Else />
76
- <input
77
- {...props}
78
- className="text_input"
79
- disabled={disabled}
80
- id={id}
81
- name={name}
82
- onChange={onChange}
83
- placeholder={placeholder}
84
- ref={ref}
85
- required={required}
86
- type={type}
87
- value={value}
133
+ <div className={`${addOnCss} text_input_wrapper`}>
134
+ <Choose>
135
+ <When condition={children}>{children}</When>
136
+ <When condition={shouldShowAddOn}>{addOnInput}</When>
137
+ <Otherwise>{textInput}</Otherwise>
138
+ </Choose>
139
+ <If condition={error}>
140
+ <Body
141
+ status="negative"
142
+ text={error}
88
143
  />
89
- <If condition={error}>
90
- <Body
91
- status="negative"
92
- text={error}
93
- />
94
- </If>
95
144
  </If>
96
145
  </div>
97
146
  </div>
@@ -36,6 +36,16 @@
36
36
  }
37
37
  }
38
38
  &.dark {
39
+ .add_on_left {
40
+ .text_input {
41
+ border-left: 0;
42
+ }
43
+ }
44
+ .add_on_right {
45
+ .text_input {
46
+ border-right: 0;
47
+ }
48
+ }
39
49
  .text_input_wrapper {
40
50
  margin-bottom: 1rem;
41
51
  input::placeholder,
@@ -80,3 +90,91 @@
80
90
  }
81
91
  }
82
92
  }
93
+
94
+ .text_input_wrapper_add_on {
95
+ & > [class^=pb_text_input_kit]:not(:last-child) {
96
+ .text_input_wrapper_add_on input, [class^=pb_text_input_kit] .text_input_wrapper_add_on .text_input {
97
+ border-bottom-right-radius: 0;
98
+ border-top-right-radius: 0;
99
+ border-right-width: 0;
100
+ }
101
+ }
102
+ .section-separator span {
103
+ padding: 0;
104
+ }
105
+
106
+ .add-on {
107
+ &-card {
108
+ height: 45px;
109
+ margin: 0;
110
+ padding: 0 !important;
111
+ align-items: center;
112
+ justify-content: center;
113
+ width: 45px;
114
+ }
115
+ &-icon {
116
+ color: $text_lt_lighter;
117
+ }
118
+ &-card-dark {
119
+ background-color: $bg-dark;
120
+ }
121
+ &-left {
122
+ .text_input {
123
+ border-top-left-radius: 0 !important;
124
+ border-bottom-left-radius: 0 !important;
125
+ }
126
+ }
127
+
128
+ &-right {
129
+ .text_input{
130
+ border-top-right-radius: 0 !important;
131
+ border-bottom-right-radius: 0 !important;
132
+ }
133
+ }
134
+ }
135
+ .text_input:focus ~ .add-on-card-dark {
136
+ background-color: $focus_input_dark;
137
+ border-width: 0px;
138
+ }
139
+
140
+ .card-left-aligned {
141
+ border-top-right-radius: 0 !important;
142
+ border-bottom-right-radius: 0 !important;
143
+ }
144
+
145
+ .card-right-aligned {
146
+ border-top-left-radius: 0 !important;
147
+ border-bottom-left-radius: 0 !important;
148
+ }
149
+
150
+ .border {
151
+ &_right_off {
152
+ .card-left-aligned {
153
+ border-right: 0;
154
+ }
155
+ .text_input {
156
+ border-left: 0 !important;
157
+ padding-left: 0 !important;
158
+ }
159
+ }
160
+ &_left_on {
161
+ .card-right-aligned {
162
+ border-left: 0;
163
+ }
164
+ }
165
+ &_right_on {
166
+ .card-left-aligned {
167
+ border-right: 0;
168
+ }
169
+ }
170
+ &_left_off {
171
+ .card-right-aligned {
172
+ border-left: 0;
173
+ }
174
+ .text_input {
175
+ border-right: 0 !important;
176
+ padding-right: 0 !important;
177
+ }
178
+ }
179
+ }
180
+ }
@@ -0,0 +1,13 @@
1
+ <%= pb_rails("flex", props: { classname: "add-on-#{alignment} #{border_css}", vertical: "center"}) do %>
2
+ <% if left_aligned? %>
3
+ <%= pb_rails("card", props: {classname: "#{dark_mode_css} add-on-card card-left-aligned", dark: dark}) do %>
4
+ <%= pb_rails("icon", props: { icon: icon, classname: "add-on-icon", fixed_width: false, dark: dark }) %>
5
+ <% end %>
6
+ <%= content %>
7
+ <% else %>
8
+ <%= content %>
9
+ <%= pb_rails("card", props: {classname: "#{dark_mode_css} add-on-card card-right-aligned", dark: dark}) do %>
10
+ <%= pb_rails("icon", props: { icon: icon, classname: "add-on-icon", fixed_width: false, dark: dark }) %>
11
+ <% end %>
12
+ <% end %>
13
+ <% end %>
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbTextInput
5
+ class AddOn < Playbook::KitBase
6
+ prop :icon, type: Playbook::Props::String, required: true
7
+ prop :alignment, type: Playbook::Props::Enum, values: %w[right left], default: "right"
8
+ prop :border, type: Playbook::Props::Boolean, default: true
9
+
10
+ def border_css
11
+ border_toggle = border ? "on" : "off"
12
+ border_to_change = if alignment == "left"
13
+ "right"
14
+ else
15
+ "left"
16
+ end
17
+
18
+ "border_#{border_to_change}_#{border_toggle}"
19
+ end
20
+
21
+ def left_aligned?
22
+ alignment == "left"
23
+ end
24
+
25
+ def dark_mode_css
26
+ dark ? "add-on-card-dark" : nil
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ <%= pb_rails("text_input", props: {
2
+ label: "Add On With Defaults",
3
+ add_on: { icon: "bat" }
4
+ }) %>
5
+
6
+ <%= pb_rails("text_input", props: {
7
+ label: "Right-Aligned Add On With Border",
8
+ add_on: { icon: "user", alignment: 'right', border: true }
9
+ }) %>
10
+
11
+ <%= pb_rails("text_input", props: {
12
+ label: "Left-Aligned Add On With No Border",
13
+ add_on: { icon: "percent", alignment: 'left', border: false }
14
+ }) %>
15
+
16
+ <%= pb_rails("text_input", props: {
17
+ label: "Left-Aligned Add On With Border",
18
+ add_on: { icon: "user", alignment: 'left', border: true }
19
+ }) %>
20
+
21
+ <%= pb_rails("text_input", props: {
22
+ label: "Right-Aligned Add On With No Border",
23
+ add_on: { icon: "percent", alignment: 'right', border: false }
24
+ }) %>
@@ -0,0 +1,82 @@
1
+ import React, { useState } from 'react'
2
+ import { TextInput } from '../../'
3
+
4
+ const TextInputAddOn = (props) => {
5
+ const [defaultInput, setDefaultInput] = useState('')
6
+ const [firstInput, setFirstInput] = useState('')
7
+ const [secondInput, setSecondInput] = useState('')
8
+ const [thirdInput, setThirdInput] = useState('')
9
+ const [fourthInput, setFourthInput] = useState('')
10
+
11
+ const handleUpdateDefaultInput = ({ target }) => {
12
+ setDefaultInput(target.value)
13
+ }
14
+
15
+ const handleUpdateFirstInput = ({ target }) => {
16
+ setFirstInput(target.value)
17
+ }
18
+
19
+ const handleUpdateSecondInput = ({ target }) => {
20
+ setSecondInput(target.value)
21
+ }
22
+
23
+ const handleUpdateThirdInput = ({ target }) => {
24
+ setThirdInput(target.value)
25
+ }
26
+
27
+ const handleUpdateFourthInput = ({ target }) => {
28
+ setFourthInput(target.value)
29
+ }
30
+
31
+ return (
32
+ <>
33
+ <div>
34
+ <TextInput
35
+ addOn={{ icon: 'bat' }}
36
+ label="Add On With Defaults"
37
+ onChange={handleUpdateDefaultInput}
38
+ value={defaultInput}
39
+ {...props}
40
+ />
41
+ </div>
42
+ <div>
43
+ <TextInput
44
+ addOn={{ icon: 'user', alignment: 'right', border: true }}
45
+ label="Right-Aligned Add On With Border"
46
+ onChange={handleUpdateFirstInput}
47
+ value={firstInput}
48
+ {...props}
49
+ />
50
+ </div>
51
+ <div>
52
+ <TextInput
53
+ addOn={{ icon: 'percent', alignment: 'left', border: false }}
54
+ label="Left-Aligned Add On With No Border"
55
+ onChange={handleUpdateSecondInput}
56
+ value={secondInput}
57
+ {...props}
58
+ />
59
+ </div>
60
+ <div>
61
+ <TextInput
62
+ addOn={{ icon: 'percent', alignment: 'right', border: false }}
63
+ label="Right-Aligned Add On With No Border"
64
+ onChange={handleUpdateThirdInput}
65
+ value={thirdInput}
66
+ {...props}
67
+ />
68
+ </div>
69
+ <div>
70
+ <TextInput
71
+ addOn={{ icon: 'percent', alignment: 'left', border: true }}
72
+ label="Left-Aligned Add On With Border"
73
+ onChange={handleUpdateFourthInput}
74
+ value={fourthInput}
75
+ {...props}
76
+ />
77
+ </div>
78
+ </>
79
+ )
80
+ }
81
+
82
+ export default TextInputAddOn
@@ -1,3 +1,3 @@
1
1
  <%= pb_rails("text_input", props: {label: "Custom Input"}) do %>
2
2
  <input placeholder="Custom placeholder" name="custom-name"></input>
3
- <% end %>
3
+ <% end %>
@@ -4,8 +4,10 @@ examples:
4
4
  - text_input_error: With Error
5
5
  - text_input_custom: Custom
6
6
  - text_input_disabled: Disabled
7
+ - text_input_add_on: Add On
7
8
  react:
8
9
  - text_input_default: Default
9
10
  - text_input_error: With Error
10
11
  - text_input_custom: Custom
11
12
  - text_input_disabled: Disabled
13
+ - text_input_add_on: Add On
@@ -2,3 +2,4 @@ export { default as TextInputDefault } from './_text_input_default.jsx'
2
2
  export { default as TextInputCustom } from './_text_input_custom.jsx'
3
3
  export { default as TextInputError } from './_text_input_error.jsx'
4
4
  export { default as TextInputDisabled } from './_text_input_disabled.jsx'
5
+ export { default as TextInputAddOn } from './_text_input_add_on.jsx'
@@ -5,25 +5,16 @@
5
5
  <% if object.label.present? %>
6
6
  <%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label" }) %>
7
7
  <% end %>
8
- <%= content_tag(:div, class: "text_input_wrapper") do %>
8
+ <%= content_tag(:div, class: "#{add_on_class} text_input_wrapper") do %>
9
9
  <% if content.present? %>
10
10
  <%= content %>
11
+ <% elsif has_add_on? %>
12
+ <%= pb_rails("text_input/add_on", props: object.add_on_props) do %>
13
+ <%= input_tag %>
14
+ <% end %>
11
15
  <% else %>
12
- <%= tag(:input,
13
- autocomplete: object.autocomplete ? nil : "off",
14
- class: "text_input",
15
- data: object.validation_data,
16
- disabled: object.disabled,
17
- id: object.id,
18
- name: object.name,
19
- pattern: object.validation_pattern,
20
- placeholder: object.placeholder,
21
- required: object.required,
22
- type: object.type,
23
- value: object.value) %>
24
- <% end %>
25
- <% if object.error %>
26
- <%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error}) %>
16
+ <%= input_tag %>
27
17
  <% end %>
18
+ <%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error}) if object.error %>
28
19
  <% end %>
29
20
  <% end %>
@@ -17,11 +17,47 @@ module Playbook
17
17
  prop :validation, type: Playbook::Props::Hash,
18
18
  default: {}
19
19
  prop :value
20
+ prop :add_on, type: Playbook::Props::NestedProps,
21
+ nested_kit: Playbook::PbTextInput::AddOn
20
22
 
21
23
  def classname
22
24
  generate_classname("pb_text_input_kit") + error_class
23
25
  end
24
26
 
27
+ def input_tag
28
+ tag(:input, input_options)
29
+ end
30
+
31
+ def has_add_on?
32
+ add_on.present?
33
+ end
34
+
35
+ def add_on_class
36
+ has_add_on? ? 'text_input_wrapper_add_on' : nil
37
+ end
38
+
39
+ def add_on_props
40
+ { dark: dark }.merge(add_on || {})
41
+ end
42
+
43
+ private
44
+
45
+ def input_options
46
+ {
47
+ autocomplete: autocomplete ? nil : "off",
48
+ class: "text_input",
49
+ data: validation_data,
50
+ disabled: disabled,
51
+ id: id,
52
+ name: name,
53
+ pattern: validation_pattern,
54
+ placeholder: placeholder,
55
+ required: required,
56
+ type: type,
57
+ value: value
58
+ }
59
+ end
60
+
25
61
  def validation_message
26
62
  validation[:message] || ""
27
63
  end
@@ -36,8 +72,6 @@ module Playbook
36
72
  fields
37
73
  end
38
74
 
39
- private
40
-
41
75
  def error_class
42
76
  error ? " error" : ""
43
77
  end
@@ -17,6 +17,7 @@ require_relative "./props/numeric"
17
17
  require_relative "./props/percentage"
18
18
  require_relative "./props/proc"
19
19
  require_relative "./props/string"
20
+ require_relative "./props/nested_props"
20
21
 
21
22
  module Playbook
22
23
  module Props
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module Props
5
+ class NestedProps < Playbook::Props::Base
6
+ def initialize(nested_kit:, **kwargs)
7
+ super **kwargs
8
+ @nested_kit = nested_kit
9
+ end
10
+
11
+ def validate(values)
12
+ return true if values.nil?
13
+
14
+ @nested_kit.props.each do |prop_key, definition|
15
+ definition.validate! definition.value(values[prop_key])
16
+ end
17
+ true
18
+ rescue Playbook::Props::Error
19
+ false
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- VERSION = "9.10.0.pre.alpha1"
4
+ VERSION = "9.12.0.pre.text.addon"
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playbook_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.10.0.pre.alpha1
4
+ version: 9.12.0.pre.text.addon
5
5
  platform: ruby
6
6
  authors:
7
7
  - Power UX
8
8
  - Power Devs
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-04-26 00:00:00.000000000 Z
12
+ date: 2021-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -17,7 +17,7 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 5.2.4.4
20
+ version: 5.2.4.5
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
23
  version: '7.0'
@@ -27,7 +27,7 @@ dependencies:
27
27
  requirements:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
- version: 5.2.4.4
30
+ version: 5.2.4.5
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '7.0'
@@ -37,7 +37,7 @@ dependencies:
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 5.2.4.4
40
+ version: 5.2.4.5
41
41
  - - "<"
42
42
  - !ruby/object:Gem::Version
43
43
  version: '7.0'
@@ -47,7 +47,7 @@ dependencies:
47
47
  requirements:
48
48
  - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 5.2.4.4
50
+ version: 5.2.4.5
51
51
  - - "<"
52
52
  - !ruby/object:Gem::Version
53
53
  version: '7.0'
@@ -57,7 +57,7 @@ dependencies:
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 5.2.4.4
60
+ version: 5.2.4.5
61
61
  - - "<"
62
62
  - !ruby/object:Gem::Version
63
63
  version: '7.0'
@@ -67,7 +67,7 @@ dependencies:
67
67
  requirements:
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
- version: 5.2.4.4
70
+ version: 5.2.4.5
71
71
  - - "<"
72
72
  - !ruby/object:Gem::Version
73
73
  version: '7.0'
@@ -299,22 +299,22 @@ dependencies:
299
299
  name: rspec-rails
300
300
  requirement: !ruby/object:Gem::Requirement
301
301
  requirements:
302
- - - ">="
303
- - !ruby/object:Gem::Version
304
- version: 3.8.0
305
302
  - - "~>"
306
303
  - !ruby/object:Gem::Version
307
304
  version: '3.8'
305
+ - - ">="
306
+ - !ruby/object:Gem::Version
307
+ version: 3.8.0
308
308
  type: :development
309
309
  prerelease: false
310
310
  version_requirements: !ruby/object:Gem::Requirement
311
311
  requirements:
312
- - - ">="
313
- - !ruby/object:Gem::Version
314
- version: 3.8.0
315
312
  - - "~>"
316
313
  - !ruby/object:Gem::Version
317
314
  version: '3.8'
315
+ - - ">="
316
+ - !ruby/object:Gem::Version
317
+ version: 3.8.0
318
318
  - !ruby/object:Gem::Dependency
319
319
  name: rubocop
320
320
  requirement: !ruby/object:Gem::Requirement
@@ -1792,8 +1792,12 @@ files:
1792
1792
  - app/pb_kits/playbook/pb_table/table_row.rb
1793
1793
  - app/pb_kits/playbook/pb_text_input/_text_input.jsx
1794
1794
  - app/pb_kits/playbook/pb_text_input/_text_input.scss
1795
+ - app/pb_kits/playbook/pb_text_input/add_on.html.erb
1796
+ - app/pb_kits/playbook/pb_text_input/add_on.rb
1795
1797
  - app/pb_kits/playbook/pb_text_input/docs/_description.md
1796
1798
  - app/pb_kits/playbook/pb_text_input/docs/_footer.md
1799
+ - app/pb_kits/playbook/pb_text_input/docs/_text_input_add_on.html.erb
1800
+ - app/pb_kits/playbook/pb_text_input/docs/_text_input_add_on.jsx
1797
1801
  - app/pb_kits/playbook/pb_text_input/docs/_text_input_custom.html.erb
1798
1802
  - app/pb_kits/playbook/pb_text_input/docs/_text_input_custom.jsx
1799
1803
  - app/pb_kits/playbook/pb_text_input/docs/_text_input_default.html.erb
@@ -2109,6 +2113,7 @@ files:
2109
2113
  - lib/playbook/props/enum.rb
2110
2114
  - lib/playbook/props/hash.rb
2111
2115
  - lib/playbook/props/hash_array.rb
2116
+ - lib/playbook/props/nested_props.rb
2112
2117
  - lib/playbook/props/number.rb
2113
2118
  - lib/playbook/props/number_array.rb
2114
2119
  - lib/playbook/props/numeric.rb
@@ -2123,7 +2128,7 @@ homepage: http://playbook.powerapp.cloud
2123
2128
  licenses:
2124
2129
  - MIT
2125
2130
  metadata: {}
2126
- post_install_message:
2131
+ post_install_message:
2127
2132
  rdoc_options: []
2128
2133
  require_paths:
2129
2134
  - lib
@@ -2138,8 +2143,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2138
2143
  - !ruby/object:Gem::Version
2139
2144
  version: 1.3.1
2140
2145
  requirements: []
2141
- rubygems_version: 3.0.3
2142
- signing_key:
2146
+ rubyforge_project:
2147
+ rubygems_version: 2.7.3
2148
+ signing_key:
2143
2149
  specification_version: 4
2144
2150
  summary: Playbook Design System
2145
2151
  test_files: []