playbook_ui 14.4.0 → 14.5.0.pre.alpha.PBNTR568dropdowncleaning4041

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/SortIconButton.tsx +23 -4
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/index.js +60 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +1 -9
  7. data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +1 -9
  8. data/app/pb_kits/playbook/pb_button/_button.tsx +6 -2
  9. data/app/pb_kits/playbook/pb_contact/_contact.tsx +17 -5
  10. data/app/pb_kits/playbook/pb_contact/contact.html.erb +14 -6
  11. data/app/pb_kits/playbook/pb_contact/contact.rb +4 -0
  12. data/app/pb_kits/playbook/pb_contact/contact.test.js +1 -1
  13. data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +2 -6
  14. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +2 -7
  15. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +4 -3
  16. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +1 -1
  17. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +4 -0
  18. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +6 -3
  19. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_header_styles.scss +6 -2
  21. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +2 -0
  22. data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +1 -1
  23. data/app/pb_kits/playbook/pb_drawer/_close_icon.tsx +25 -0
  24. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +465 -0
  25. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +195 -0
  26. data/app/pb_kits/playbook/pb_drawer/_drawer_context.tsx +3 -0
  27. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +117 -0
  28. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +43 -0
  29. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.html.erb +1 -0
  30. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.jsx +63 -0
  31. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +55 -0
  32. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.jsx +113 -0
  33. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +12 -0
  34. data/app/pb_kits/playbook/pb_drawer/docs/index.js +5 -0
  35. data/app/pb_kits/playbook/pb_drawer/drawer.html.erb +12 -0
  36. data/app/pb_kits/playbook/pb_drawer/drawer.rb +8 -0
  37. data/app/pb_kits/playbook/pb_drawer/drawer.test.jsx +77 -0
  38. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +20 -4
  39. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.jsx +45 -0
  40. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +1 -0
  41. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +1 -0
  42. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +10 -2
  43. data/app/pb_kits/playbook/pb_filter/docs/_filter_max_height.html.erb +5 -1
  44. data/app/pb_kits/playbook/pb_filter/docs/_filter_max_width.html.erb +5 -1
  45. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_background.html.erb +5 -1
  46. data/app/pb_kits/playbook/pb_filter/docs/_filter_no_sort.html.erb +5 -1
  47. data/app/pb_kits/playbook/pb_filter/docs/_filter_only.html.erb +5 -1
  48. data/app/pb_kits/playbook/pb_filter/docs/_filter_placement.html.erb +5 -1
  49. data/app/pb_kits/playbook/pb_filter/docs/_filter_single.html.erb +5 -1
  50. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +9 -1
  51. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.html.erb +19 -0
  52. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.jsx +27 -0
  53. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.md +1 -0
  54. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -0
  55. data/app/pb_kits/playbook/pb_form_pill/docs/index.js +1 -0
  56. data/app/pb_kits/playbook/pb_map/_map_controls.tsx +7 -1
  57. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +210 -232
  58. data/app/pb_kits/playbook/pb_multi_level_select/context/index.tsx +5 -0
  59. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +1 -1
  60. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +105 -0
  61. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.md +1 -0
  62. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +106 -0
  63. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.md +1 -0
  64. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +3 -0
  65. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +2 -0
  66. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select_options.tsx +149 -0
  67. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change.jsx +12 -1
  68. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change_react.md +3 -1
  69. data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +10 -2
  70. data/app/pb_kits/playbook/pb_popover/docs/_popover_list.html.erb +14 -13
  71. data/app/pb_kits/playbook/pb_popover/docs/_popover_list.jsx +4 -4
  72. data/app/pb_kits/playbook/pb_radio/_radio.tsx +92 -33
  73. data/app/pb_kits/playbook/pb_radio/docs/_radio_custom_children.html.erb +2 -0
  74. data/app/pb_kits/playbook/pb_radio/docs/_radio_custom_children.jsx +62 -0
  75. data/app/pb_kits/playbook/pb_radio/docs/example.yml +1 -0
  76. data/app/pb_kits/playbook/pb_radio/docs/index.js +1 -0
  77. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/ToolbarDropdown.tsx +12 -5
  78. data/app/pb_kits/playbook/pb_select/_select.tsx +5 -2
  79. data/app/pb_kits/playbook/pb_select/select.html.erb +1 -1
  80. data/app/pb_kits/playbook/pb_select/select.rb +4 -0
  81. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +0 -1
  82. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +17 -13
  83. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +0 -1
  84. data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +14 -0
  85. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +7 -1
  86. data/app/pb_kits/playbook/pb_typeahead/components/Control.tsx +6 -5
  87. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +3 -1
  88. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_margin_bottom.html.erb +88 -0
  89. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_margin_bottom.jsx +60 -0
  90. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  91. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  92. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +2 -1
  93. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +9 -2
  94. data/app/pb_kits/playbook/utilities/icons/allicons.tsx +136 -13
  95. data/app/pb_kits/playbook/utilities/icons/angle-down.svg +3 -0
  96. data/app/pb_kits/playbook/utilities/icons/envelope.svg +3 -0
  97. data/dist/chunks/_typeahead-CT2ByCBK.js +22 -0
  98. data/dist/chunks/_weekday_stacked-CwIBeloD.js +45 -0
  99. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  100. data/dist/chunks/lib-CEpcaI8y.js +29 -0
  101. data/dist/chunks/{pb_form_validation-zV9OpdSt.js → pb_form_validation-D9zkwt2b.js} +1 -1
  102. data/dist/chunks/vendor.js +1 -1
  103. data/dist/menu.yml +3 -1
  104. data/dist/playbook-doc.js +1 -1
  105. data/dist/playbook-rails-react-bindings.js +1 -1
  106. data/dist/playbook-rails.js +1 -1
  107. data/dist/playbook.css +1 -1
  108. data/lib/playbook/pagination_renderer.rb +10 -2
  109. data/lib/playbook/pb_doc_helper.rb +5 -5
  110. data/lib/playbook/version.rb +2 -2
  111. metadata +40 -10
  112. data/dist/chunks/_typeahead-B2zRxReA.js +0 -22
  113. data/dist/chunks/_weekday_stacked-BIfZDNDm.js +0 -45
  114. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  115. data/dist/chunks/lib-D2U4I1U6.js +0 -16
@@ -0,0 +1,465 @@
1
+ @import "../tokens/positioning";
2
+ @import "../tokens/colors";
3
+ @import "../pb_card/card_mixin";
4
+ @import "../tokens/shadows";
5
+ @import "../tokens/border_radius";
6
+ @import "../tokens/spacing";
7
+ @import "../tokens/animation-curves";
8
+ @import "../tokens/positioning";
9
+
10
+ // Drawer animations
11
+ // Drawer animations for fading in and out from the center
12
+ @keyframes modalFadeIn {
13
+ from {
14
+ transform: translate3d(0, -100%, 0);
15
+ opacity: 0;
16
+ }
17
+ to {
18
+ transform: translate3d(0, 0, 0);
19
+ opacity: 1;
20
+ }
21
+ }
22
+
23
+ @keyframes modalFadeOut {
24
+ from {
25
+ transform: translate3d(0, 0, 0);
26
+ opacity: 1;
27
+ }
28
+ to {
29
+ transform: translate3d(0, -50%, 0);
30
+ opacity: 0;
31
+ }
32
+ }
33
+
34
+ // Drawer animations for fading in and out from the right side
35
+
36
+ @keyframes overlayFade {
37
+ from {
38
+ opacity: 0;
39
+ transform: translateY(0);
40
+ }
41
+ to {
42
+ opacity: 1;
43
+ transform: translateY(0);
44
+ }
45
+ }
46
+
47
+ @keyframes overlayFadeOut {
48
+ from {
49
+ opacity: 1;
50
+ }
51
+ to {
52
+ opacity: 0;
53
+ }
54
+ }
55
+
56
+ body.ReactModal__Body--open {
57
+ transition: margin-left 0.3s ease-in-out, margin-right 0.3s ease-in-out;
58
+ }
59
+
60
+ .pb_drawer_lg_left.pb_drawer {
61
+ transform: translateX(-100%);
62
+ }
63
+
64
+ .pb_drawer_lg_right.pb_drawer {
65
+ transform: translateX(100%);
66
+ }
67
+
68
+ .pb_drawer.pb_drawer_after_open {
69
+ transform: translateX(0); /* Slide in */
70
+ }
71
+ // Drawer Styles
72
+ .pb_drawer {
73
+
74
+ // Local Variables
75
+ $gutter: $space_lg;
76
+ $xsmall: 64px;
77
+ $small: 200px;
78
+ $medium: 250px;
79
+ $large: 300px;
80
+ $xlarge: 365px;
81
+ $animation-duration: .2s;
82
+ $z-index: 100;
83
+ $opacity_visible: 1;
84
+ $opacity_hidden: 0;
85
+
86
+ .drawer {
87
+ position: sticky;
88
+ top: 0;
89
+ background-color: $white;
90
+ z-index: $z_8;
91
+ }
92
+
93
+ // @include pb_card;
94
+ background-color: $white;
95
+ border: 0;
96
+ box-shadow: $shadow_deepest; // border class here
97
+ max-height: calc(100vh - #{$gutter * 2});
98
+ max-width: calc(100vw - #{$gutter * 2});
99
+ overflow: auto;
100
+ animation-name: modalFadeIn;
101
+ animation-duration: $animation-duration;
102
+ outline: none;
103
+ animation-timing-function: $easeInOutQuint;
104
+ transition: transform 0.3s ease-in-out;
105
+
106
+ &.drawer_border_full {
107
+ box-shadow: none;
108
+ border: 2px solid #f3f7fb;
109
+ }
110
+
111
+ &.drawer_border_right {
112
+ border-right: 2px solid #f3f7fb;
113
+ }
114
+
115
+ &.drawer_border_left {
116
+ border-left: 2px solid #f3f7fb;
117
+ }
118
+
119
+ &[class*="_left"] {
120
+ animation-name: modalFadeInLeft;
121
+ &[class*="_before_close"] {
122
+ animation-name: modalFadeOutLeft;
123
+ animation-duration: $animation-duration;
124
+ opacity: $opacity_hidden;
125
+ }
126
+ }
127
+
128
+ &[class*="_right"] {
129
+ animation-name: modalFadeInRight;
130
+ &[class*="_before_close"] {
131
+ animation-name: modalFadeOutRight;
132
+ animation-duration: $animation-duration;
133
+ opacity: $opacity_hidden;
134
+ }
135
+ }
136
+
137
+ &[class*="_xs_"] {
138
+ width: $xsmall;
139
+ max-width: $xsmall;
140
+ }
141
+
142
+ &[class*="_sm_"] {
143
+ width: $small;
144
+ max-width: $small;
145
+ }
146
+
147
+ &[class*="_md_"] {
148
+ width: $medium;
149
+ max-width: $medium;
150
+ }
151
+
152
+ &[class*="_lg_"] {
153
+ width: $large;
154
+ max-width: $large;
155
+ }
156
+
157
+ &[class*="_xl_"] {
158
+ width: $xlarge;
159
+ max-width: $xlarge;
160
+ }
161
+
162
+ &_body_open {
163
+ overflow: hidden;
164
+ }
165
+
166
+ &_after_open {
167
+ opacity: $opacity_visible;
168
+ }
169
+
170
+ &.no-background {
171
+ background-color: transparent;
172
+ }
173
+
174
+ &[class*="_before_close"] {
175
+ animation-name: modalFadeOut;
176
+ animation-duration: $animation-duration;
177
+ opacity: $opacity_hidden;
178
+ }
179
+
180
+ &_close_icon {
181
+ cursor: pointer;
182
+ }
183
+
184
+ &_overlay {
185
+ position: fixed;
186
+ top: 0;
187
+ left: 0;
188
+ right: 0;
189
+ bottom: 0;
190
+ display: flex;
191
+ align-items: center;
192
+ justify-content: center;
193
+ background-color: rgba($bg_dark, $opacity_4);
194
+ z-index: $z-index;
195
+ animation-name: overlayFade;
196
+ animation-duration: $animation-duration;
197
+
198
+ &_after_open {
199
+ opacity: $opacity_visible;
200
+ }
201
+ &_before_close {
202
+ animation-name: overlayFadeOut;
203
+ animation-duration: $animation-duration;
204
+ opacity: $opacity_hidden;
205
+ }
206
+ &[class*="full_height"] {
207
+ &[class*="_left"]{
208
+ justify-content: flex-start;
209
+ }
210
+
211
+ &[class*="_center"]{
212
+ justify-content: center;
213
+ }
214
+
215
+ &[class*="_right"]{
216
+ justify-content: flex-end;
217
+ }
218
+
219
+ .pb_drawer {
220
+ height: 100%;
221
+ max-height: 100%;
222
+ max-width: none;
223
+ // This empty div only has height when drawer is full height
224
+ // Fix for drawer body content disappearing behind sticky footer
225
+ .drawer-pseudo-footer {
226
+ height: $space_xl * 2;
227
+ }
228
+ .drawer_footer {
229
+ position: fixed;
230
+ bottom: 0;
231
+ background-color: $white;
232
+ max-width: 100%;
233
+ }
234
+ &[class*="_xs_"] {
235
+ width: $xsmall;
236
+ .dialog_footer {
237
+ width: $xsmall;
238
+ }
239
+ }
240
+ &[class*="_sm_"] {
241
+ width: $small;
242
+ .dialog_footer {
243
+ width: $small;
244
+ }
245
+ }
246
+ &[class*="_md_"] {
247
+ width: $medium;
248
+ .dialog_footer {
249
+ width: $medium;
250
+ }
251
+ }
252
+ &[class*="_lg_"] {
253
+ width: $large;
254
+ .dialog_footer {
255
+ width: $large;
256
+ }
257
+ }
258
+ &[class*="_xl_"] {
259
+ width: $xlarge;
260
+ .dialog_footer {
261
+ width: $xlarge;
262
+ }
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ &_no_overlay {
269
+ position: fixed;
270
+ top: 0;
271
+ left: 0;
272
+ right: 0;
273
+ bottom: 0;
274
+ display: flex;
275
+ align-items: center;
276
+ justify-content: center;
277
+ z-index: $z-index;
278
+ animation-name: overlayFade;
279
+ animation-duration: $animation-duration;
280
+ overflow: none; /* Ensure body remains scrollable */
281
+ pointer-events: none; /* Allow interaction inside the drawer itself */
282
+
283
+ body.ReactModal__Body--open {
284
+ overflow: none; /* Ensure body remains scrollable */
285
+ pointer-events: none; /* Allow interaction inside the drawer itself */
286
+ }
287
+
288
+ &_after_open {
289
+ opacity: $opacity_visible;
290
+ overflow: none; /* Ensure body remains scrollable */
291
+ pointer-events: none; /* Allow interaction inside the drawer itself */
292
+ }
293
+ &_before_close {
294
+ animation-name: overlayFadeOut;
295
+ animation-duration: $animation-duration;
296
+ opacity: $opacity_hidden;
297
+ }
298
+ &[class*="full_height"] {
299
+ &[class*="_left"]{
300
+ justify-content: flex-start;
301
+ }
302
+
303
+ &[class*="_center"]{
304
+ justify-content: center;
305
+ }
306
+
307
+ &[class*="_right"]{
308
+ justify-content: flex-end;
309
+ }
310
+
311
+ .pb_drawer {
312
+ height: 100%;
313
+ max-height: 100%;
314
+ max-width: none;
315
+ // This empty div only has height when drawer is full height
316
+ // Fix for drawer body content disappearing behind sticky footer
317
+ .drawer-pseudo-footer {
318
+ height: $space_xl * 2;
319
+ }
320
+ .drawer_footer {
321
+ position: fixed;
322
+ bottom: 0;
323
+ background-color: $white;
324
+ max-width: 100%;
325
+ }
326
+ &[class*="_xs_"] {
327
+ width: $xsmall;
328
+ .dialog_footer {
329
+ width: $xsmall;
330
+ }
331
+ }
332
+ &[class*="_sm_"] {
333
+ width: $small;
334
+ .dialog_footer {
335
+ width: $small;
336
+ }
337
+ }
338
+ &[class*="_md_"] {
339
+ width: $medium;
340
+ .dialog_footer {
341
+ width: $medium;
342
+ }
343
+ }
344
+ &[class*="_lg_"] {
345
+ width: $large;
346
+ .dialog_footer {
347
+ width: $large;
348
+ }
349
+ }
350
+ &[class*="_xl_"] {
351
+ width: $xlarge;
352
+ .dialog_footer {
353
+ width: $xlarge;
354
+ }
355
+ }
356
+ }
357
+ }
358
+ }
359
+
360
+ [class*="drawer_body"] {
361
+ padding: $space_sm;
362
+ }
363
+
364
+ [class*="drawer_header"] {
365
+ padding: $space_sm;
366
+ }
367
+
368
+ [class*="drawer_footer"] {
369
+ padding: $space_sm;
370
+ }
371
+
372
+ //styles specific to rails version of kit
373
+ // rails version has own wrapper because of the way the overlay functions for the HTML drawer used to create this
374
+ .pb_drawer_wrapper_rails {
375
+ $medium: 500px;
376
+ $large: 800px;
377
+ $xlarge: 1150px;
378
+
379
+ &[class*="full_height"] {
380
+ &[class*="_left"]{
381
+ .pb_drawer_rails {
382
+ margin: unset !important;
383
+ margin-right: auto !important;
384
+ }
385
+ }
386
+
387
+ &[class*="_center"]{
388
+ justify-content: center;
389
+ }
390
+
391
+ &[class*="_right"]{
392
+ .pb_drawer_rails {
393
+ margin: unset !important;
394
+ margin-left: auto !important;
395
+ }
396
+ }
397
+
398
+ .pb_drawer {
399
+ height: 100% !important;
400
+ max-height: 100% !important;
401
+ max-width: 100%;
402
+ // This empty div only has height when drawer is full height.
403
+ // Fix for drawer body content disappearing behind sticky footer
404
+ .drawer-pseudo-footer {
405
+ height: $space_xl * 2;
406
+ }
407
+ .drawer_footer {
408
+ position:fixed;
409
+ bottom: 0;
410
+ background-color: $white;
411
+ max-width: 100%;
412
+ }
413
+ &[class*="_sm"] {
414
+ width: $medium;
415
+ .drawer_footer {
416
+ width: $medium;
417
+ }
418
+ }
419
+ &[class*="_md"] {
420
+ width: $large;
421
+ .drawer_footer {
422
+ width: $large;
423
+ }
424
+ }
425
+ &[class*="_lg"] {
426
+ width: $xlarge;
427
+ .drawer_footer {
428
+ width: $xlarge;
429
+ }
430
+ }
431
+ }
432
+ }
433
+
434
+ // Fixes for stylesheets in nitro that were conflicting with our kit. DO NOT REMOVE.
435
+ // Conflicts were only apparent in nitro, not in playbook local env
436
+ .pb_drawer_rails {
437
+ position: fixed !important;
438
+ top: 0 !important;
439
+ padding: unset !important;
440
+ margin: auto;
441
+
442
+ }
443
+
444
+ // Overlay for rails kit
445
+ drawer::backdrop {
446
+ position: fixed;
447
+ top: 0;
448
+ left: 0;
449
+ right: 0;
450
+ bottom: 0;
451
+ display: flex;
452
+ align-items: center;
453
+ justify-content: center;
454
+ background-color: rgba($bg_dark, $opacity_4);
455
+ animation-name: overlayFade;
456
+ animation-duration: 0.2s;
457
+ }
458
+
459
+ .drawer-button-class {
460
+ background-color: unset;
461
+ border: none;
462
+ cursor: pointer;
463
+ }
464
+ }
465
+ }
@@ -0,0 +1,195 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import classnames from "classnames";
3
+ import Modal from "react-modal";
4
+
5
+ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
6
+ import { globalProps } from "../utilities/globalProps";
7
+
8
+ import { DialogContext } from "../pb_dialog/_dialog_context";
9
+
10
+ type DrawerProps = {
11
+ aria?: { [key: string]: string };
12
+ behavior?: "floating" | "push";
13
+ border?: "full" | "none" | "right" | "left";
14
+ breakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
15
+ children: React.ReactNode | React.ReactNode[] | string;
16
+ className?: string;
17
+ data?: { [key: string]: string };
18
+ htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
19
+ id?: string;
20
+ fullHeight?: boolean;
21
+ onClose?: () => void;
22
+ opened: boolean;
23
+ overlay: boolean;
24
+ placement?: "left" | "right";
25
+ size?: "xs" | "sm" | "md" | "lg" | "xl";
26
+ text?: string;
27
+ trigger?: string;
28
+ };
29
+
30
+ const Drawer = (props: DrawerProps): React.ReactElement => {
31
+ const {
32
+ aria = {},
33
+ behavior = "floating",
34
+ border = "none",
35
+ breakpoint = "none",
36
+ className,
37
+ data = {},
38
+ htmlOptions = {},
39
+ id,
40
+ size = "md",
41
+ children,
42
+ fullHeight = false,
43
+ opened,
44
+ onClose,
45
+ overlay = true,
46
+ placement = "left",
47
+ trigger,
48
+ } = props;
49
+ const ariaProps = buildAriaProps(aria);
50
+ const dataProps = buildDataProps(data);
51
+ const htmlProps = buildHtmlProps(htmlOptions);
52
+
53
+ let globalPropsString: string = globalProps(props);
54
+
55
+ // Check if the string contains any of the prefixes
56
+ const containsPrefix = ['p_', 'pb_', 'pt_', 'pl_', 'pr_', 'px_', 'py_'].some((prefix) =>
57
+ globalPropsString.includes(prefix)
58
+ );
59
+
60
+ // If none of the prefixes are found, append 'p_sm' to the string
61
+ if (!containsPrefix) {
62
+ globalPropsString += ' p_sm';
63
+ }
64
+
65
+ const drawerClassNames = {
66
+ base: `${classnames(
67
+ "pb_drawer",
68
+ buildCss("pb_drawer", size, placement),
69
+ {
70
+ "drawer_border_full": border === "full",
71
+ "drawer_border_right": border === "right",
72
+ "drawer_border_left": border === "left",
73
+ }
74
+ )} ${globalPropsString}`,
75
+ afterOpen: "pb_drawer_after_open",
76
+ beforeClose: "pb_drawer_before_close",
77
+ };
78
+
79
+ const fullHeightClassNames = () => {
80
+ if (!fullHeight) return null;
81
+ return `full_height_${placement}`;
82
+ };
83
+
84
+ const overlayClassNames = {
85
+ base: `pb_drawer${overlay ? '_overlay' : '_no_overlay'} ${fullHeight !== null && fullHeightClassNames()} ${!overlay ? 'no-background' : ''}`,
86
+ afterOpen: "pb_drawer_overlay_after_open",
87
+ beforeClose: "pb_drawer_overlay_before_close",
88
+ };
89
+
90
+ const classes = classnames(
91
+ buildCss("pb_drawer_wrapper"),
92
+ className
93
+ );
94
+
95
+ const [triggerOpened, setTriggerOpened] = useState(false);
96
+
97
+ const breakpointWidths: Record<DrawerProps['breakpoint'], number> = {
98
+ none: 0,
99
+ xs: 575,
100
+ sm: 768,
101
+ md: 992,
102
+ lg: 1200,
103
+ xl: 1400,
104
+ };
105
+
106
+ // State to manage opening the drawer based on breakpoint
107
+ const [isBreakpointOpen, setIsBreakpointOpen] = useState(false);
108
+
109
+ useEffect(() => {
110
+ if (breakpoint === 'none') return;
111
+
112
+ const handleResize = () => {
113
+ const width = window.innerWidth;
114
+ const breakpointWidth = breakpointWidths[breakpoint];
115
+
116
+ if (width <= breakpointWidth) {
117
+ setIsBreakpointOpen(true);
118
+ } else {
119
+ setIsBreakpointOpen(false);
120
+ }
121
+ };
122
+
123
+ window.addEventListener('resize', handleResize);
124
+
125
+ // Call handler once on mount to set initial state
126
+ handleResize();
127
+
128
+ return () => {
129
+ window.removeEventListener('resize', handleResize);
130
+ };
131
+ }, [breakpoint]);
132
+
133
+ const modalIsOpened = trigger ? triggerOpened : (opened || isBreakpointOpen);
134
+
135
+ useEffect(() => {
136
+ const sizeMap: Record<DrawerProps['size'], string> = {
137
+ xl: '365px',
138
+ lg: '300px',
139
+ md: '250px',
140
+ sm: '200px',
141
+ xs: '64px',
142
+ };
143
+ const body = document.querySelector('body');
144
+
145
+ if (modalIsOpened && behavior === 'push' && body) {
146
+ if (placement === 'left') {
147
+ body.style.cssText = `margin-left: ${sizeMap[size]} !important; margin-right: '' !important;`;
148
+ } else if (placement === 'right') {
149
+ body.style.cssText = `margin-right: ${sizeMap[size]} !important; margin-left: '' !important;`;
150
+ }
151
+
152
+ body.classList.add('ReactModal__Body--open');
153
+ } else if (body) {
154
+ body.style.cssText = ''; // Clear the styles when modal is closed or behavior is not 'push'
155
+ body.classList.remove('ReactModal__Body--open');
156
+ }
157
+ }, [modalIsOpened, behavior, placement, size]);
158
+
159
+ const api = {
160
+ onClose: trigger
161
+ ? function () {
162
+ setTriggerOpened(false);
163
+ }
164
+ : onClose,
165
+ };
166
+
167
+ return (
168
+ <DialogContext.Provider value={api}>
169
+ <div
170
+ {...ariaProps}
171
+ {...dataProps}
172
+ {...htmlProps}
173
+ className={classes}
174
+ >
175
+ <Modal
176
+ ariaHideApp={false}
177
+ className={drawerClassNames}
178
+ closeTimeoutMS={200}
179
+ contentLabel="Minimal Modal Example"
180
+ id={id}
181
+ isOpen={modalIsOpened}
182
+ onRequestClose={onClose}
183
+ overlayClassName={overlayClassNames}
184
+ shouldCloseOnOverlayClick={overlay}
185
+ >
186
+ <>
187
+ {children}
188
+ </>
189
+ </Modal>
190
+ </div>
191
+ </DialogContext.Provider>
192
+ );
193
+ };
194
+
195
+ export default Drawer;
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+
3
+ export const DrawerContext = React.createContext(null);