playbook_ui 16.2.0.pre.rc.0 → 16.2.0.pre.rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +12 -2
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +33 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_custom.jsx +71 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_custom.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +1 -1
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.tsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +10 -1
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.jsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +14 -5
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +46 -11
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.html.erb +6 -3
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.jsx +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.md +3 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +10 -4
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +9 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +7 -2
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +4 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +125 -73
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +16 -0
- data/app/pb_kits/playbook/pb_dropdown/utilities/clickOutsideHelper.tsx +6 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +6 -3
- data/app/pb_kits/playbook/pb_form/pb_form_validation.js +9 -2
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +638 -549
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +3 -3
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +4 -7
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.md +3 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +4 -4
- data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +20 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +51 -16
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_label.jsx +44 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_label.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_required_indicator.jsx +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.jsx +28 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_required_indicator.jsx +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_table/index.ts +29 -27
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +10 -10
- data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +10 -0
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.html.erb +3 -3
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.jsx +3 -0
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.md +1 -0
- data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +25 -9
- data/app/pb_kits/playbook/pb_textarea/textarea.rb +7 -1
- data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +97 -11
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.jsx +5 -2
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.jsx +16 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.rb +3 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.test.jsx +47 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +410 -323
- data/app/pb_kits/playbook/pb_typeahead/components/Control.tsx +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.html.erb +16 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.jsx +23 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +22 -21
- data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +3 -2
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -1
- data/dist/chunks/{_pb_line_graph-BgKF_zz1.js → _pb_line_graph-DuJNCf7N.js} +1 -1
- data/dist/chunks/_typeahead-BKSzddAX.js +1 -0
- data/dist/chunks/{globalProps-BhVYCqRf.js → globalProps-Bc-FVsRt.js} +1 -1
- data/dist/chunks/lib-BwX82vim.js +29 -0
- data/dist/chunks/vendor.js +3 -3
- data/dist/menu.yml +2 -2
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/forms/builder/form_field_builder.rb +1 -1
- data/lib/playbook/forms/builder/typeahead_field.rb +15 -1
- data/lib/playbook/forms/builder.rb +2 -2
- data/lib/playbook/version.rb +1 -1
- metadata +24 -6
- data/dist/chunks/_typeahead-Bfy-4mll.js +0 -1
- data/dist/chunks/lib-DD34ZrWL.js +0 -29
|
@@ -73,14 +73,11 @@ const MultiLevelSelectDefault = (props) => {
|
|
|
73
73
|
return (
|
|
74
74
|
<div>
|
|
75
75
|
<MultiLevelSelect
|
|
76
|
-
id=
|
|
76
|
+
id="select_a_department"
|
|
77
77
|
label="Select a Department"
|
|
78
78
|
onSelect={(selectedNodes) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
selectedNodes
|
|
82
|
-
)
|
|
83
|
-
}
|
|
79
|
+
console.log("Selected Items", selectedNodes)
|
|
80
|
+
}
|
|
84
81
|
treeData={treeData}
|
|
85
82
|
{...props}
|
|
86
83
|
/>
|
|
@@ -88,4 +85,4 @@ const MultiLevelSelectDefault = (props) => {
|
|
|
88
85
|
)
|
|
89
86
|
};
|
|
90
87
|
|
|
91
|
-
export default MultiLevelSelectDefault;
|
|
88
|
+
export default MultiLevelSelectDefault;
|
|
@@ -192,7 +192,7 @@ describe('MultiLevelSelect multi variant', () => {
|
|
|
192
192
|
/>
|
|
193
193
|
)
|
|
194
194
|
const kit = screen.getByTestId(testId)
|
|
195
|
-
const input = kit.querySelector('#
|
|
195
|
+
const input = kit.querySelector('#multi-disabled-test_input')
|
|
196
196
|
fireEvent.click(input)
|
|
197
197
|
|
|
198
198
|
const disabledCheckbox = kit.querySelector('input[type="checkbox"][disabled]')
|
|
@@ -227,7 +227,7 @@ describe('MultiLevelSelect single variant', () => {
|
|
|
227
227
|
/>
|
|
228
228
|
)
|
|
229
229
|
const kit = screen.getByTestId(testId)
|
|
230
|
-
const input = kit.querySelector('#
|
|
230
|
+
const input = kit.querySelector('#single-disabled-test_input')
|
|
231
231
|
fireEvent.click(input)
|
|
232
232
|
|
|
233
233
|
const disabledRadio = kit.querySelector('input[type="radio"][disabled]')
|
|
@@ -246,7 +246,7 @@ describe('MultiLevelSelect single variant', () => {
|
|
|
246
246
|
/>
|
|
247
247
|
)
|
|
248
248
|
const kit = screen.getByTestId(testId)
|
|
249
|
-
const input = kit.querySelector('#
|
|
249
|
+
const input = kit.querySelector('#single-disabled-click-test_input')
|
|
250
250
|
fireEvent.click(input)
|
|
251
251
|
|
|
252
252
|
const disabledRadio = kit.querySelector('input[type="radio"][disabled]')
|
|
@@ -267,7 +267,7 @@ describe('MultiLevelSelect single variant', () => {
|
|
|
267
267
|
/>
|
|
268
268
|
)
|
|
269
269
|
const kit = screen.getByTestId(testId)
|
|
270
|
-
const input = kit.querySelector('#
|
|
270
|
+
const input = kit.querySelector('#single-enabled-click-test_input')
|
|
271
271
|
fireEvent.click(input)
|
|
272
272
|
|
|
273
273
|
const enabledRadio = kit.querySelector('input[type="radio"]:not([disabled])')
|
|
@@ -178,22 +178,40 @@ const Passphrase = (props: PassphraseProps): React.ReactElement => {
|
|
|
178
178
|
{...inputProps}
|
|
179
179
|
/>
|
|
180
180
|
<span
|
|
181
|
+
aria-label={
|
|
182
|
+
showPassphrase
|
|
183
|
+
? "Passphrase currently visible. Click icon to hide password"
|
|
184
|
+
: "Passphrase currently hidden. Click icon to reveal password"
|
|
185
|
+
}
|
|
186
|
+
aria-pressed={showPassphrase}
|
|
181
187
|
className="show-passphrase-icon"
|
|
182
188
|
onClick={toggleShowPassphrase}
|
|
189
|
+
onKeyDown={(e) => {
|
|
190
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
191
|
+
e.preventDefault()
|
|
192
|
+
toggleShowPassphrase(e as any)
|
|
193
|
+
}
|
|
194
|
+
}}
|
|
195
|
+
role="button"
|
|
196
|
+
tabIndex={0}
|
|
183
197
|
>
|
|
184
198
|
<Body
|
|
185
199
|
className={showPassphrase ? "hide-icon" : ""}
|
|
186
200
|
color="light"
|
|
187
201
|
dark={dark}
|
|
188
202
|
>
|
|
189
|
-
<Icon
|
|
203
|
+
<Icon
|
|
204
|
+
aria={{ label: "eye icon" }}
|
|
205
|
+
icon="eye-slash"
|
|
206
|
+
/>
|
|
190
207
|
</Body>
|
|
191
208
|
<Body
|
|
192
209
|
className={showPassphrase ? "" : "hide-icon"}
|
|
193
210
|
color="light"
|
|
194
211
|
dark={dark}
|
|
195
212
|
>
|
|
196
|
-
<Icon
|
|
213
|
+
<Icon
|
|
214
|
+
aria={{ label: "eye icon" }}
|
|
197
215
|
className="svg-inline--fa"
|
|
198
216
|
customIcon={eyeIcon.icon as unknown as { [key: string]: SVGElement }}
|
|
199
217
|
/>
|
|
@@ -94,25 +94,51 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
94
94
|
|
|
95
95
|
const htmlProps = buildHtmlProps(htmlOptions)
|
|
96
96
|
|
|
97
|
+
const fieldId = id ? (id as string) : null
|
|
98
|
+
const labelElementId = fieldId ? `${fieldId}-label` : null
|
|
99
|
+
|
|
97
100
|
const handleOnEditorReady = (editorInstance: Editor) => {
|
|
98
101
|
setEditor(editorInstance)
|
|
102
|
+
|
|
99
103
|
setTimeout(() => {
|
|
100
|
-
const oldId = editorInstance.element
|
|
101
|
-
if (oldId)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
const oldId = editorInstance.element?.getAttribute("input")
|
|
105
|
+
if (!oldId) return
|
|
106
|
+
|
|
107
|
+
const hiddenInput = document.getElementById(oldId) as HTMLElement | null
|
|
108
|
+
if (!hiddenInput) return
|
|
109
|
+
|
|
110
|
+
const hiddenInputId = (inputOptions.id as string) || oldId
|
|
111
|
+
|
|
112
|
+
if (hiddenInputId !== oldId) {
|
|
113
|
+
hiddenInput.id = hiddenInputId
|
|
114
|
+
editorInstance.element?.setAttribute("input", hiddenInputId)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (inputOptions.name) {
|
|
118
|
+
hiddenInput.setAttribute("name", inputOptions.name as string)
|
|
112
119
|
}
|
|
120
|
+
|
|
121
|
+
const editorDomId = (id as string) || `${hiddenInputId}_trix`
|
|
122
|
+
const trixLabelId = ((id as string) || hiddenInputId) + "-label"
|
|
123
|
+
|
|
124
|
+
if (label) {
|
|
125
|
+
editorInstance.element?.setAttribute("aria-labelledby", trixLabelId)
|
|
126
|
+
}
|
|
127
|
+
editorInstance.element!.id = editorDomId
|
|
113
128
|
})
|
|
114
129
|
}
|
|
115
130
|
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (!advancedEditor || !fieldId || !labelElementId) return
|
|
133
|
+
|
|
134
|
+
const dom = advancedEditor.view?.dom as HTMLElement | undefined
|
|
135
|
+
if (!dom) return
|
|
136
|
+
|
|
137
|
+
dom.setAttribute("aria-labelledby", labelElementId)
|
|
138
|
+
dom.setAttribute("role", "textbox")
|
|
139
|
+
dom.setAttribute("aria-multiline", "true")
|
|
140
|
+
}, [advancedEditor, fieldId, labelElementId])
|
|
141
|
+
|
|
116
142
|
// DOM manipulation must wait for editor to be ready
|
|
117
143
|
if (editor && editor.element) {
|
|
118
144
|
const toolbarElement = editor.element.parentElement.querySelector('trix-toolbar') as HTMLElement,
|
|
@@ -214,6 +240,8 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
214
240
|
// Determine if toolbar should be shown
|
|
215
241
|
const shouldShowToolbar = focus && advancedEditor ? showToolbarOnFocus : advancedEditorToolbar
|
|
216
242
|
|
|
243
|
+
const labelFor = advancedEditor ? fieldId : (id ? id : (inputOptions.id ? `${inputOptions.id}_trix` : undefined))
|
|
244
|
+
|
|
217
245
|
return (
|
|
218
246
|
<div
|
|
219
247
|
{...ariaProps}
|
|
@@ -223,7 +251,14 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
223
251
|
ref={focus ? containerRef : undefined}
|
|
224
252
|
>
|
|
225
253
|
{label && (
|
|
226
|
-
<label
|
|
254
|
+
<label
|
|
255
|
+
{...(labelFor ? { htmlFor: labelFor, id: labelElementId } : {})}
|
|
256
|
+
onMouseDown={(e) => {
|
|
257
|
+
if (!advancedEditor || !fieldId) return
|
|
258
|
+
e.preventDefault()
|
|
259
|
+
advancedEditor.commands.focus()
|
|
260
|
+
}}
|
|
261
|
+
>
|
|
227
262
|
{
|
|
228
263
|
requiredIndicator ? (
|
|
229
264
|
<Caption className="pb_text_input_kit_label"
|
|
@@ -246,9 +281,9 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
246
281
|
advancedEditor ? (
|
|
247
282
|
<div
|
|
248
283
|
className={classnames(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
284
|
+
"pb_rich_text_editor_advanced_container",
|
|
285
|
+
{ [`input_height_${inputHeight}`]: !!inputHeight,[`input_min_height_${inputMinHeight}`]: !!inputMinHeight ,["toolbar-active"]: shouldShowToolbar }
|
|
286
|
+
)}
|
|
252
287
|
>
|
|
253
288
|
{shouldShowToolbar && (
|
|
254
289
|
<EditorToolbar editor={advancedEditor}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import RichTextEditor from '../../pb_rich_text_editor/_rich_text_editor'
|
|
3
|
+
import { useEditor, EditorContent } from "@tiptap/react"
|
|
4
|
+
import StarterKit from "@tiptap/starter-kit"
|
|
5
|
+
import Link from '@tiptap/extension-link'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const RichTextEditorAdvancedLabel = (props) => {
|
|
9
|
+
|
|
10
|
+
const editor = useEditor({
|
|
11
|
+
extensions: [StarterKit, Link],
|
|
12
|
+
content: "Add your text here. You can format your text, add links, quotes, and bullets.",
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const editorNoLabel = useEditor({
|
|
16
|
+
extensions: [StarterKit, Link],
|
|
17
|
+
content: "Add your text here. You can format your text, add links, quotes, and bullets.",
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
if (!editor || !editorNoLabel) return null
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div>
|
|
24
|
+
<RichTextEditor
|
|
25
|
+
advancedEditor={editor}
|
|
26
|
+
id={"advanced-example"}
|
|
27
|
+
label="Advanced Example Label"
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
30
|
+
<EditorContent editor={editor}/>
|
|
31
|
+
</RichTextEditor>
|
|
32
|
+
<br/>
|
|
33
|
+
<RichTextEditor
|
|
34
|
+
advancedEditor={editorNoLabel}
|
|
35
|
+
label="Advanced Example Label No ID"
|
|
36
|
+
{...props}
|
|
37
|
+
>
|
|
38
|
+
<EditorContent editor={editorNoLabel}/>
|
|
39
|
+
</RichTextEditor>
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default RichTextEditorAdvancedLabel
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
The optional `label` prop adds a visible label to the advanced editor. Passing in the `id` prop associates the `label` with the editor for accessibility, enabling screen reader support and label-based focus behavior.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import RichTextEditor from '../../pb_rich_text_editor/_rich_text_editor'
|
|
3
|
+
|
|
4
|
+
const RichTextEditorLabel = (props) => {
|
|
5
|
+
const [value, setValue] = useState(''),
|
|
6
|
+
handleOnChange = (html) => setValue(html)
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div>
|
|
10
|
+
<RichTextEditor
|
|
11
|
+
id="example"
|
|
12
|
+
label="Example Label"
|
|
13
|
+
onChange={handleOnChange}
|
|
14
|
+
value={value}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
<br/>
|
|
18
|
+
<RichTextEditor
|
|
19
|
+
label="Example Label No ID"
|
|
20
|
+
onChange={handleOnChange}
|
|
21
|
+
value={value}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default RichTextEditorLabel
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
The optional `label` prop adds a visible label to the editor. Passing in the `id` prop associates the `label` with the editor for accessibility, enabling screen reader support and label-based focus behavior.
|
|
@@ -32,6 +32,8 @@ examples:
|
|
|
32
32
|
- rich_text_editor_advanced_inline: Advanced (Inline)
|
|
33
33
|
- rich_text_editor_advanced_height: Advanced Height
|
|
34
34
|
- rich_text_editor_advanced_min_height: Advanced Min Height
|
|
35
|
+
- rich_text_editor_label: Label
|
|
36
|
+
- rich_text_editor_advanced_label: Advanced (Label)
|
|
35
37
|
- rich_text_editor_required_indicator: Required Indicator
|
|
36
38
|
- rich_text_editor_advanced_required_indicator: Advanced Required Indicator
|
|
37
39
|
- rich_text_editor_preview: Preview
|
|
@@ -21,3 +21,5 @@ export { default as RichTextEditorAdvancedHeight } from './_rich_text_editor_adv
|
|
|
21
21
|
export { default as RichTextEditorAdvancedMinHeight } from './_rich_text_editor_advanced_min_height.jsx'
|
|
22
22
|
export { default as RichTextEditorRequiredIndicator } from './_rich_text_editor_required_indicator.jsx'
|
|
23
23
|
export { default as RichTextEditorAdvancedRequiredIndicator } from './_rich_text_editor_advanced_required_indicator.jsx'
|
|
24
|
+
export { default as RichTextEditorLabel } from './_rich_text_editor_label.jsx'
|
|
25
|
+
export { default as RichTextEditorAdvancedLabel } from './_rich_text_editor_advanced_label.jsx'
|
|
@@ -79,21 +79,22 @@ export default class PbTable extends PbEnhancedElement {
|
|
|
79
79
|
header.classList.add('sticky-left-shadow');
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
const headerWidth = (header as HTMLElement).offsetWidth;
|
|
83
|
+
accumulatedWidth += headerWidth;
|
|
84
|
+
|
|
85
|
+
cells.forEach((cell) => {
|
|
86
|
+
cell.classList.add('sticky');
|
|
87
|
+
(cell as HTMLElement).style.left = `${accumulatedWidth - headerWidth}px`;
|
|
88
|
+
|
|
89
|
+
if (!isLastColumn) {
|
|
90
|
+
cell.classList.add('with-border-right');
|
|
91
|
+
cell.classList.remove('sticky-left-shadow');
|
|
92
|
+
} else {
|
|
93
|
+
cell.classList.remove('with-border-right');
|
|
94
|
+
cell.classList.add('sticky-left-shadow');
|
|
95
|
+
}
|
|
96
|
+
});
|
|
83
97
|
}
|
|
84
|
-
|
|
85
|
-
cells.forEach((cell) => {
|
|
86
|
-
cell.classList.add('sticky');
|
|
87
|
-
(cell as HTMLElement).style.left = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;
|
|
88
|
-
|
|
89
|
-
if (!isLastColumn) {
|
|
90
|
-
cell.classList.add('with-border-right');
|
|
91
|
-
cell.classList.remove('sticky-left-shadow');
|
|
92
|
-
} else {
|
|
93
|
-
cell.classList.remove('with-border-right');
|
|
94
|
-
cell.classList.add('sticky-left-shadow');
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
98
|
});
|
|
98
99
|
}
|
|
99
100
|
|
|
@@ -140,21 +141,22 @@ export default class PbTable extends PbEnhancedElement {
|
|
|
140
141
|
header.classList.add('sticky-right-shadow');
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
const headerWidth = (header as HTMLElement).offsetWidth;
|
|
145
|
+
accumulatedWidth += headerWidth;
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
cells.forEach((cell) => {
|
|
148
|
+
cell.classList.add('sticky');
|
|
149
|
+
(cell as HTMLElement).style.right = `${accumulatedWidth - headerWidth}px`;
|
|
149
150
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
151
|
+
if (!isLastColumn) {
|
|
152
|
+
cell.classList.add('with-border-left');
|
|
153
|
+
cell.classList.remove('sticky-right-shadow');
|
|
154
|
+
} else {
|
|
155
|
+
cell.classList.remove('with-border-left');
|
|
156
|
+
cell.classList.add('sticky-right-shadow');
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
158
160
|
});
|
|
159
161
|
}
|
|
160
162
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
<%= pb_content_tag(:div, id: nil
|
|
1
|
+
<%= pb_content_tag(:div, id: nil) do %>
|
|
2
2
|
<% if object.label.present? %>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
<label for="<%= object.input_options[:id] || object.id %>">
|
|
4
|
+
<% if object.required_indicator %>
|
|
5
|
+
<%= pb_rails("caption", props: { dark: object.dark, classname: "pb_text_input_kit_label" }) do %>
|
|
6
|
+
<%= object.label %><span style="color: #DA0014;"> *</span>
|
|
7
|
+
<% end %>
|
|
8
|
+
<% else %>
|
|
9
|
+
<%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label" }) %>
|
|
7
10
|
<% end %>
|
|
8
|
-
|
|
9
|
-
<%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label" }) %>
|
|
10
|
-
<% end %>
|
|
11
|
-
</label>
|
|
11
|
+
</label>
|
|
12
12
|
<% end %>
|
|
13
|
+
|
|
13
14
|
<%= content_tag(:div, class: "#{add_on_class} text_input_wrapper") do %>
|
|
14
15
|
<% if content.present? %>
|
|
15
16
|
<%= content %>
|
|
@@ -26,4 +27,3 @@
|
|
|
26
27
|
<%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error, id: object.error_id, aria: { atomic: "true", live: "polite" }, html_options: { role: "alert" }}) if object.error %>
|
|
27
28
|
<% end %>
|
|
28
29
|
<% end %>
|
|
29
|
-
|
|
@@ -120,6 +120,7 @@ const Textarea = ({
|
|
|
120
120
|
const characterCounter = () => {
|
|
121
121
|
return maxCharacters && characterCount ? `${checkIfZero(characterCount)} / ${maxCharacters}` : `${checkIfZero(characterCount)}`
|
|
122
122
|
}
|
|
123
|
+
const errorId = error ? `${id}-error` : undefined
|
|
123
124
|
|
|
124
125
|
return (
|
|
125
126
|
<div
|
|
@@ -145,7 +146,10 @@ const Textarea = ({
|
|
|
145
146
|
)}
|
|
146
147
|
{children || (
|
|
147
148
|
<textarea
|
|
149
|
+
aria-describedby={errorId}
|
|
150
|
+
aria-invalid={!!error}
|
|
148
151
|
disabled={disabled}
|
|
152
|
+
id={id}
|
|
149
153
|
name={name}
|
|
150
154
|
onChange={emojiMask ? handleChange : onChange}
|
|
151
155
|
onPaste={emojiMask ? handlePaste : undefined}
|
|
@@ -167,6 +171,9 @@ const Textarea = ({
|
|
|
167
171
|
>
|
|
168
172
|
<FlexItem>
|
|
169
173
|
<Body
|
|
174
|
+
aria={{ atomic: "true", live: "polite" }}
|
|
175
|
+
htmlOptions={{ role: "alert" }}
|
|
176
|
+
id={errorId}
|
|
170
177
|
margin="none"
|
|
171
178
|
status="negative"
|
|
172
179
|
text={error}
|
|
@@ -182,6 +189,9 @@ const Textarea = ({
|
|
|
182
189
|
</Flex>
|
|
183
190
|
) : (
|
|
184
191
|
<Body
|
|
192
|
+
aria={{ atomic: "true", live: "polite" }}
|
|
193
|
+
htmlOptions={{ role: "alert" }}
|
|
194
|
+
id={errorId}
|
|
185
195
|
status="negative"
|
|
186
196
|
text={error}
|
|
187
197
|
/>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
<%= pb_rails("textarea", props: { label: "Label", rows: 4}) %>
|
|
1
|
+
<%= pb_rails("textarea", props: { label: "Label", rows: 4, id: "default-example-1" }) %>
|
|
2
2
|
|
|
3
3
|
<br/>
|
|
4
4
|
|
|
5
|
-
<%= pb_rails("textarea", props: { label: "Label", placeholder: "Placeholder text" }) %>
|
|
5
|
+
<%= pb_rails("textarea", props: { label: "Label", placeholder: "Placeholder text", id: "default-example-2" }) %>
|
|
6
6
|
|
|
7
7
|
<br/>
|
|
8
8
|
|
|
9
|
-
<%= pb_rails("textarea", props: { label: "Label", name: "comment", value: "Default value text" }) %>
|
|
9
|
+
<%= pb_rails("textarea", props: { label: "Label", name: "comment", value: "Default value text", id: "default-example-3" }) %>
|
|
@@ -13,6 +13,7 @@ const TextareaDefault = (props) => {
|
|
|
13
13
|
label="Label"
|
|
14
14
|
rows={4}
|
|
15
15
|
{...props}
|
|
16
|
+
id="default-example-1"
|
|
16
17
|
/>
|
|
17
18
|
|
|
18
19
|
<br />
|
|
@@ -21,6 +22,7 @@ const TextareaDefault = (props) => {
|
|
|
21
22
|
label="Label"
|
|
22
23
|
placeholder="Placeholder text"
|
|
23
24
|
{...props}
|
|
25
|
+
id="default-example-2"
|
|
24
26
|
/>
|
|
25
27
|
|
|
26
28
|
<br />
|
|
@@ -32,6 +34,7 @@ const TextareaDefault = (props) => {
|
|
|
32
34
|
placeholder="Placeholder text"
|
|
33
35
|
value={value}
|
|
34
36
|
{...props}
|
|
37
|
+
id="default-example-3"
|
|
35
38
|
/>
|
|
36
39
|
|
|
37
40
|
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Add an `id` to your Textarea so that clicking the label will move focus directly to the input.
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
<%= pb_content_tag do %>
|
|
1
|
+
<%= pb_content_tag(:div, id: nil) do %>
|
|
2
2
|
<% if object.label.present? %>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<%= object.label
|
|
3
|
+
<label for="<%= object.input_options[:id] || object.id %>" >
|
|
4
|
+
<% if object.required_indicator %>
|
|
5
|
+
<%= pb_rails("caption", props: { text: object.label, dark: object.dark }) do %>
|
|
6
|
+
<%= object.label %><span style="color: #DA0014;"> *</span>
|
|
7
|
+
<% end %>
|
|
8
|
+
<% else %>
|
|
9
|
+
<%= pb_rails("caption", props: {text: object.label, dark: object.dark}) %>
|
|
6
10
|
<% end %>
|
|
7
|
-
|
|
8
|
-
<%= pb_rails("caption", props: {text: object.label, dark: object.dark}) %>
|
|
9
|
-
<% end %>
|
|
11
|
+
</label>
|
|
10
12
|
<% end %>
|
|
11
13
|
<% if content.present? %>
|
|
12
14
|
<%= content %>
|
|
@@ -22,14 +24,28 @@
|
|
|
22
24
|
<% if object.character_count %>
|
|
23
25
|
<%= pb_rails("flex", props: { spacing: "between", vertical: "center" }) do %>
|
|
24
26
|
<%= pb_rails("flex/flex_item") do %>
|
|
25
|
-
|
|
27
|
+
<%= pb_rails("body", props: {
|
|
28
|
+
dark: object.dark,
|
|
29
|
+
status: "negative",
|
|
30
|
+
text: object.error,
|
|
31
|
+
id: object.error_id,
|
|
32
|
+
aria: { atomic: "true", live: "polite" },
|
|
33
|
+
html_options: { role: "alert" },
|
|
34
|
+
}) %>
|
|
26
35
|
<% end %>
|
|
27
36
|
<%= pb_rails("flex/flex_item") do %>
|
|
28
37
|
<%= pb_rails("caption", props: { margin: "none", size: "xs", text: object.character_counter }) %>
|
|
29
38
|
<% end %>
|
|
30
39
|
<% end %>
|
|
31
40
|
<% else %>
|
|
32
|
-
<%= pb_rails("body", props: {
|
|
41
|
+
<%= pb_rails("body", props: {
|
|
42
|
+
dark: object.dark,
|
|
43
|
+
status: "negative",
|
|
44
|
+
text: object.error,
|
|
45
|
+
id: object.error_id,
|
|
46
|
+
aria: { atomic: "true", live: "polite" },
|
|
47
|
+
html_options: { role: "alert" },
|
|
48
|
+
}) %>
|
|
33
49
|
<% end %>
|
|
34
50
|
<% else %>
|
|
35
51
|
<%= pb_rails("caption", props: { margin: "none", size: "xs", text: object.character_counter }) %>
|
|
@@ -47,7 +47,9 @@ module Playbook
|
|
|
47
47
|
merged_data = data_attrs.merge(input_data)
|
|
48
48
|
|
|
49
49
|
base_attributes = {
|
|
50
|
-
|
|
50
|
+
'aria-describedby': error.present? ? error_id : nil,
|
|
51
|
+
'aria-invalid': error.present?,
|
|
52
|
+
id: input_options[:id] || id || "object_method",
|
|
51
53
|
max_characters: max_characters,
|
|
52
54
|
name: name,
|
|
53
55
|
onkeyup: onkeyup,
|
|
@@ -66,6 +68,10 @@ module Playbook
|
|
|
66
68
|
result
|
|
67
69
|
end
|
|
68
70
|
|
|
71
|
+
def error_id
|
|
72
|
+
"#{id}-error" if error.present?
|
|
73
|
+
end
|
|
74
|
+
|
|
69
75
|
private
|
|
70
76
|
|
|
71
77
|
def error_class
|