playbook_ui_docs 16.10.0.pre.alpha.PLAY3053advancedtablebottompinnedrowsreact17469 → 16.10.0.pre.alpha.PLAY3059dialogpopoverportalingfullscreen17455

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54da223a58079747e07a434617596364176d18e253953d3538b471b5682514fc
4
- data.tar.gz: c9ac712cb4fc7704c4d122cf27377c4847d432664f7871a3536104332e85ddfe
3
+ metadata.gz: defe35c0433c7a7ddcc57558f4b80bd7e325b43eff9e3cd67a8978e1e1034a4c
4
+ data.tar.gz: f6a79ad144af1026e7e748b90ed8ec8e68425e88120fd4f92022526f5d9a477c
5
5
  SHA512:
6
- metadata.gz: 845a59d6693e7e4c17c38ecc339b30cf06fa815a77e222f40c4521b98a513dfeff8166aaae4f5a7fd35e5ae30e30a271e2d55a6fd7bbbe6197b73428d8f33e52
7
- data.tar.gz: db593af6693a42cde0cbe0ae239e25890041de12bc1957788210ac2db85a81e48cd499a8997c72e9bb39993c2fc8a039e3343a2e52061eb312c90711a5793333
6
+ metadata.gz: dd921a3952a3e98f028b9b51a25705904c42944827fc898ac87c5077a9c9a8f5fde6d24d0f4cd9651c68d5758c8618fa3cd11c2076b7f9950bab3cb88c794438
7
+ data.tar.gz: 41ff708cebbb2685675aa8ee17afc8a0fc2994846efc52e7d6f9691989f5b39c14e79b0ae2fa581cf20a01119a04d8096274c1147741d21d0f97039c0a599565
@@ -1,7 +1,6 @@
1
1
  import React, { useState } from "react"
2
2
  import AdvancedTable from '../_advanced_table'
3
3
  import MOCK_DATA_WITH_ID from "./advanced_table_mock_data_with_id.json"
4
- import Caption from "../../pb_caption/_caption"
5
4
 
6
5
  const AdvancedTableRowPinning = (props) => {
7
6
  const columnDefinitions = [
@@ -36,30 +35,14 @@ const AdvancedTableRowPinning = (props) => {
36
35
  },
37
36
  ]
38
37
 
39
- const [pinnedRowsTop, setPinnedRowsTop] = useState({top: ["8"]})
40
- const [pinnedRowsBottom, setPinnedRowsBottom] = useState({bottom: ["8"]})
38
+ const [pinnedRows, setPinnedRows] = useState({top: ["8"]})
41
39
 
42
40
  return (
43
41
  <div>
44
- <Caption text="Pinned Rows Top" />
45
42
  <AdvancedTable
46
43
  columnDefinitions={columnDefinitions}
47
44
  maxHeight="xs"
48
- pinnedRows={{value: pinnedRowsTop, onChange: setPinnedRowsTop}}
49
- tableData={MOCK_DATA_WITH_ID}
50
- tableProps={{sticky: true}}
51
- {...props}
52
- >
53
- <AdvancedTable.Header enableSorting />
54
- <AdvancedTable.Body />
55
- </AdvancedTable>
56
- <Caption marginTop="md"
57
- text="Pinned Rows Bottom"
58
- />
59
- <AdvancedTable
60
- columnDefinitions={columnDefinitions}
61
- maxHeight="xs"
62
- pinnedRows={{value: pinnedRowsBottom, onChange: setPinnedRowsBottom}}
45
+ pinnedRows={{value: pinnedRows, onChange: setPinnedRows}}
63
46
  tableData={MOCK_DATA_WITH_ID}
64
47
  tableProps={{sticky: true}}
65
48
  {...props}
@@ -1,7 +1,7 @@
1
- Use the `pinnedRows` prop to pin specific rows to the top or bottom of an Advanced Table. Pinned rows will remain at the top or bottom when scrolling through table data and will not change position if sorting is used.
1
+ Use the `pinnedRows` prop to pin specific rows to the top of an Advanced Table. Pinned rows will remain at the top when scrolling through table data and will not change position if sorting is used.
2
2
 
3
3
  **NOTE:**
4
4
  - Sticky header required: Pinned rows must be used with `sticky: true` via `tableProps` (works with both responsive and non-responsive tables)
5
5
  - Row ids required: Each object within the `tableData` Array must contain a unique id in order to attach an id to all Rows for this to function.
6
- - `pinnedRows` takes an array of row ids to the `top` or `bottom` property as shown in the code snippet below (both can be used on the same table).
6
+ - `pinnedRows` takes an array of row ids to the `top` property as shown in the code snippet below.
7
7
  - For expandable rows, use the parent id in `pinnedRows`, all its children will automatically be pinned with it. If id for a child is passed in without parent being pinned, nothing will be pinned.
@@ -89,4 +89,5 @@ examples:
89
89
  - advanced_table_column_styling_background_multi: Column Styling Background Color with Multiple Headers
90
90
  - advanced_table_padding_control: Padding Control using Column Styling
91
91
  - advanced_table_column_border_color: Column Group Border Color
92
+ - advanced_table_fullscreen: Fullscreen
92
93
  - advanced_table_infinite_scroll: Infinite Scroll
@@ -4,7 +4,6 @@ examples:
4
4
  - file_upload_default: File Upload
5
5
  - file_upload_custom: Custom
6
6
  - file_upload_error: Error
7
- - file_upload_remove_replace: Remove and Replace
8
7
 
9
8
  react:
10
9
  - file_upload_default: Default List of files to upload
@@ -12,5 +11,4 @@ examples:
12
11
  - file_upload_custom_message: Add a custom message
13
12
  - file_upload_custom_description: Add your one accepted files description
14
13
  - file_upload_max_size: Set a file size limit
15
- - file_upload_error: Error
16
- - file_upload_remove_replace: Remove and Replace
14
+ - file_upload_error: Error
@@ -4,4 +4,3 @@ export { default as FileUploadCustomMessage } from './_file_upload_custom_messag
4
4
  export { default as FileUploadCustomDescription } from './_file_upload_custom_description.jsx'
5
5
  export { default as FileUploadMaxSize } from './_file_upload_max_size.jsx'
6
6
  export { default as FileUploadError } from './_file_upload_error.jsx'
7
- export { default as FileUploadRemoveReplace } from './_file_upload_remove_replace.jsx'
@@ -90,7 +90,7 @@ const FullScreenTableAndFilter = (props) => {
90
90
  double
91
91
  maxHeight="50vh"
92
92
  minWidth="xs"
93
- popoverProps={{ width: "350px", appendTo: ".fullscreen-overlay" }}
93
+ popoverProps={{ width: "350px" }}
94
94
  results={50}
95
95
  sortOptions={{
96
96
  territory_id: "Territory ID",
@@ -1 +1 @@
1
- Full Screen can host composed workflows such as a filter paired with a data table. For popovers inside the overlay, set the popover append target to `.fullscreen-overlay` so menus render within the fullscreen layer.
1
+ Full Screen can host composed workflows such as a filter paired with a data table. Filter and sort popovers automatically append to the fullscreen overlay; dropdown menus inside them portal above the overlay via the shared floating UI stack.
@@ -1,21 +1,523 @@
1
- import React from 'react'
1
+ import React, { useState } from 'react'
2
2
 
3
3
  import Typeahead from '../_typeahead'
4
+ import Dropdown from '../../pb_dropdown/_dropdown'
5
+ import MultiLevelSelect from '../../pb_multi_level_select/_multi_level_select'
6
+ import DatePicker from '../../pb_date_picker/_date_picker'
7
+ import TimePicker from '../../pb_time_picker/_time_picker'
8
+ import FullScreen from '../../pb_full_screen/_full_screen'
9
+ import Button from '../../pb_button/_button'
10
+ import Dialog from '../../pb_dialog/_dialog'
11
+ import Flex from '../../pb_flex/_flex'
12
+ import Body from '../../pb_body/_body'
13
+ import Caption from '../../pb_caption/_caption'
14
+ import SectionSeparator from '../../pb_section_separator/_section_separator'
15
+ import Filter from '../../pb_filter/_filter'
4
16
 
5
- const options = [
6
- { label: 'Orange', value: '#FFA500' },
7
- { label: 'Red', value: '#FF0000' },
8
- { label: 'Green', value: '#00FF00' },
9
- { label: 'Blue', value: '#0000FF' },
17
+ const typeaheadOptions = [
18
+ { label: 'United States', value: 'unitedStates', id: 'us' },
19
+ { label: 'United Kingdom', value: 'unitedKingdom', id: 'gb' },
20
+ { label: 'Canada', value: 'canada', id: 'ca' },
21
+ { label: 'Australia', value: 'australia', id: 'au' },
22
+ { label: 'Germany', value: 'germany', id: 'de' },
23
+ { label: 'France', value: 'france', id: 'fr' },
24
+ { label: 'Japan', value: 'japan', id: 'jp' },
25
+ { label: 'Brazil', value: 'brazil', id: 'br' },
26
+ { label: 'Mexico', value: 'mx', id: 'mx' },
27
+ { label: 'Italy', value: 'it', id: 'it' },
28
+ { label: 'Spain', value: 'es', id: 'es' },
29
+ { label: 'Netherlands', value: 'nl', id: 'nl' },
30
+ { label: 'Sweden', value: 'se', id: 'se' },
31
+ { label: 'Norway', value: 'no', id: 'no' },
32
+ { label: 'Denmark', value: 'dk', id: 'dk' },
33
+ { label: 'Finland', value: 'fi', id: 'fi' },
34
+ { label: 'Poland', value: 'pl', id: 'pl' },
35
+ { label: 'Switzerland', value: 'ch', id: 'ch' },
36
+ { label: 'Austria', value: 'at', id: 'at' },
37
+ { label: 'Belgium', value: 'be', id: 'be' },
38
+ { label: 'Ireland', value: 'ie', id: 'ie' },
39
+ { label: 'Portugal', value: 'pt', id: 'pt' },
40
+ { label: 'Greece', value: 'gr', id: 'gr' },
41
+ { label: 'Czech Republic', value: 'cz', id: 'cz' },
42
+ { label: 'Hungary', value: 'hu', id: 'hu' },
43
+ { label: 'New Zealand', value: 'nz', id: 'nz' },
44
+ { label: 'Singapore', value: 'sg', id: 'sg' },
45
+ { label: 'South Korea', value: 'kr', id: 'kr' },
46
+ { label: 'India', value: 'in', id: 'in' },
47
+ { label: 'China', value: 'cn', id: 'cn' },
10
48
  ]
11
49
 
12
- const TypeaheadDefault = (props) => {
13
- return (
50
+ const dropdownDocOptions = [
51
+ { label: 'United States', value: 'unitedStates', id: 'us' },
52
+ { label: 'Canada', value: 'canada', id: 'ca' },
53
+ { label: 'United Kingdom', value: 'unitedKingdom', id: 'gb' },
54
+ { label: 'Japan', value: 'japan', id: 'jp' },
55
+ { label: 'Brazil', value: 'brazil', id: 'br' },
56
+ ]
57
+
58
+ const suffixTreeIds = (nodes, suffix) =>
59
+ nodes.map((node) => {
60
+ const next = {
61
+ ...node,
62
+ id: `${node.id}-${suffix}`,
63
+ }
64
+ if (node.children?.length) {
65
+ next.children = suffixTreeIds(node.children, suffix)
66
+ }
67
+ return next
68
+ })
69
+
70
+ /** From `pb_multi_level_select` default doc example */
71
+ const MLS_DEFAULT_TREE_DATA = [
72
+ {
73
+ label: 'Power Home Remodeling',
74
+ value: 'powerHomeRemodeling',
75
+ id: 'powerhome1',
76
+ expanded: true,
77
+ children: [
78
+ {
79
+ label: 'People',
80
+ value: 'people',
81
+ id: 'people1',
82
+ expanded: true,
83
+ children: [
84
+ {
85
+ label: 'Talent Acquisition',
86
+ value: 'talentAcquisition',
87
+ id: 'talent1',
88
+ },
89
+ {
90
+ label: 'Business Affairs',
91
+ value: 'businessAffairs',
92
+ id: 'business1',
93
+ children: [
94
+ {
95
+ label: 'Initiatives',
96
+ value: 'initiatives',
97
+ id: 'initiative1',
98
+ },
99
+ {
100
+ label: 'Learning & Development',
101
+ value: 'learningAndDevelopment',
102
+ id: 'development1',
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ label: 'People Experience',
108
+ value: 'peopleExperience',
109
+ id: 'experience1',
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ label: 'Contact Center',
115
+ value: 'contactCenter',
116
+ id: 'contact1',
117
+ children: [
118
+ {
119
+ label: 'Appointment Management',
120
+ value: 'appointmentManagement',
121
+ id: 'appointment1',
122
+ },
123
+ {
124
+ label: 'Customer Service',
125
+ value: 'customerService',
126
+ id: 'customer1',
127
+ },
128
+ {
129
+ label: 'Energy',
130
+ value: 'energy',
131
+ id: 'energy1',
132
+ },
133
+ ],
134
+ },
135
+ ],
136
+ },
137
+ ]
138
+
139
+ /** From `pb_multi_level_select` single-select doc example */
140
+ const MLS_SINGLE_TREE_DATA = [
141
+ {
142
+ label: 'HQ',
143
+ value: 'hQ',
144
+ id: 'hq',
145
+ },
146
+ {
147
+ label: 'Philadelphia',
148
+ value: 'philadelphia',
149
+ id: 'phl',
150
+ children: [
151
+ {
152
+ label: 'Marketing & Sales PHL',
153
+ value: 'marketingAndSalesPhl',
154
+ id: 'marketingPHL',
155
+ },
156
+ {
157
+ label: 'Installation Office PHL',
158
+ value: 'installationOfficePhl',
159
+ id: 'installationPHL',
160
+ },
161
+ {
162
+ label: 'Warehouse PHL',
163
+ value: 'warehousePhl',
164
+ id: 'warehousePHL',
165
+ },
166
+ ],
167
+ },
168
+ {
169
+ label: 'New Jersey',
170
+ value: 'newJersey',
171
+ id: 'nj',
172
+ children: [
173
+ {
174
+ label: 'New Jersey',
175
+ value: 'newJersey',
176
+ id: 'nj1',
177
+ children: [
178
+ {
179
+ label: 'Marketing & Sales NJ',
180
+ value: 'marketingAndSalesNj',
181
+ id: 'marketingNJ',
182
+ },
183
+ {
184
+ label: 'Installation Office NJ',
185
+ value: 'installationOfficeNj',
186
+ id: 'installationNJ',
187
+ },
188
+ {
189
+ label: 'Warehouse NJ',
190
+ value: 'warehouseNj',
191
+ id: 'warehouseNJ',
192
+ },
193
+ ],
194
+ },
195
+ {
196
+ label: 'Princeton',
197
+ value: 'princeton',
198
+ id: 'princeton',
199
+ children: [
200
+ {
201
+ label: 'Marketing & Sales Princeton',
202
+ value: 'marketingAndSalesPrinceton',
203
+ id: 'marketingPR',
204
+ },
205
+ {
206
+ label: 'Installation Office Princeton',
207
+ value: 'installationOfficePrinceton',
208
+ id: 'installationPR',
209
+ },
210
+ {
211
+ label: 'Warehouse Princeton',
212
+ value: 'warehousePrinceton',
213
+ id: 'warehousePR',
214
+ },
215
+ ],
216
+ },
217
+ ],
218
+ },
219
+ {
220
+ label: 'Maryland',
221
+ value: 'maryland',
222
+ id: 'MD',
223
+ children: [
224
+ {
225
+ label: 'Marketing & Sales MD',
226
+ value: 'marketingAndSalesMd',
227
+ id: 'marketingMD',
228
+ },
229
+ {
230
+ label: 'Installation Office MD',
231
+ value: 'installationOfficeMd',
232
+ id: 'installationMD',
233
+ },
234
+ {
235
+ label: 'Warehouse MD',
236
+ value: 'warehouseMd',
237
+ id: 'warehouseMD',
238
+ },
239
+ ],
240
+ },
241
+ {
242
+ label: 'Connecticut',
243
+ value: 'connecticut',
244
+ id: 'CT',
245
+ children: [
246
+ {
247
+ label: 'Marketing & Sales CT',
248
+ value: 'marketingAndSalesCt',
249
+ id: 'marketingCT',
250
+ },
251
+ {
252
+ label: 'Installation Office CT',
253
+ value: 'installationOfficeCt',
254
+ id: 'installationCT',
255
+ },
256
+ {
257
+ label: 'Warehouse CT',
258
+ value: 'warehouseCt',
259
+ id: 'warehouseCT',
260
+ },
261
+ ],
262
+ },
263
+ ]
264
+
265
+ const mlsDefaultTreeFor = (suffix) =>
266
+ suffixTreeIds(MLS_DEFAULT_TREE_DATA, suffix)
267
+
268
+ const mlsSingleTreeFor = (suffix) =>
269
+ suffixTreeIds(MLS_SINGLE_TREE_DATA, suffix)
270
+
271
+ const TITLE_TYPEAHEAD_OPTIONS = [
272
+ { key: 'senior-ux-engineer', label: 'Senior UX Engineer', value: 'senior-ux-engineer' },
273
+ { key: 'ux-engineer-ii', label: 'UX Engineer II', value: 'ux-engineer-ii' },
274
+ { key: 'ux-engineer', label: 'UX Engineer', value: 'ux-engineer' },
275
+ { key: 'ux-designer', label: 'UX Designer', value: 'ux-designer' },
276
+ { key: 'director-uxe', label: 'Director of User Experience Engineering', value: 'director-uxe' },
277
+ { key: 'product-manager', label: 'Product Manager', value: 'product-manager' },
278
+ { key: 'engineering-manager', label: 'Engineering Manager', value: 'engineering-manager' },
279
+ { key: 'staff-engineer', label: 'Staff Engineer', value: 'staff-engineer' },
280
+ { key: 'principal-engineer', label: 'Principal Engineer', value: 'principal-engineer' },
281
+ { key: 'data-analyst', label: 'Data Analyst', value: 'data-analyst' },
282
+ { key: 'qa-engineer', label: 'QA Engineer', value: 'qa-engineer' },
283
+ { key: 'devops-engineer', label: 'DevOps Engineer', value: 'devops-engineer' },
284
+ { key: 'technical-writer', label: 'Technical Writer', value: 'technical-writer' },
285
+ { key: 'scrum-master', label: 'Scrum Master', value: 'scrum-master' },
286
+ { key: 'nitro-producteer', label: 'Nitro Producteer', value: 'nitro-producteer' },
287
+ ]
288
+
289
+ const filterSortProps = {
290
+ results: 50,
291
+ sortOptions: {
292
+ started_on: 'Start Date',
293
+ title_name: 'Title',
294
+ department_name: 'Department',
295
+ branch_branch_name: 'Branch',
296
+ },
297
+ sortValue: [{ name: 'started_on', dir: 'asc' }],
298
+ }
299
+
300
+ const datePickerDocProps = {
301
+ customQuickPickDates: { override: true, dates: [] },
302
+ maxDate: '',
303
+ minDate: '',
304
+ staticPosition: true,
305
+ }
306
+
307
+ const renderDateTimePickers = (suffix) => (
308
+ <>
309
+ <DatePicker
310
+ {...datePickerDocProps}
311
+ label="Date picker"
312
+ name={`typeahead-doc-date-picker-${suffix}`}
313
+ pickerId={`inputs-overflow-date-picker-${suffix}`}
314
+ selectionType="quickpick"
315
+ />
316
+ <TimePicker
317
+ id={`inputs-overflow-time-picker-${suffix}`}
318
+ label="Time picker"
319
+ />
320
+ </>
321
+ )
322
+ const renderFilterPopover = (closePopover, suffix) => (
323
+ <>
14
324
  <Typeahead
15
- label="Colors"
16
- options={options}
17
- {...props}
325
+ id={`overflow-visible-title-${suffix}`}
326
+ isMulti={false}
327
+ label="Typeahead"
328
+ marginBottom="none"
329
+ options={TITLE_TYPEAHEAD_OPTIONS}
330
+ placeholder="Search title…"
18
331
  />
332
+ <Dropdown
333
+ blankSelection="Select country…"
334
+ id={`overflow-visible-dropdown-${suffix}`}
335
+ label="Dropdown"
336
+ options={dropdownDocOptions}
337
+ />
338
+ <MultiLevelSelect
339
+ id={`overflow-visible-multi-level-select-${suffix}-single`}
340
+ inputName="Power"
341
+ label="Multi level select (single)"
342
+ name={`typeahead_doc_filter_${suffix}_mls_single`}
343
+ placeholder="Start typing..."
344
+ treeData={mlsSingleTreeFor(`filter-${suffix}-single`)}
345
+ variant="single"
346
+ />
347
+ <MultiLevelSelect
348
+ id={`overflow-visible-multi-level-select-${suffix}-multi`}
349
+ label="Multi level select (default)"
350
+ name={`typeahead_doc_filter_${suffix}_mls_multi`}
351
+ placeholder="Start typing..."
352
+ treeData={mlsDefaultTreeFor(`filter-${suffix}-multi`)}
353
+ />
354
+ {renderDateTimePickers(`filter-${suffix}`)}
355
+ <Flex spacing="between">
356
+ <Button
357
+ onClick={() => {
358
+ alert('No filtering functionality - just a pattern demo!')
359
+ closePopover()
360
+ }}
361
+ text="Filter"
362
+ />
363
+ <Button
364
+ text="Defaults"
365
+ variant="secondary"
366
+ />
367
+ </Flex>
368
+ </>
369
+ )
370
+
371
+ const TypeaheadDefault = () => {
372
+ const [isOpen, setIsOpen] = useState(false)
373
+ const [isScrollableOpen, setIsScrollableOpen] = useState(false);
374
+ const close = () => setIsOpen(false);
375
+ const open = () => setIsOpen(true);
376
+ const closeScrollable = () => setIsScrollableOpen(false);
377
+ const openScrollable = () => setIsScrollableOpen(true);
378
+ return (
379
+ <>
380
+ <div style={{ height: "2000px" }}>
381
+ <FullScreen
382
+ headerText="Fullscreen"
383
+ trigger={({ onClick, isOpen }) => (
384
+ <Button
385
+ onClick={onClick}
386
+ text={isOpen ? "Exit Fullscreen" : "Enter Fullscreen"}
387
+ variant="secondary"
388
+ />
389
+ )}
390
+ >
391
+ <Button marginY="md"
392
+ onClick={open}
393
+ >
394
+ {"Open dialog: Input kits inside"}
395
+ </Button>
396
+ <Dialog onClose={close}
397
+ opened={isOpen}
398
+ size="md"
399
+ >
400
+ <Dialog.Header>
401
+ <Body>{"Input kits inside Dialog"}</Body>
402
+ </Dialog.Header>
403
+ <Dialog.Body>
404
+ <Typeahead
405
+ label="Typeahead"
406
+ marginBottom="none"
407
+ options={typeaheadOptions}
408
+ placeholder="Search country…"
409
+ />
410
+ <Dropdown
411
+ blankSelection="Select country…"
412
+ id="inputs-overflow-dropdown-js"
413
+ label="Dropdown"
414
+ options={dropdownDocOptions}
415
+ />
416
+ <MultiLevelSelect
417
+ id="inputs-overflow-multi-level-select-dialog-js-single"
418
+ inputName="Power"
419
+ label="Multi level select (single)"
420
+ name="typeahead_doc_dialog_mls_js_single"
421
+ placeholder="Start typing..."
422
+ treeData={mlsSingleTreeFor("dialog-single")}
423
+ variant="single"
424
+ />
425
+ <MultiLevelSelect
426
+ id="inputs-overflow-multi-level-select-dialog-js-multi"
427
+ label="Multi level select (default)"
428
+ name="typeahead_doc_dialog_mls_js_multi"
429
+ placeholder="Start typing..."
430
+ treeData={mlsDefaultTreeFor("dialog-multi")}
431
+ />
432
+ {renderDateTimePickers('dialog')}
433
+ </Dialog.Body>
434
+ <Dialog.Footer>
435
+ <Button onClick={close}>{"Save"}</Button>
436
+ <Button onClick={close}
437
+ variant="link"
438
+ >
439
+ {"Cancel"}
440
+ </Button>
441
+ </Dialog.Footer>
442
+ </Dialog>
443
+ <Button marginBottom="md"
444
+ onClick={openScrollable}
445
+ >
446
+ {"Open scrollable dialog: Input kits inside"}
447
+ </Button>
448
+ <Dialog onClose={closeScrollable}
449
+ opened={isScrollableOpen}
450
+ size="md"
451
+ >
452
+ <Dialog.Header>
453
+ <Body>{"Input kits inside Dialog"}</Body>
454
+ </Dialog.Header>
455
+ <Dialog.Body>
456
+ <Body text="At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat." />
457
+ <Typeahead
458
+ label="Typeahead"
459
+ marginBottom="none"
460
+ options={typeaheadOptions}
461
+ placeholder="Search country…"
462
+ />
463
+ <Dropdown
464
+ blankSelection="Select country…"
465
+ id="inputs-overflow-dropdown-js"
466
+ label="Dropdown"
467
+ options={dropdownDocOptions}
468
+ />
469
+ <MultiLevelSelect
470
+ id="inputs-overflow-multi-level-select-scrollable-js-single"
471
+ inputName="Power"
472
+ label="Multi level select (single)"
473
+ name="typeahead_doc_dialog_scrollable_mls_js_single"
474
+ placeholder="Start typing..."
475
+ treeData={mlsSingleTreeFor("dialog-scrollable-single")}
476
+ variant="single"
477
+ />
478
+ <MultiLevelSelect
479
+ id="inputs-overflow-multi-level-select-scrollable-js-multi"
480
+ label="Multi level select (default)"
481
+ name="typeahead_doc_dialog_scrollable_mls_js_multi"
482
+ placeholder="Start typing..."
483
+ treeData={mlsDefaultTreeFor("dialog-scrollable-multi")}
484
+ />
485
+ {renderDateTimePickers('dialog-scrollable')}
486
+ </Dialog.Body>
487
+ <Dialog.Footer>
488
+ <Button onClick={closeScrollable}>{"Save"}</Button>
489
+ <Button onClick={closeScrollable}
490
+ variant="link"
491
+ >
492
+ {"Cancel"}
493
+ </Button>
494
+ </Dialog.Footer>
495
+ </Dialog>
496
+ <Caption text="FILTER #1 HAS NO MAX HEIGHT" />
497
+ <Filter
498
+ background={false}
499
+ double
500
+ minWidth="xs"
501
+ popoverProps={{ width: '350px' }}
502
+ {...filterSortProps}
503
+ >
504
+ {({ closePopover }) => renderFilterPopover(closePopover, '1')}
505
+ </Filter>
506
+ <SectionSeparator />
507
+ <Caption text="FILTER #2 HAS MAX HEIGHT" />
508
+ <Filter
509
+ background={false}
510
+ double
511
+ maxHeight="50vh"
512
+ minWidth="xs"
513
+ popoverProps={{ width: '350px' }}
514
+ {...filterSortProps}
515
+ >
516
+ {({ closePopover }) => renderFilterPopover(closePopover, '2')}
517
+ </Filter>
518
+ </FullScreen>
519
+ </div>
520
+ </>
19
521
  )
20
522
  }
21
523
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playbook_ui_docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.10.0.pre.alpha.PLAY3053advancedtablebottompinnedrowsreact17469
4
+ version: 16.10.0.pre.alpha.PLAY3059dialogpopoverportalingfullscreen17455
5
5
  platform: ruby
6
6
  authors:
7
7
  - Power UX
@@ -1092,9 +1092,6 @@ files:
1092
1092
  - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.html.erb
1093
1093
  - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.jsx
1094
1094
  - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_max_size.jsx
1095
- - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.html.erb
1096
- - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.jsx
1097
- - app/pb_kits/playbook/pb_file_upload/docs/_file_upload_remove_replace.md
1098
1095
  - app/pb_kits/playbook/pb_file_upload/docs/_playground.json
1099
1096
  - app/pb_kits/playbook/pb_file_upload/docs/_playground.overrides.json
1100
1097
  - app/pb_kits/playbook/pb_file_upload/docs/example.yml
@@ -1,66 +0,0 @@
1
- <div id="file-upload-remove-replace">
2
- <%= pb_rails("list", props: { id: "selected-files-list", margin_bottom: "sm" }) %>
3
-
4
- <%= pb_rails("file_upload", props: {
5
- id: "remove_replace",
6
- input_options: { multiple: true },
7
- }) %>
8
- </div>
9
-
10
- <template id="file-list-item-template">
11
- <%= pb_rails("list/item") do %>
12
- <%= pb_rails("flex", props: { align: "center", justify: "between", width: "100%" }) do %>
13
- <%= pb_rails("body", props: { data: { file_name: true } }) %>
14
- <%= pb_rails("circle_icon_button", props: {
15
- icon: "times",
16
- variant: "secondary",
17
- input_options: { classname: "remove-file-button" },
18
- }) %>
19
- <% end %>
20
- <% end %>
21
- </template>
22
-
23
- <%= javascript_tag defer: "defer" do %>
24
- document.addEventListener("DOMContentLoaded", function () {
25
- const fileInput = document.getElementById("upload-remove_replace")
26
- const list = document.getElementById("selected-files-list")
27
- const template = document.getElementById("file-list-item-template")
28
- let files = []
29
-
30
- if (!fileInput || !list || !template) return
31
-
32
- function syncInput() {
33
- const dataTransfer = new DataTransfer()
34
- files.forEach((file) => dataTransfer.items.add(file))
35
- fileInput.files = dataTransfer.files
36
- }
37
-
38
- function render() {
39
- list.innerHTML = ""
40
-
41
- files.forEach((file, index) => {
42
- const clone = template.content.cloneNode(true)
43
- const nameElement = clone.querySelector("[data-file-name]")
44
- const removeButton = clone.querySelector(".remove-file-button")
45
-
46
- nameElement.textContent = file.name
47
- removeButton.addEventListener("click", function (event) {
48
- event.preventDefault()
49
- event.stopPropagation()
50
- files = files.filter((_, fileIndex) => fileIndex !== index)
51
- syncInput()
52
- render()
53
- })
54
-
55
- list.appendChild(clone)
56
- })
57
- }
58
-
59
- fileInput.addEventListener("change", function () {
60
- const newFiles = Array.from(fileInput.files)
61
- files = [...files, ...newFiles]
62
- syncInput()
63
- render()
64
- })
65
- })
66
- <% end %>
@@ -1,53 +0,0 @@
1
-
2
- import React, { useState } from 'react'
3
-
4
- import Body from '../../pb_body/_body'
5
- import CircleIconButton from '../../pb_circle_icon_button/_circle_icon_button'
6
- import FileUpload from '../../pb_file_upload/_file_upload'
7
- import Flex from '../../pb_flex/_flex'
8
- import List from '../../pb_list/_list'
9
- import ListItem from '../../pb_list/_list_item'
10
-
11
- const FileUploadRemoveReplace = (props) => {
12
- const [filesToUpload, setFilesToUpload] = useState([])
13
-
14
- const handleOnFilesAccepted = (files) => {
15
- setFilesToUpload([...filesToUpload, ...files])
16
- }
17
-
18
- const handleRemoveFile = (index) => {
19
- setFilesToUpload(filesToUpload.filter((_, fileIndex) => fileIndex !== index))
20
- }
21
-
22
- return (
23
- <div>
24
- {filesToUpload.length > 0 && (
25
- <List marginBottom="sm">
26
- {filesToUpload.map((file, index) => (
27
- <ListItem key={`${file.name}-${index}`}>
28
- <Flex
29
- align="center"
30
- justify="between"
31
- width="100%"
32
- >
33
- <Body text={file.name} />
34
- <CircleIconButton
35
- aria={{ label: `Remove ${file.name}` }}
36
- icon="times"
37
- onClick={() => handleRemoveFile(index)}
38
- variant="secondary"
39
- />
40
- </Flex>
41
- </ListItem>
42
- ))}
43
- </List>
44
- )}
45
- <FileUpload
46
- onFilesAccepted={handleOnFilesAccepted}
47
- {...props}
48
- />
49
- </div>
50
- )
51
- }
52
-
53
- export default FileUploadRemoveReplace
@@ -1,5 +0,0 @@
1
- The File Upload kit does not include built-in remove or replace behavior. Manage selected files in application state and compose the kit with other Playbook components.
2
-
3
- **Remove** — Track accepted files in state and filter out the file to remove. In React, pair `List` with `CircleIconButton`. In Rails, listen for `change` on the file input, keep files in a JavaScript array, and use `DataTransfer` to sync the input when a file is removed.
4
-
5
- **Replace** — Selecting a new file on the native Rails input replaces the current selection. For single-file React workflows, set state to the newly accepted files instead of appending: `setFilesToUpload(files)`.