playbook_ui 14.20.0.pre.rc.2 → 14.21.0.pre.alpha.PLAY2167advtablenitrorowborderdoubling8097

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +116 -49
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +61 -35
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +37 -23
  6. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +58 -2
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +16 -4
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +7 -3
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +46 -21
  11. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -3
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +16 -1
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +61 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -2
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +1 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.html.erb +33 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +0 -1
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +57 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.html.erb +33 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.jsx +53 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +8 -2
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
  31. data/app/pb_kits/playbook/pb_advanced_table/index.js +157 -12
  32. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  33. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  34. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -0
  35. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
  36. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
  37. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
  38. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
  39. data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
  40. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_date_display.html.erb +13 -0
  41. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +17 -58
  42. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -1
  43. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +86 -19
  44. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +42 -0
  45. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +1 -0
  46. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
  47. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
  48. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
  49. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
  50. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
  51. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
  52. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
  53. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
  54. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
  55. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
  59. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
  60. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
  61. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
  62. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
  63. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +13 -1
  64. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +6 -0
  65. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
  66. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +16 -2
  67. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +108 -2
  68. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +34 -13
  69. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +3 -1
  70. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
  71. data/app/pb_kits/playbook/pb_dropdown/index.js +357 -40
  72. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
  73. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +26 -18
  74. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +96 -19
  75. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
  76. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  77. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
  78. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
  79. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
  80. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
  81. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
  82. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  83. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
  84. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  85. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  86. data/app/pb_kits/playbook/pb_popover/index.ts +9 -4
  87. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
  88. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
  89. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
  90. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  91. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  92. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
  93. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
  94. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
  95. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
  96. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
  97. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
  98. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  99. data/dist/chunks/_typeahead-CoOpeYom.js +22 -0
  100. data/dist/chunks/_weekday_stacked-B_jpa2Rz.js +45 -0
  101. data/dist/chunks/lib-D7Va7yqa.js +29 -0
  102. data/dist/chunks/{pb_form_validation-WWvUXPKD.js → pb_form_validation-DSkdRDMf.js} +1 -1
  103. data/dist/chunks/vendor.js +1 -1
  104. data/dist/menu.yml +1 -1
  105. data/dist/playbook-doc.js +2 -2
  106. data/dist/playbook-rails-react-bindings.js +1 -1
  107. data/dist/playbook-rails.js +1 -1
  108. data/dist/playbook.css +1 -1
  109. data/lib/playbook/kit_base.rb +3 -3
  110. data/lib/playbook/version.rb +2 -2
  111. metadata +48 -7
  112. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
  113. data/dist/chunks/_typeahead-B9-s4j4U.js +0 -22
  114. data/dist/chunks/_weekday_stacked-CvzpmXD5.js +0 -45
  115. data/dist/chunks/lib-B20MXZcW.js +0 -29
@@ -10,6 +10,7 @@ import { globalProps } from "../../utilities/globalProps";
10
10
  import { useHandleOnKeyDown } from "../hooks/useHandleOnKeydown";
11
11
 
12
12
  import DropdownContext from "../context";
13
+ import MultiSelectTriggerDisplay from "./MultiSelectTriggerDisplay";
13
14
 
14
15
  import Body from "../../pb_body/_body";
15
16
  import Icon from "../../pb_icon/_icon";
@@ -43,14 +44,18 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
43
44
 
44
45
  const {
45
46
  autocomplete,
47
+ closeOnSelection,
46
48
  filterItem,
49
+ handleBackspace,
47
50
  handleChange,
48
51
  handleWrapperClick,
49
52
  inputRef,
50
53
  inputWrapperRef,
51
54
  isDropDownClosed,
52
55
  isInputFocused,
56
+ multiSelect,
53
57
  selected,
58
+ setIsDropDownClosed,
54
59
  setIsInputFocused,
55
60
  toggleDropdown,
56
61
  } = useContext(DropdownContext);
@@ -69,9 +74,19 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
69
74
  const triggerWrapperClasses = buildCss(
70
75
  "dropdown_trigger_wrapper",
71
76
  isInputFocused && "focus",
72
- !autocomplete && "select_only"
77
+ !autocomplete && !multiSelect && "select_only"
73
78
  );
74
79
 
80
+ const selectedArray = Array.isArray(selected)
81
+ ? selected
82
+ : selected && Object.keys(selected).length
83
+ ? [selected]
84
+ : [];
85
+
86
+ const joinedLabels = multiSelect
87
+ ? ""
88
+ : selectedArray.map((option) => option.label).join(", ");
89
+
75
90
  const customDisplayPlaceholder = selected?.label ? (
76
91
  ""
77
92
  ) : autocomplete ? (
@@ -82,19 +97,34 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
82
97
  "Select..."
83
98
  );
84
99
 
85
- const defaultDisplayPlaceholder = selected?.label
86
- ? selected.label
100
+ const defaultDisplayPlaceholder = joinedLabels
101
+ ? joinedLabels
87
102
  : autocomplete
88
103
  ? ""
89
104
  : placeholder
90
105
  ? placeholder
91
106
  : "Select...";
92
107
 
108
+ // Click handler that respects closeOnSelection
109
+ const handleInputClick = (e: React.MouseEvent) => {
110
+ e.stopPropagation(); // keep the wrapper's handler from firing
111
+ if (isDropDownClosed) {
112
+ // Always open if closed
113
+ setIsDropDownClosed(false);
114
+ } else if (!closeOnSelection) {
115
+ // Keep open if closeOnSelection is false
116
+ return;
117
+ } else {
118
+ // Default behavior - toggle
119
+ toggleDropdown();
120
+ }
121
+ };
122
+
93
123
  return (
94
- <div {...ariaProps}
95
- {...dataProps}
124
+ <div {...ariaProps}
125
+ {...dataProps}
96
126
  {...htmlProps}
97
- className={classes}
127
+ className={classes}
98
128
  id={id}
99
129
  >
100
130
  {
@@ -125,34 +155,65 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
125
155
  paddingX="sm"
126
156
  paddingY="xs"
127
157
  >
128
- <FlexItem>
129
- <Flex align="center">
158
+ <FlexItem fixedSize={multiSelect ? "85%" : ""}>
159
+ <Flex align="center"
160
+ wrap
161
+ >
130
162
  {customDisplay ? (
131
163
  <Flex align="center">
132
164
  {customDisplay}
133
- <Body dark={dark}
134
- paddingLeft={`${selected.label ? "xs" : "none"}`}
165
+ <Body dark={dark}
166
+ paddingLeft={`${joinedLabels ? "xs" : "none"}`}
135
167
  >
136
168
  {customDisplayPlaceholder}
137
169
  </Body>
138
170
  </Flex>
139
171
  ) : (
140
- <Body dark={dark}
141
- text={defaultDisplayPlaceholder}
142
- />
172
+ multiSelect ? (
173
+ <>
174
+ <MultiSelectTriggerDisplay
175
+ autocomplete={autocomplete}
176
+ dark={dark}
177
+ placeholder={placeholder}
178
+ selected={selectedArray}
179
+ />
180
+ {autocomplete && (
181
+ <input
182
+ className="dropdown_input"
183
+ onChange={handleChange}
184
+ onClick={handleInputClick}
185
+ onFocus={() => setIsInputFocused(true)}
186
+ onKeyDown={(e) => {
187
+ handleKeyDown(e);
188
+ e.stopPropagation(); //Fixes issue with keyboard accessibility
189
+ }}
190
+ placeholder={
191
+ joinedLabels
192
+ ? ""
193
+ : placeholder
194
+ ? placeholder
195
+ : "Select..."
196
+ }
197
+ ref={inputRef}
198
+ value={filterItem}
199
+ />
200
+ )}
201
+ </>
202
+ ) : (
203
+ <Body dark={dark}
204
+ text={defaultDisplayPlaceholder}
205
+ />
206
+ )
143
207
  )}
144
- {autocomplete && (
208
+ {autocomplete && !multiSelect && (
145
209
  <input
146
210
  className="dropdown_input"
147
211
  onChange={handleChange}
148
- onClick={(e) => {
149
- e.stopPropagation();// keep the wrapper’s handler from firing
150
- toggleDropdown();
151
- }}
212
+ onClick={handleInputClick}
152
213
  onFocus={() => setIsInputFocused(true)}
153
214
  onKeyDown={handleKeyDown}
154
215
  placeholder={
155
- selected.label
216
+ joinedLabels
156
217
  ? ""
157
218
  : placeholder
158
219
  ? placeholder
@@ -164,7 +225,9 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
164
225
  )}
165
226
  </Flex>
166
227
  </FlexItem>
228
+ <FlexItem>
167
229
  <Body
230
+ alignItems="center"
168
231
  dark={dark}
169
232
  display="flex"
170
233
  htmlOptions={{
@@ -172,6 +235,19 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
172
235
  }}
173
236
  key={`${isDropDownClosed ? "chevron-down" : "chevron-up"}`}
174
237
  >
238
+ {
239
+ selectedArray.length > 0 && (
240
+ <div onClick={(e)=>{e.stopPropagation();handleBackspace()}}>
241
+ <Icon
242
+ cursor="pointer"
243
+ dark={dark}
244
+ icon="times"
245
+ paddingRight="xs"
246
+ size="sm"
247
+ />
248
+ </div>
249
+ )
250
+ }
175
251
  <Icon
176
252
  cursor="pointer"
177
253
  dark={dark}
@@ -179,6 +255,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
179
255
  size="sm"
180
256
  />
181
257
  </Body>
258
+ </FlexItem>
182
259
  </Flex>
183
260
  </>
184
261
  )
@@ -0,0 +1,58 @@
1
+ import React, { useContext } from "react";
2
+ import FormPill from "../../pb_form_pill/_form_pill";
3
+ import Flex from "../../pb_flex/_flex";
4
+ import Body from "../../pb_body/_body";
5
+ import { GenericObject } from "../../types";
6
+ import DropdownContext
7
+ from "../context";
8
+ type MultiSelectTriggerDisplayProps = {
9
+ autocomplete?: boolean;
10
+ selected: GenericObject[];
11
+ placeholder?: string;
12
+ dark?: boolean;
13
+ };
14
+
15
+ const MultiSelectTriggerDisplay = ({
16
+ autocomplete,
17
+ selected,
18
+ placeholder,
19
+ dark = false,
20
+ }: MultiSelectTriggerDisplayProps) => {
21
+
22
+ const { setSelected, onSelect, formPillProps } = useContext(DropdownContext);
23
+
24
+ if (selected.length === 0) {
25
+ if (autocomplete) return null;
26
+ return (
27
+ <Body dark={dark}
28
+ text={placeholder ? placeholder : "Select..."}
29
+ />
30
+ )
31
+ }
32
+
33
+ const handleRemoveIconClick = (option: GenericObject) => {
34
+ setSelected((prev: GenericObject[]) => {
35
+ const next = prev.filter((item) => item.label !== option.label);
36
+ onSelect && onSelect(next);
37
+ return next;
38
+ });
39
+ }
40
+
41
+ return (
42
+ <Flex wrap>
43
+ {selected.map((option, i) => (
44
+ <FormPill
45
+ dark={dark}
46
+ key={i}
47
+ marginRight="xs"
48
+ onClick={(e)=>{e.stopPropagation();handleRemoveIconClick(option)}}
49
+ tabIndex={0}
50
+ text={option.label}
51
+ {...formPillProps}
52
+ />
53
+ ))}
54
+ </Flex>
55
+ );
56
+ };
57
+
58
+ export default MultiSelectTriggerDisplay;
@@ -99,6 +99,7 @@
99
99
  <%= form.url_field :example_url_field, props: { label: true } %>
100
100
  <%= form.text_area :example_text_area, props: { label: true } %>
101
101
  <%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options } %>
102
+ <%= form.dropdown_field :example_dropdown_multi, props: { label: true, options: example_dropdown_options, multi_select: true } %>
102
103
  <%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true } %>
103
104
  <%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true } %>
104
105
  <%= form.check_box :example_checkbox,
@@ -98,6 +98,7 @@
98
98
  <%= form.url_field :example_url_field_validation, props: { label: true, required: true } %>
99
99
  <%= form.text_area :example_text_area_validation, props: { label: true, required: true } %>
100
100
  <%= form.dropdown_field :example_dropdown_validation, props: { label: true, options: example_dropdown_options, required: true } %>
101
+ <%= form.dropdown_field :example_dropdown_validation_multi, props: { label: true, options: example_dropdown_options, multi_select: true, required: true } %>
101
102
  <%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true, validation_message: "Please, select an option." } %>
102
103
  <%= form.collection_select :example_collection_select_validation, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
103
104
  <%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
@@ -33,6 +33,7 @@ type PhoneNumberInputProps = {
33
33
  onChange?: (e: React.FormEvent<HTMLInputElement>) => void,
34
34
  onValidate?: Callback<boolean, void>,
35
35
  onlyCountries: string[],
36
+ excludeCountries: string[],
36
37
  preferredCountries?: string[],
37
38
  required?: boolean,
38
39
  value?: string,
@@ -88,6 +89,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
88
89
  },
89
90
  onValidate = () => null,
90
91
  onlyCountries = [],
92
+ excludeCountries = [],
91
93
  required = false,
92
94
  preferredCountries = [],
93
95
  value = "",
@@ -234,6 +236,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
234
236
  const fallbackCountry =
235
237
  preferredCountries.length > 0 ? preferredCountries[0] :
236
238
  onlyCountries.length > 0 ? onlyCountries.sort()[0] :
239
+ excludeCountries.length > 0 ? excludeCountries.sort()[0] :
237
240
  "af";
238
241
 
239
242
  useEffect(() => {
@@ -244,6 +247,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
244
247
  autoInsertDialCode: false,
245
248
  initialCountry: initialCountry || fallbackCountry,
246
249
  onlyCountries,
250
+ excludeCountries,
247
251
  countrySearch: countrySearch,
248
252
  fixDropdownWidth: false,
249
253
  formatAsYouType: formatAsYouType,
@@ -0,0 +1,4 @@
1
+ <%= pb_rails("phone_number_input", props: {
2
+ initial_country: 'gb',
3
+ exclude_countries: ['us', 'br']
4
+ }) %>
@@ -0,0 +1,15 @@
1
+ import React from 'react'
2
+ import PhoneNumberInput from '../../pb_phone_number_input/_phone_number_input'
3
+
4
+ const PhoneNumberInputExcludeCountries = (props) => (
5
+ <>
6
+ <PhoneNumberInput
7
+ excludeCountries={['us', 'br']}
8
+ id='exclude'
9
+ initialCountry='gb'
10
+ {...props}
11
+ />
12
+ </>
13
+ )
14
+
15
+ export default PhoneNumberInputExcludeCountries
@@ -0,0 +1 @@
1
+ Excluding countries removes the selected countries from the dropdown.
@@ -6,7 +6,7 @@ const PhoneNumberInputOnlyCountries = (props) => (
6
6
  <PhoneNumberInput
7
7
  id='only'
8
8
  onlyCountries={['us', 'br']}
9
- {...props}
9
+ {...props}
10
10
  />
11
11
  </>
12
12
  )
@@ -4,7 +4,8 @@ examples:
4
4
  - phone_number_input_default: Default
5
5
  - phone_number_input_preferred_countries: Preferred Countries
6
6
  - phone_number_input_initial_country: Initial Country
7
- - phone_number_input_only_countries: Limited Countries
7
+ - phone_number_input_only_countries: Only Countries
8
+ - phone_number_input_exclude_countries: Exclude Countries
8
9
  - phone_number_input_validation: Form Validation
9
10
  - phone_number_input_clear_field: Clearing the Input Field
10
11
  - phone_number_input_access_input_element: Accessing the Input Element
@@ -15,9 +16,9 @@ examples:
15
16
  - phone_number_input_default: Default
16
17
  - phone_number_input_preferred_countries: Preferred Countries
17
18
  - phone_number_input_initial_country: Initial Country
18
- - phone_number_input_only_countries: Limited Countries
19
+ - phone_number_input_only_countries: Only Countries
20
+ - phone_number_input_exclude_countries: Exclude Countries
19
21
  - phone_number_input_validation: Form Validation
20
22
  - phone_number_input_format: Format as You Type
21
23
  - phone_number_input_hidden_inputs: Hidden Inputs
22
24
  - phone_number_input_country_search: Country Search
23
-
@@ -2,6 +2,7 @@ export { default as PhoneNumberInputDefault } from './_phone_number_input_defaul
2
2
  export { default as PhoneNumberInputPreferredCountries } from './_phone_number_input_preferred_countries'
3
3
  export { default as PhoneNumberInputInitialCountry } from './_phone_number_input_initial_country'
4
4
  export { default as PhoneNumberInputOnlyCountries } from './_phone_number_input_only_countries'
5
+ export { default as PhoneNumberInputExcludeCountries } from './_phone_number_input_exclude_countries'
5
6
  export { default as PhoneNumberInputValidation } from './_phone_number_input_validation'
6
7
  export { default as PhoneNumberInputClearField } from './_phone_number_input_clear_field'
7
8
  export { default as PhoneNumberInputAccessInputElement } from './_phone_number_input_access_input_element'
@@ -15,6 +15,8 @@ module Playbook
15
15
  default: ""
16
16
  prop :only_countries, type: Playbook::Props::Array,
17
17
  default: []
18
+ prop :exclude_countries, type: Playbook::Props::Array,
19
+ default: []
18
20
  prop :preferred_countries, type: Playbook::Props::Array,
19
21
  default: []
20
22
  prop :error, type: Playbook::Props::String,
@@ -44,6 +46,7 @@ module Playbook
44
46
  label: label,
45
47
  name: name,
46
48
  onlyCountries: only_countries,
49
+ excludeCountries: exclude_countries,
47
50
  preferredCountries: preferred_countries,
48
51
  required: required,
49
52
  value: value,
@@ -13,19 +13,24 @@ export default class PbPopover extends PbEnhancedElement {
13
13
  }
14
14
 
15
15
  moveTooltip() {
16
- let container: HTMLElement | null;
16
+ let container: HTMLElement | null = document.querySelector('body');
17
17
 
18
18
  if (this.appendTo === "parent") {
19
- container = this.element.parentElement;
19
+ container = this.element.parentElement && this.element.parentElement
20
20
  } else if (this.appendTo) {
21
- container = document.querySelector(this.appendTo);
21
+ container = document.querySelector(this.appendTo)
22
22
  }
23
23
 
24
- (container || document.body).appendChild(this.tooltip);
24
+ container.appendChild(this.tooltip);
25
25
  }
26
26
 
27
27
  connect() {
28
+ if (!this.triggerElement || !this.tooltip) {
29
+ console.warn('Popover requires both trigger and tooltip elements to be defined.')
30
+ return
31
+ }
28
32
  this.moveTooltip()
33
+
29
34
  this.popper = createPopper (this.triggerElement, this.tooltip, {
30
35
  placement: this.position as Placement,
31
36
  strategy: 'fixed',
@@ -0,0 +1,12 @@
1
+ <%= pb_rails("select", props: { label: "Favorite Animal" }) do %>
2
+ <select name="animal" id="animal">
3
+ <optgroup label="Mammal">
4
+ <option value="1">Cat</option>
5
+ <option value="2">Dog</option>
6
+ </optgroup>
7
+ <optgroup label="Amphibian">
8
+ <option value="3">Frog</option>
9
+ <option value="4">Salamander</option>
10
+ </optgroup>
11
+ </select>
12
+ <% end %>
@@ -0,0 +1,31 @@
1
+ import React from 'react'
2
+
3
+ import Select from '../_select'
4
+
5
+ const SelectCustomSelectSubheaders = (props) => {
6
+ return (
7
+ <div>
8
+ <Select
9
+ label="Favorite Animal"
10
+ {...props}
11
+ >
12
+ <select
13
+ id="animal"
14
+ name="animal"
15
+ {...props}
16
+ >
17
+ <optgroup label="Mammal">
18
+ <option value="1">{'Cat'}</option>
19
+ <option value="2">{'Dog'}</option>
20
+ </optgroup>
21
+ <optgroup label="Amphibian">
22
+ <option value="3">{'Frog'}</option>
23
+ <option value="4">{'Salamander'}</option>
24
+ </optgroup>
25
+ </select>
26
+ </Select>
27
+ </div>
28
+ )
29
+ }
30
+
31
+ export default SelectCustomSelectSubheaders
@@ -0,0 +1 @@
1
+ To create a select with non-selectable subheaders, use a Custom Select component to render a native `<select>` containing `<optgroup>` elements. The [optgroup HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/optgroup) groups related options under a non-selectable label in the dropdown.
@@ -8,6 +8,7 @@ examples:
8
8
  - select_required: Required Select Field
9
9
  - select_value_text_same: Equal option value and value text
10
10
  - select_custom_select: Custom Select
11
+ - select_custom_select_subheaders: Custom Select Subheaders
11
12
  - select_error: Select w/ Error
12
13
  - select_inline: Select Inline
13
14
  - select_inline_show_arrow: Select Inline (Always Show Arrow)
@@ -25,6 +26,7 @@ examples:
25
26
  - select_required: Required Select Field
26
27
  - select_value_text_same: Equal option value and value text
27
28
  - select_custom_select: Custom Select
29
+ - select_custom_select_subheaders: Custom Select Subheaders
28
30
  - select_error: Select w/ Error
29
31
  - select_inline: Select Inline
30
32
  - select_inline_show_arrow: Select Inline (Always Show Arrow)
@@ -11,3 +11,4 @@ export { default as SelectInlineShowArrow } from './_select_inline_show_arrow.js
11
11
  export { default as SelectInlineCompact } from './_select_inline_compact.jsx'
12
12
  export { default as SelectMultiple } from './_select_multiple.jsx'
13
13
  export { default as SelectReactHook } from './_select_react_hook.jsx'
14
+ export { default as SelectCustomSelectSubheaders } from './_select_custom_select_subheaders.jsx'
@@ -18,7 +18,7 @@
18
18
  checked: true,
19
19
  value: "checkbox-value",
20
20
  name: "main-checkbox-selectable",
21
- indeterminate: true,
21
+ indeterminate_main: true,
22
22
  id: "checkbox-selectable"
23
23
  }) %>
24
24
  <% end %>
@@ -33,7 +33,7 @@
33
33
  <% checkboxes.each_with_index do |checkbox, index| %>
34
34
  <%= pb_rails("table/table_row") do %>
35
35
  <%= pb_rails("table/table_cell") do %>
36
- <%= pb_rails("checkbox", props: { checked: checkbox[:checked], id: "#{checkbox[:id]}-selectable-checkbox", name: "#{checkbox[:id]}-selectable-checkbox", on_change: "updateCheckboxes(#{index})", value: "check-box value" }) %>
36
+ <%= pb_rails("checkbox", props: { checked: checkbox[:checked], id: "#{checkbox[:id]}-selectable-checkbox", name: "#{checkbox[:id]}-selectable-checkbox", on_change: "updateCheckboxes(#{index})", value: "check-box value", indeterminate_parent: "checkbox-selectable" }) %>
37
37
  <% end %>
38
38
  <%= pb_rails("table/table_cell") do %>
39
39
  <%= pb_rails("image", props: { alt: "picture of a misty forest", size: "xs", url: "https://unsplash.it/500/400/?image=634" }) %>
@@ -45,52 +45,4 @@
45
45
  <% end %>
46
46
  <% end %>
47
47
  <% end %>
48
- <% end %>
49
-
50
- <script>
51
- document.addEventListener('DOMContentLoaded', function() {
52
- const mainCheckboxWrapper = document.getElementById('checkbox-selectable');
53
- const mainCheckbox = document.getElementsByName("main-checkbox-selectable")[0];
54
- const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="selectable-checkbox"]');
55
- const deleteButton = document.getElementById('delete-button');
56
-
57
- const updateDeleteButton = () => {
58
- const anyChecked = Array.from(childCheckboxes).some(checkbox => checkbox.checked);
59
- deleteButton.style.display = anyChecked ? 'block' : 'none';
60
- };
61
-
62
- const updateMainCheckbox = () => {
63
- // Count the number of checked child checkboxes
64
- const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
65
- // Determine if the main checkbox should be in an indeterminate state
66
- const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
67
-
68
- // Set the main checkbox states
69
- mainCheckbox.indeterminate = indeterminate;
70
- mainCheckbox.checked = checkedCount > 0;
71
-
72
- // Determine the icon class to add and remove based on the number of checked checkboxes
73
- const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
74
- const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
75
-
76
- // Add and remove the icon class to the main checkbox wrapper
77
- mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
78
- mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
79
-
80
- // Toggle the visibility of the checkbox icon based on the indeterminate state
81
- mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
82
- mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
83
-
84
- updateDeleteButton();
85
- };
86
-
87
- mainCheckbox.addEventListener('change', function() {
88
- childCheckboxes.forEach(cb => cb.checked = this.checked);
89
- updateMainCheckbox();
90
- });
91
-
92
- childCheckboxes.forEach(cb => {
93
- cb.addEventListener('change', updateMainCheckbox);
94
- });
95
- });
96
- </script>
48
+ <% end %>
@@ -3,7 +3,7 @@
3
3
  @import "../../pb_caption/caption_mixin";
4
4
 
5
5
  @media only screen and (max-width: $screen-xs-max) {
6
- [class^=pb_table] {
6
+ [class^=pb_table]:not(.table-responsive-scroll) {
7
7
  &.table-sm.table-collapse-sm,
8
8
  &.table-md.table-collapse-sm,
9
9
  &.table-lg.table-collapse-sm {