playbook_ui 14.7.0 → 14.8.0.pre.alpha.PBNTR713dropdowncustomtriggerbug4696

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/pb_card/docs/_card_light.md +1 -1
  4. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +2 -2
  5. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +0 -4
  6. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +84 -7
  7. data/app/pb_kits/playbook/pb_date/_date.scss +3 -0
  8. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +1 -1
  9. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_default_date.html.erb +42 -0
  10. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_default_date.jsx +44 -0
  11. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_default_date.md +1 -0
  12. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  13. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
  14. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +17 -1
  15. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default_rails.html.erb +26 -0
  16. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default_rails.md +7 -0
  17. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_rails.html.erb +38 -0
  18. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_rails.md +0 -0
  19. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.html.erb +19 -0
  20. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +6 -0
  21. data/app/pb_kits/playbook/pb_draggable/draggable.html.erb +3 -0
  22. data/app/pb_kits/playbook/pb_draggable/draggable.rb +18 -0
  23. data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +3 -0
  24. data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +15 -0
  25. data/app/pb_kits/playbook/pb_draggable/draggable_item.html.erb +7 -0
  26. data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +18 -0
  27. data/app/pb_kits/playbook/pb_draggable/index.js +125 -0
  28. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +88 -175
  29. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +79 -47
  30. data/app/pb_kits/playbook/pb_drawer/drawer.test.jsx +20 -16
  31. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -0
  32. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -1
  33. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -4
  34. data/app/pb_kits/playbook/pb_dropdown/utilities/subComponentHelper.tsx +13 -2
  35. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +2 -2
  36. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +1 -1
  37. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +63 -12
  38. data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_default.html.erb +2 -1
  39. data/app/pb_kits/playbook/pb_table/_table.tsx +103 -24
  40. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.jsx +87 -0
  41. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_react.md +2 -0
  42. data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
  43. data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -0
  44. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +4 -0
  45. data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +18 -0
  46. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +43 -1
  47. data/app/pb_kits/playbook/pb_timeline/_timeline.tsx +6 -2
  48. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.html.erb +47 -0
  49. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.jsx +59 -0
  50. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_gap.html.erb +94 -0
  51. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_gap.jsx +180 -0
  52. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_gap.md +1 -0
  53. data/app/pb_kits/playbook/pb_timeline/docs/example.yml +5 -3
  54. data/app/pb_kits/playbook/pb_timeline/docs/index.js +2 -0
  55. data/app/pb_kits/playbook/pb_timeline/timeline.rb +11 -1
  56. data/app/pb_kits/playbook/pb_timeline/timeline.test.js +4 -4
  57. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +3 -0
  58. data/app/pb_kits/playbook/pb_typeahead/index.ts +29 -3
  59. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +5 -2
  60. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +4 -0
  61. data/app/pb_kits/playbook/tokens/_height.scss +19 -0
  62. data/app/pb_kits/playbook/tokens/exports/_height.module.scss +37 -0
  63. data/app/pb_kits/playbook/utilities/_height.scss +33 -0
  64. data/app/pb_kits/playbook/utilities/_hover.scss +40 -27
  65. data/app/pb_kits/playbook/utilities/_max_width.scss +4 -0
  66. data/app/pb_kits/playbook/utilities/_min_width.scss +1 -1
  67. data/app/pb_kits/playbook/utilities/globalPropNames.mjs +0 -1
  68. data/app/pb_kits/playbook/utilities/globalProps.ts +29 -3
  69. data/app/pb_kits/playbook/utilities/test/globalProps/hover.test.js +79 -0
  70. data/dist/chunks/_typeahead-C8Q_fFYF.js +22 -0
  71. data/dist/chunks/_weekday_stacked-CUJfwh5E.js +45 -0
  72. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  73. data/dist/chunks/{lib-D-mTv-kp.js → lib-SyD3buPZ.js} +1 -1
  74. data/dist/chunks/{pb_form_validation-BkWGwJsl.js → pb_form_validation-Dt8UJgrJ.js} +1 -1
  75. data/dist/chunks/vendor.js +1 -1
  76. data/dist/menu.yml +322 -1
  77. data/dist/playbook-doc.js +1 -1
  78. data/dist/playbook-rails-react-bindings.js +1 -1
  79. data/dist/playbook-rails.js +1 -1
  80. data/dist/playbook.css +1 -1
  81. data/lib/playbook/classnames.rb +3 -0
  82. data/lib/playbook/forms/builder/typeahead_field.rb +13 -0
  83. data/lib/playbook/height.rb +29 -0
  84. data/lib/playbook/hover.rb +1 -1
  85. data/lib/playbook/kit_base.rb +16 -1
  86. data/lib/playbook/max_height.rb +29 -0
  87. data/lib/playbook/min_height.rb +29 -0
  88. data/lib/playbook/version.rb +2 -2
  89. metadata +39 -10
  90. data/dist/chunks/_typeahead-DhLic2Fe.js +0 -22
  91. data/dist/chunks/_weekday_stacked-CHPFjl8J.js +0 -45
  92. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbcb00498c9dc4a636179bd7186dd8212f9fed6f9d096d615f63b93861fba2c7
4
- data.tar.gz: b30eca9b5879d8346fe092421ec5070e3259e2f096792145e5d53c04902d0463
3
+ metadata.gz: 7776c1f464d6ba8dfb924b88a819e7d8ffaa73a2e5bb8c634d842d74e518b181
4
+ data.tar.gz: 426631d54aa230c2730bd84e2f100ddc1bdabd7ac2e665d1b467a7be5e5ea1e3
5
5
  SHA512:
6
- metadata.gz: '09475c887b1c4e75768fb5435c13ce28584456eaf67bb039acfbf211c7b627e4cb56feb85e0cb83c49a05f6c016ceb0282b0f426d9cadf4ec703cdfa97f084c2'
7
- data.tar.gz: 7f46c632e40e670b7456ade4b36105db7cb995d7801e80f156536b118a18e65738c3ef3a0ef9a9df280c3e98da5c3be3e283e4da2d9b9494ecf906f5680783c0
6
+ metadata.gz: d0eff8fe9fecb531b16b97bf63c76c1bb6c0746e3542f5a401947cf1d62e4b314700d0ed23e616d00faa36d057e8d39a06734db7b54322625c295339b0fe5af3
7
+ data.tar.gz: a2807364db12b9e5594df46d76931e33d4602f6b74892ae578efd465a46c9f7ef93e947e2e6c969c6c96518900cbe9f6fbfb25cc8dee868376197ee165050f1d
@@ -126,3 +126,4 @@
126
126
  @import 'utilities/overflow';
127
127
  @import 'utilities/truncate';
128
128
  @import 'utilities/vertical_align';
129
+ @import 'utilities/height';
@@ -1 +1 @@
1
- Card can leverage the max-width property. Learn more in our <a href="https://playbook.powerapp.cloud/visual_guidelines" target="_blank">visual guidelines.</a>
1
+ Card can leverage the max-width property. Learn more in our <a href="https://playbook.powerapp.cloud/visual_guidelines" target="_blank">visual guidelines.</a>
@@ -6,12 +6,12 @@
6
6
  ) do %>
7
7
  <%= content.presence || object.input %>
8
8
  <% if object.indeterminate %>
9
- <span class="pb_checkbox_indeterminate">
9
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_indeterminate">
10
10
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon", fixed_width: true}) %>
11
11
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon hidden", fixed_width: true}) %>
12
12
  </span>
13
13
  <% else %>
14
- <span class="pb_checkbox_checkmark">
14
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
15
15
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
16
16
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
17
17
  </span>
@@ -18,10 +18,6 @@ module Playbook
18
18
  prop :form_spacing, type: Playbook::Props::Boolean,
19
19
  default: false
20
20
 
21
- def checked_html
22
- checked ? "checked='true'" : nil
23
- end
24
-
25
21
  def classname
26
22
  generate_classname("pb_checkbox_kit", checked_class) + indeterminate_class + error_class
27
23
  end
@@ -1,7 +1,84 @@
1
- <%= pb_rails("checkbox" , props: {
2
- text: "Select ",
3
- value: "checkbox-value",
4
- name: "main",
5
- indeterminate: true,
6
- id: "test-indeterminate-js"
7
- }) %>
1
+ <% checkboxes = [
2
+ { name: 'Coffee', id: 'coffee', checked: false },
3
+ { name: 'Ice Cream', id: 'ice-cream', checked: false },
4
+ { name: 'Chocolate', id: 'chocolate', checked: true }
5
+ ] %>
6
+
7
+ <%= pb_rails("table", props: { container: false, size: "md" }) do %>
8
+ <thead>
9
+ <tr>
10
+ <th>
11
+ <%= pb_rails("checkbox", props: {
12
+ checked: true,
13
+ text: "Uncheck All",
14
+ value: "checkbox-value",
15
+ name: "main-checkbox",
16
+ indeterminate: true,
17
+ id: "indeterminate-checkbox"
18
+ }) %>
19
+ </th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <% checkboxes.each do |checkbox| %>
25
+ <tr>
26
+ <td>
27
+ <%= pb_rails("checkbox", props: {
28
+ checked: checkbox[:checked],
29
+ text: checkbox[:name],
30
+ value: checkbox[:id],
31
+ name: "#{checkbox[:id]}-indeterminate-checkbox",
32
+ id: "#{checkbox[:id]}-indeterminate-checkbox",
33
+ }) %>
34
+ </td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ <% end %>
39
+
40
+ <script>
41
+ document.addEventListener('DOMContentLoaded', function() {
42
+ const mainCheckboxWrapper = document.getElementById('indeterminate-checkbox');
43
+ const mainCheckbox = document.getElementsByName("main-checkbox")[0];
44
+ const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="indeterminate-checkbox"]');
45
+
46
+ const updateMainCheckbox = () => {
47
+ // Count the number of checked child checkboxes
48
+ const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
49
+ // Determine if the main checkbox should be in an indeterminate state
50
+ const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
51
+
52
+ // Set the main checkbox states
53
+ mainCheckbox.indeterminate = indeterminate;
54
+ mainCheckbox.checked = checkedCount > 0;
55
+
56
+ // Determine the main checkbox label based on the number of checked checkboxes
57
+ const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
58
+
59
+ // Determine the icon class to add and remove based on the number of checked checkboxes
60
+ const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
61
+ const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
62
+
63
+ // Update main checkbox label
64
+ mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
65
+
66
+ // Add and remove the icon class to the main checkbox wrapper
67
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
68
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
69
+
70
+ // Toggle the visibility of the checkbox icon based on the indeterminate state
71
+ mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
72
+ mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
73
+ };
74
+
75
+ mainCheckbox.addEventListener('change', function() {
76
+ childCheckboxes.forEach(cb => cb.checked = this.checked);
77
+ updateMainCheckbox();
78
+ });
79
+
80
+ childCheckboxes.forEach(cb => {
81
+ cb.addEventListener('change', updateMainCheckbox);
82
+ });
83
+ });
84
+ </script>
@@ -28,5 +28,8 @@
28
28
  [class^=pb_title_kit] {
29
29
  color: $text_dk_default !important;
30
30
  }
31
+ [class^=pb_body_kit], [class^=pb_caption_kit] {
32
+ color: $text_dk_light !important;
33
+ }
31
34
  }
32
35
  }
@@ -143,7 +143,7 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
143
143
 
144
144
  } else if (selectionType === "quickpick") {
145
145
  //------- QUICKPICK VARIANT PLUGIN -------------//
146
- pluginList.push(quickPickPlugin(thisRangesEndToday, customQuickPickDates))
146
+ pluginList.push(quickPickPlugin(thisRangesEndToday, customQuickPickDates, defaultDate as string))
147
147
  }
148
148
 
149
149
  // time selection
@@ -0,0 +1,42 @@
1
+ <%= pb_rails("date_picker", props: {
2
+ allow_input: true,
3
+ default_date: "This month",
4
+ end_date_id: "quick-pick-end-date",
5
+ end_date_name: "quick-pick-end-date",
6
+ mode: "range",
7
+ picker_id: "quick-pick-default-date",
8
+ placeholder: "mm/dd/yyyy to mm/dd/yyyy",
9
+ selection_type: "quickpick",
10
+ start_date_id: "quick-pick-start-date",
11
+ start_date_name: "quick-pick-start-date"
12
+ }) %>
13
+
14
+ <%= pb_rails("date_picker", props: {
15
+ allow_input: true,
16
+ custom_quick_pick_dates: {
17
+ dates: [
18
+ {
19
+ label: "Last 15 months",
20
+ value: {
21
+ timePeriod: "months",
22
+ amount: 15,
23
+ },
24
+ },
25
+ {
26
+ label: "First Week of June 2022",
27
+ value: ["06/01/2022", "06/07/2022"],
28
+ },
29
+ ],
30
+ },
31
+ default_date: "First Week of June 2022",
32
+ end_date_id: "quick-pick-end-date",
33
+ end_date_name: "quick-pick-end-date",
34
+ label: "Custom Date Picker",
35
+ mode: "range",
36
+ picker_id: "custom-quick-pick-default-date",
37
+ placeholder: "mm/dd/yyyy to mm/dd/yyyy",
38
+ selection_type: "quickpick",
39
+ start_date_id: "quick-pick-start-date",
40
+ start_date_name: "quick-pick-start-date"
41
+ }) %>
42
+
@@ -0,0 +1,44 @@
1
+ import React from "react"
2
+ import DatePicker from "../_date_picker"
3
+
4
+ const DatePickerQuickPickDefaultDate = (props) => (
5
+ <>
6
+ <DatePicker
7
+ allowInput
8
+ defaultDate="This month"
9
+ mode="range"
10
+ pickerId="quick-pick-default-date"
11
+ placeholder="mm/dd/yyyy to mm/dd/yyyy"
12
+ selectionType="quickpick"
13
+ {...props}
14
+ />
15
+
16
+ <DatePicker
17
+ allowInput
18
+ customQuickPickDates={{
19
+ dates: [
20
+ {
21
+ label: "Last 15 months",
22
+ value: {
23
+ timePeriod: "months",
24
+ amount: 15,
25
+ },
26
+ },
27
+ {
28
+ label: "First Week of June 2022",
29
+ value: ["06/01/2022", "06/07/2022"],
30
+ },
31
+ ],
32
+ }}
33
+ defaultDate="First Week of June 2022"
34
+ label="Custom Date Picker"
35
+ mode="range"
36
+ pickerId="custom-quick-pick-default-date"
37
+ placeholder="mm/dd/yyyy to mm/dd/yyyy"
38
+ selectionType="quickpick"
39
+ {...props}
40
+ />
41
+ </>
42
+ )
43
+
44
+ export default DatePickerQuickPickDefaultDate
@@ -0,0 +1 @@
1
+ To set a default value using Quick Pick, use the `defaultDate` or `default_date` prop. This prop should match one of the labels displayed in the UI of the dropdown menu.
@@ -12,6 +12,7 @@ examples:
12
12
  - date_picker_quick_pick_range_limit: Range (Quick Pick w/ “This” Range limit)
13
13
  - date_picker_quick_pick_custom: Custom Quick Pick Dates
14
14
  - date_picker_quick_pick_custom_override: Custom Quick Pick Dates (append to defaults)
15
+ - date_picker_quick_pick_default_date: Range (Quick Pick w/ Default Date)
15
16
  - date_picker_format: Format
16
17
  - date_picker_disabled: Disabled Dates
17
18
  - date_picker_min_max: Min Max
@@ -42,6 +43,7 @@ examples:
42
43
  - date_picker_quick_pick_range_limit: Range (Quick Pick w/ “This” Range limit)
43
44
  - date_picker_quick_pick_custom: Custom Quick Pick Dates
44
45
  - date_picker_quick_pick_custom_override: Custom Quick Pick Dates (append to defaults)
46
+ - date_picker_quick_pick_default_date: Range (Quick Pick w/ Default Date)
45
47
  - date_picker_format: Format
46
48
  - date_picker_disabled: Disabled Dates
47
49
  - date_picker_min_max: Min Max
@@ -25,3 +25,4 @@ export { default as DatePickerQuickPickRangeLimit } from './_date_picker_quick_p
25
25
  export { default as DatePickerOnClose } from './_date_picker_on_close.jsx'
26
26
  export { default as DatePickerQuickPickCustom } from './_date_picker_quick_pick_custom'
27
27
  export { default as DatePickerQuickPickCustomOverride } from './_date_picker_quick_pick_custom_override'
28
+ export { default as DatePickerQuickPickDefaultDate } from './_date_picker_quick_pick_default_date'
@@ -26,7 +26,7 @@ type customQuickPickDatesType = {
26
26
 
27
27
  let activeLabel = ""
28
28
 
29
- const quickPickPlugin = (thisRangesEndToday: boolean, customQuickPickDates: customQuickPickDatesType | undefined) => {
29
+ const quickPickPlugin = (thisRangesEndToday: boolean, customQuickPickDates: customQuickPickDatesType | undefined, defaultDate: string) => {
30
30
  return function (fp: FpTypes & any): any {
31
31
  const today = new Date()
32
32
  const yesterday = DateTime.getYesterdayDate(new Date())
@@ -185,6 +185,8 @@ const quickPickPlugin = (thisRangesEndToday: boolean, customQuickPickDates: cust
185
185
  return {
186
186
  // onReady is a hook from flatpickr that runs when calendar is in a ready state
187
187
  onReady(selectedDates: Array<Date>) {
188
+ let defaultDateRange
189
+
188
190
  // loop through the ranges and create an anchor tag for each range and add an event listener to set the date when user clicks on a date range
189
191
  for (const [label, range] of Object.entries(pluginData.ranges)) {
190
192
  addRangeButton(label).addEventListener('click', function () {
@@ -201,6 +203,14 @@ const quickPickPlugin = (thisRangesEndToday: boolean, customQuickPickDates: cust
201
203
  fp.close();
202
204
  }
203
205
  });
206
+
207
+ // check if there is a default date and set the default date range and label for quick pick
208
+ if (defaultDate) {
209
+ if (label.toLowerCase() === defaultDate.toLowerCase()) {
210
+ activeLabel = label
211
+ defaultDateRange = range
212
+ }
213
+ }
204
214
  }
205
215
  // conditional to check if there is a dropdown to add it to the calendar container and get it the classes it needs
206
216
  if (pluginData.rangesNav.children.length > 0) {
@@ -216,6 +226,12 @@ const quickPickPlugin = (thisRangesEndToday: boolean, customQuickPickDates: cust
216
226
  // function to give the active button the active class
217
227
  selectActiveRangeButton(selectedDates);
218
228
  }
229
+
230
+ // set the default date range if there is one and select the active button
231
+ if (defaultDateRange) {
232
+ fp.setDate(defaultDateRange, false);
233
+ selectActiveRangeButton(defaultDateRange);
234
+ }
219
235
  },
220
236
  onValueUpdate(selectedDates: Array<Date>) {
221
237
  selectActiveRangeButton(selectedDates)
@@ -0,0 +1,26 @@
1
+ <% initial_items = [
2
+ {
3
+ id: "1",
4
+ url: "https://unsplash.it/500/400/?image=633",
5
+ },
6
+ {
7
+ id: "2",
8
+ url: "https://unsplash.it/500/400/?image=634",
9
+ },
10
+ {
11
+ id: "3",
12
+ url: "https://unsplash.it/500/400/?image=637",
13
+ },
14
+ ] %>
15
+
16
+ <%= pb_rails("draggable", props: {initial_items: initial_items}) do %>
17
+ <%= pb_rails("draggable/draggable_container") do %>
18
+ <%= pb_rails("flex") do %>
19
+ <% initial_items.each do |item| %>
20
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: item[:id]}) do %>
21
+ <%= pb_rails("image", props: { alt: item[:id], size: "md", url: item[:url], margin: "xs" }) %>
22
+ <% end %>
23
+ <% end %>
24
+ <% end %>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,7 @@
1
+ The `draggable` kit gives you a full subcomponent structure that allows it to be used with almost any kit.
2
+
3
+ `initial_items` is a REQUIRED prop, which is the array of objects that contains data for the the draggable items.
4
+
5
+ `draggable/draggable_container` = This specifies the container within which items can be dropped.
6
+
7
+ `draggable/draggable_item` = This specifies the items that can be dragged and dropped. `drag_id` is a REQUIRED prop for draggable_item and must match the id on the items within `initial_items`.
@@ -0,0 +1,38 @@
1
+ <% initial_items = [
2
+ { id: "21", name: "Joe Black" },
3
+ { id: "22", name: "Nancy White" },
4
+ { id: "23", name: "Bill Green" },
5
+ ] %>
6
+
7
+ <%= pb_rails("draggable", props: {initial_items: initial_items}) do %>
8
+ <%= pb_rails("draggable/draggable_container") do %>
9
+ <% initial_items.each do |item| %>
10
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: item[:id]}) do %>
11
+ <%= pb_rails("card", props: {highlight: {position: "side", color:"primary"}, margin_bottom: "xs", padding: "xs"}) do %>
12
+ <%= pb_rails("flex", props:{align_items: "stretch", flex_direction:"column"}) do %>
13
+ <%= pb_rails("flex", props:{gap: "xs"}) do %>
14
+ <%= pb_rails("title", props: { text: item[:name], tag: "h4", size: 4 }) %>
15
+ <%= pb_rails("badge", props: {text:"35-12345" ,variant: "primary"}) %>
16
+ <% end %>
17
+ <%= pb_rails("caption", props: { size: "xs", text: "8:00A • Township Name • 90210" }) %>
18
+ <%= pb_rails("flex", props:{gap: "xxs", spacing:"between"}) do %>
19
+ <%= pb_rails("flex", props:{gap: "xxs"}) do %>
20
+ <%= pb_rails("caption", props: { size: "xs" , color: "error" }) do %>
21
+ <%= pb_rails("icon", props: { icon: "house-circle-exclamation", fixed_width: true }) %>
22
+ <% end %>
23
+ <%= pb_rails("caption", props: { size: "xs" , color: "success" }) do %>
24
+ <%= pb_rails("icon", props: { icon: "file-circle-check", fixed_width: true }) %>
25
+ <% end %>
26
+ <% end %>
27
+ <%= pb_rails("flex") do %>
28
+ <%= pb_rails("badge", props: {text:"Schedule QA" ,variant: "warning", rounded: true}) %>
29
+ <%= pb_rails("badge", props: {text:"Flex" ,variant: "primary", rounded: true}) %>
30
+ <%= pb_rails("badge", props: {text:"R99" ,variant: "primary", rounded: true}) %>
31
+ <% end %>
32
+ <% end %>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <% initial_items = [
2
+ { id: "31", name: "Philadelphia" },
3
+ { id: "32", name: "New Jersey" },
4
+ { id: "33", name: "Maryland" },
5
+ { id: "34", name: "Connecticut" },
6
+
7
+ ] %>
8
+
9
+ <%= pb_rails("draggable", props: {initial_items: initial_items}) do %>
10
+ <%= pb_rails("draggable/draggable_container") do %>
11
+ <%= pb_rails("list", props: {ordered: false}) do %>
12
+ <% initial_items.each do |item| %>
13
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: item[:id]}) do %>
14
+ <%= pb_rails("list/item") do %><%= item[:name] %><% end %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+ <% end %>
@@ -8,4 +8,10 @@ examples:
8
8
  - draggable_with_cards: Draggable with Cards
9
9
  - draggable_multiple_containers: Dragging Across Multiple Containers
10
10
 
11
+ rails:
12
+ - draggable_default_rails: Default
13
+ - draggable_with_list_rails: Draggable with List Kit
14
+ - draggable_with_cards_rails: Draggable with Cards
15
+
16
+
11
17
 
@@ -0,0 +1,3 @@
1
+ <%= pb_content_tag do %>
2
+ <%= content.presence %>
3
+ <% end %>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbDraggable
5
+ class Draggable < ::Playbook::KitBase
6
+ prop :initial_items, type: Playbook::Props::Array,
7
+ default: []
8
+
9
+ def data
10
+ Hash(prop(:data)).merge(pb_draggable: true)
11
+ end
12
+
13
+ def classname
14
+ generate_classname("pb_draggable")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ <%= pb_content_tag do %>
2
+ <%= content.presence %>
3
+ <% end %>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbDraggable
5
+ class DraggableContainer < ::Playbook::KitBase
6
+ def data
7
+ Hash(prop(:data)).merge(pb_draggable_container: true)
8
+ end
9
+
10
+ def classname
11
+ generate_classname("pb_draggable_container")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ <%= pb_content_tag(:div, {
2
+ id: "item_#{object.drag_id}",
3
+ draggable: true
4
+ }) do %>
5
+ <%= content.presence %>
6
+ <% end %>
7
+
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbDraggable
5
+ class DraggableItem < ::Playbook::KitBase
6
+ prop :drag_id, type: Playbook::Props::String,
7
+ default: ""
8
+
9
+ def data
10
+ Hash(prop(:data)).merge(pb_draggable_item: true)
11
+ end
12
+
13
+ def classname
14
+ generate_classname("pb_draggable_item")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,125 @@
1
+ import PbEnhancedElement from "../pb_enhanced_element";
2
+
3
+ const DRAGGABLE_SELECTOR = "[data-pb-draggable]";
4
+ const DRAGGABLE_CONTAINER = ".pb_draggable_container";
5
+
6
+ export default class PbDraggable extends PbEnhancedElement {
7
+ static get selector() {
8
+ return DRAGGABLE_SELECTOR;
9
+ }
10
+
11
+ connect() {
12
+ this.draggedItem = null;
13
+ this.draggedItemId = null;
14
+ document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
15
+ }
16
+
17
+ bindEventListeners() {
18
+ // Needed to prevent images within draggable items from being independently draggable
19
+ // Needed if using Image kit in draggable items
20
+ this.element.querySelectorAll(".pb_draggable_item img").forEach(img => {
21
+ img.setAttribute("draggable", "false");
22
+ });
23
+
24
+ this.element.querySelectorAll(".pb_draggable_item").forEach(item => {
25
+ item.addEventListener("dragstart", this.handleDragStart.bind(this));
26
+ item.addEventListener("dragend", this.handleDragEnd.bind(this));
27
+ item.addEventListener("dragenter", this.handleDragEnter.bind(this));
28
+ });
29
+
30
+ const container = this.element.querySelector(DRAGGABLE_CONTAINER);
31
+ if (container) {
32
+ container.addEventListener("dragover", this.handleDragOver.bind(this));
33
+ container.addEventListener("drop", this.handleDrop.bind(this));
34
+ }
35
+ }
36
+
37
+ handleDragStart(event) {
38
+ // Needed to prevent images within draggable items from being independently draggable
39
+ // Needed if using Image kit in draggable items
40
+ if (event.target.tagName.toLowerCase() === 'img') {
41
+ event.preventDefault();
42
+ return;
43
+ }
44
+
45
+ this.draggedItem = event.target;
46
+ this.draggedItemId = event.target.id;
47
+ event.target.classList.add("is_dragging");
48
+
49
+ if (event.dataTransfer) {
50
+ event.dataTransfer.effectAllowed = 'move';
51
+ event.dataTransfer.setData('text/plain', this.draggedItemId);
52
+ }
53
+
54
+ setTimeout(() => {
55
+ event.target.style.opacity = '0.5';
56
+ }, 0);
57
+ }
58
+
59
+ handleDragEnter(event) {
60
+ if (!this.draggedItem || event.target === this.draggedItem) return;
61
+
62
+ const targetItem = event.target.closest('.pb_draggable_item');
63
+ if (!targetItem) return;
64
+
65
+ const container = targetItem.parentNode;
66
+ const items = Array.from(container.children);
67
+ const draggedIndex = items.indexOf(this.draggedItem);
68
+ const targetIndex = items.indexOf(targetItem);
69
+
70
+ if (draggedIndex > targetIndex) {
71
+ container.insertBefore(this.draggedItem, targetItem);
72
+ } else {
73
+ container.insertBefore(this.draggedItem, targetItem.nextSibling);
74
+ }
75
+ }
76
+
77
+ handleDragOver(event) {
78
+ event.preventDefault();
79
+ const container = event.target.closest(DRAGGABLE_CONTAINER);
80
+
81
+ if (container) {
82
+ container.classList.add("active_container");
83
+ }
84
+ }
85
+
86
+ handleDrop(event) {
87
+ event.preventDefault();
88
+ const container = event.target.closest(DRAGGABLE_CONTAINER);
89
+ if (!container || !this.draggedItem) return;
90
+
91
+ container.classList.remove("active_container");
92
+ this.draggedItem.style.opacity = '1';
93
+
94
+ // Updated order of items as an array of item IDs
95
+ const reorderedItems = Array.from(container.children)
96
+ .filter(item => item.classList.contains("pb_draggable_item"))
97
+ .map(item => item.id.replace("item_", ""));
98
+
99
+ // Store reordered items in a data attribute on the container
100
+ container.setAttribute("data-reordered-items", JSON.stringify(reorderedItems));
101
+
102
+ const customEvent = new CustomEvent('pb-draggable-reorder', {
103
+ detail: {
104
+ reorderedItems,
105
+ containerId: container.id,
106
+ }
107
+ });
108
+ this.element.dispatchEvent(customEvent);
109
+
110
+ this.draggedItem = null;
111
+ this.draggedItemId = null;
112
+ }
113
+
114
+
115
+ handleDragEnd(event) {
116
+ event.target.classList.remove("is_dragging");
117
+ event.target.style.opacity = '1';
118
+ this.draggedItem = null;
119
+ this.draggedItemId = null;
120
+
121
+ this.element.querySelectorAll(DRAGGABLE_CONTAINER).forEach(container => {
122
+ container.classList.remove("active_container");
123
+ });
124
+ }
125
+ }