playbook_ui 14.21.0.pre.rc.0 → 14.21.0.pre.rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +8 -0
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
- data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +108 -2
- data/app/pb_kits/playbook/pb_dropdown/index.js +24 -0
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
- data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
- data/dist/chunks/{_typeahead-BmOWdDtp.js → _typeahead-CRW6dJbW.js} +1 -1
- data/dist/chunks/{_weekday_stacked-CvcuQyr9.js → _weekday_stacked-C4d17aYW.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feaf6f2c267cd3a356273dca3cb6ce00b49ceb72745c5fd8f3e217d9262b4a32
|
4
|
+
data.tar.gz: e5d40c29302026274aa4ad7557de1d057d3dd18addbdc530ca3ecdee1f068e94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eafcb51b853cd63b2d3744c88be09685bdb4e12657fbcbea9ccca1af21b630057300f9cb90a216c385dd32406c325edbcd22e06328a312a366b77fbd37826552
|
7
|
+
data.tar.gz: d44e83bea74f94b307b6fee2d8ddb7d5973d9b315868ae58c928665ccfb944475c681cda5de75f6b3fda503cdb58d6d27b3ddab160714d3d8c63c8703a31e06d
|
@@ -368,6 +368,10 @@
|
|
368
368
|
box-shadow: 1px 0px 0px 0px var(--column-border-color) !important;
|
369
369
|
}
|
370
370
|
|
371
|
+
.pb_table_td:nth-child(2) {
|
372
|
+
box-shadow: inset 1px 0px 0px 0px var(--column-border-color) !important;
|
373
|
+
}
|
374
|
+
|
371
375
|
// Color for collapsible trail
|
372
376
|
.collapsible-trail {
|
373
377
|
background-color: $border_light !important;
|
@@ -564,6 +568,10 @@
|
|
564
568
|
box-shadow: $shadow_deep !important;
|
565
569
|
}
|
566
570
|
|
571
|
+
.pb_table_td:nth-child(2) {
|
572
|
+
box-shadow: 0 0 0 0 !important;
|
573
|
+
}
|
574
|
+
|
567
575
|
.pb_advanced_table_header,
|
568
576
|
.pb_advanced_table_body {
|
569
577
|
th.sticky-left,
|
@@ -1,16 +1,9 @@
|
|
1
1
|
<%= pb_content_tag(:label) do %>
|
2
2
|
<%= content.presence || object.input %>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
</span>
|
8
|
-
<% else %>
|
9
|
-
<span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
|
10
|
-
<%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
|
11
|
-
<%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
|
12
|
-
</span>
|
13
|
-
<% end %>
|
3
|
+
<span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
|
4
|
+
<%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
|
5
|
+
<%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
|
6
|
+
</span>
|
14
7
|
<span class="pb_checkbox_label">
|
15
8
|
<%= pb_rails("body", props: { status: object.checkbox_label_status, text: object.text, dark: object.dark, margin_right: object.form_spacing ? "xs" : "" }) %>
|
16
9
|
</span>
|
@@ -5,7 +5,8 @@ module Playbook
|
|
5
5
|
class Checkbox < Playbook::KitBase
|
6
6
|
prop :error, type: Playbook::Props::Boolean, default: false
|
7
7
|
prop :checked, type: Playbook::Props::Boolean, default: false
|
8
|
-
prop :
|
8
|
+
prop :indeterminate_main, type: Playbook::Props::Boolean, default: false
|
9
|
+
prop :indeterminate_parent
|
9
10
|
prop :text
|
10
11
|
prop :value
|
11
12
|
prop :name
|
@@ -19,7 +20,7 @@ module Playbook
|
|
19
20
|
default: false
|
20
21
|
|
21
22
|
def classname
|
22
|
-
generate_classname("pb_checkbox_kit", checked_class) +
|
23
|
+
generate_classname("pb_checkbox_kit", checked_class) + error_class
|
23
24
|
end
|
24
25
|
|
25
26
|
def input
|
@@ -30,6 +31,13 @@ module Playbook
|
|
30
31
|
error ? "negative" : nil
|
31
32
|
end
|
32
33
|
|
34
|
+
def data
|
35
|
+
Hash(prop(:data)).merge(
|
36
|
+
pb_checkbox_indeterminate_main: indeterminate_main,
|
37
|
+
pb_checkbox_indeterminate_parent: indeterminate_parent
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
33
41
|
private
|
34
42
|
|
35
43
|
def error_class
|
@@ -39,10 +47,6 @@ module Playbook
|
|
39
47
|
def checked_class
|
40
48
|
checked ? "on" : "off"
|
41
49
|
end
|
42
|
-
|
43
|
-
def indeterminate_class
|
44
|
-
indeterminate ? " indeterminate" : ""
|
45
|
-
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -9,11 +9,10 @@
|
|
9
9
|
<tr>
|
10
10
|
<th>
|
11
11
|
<%= pb_rails("checkbox", props: {
|
12
|
-
checked: true,
|
13
12
|
text: "Uncheck All",
|
14
13
|
value: "checkbox-value",
|
15
14
|
name: "main-checkbox",
|
16
|
-
|
15
|
+
indeterminate_main: true,
|
17
16
|
id: "indeterminate-checkbox"
|
18
17
|
}) %>
|
19
18
|
</th>
|
@@ -30,55 +29,10 @@
|
|
30
29
|
value: checkbox[:id],
|
31
30
|
name: "#{checkbox[:id]}-indeterminate-checkbox",
|
32
31
|
id: "#{checkbox[:id]}-indeterminate-checkbox",
|
32
|
+
indeterminate_parent: "indeterminate-checkbox",
|
33
33
|
}) %>
|
34
34
|
</td>
|
35
35
|
</tr>
|
36
36
|
<% end %>
|
37
37
|
</tbody>
|
38
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>
|
@@ -0,0 +1 @@
|
|
1
|
+
If you want to use indeterminate, "check/uncheck all" checkboxes, add `indeterminate_main: true` and an `id` to the main checkbox. Then, add an `indeterminate_parent` prop with the main checkbox's `id` to the children checkboxes.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import PbEnhancedElement from "../pb_enhanced_element"
|
2
|
+
|
3
|
+
const INDETERMINATE_MAIN_CHECKBOX_SELECTOR = "[data-pb-checkbox-indeterminate-main='true']"
|
4
|
+
|
5
|
+
export default class PbCheckbox extends PbEnhancedElement {
|
6
|
+
static get selector() {
|
7
|
+
return INDETERMINATE_MAIN_CHECKBOX_SELECTOR
|
8
|
+
}
|
9
|
+
|
10
|
+
connect() {
|
11
|
+
const mainCheckboxWrapper = this.element;
|
12
|
+
const mainCheckbox = mainCheckboxWrapper.querySelector('input')
|
13
|
+
const childCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${this.element.id}"] input[type="checkbox"]`);
|
14
|
+
|
15
|
+
const updateMainCheckbox = () => {
|
16
|
+
// Count the number of checked child checkboxes
|
17
|
+
const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
|
18
|
+
// Determine if the main checkbox should be in an indeterminate state
|
19
|
+
const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
|
20
|
+
|
21
|
+
// Set the main checkbox states
|
22
|
+
mainCheckbox.indeterminate = indeterminate;
|
23
|
+
mainCheckbox.checked = checkedCount > 0;
|
24
|
+
|
25
|
+
// Determine the main checkbox label based on the number of checked checkboxes
|
26
|
+
const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
|
27
|
+
|
28
|
+
// Determine the icon class to add and remove based on the number of checked checkboxes
|
29
|
+
const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
|
30
|
+
const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
|
31
|
+
|
32
|
+
// Update main checkbox label
|
33
|
+
mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
|
34
|
+
|
35
|
+
// Add and remove the icon class to the main checkbox wrapper
|
36
|
+
mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
|
37
|
+
mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
|
38
|
+
|
39
|
+
// Toggle the visibility of the checkbox icon based on the indeterminate state
|
40
|
+
mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
|
41
|
+
mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
|
42
|
+
};
|
43
|
+
|
44
|
+
// Set indeterminate icon on main checkbox if initial children checkboxes are checked
|
45
|
+
updateMainCheckbox();
|
46
|
+
|
47
|
+
this.element.querySelector('input').addEventListener('change', function() {
|
48
|
+
childCheckboxes.forEach(cb => cb.checked = this.checked);
|
49
|
+
updateMainCheckbox();
|
50
|
+
});
|
51
|
+
|
52
|
+
childCheckboxes.forEach(cb => {
|
53
|
+
cb.addEventListener('change', updateMainCheckbox);
|
54
|
+
});
|
55
|
+
}
|
56
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from "react"
|
2
|
-
import { render, screen } from "../utilities/test-utils"
|
2
|
+
import { render, screen, fireEvent } from "../utilities/test-utils"
|
3
3
|
|
4
4
|
import { Dropdown, Icon, IconCircle } from 'playbook-ui'
|
5
5
|
|
@@ -263,4 +263,110 @@ test("searchbar prop to render TextInput in container", () => {
|
|
263
263
|
const kit = screen.getByTestId(testId)
|
264
264
|
const searchbar = kit.querySelector('.pb_text_input_kit')
|
265
265
|
expect(searchbar).toBeInTheDocument()
|
266
|
-
})
|
266
|
+
})
|
267
|
+
|
268
|
+
test("MultiSelect prop to allow multiple selections + add correct Form Pills", () => {
|
269
|
+
render(
|
270
|
+
<Dropdown
|
271
|
+
data={{ testid: testId }}
|
272
|
+
multiSelect
|
273
|
+
options={options}
|
274
|
+
/>
|
275
|
+
);
|
276
|
+
|
277
|
+
const kit = screen.getByTestId(testId);
|
278
|
+
const option = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
|
279
|
+
fireEvent.click(option[0]); // Select first option
|
280
|
+
fireEvent.click(option[1]); // Select second option
|
281
|
+
const formPills = kit.querySelectorAll(".pb_form_pill_kit_primary");
|
282
|
+
expect(formPills.length).toBe(2);
|
283
|
+
expect(formPills[0]).toHaveTextContent("United States");
|
284
|
+
expect(formPills[1]).toHaveTextContent("Canada");
|
285
|
+
});
|
286
|
+
|
287
|
+
test("hides each selected option from the dropdown", () => {
|
288
|
+
|
289
|
+
render(
|
290
|
+
<Dropdown
|
291
|
+
data={{ testid: testId }}
|
292
|
+
multiSelect
|
293
|
+
options={options}
|
294
|
+
/>
|
295
|
+
);
|
296
|
+
|
297
|
+
const kit = screen.getByTestId(testId);
|
298
|
+
const option = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
|
299
|
+
const firstOpt = options[0].label
|
300
|
+
fireEvent.click(option[0]);
|
301
|
+
const option2 = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
|
302
|
+
expect(option2[0]).not.toHaveTextContent(firstOpt)
|
303
|
+
})
|
304
|
+
|
305
|
+
test("renders form pills inside trigger", () => {
|
306
|
+
render(
|
307
|
+
<Dropdown
|
308
|
+
data={{ testid: testId }}
|
309
|
+
multiSelect
|
310
|
+
options={options}
|
311
|
+
/>
|
312
|
+
);
|
313
|
+
|
314
|
+
const kit = screen.getByTestId(testId)
|
315
|
+
const option = kit.querySelector('.pb_dropdown_option_list')
|
316
|
+
fireEvent.click(option)
|
317
|
+
const formPill = kit.querySelector(".pb_form_pill_kit_primary")
|
318
|
+
expect(formPill).toBeInTheDocument()
|
319
|
+
})
|
320
|
+
|
321
|
+
test("multiSelect and autocomplete to work together", () => {
|
322
|
+
render (
|
323
|
+
<Dropdown
|
324
|
+
autocomplete
|
325
|
+
data={{ testid: testId }}
|
326
|
+
multiSelect
|
327
|
+
options={options}
|
328
|
+
/>
|
329
|
+
)
|
330
|
+
|
331
|
+
const kit = screen.getByTestId(testId)
|
332
|
+
const input = kit.querySelector('.dropdown_input')
|
333
|
+
expect(input).toBeInTheDocument()
|
334
|
+
const option = kit.querySelector('.pb_dropdown_option_list')
|
335
|
+
fireEvent.click(option)
|
336
|
+
const formPill = kit.querySelector(".pb_form_pill_kit_primary")
|
337
|
+
expect(formPill).toBeInTheDocument()
|
338
|
+
})
|
339
|
+
|
340
|
+
test("renders form pills with size and color", () => {
|
341
|
+
render(
|
342
|
+
<Dropdown
|
343
|
+
data={{ testid: testId }}
|
344
|
+
formPillProps={{ size: "small", color: "neutral" }}
|
345
|
+
multiSelect
|
346
|
+
options={options}
|
347
|
+
/>
|
348
|
+
);
|
349
|
+
|
350
|
+
const kit = screen.getByTestId(testId)
|
351
|
+
const option = kit.querySelector('.pb_dropdown_option_list')
|
352
|
+
fireEvent.click(option)
|
353
|
+
const formPill = kit.querySelector(".pb_form_pill_kit_neutral")
|
354
|
+
expect(formPill).toBeInTheDocument()
|
355
|
+
expect(formPill).toHaveClass("small")
|
356
|
+
})
|
357
|
+
|
358
|
+
test("defaultValue works with multiSelect", () => {
|
359
|
+
render(
|
360
|
+
<Dropdown
|
361
|
+
data={{ testid: testId }}
|
362
|
+
defaultValue={[options[0], options[2]]}
|
363
|
+
multiSelect
|
364
|
+
options={options}
|
365
|
+
/>
|
366
|
+
)
|
367
|
+
const kit = screen.getByTestId(testId)
|
368
|
+
expect(kit.querySelectorAll(".pb_form_pill_kit_primary")).toHaveLength(2)
|
369
|
+
const option2 = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
|
370
|
+
const firstOpt = options[0].label
|
371
|
+
expect(option2[0]).not.toHaveTextContent(firstOpt)
|
372
|
+
})
|
@@ -115,6 +115,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
115
115
|
|
116
116
|
handleSearch(term = "") {
|
117
117
|
const lcTerm = term.toLowerCase();
|
118
|
+
let hasMatch = false
|
118
119
|
this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
|
119
120
|
//make it so that if the option is selected, it will not show up in the search results
|
120
121
|
if (this.isMultiSelect && this.selectedOptions.has(opt.dataset.dropdownOptionLabel)) {
|
@@ -128,9 +129,32 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
128
129
|
// hide or show option
|
129
130
|
const match = label.includes(lcTerm);
|
130
131
|
opt.style.display = match ? "" : "none";
|
132
|
+
if (match) hasMatch = true
|
131
133
|
});
|
132
134
|
|
133
135
|
this.adjustDropdownHeight();
|
136
|
+
|
137
|
+
this.removeNoOptionsMessage()
|
138
|
+
if (!hasMatch) {
|
139
|
+
this.showNoOptionsMessage()
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
showNoOptionsMessage() {
|
144
|
+
if (this.element.querySelector(".dropdown_no_options")) return;
|
145
|
+
|
146
|
+
const noOptionElement = document.createElement("div");
|
147
|
+
noOptionElement.className = "pb_body_kit_light dropdown_no_options pb_item_kit p_xs display_flex justify_content_center";
|
148
|
+
noOptionElement.textContent = "no option";
|
149
|
+
|
150
|
+
this.target.appendChild(noOptionElement);
|
151
|
+
}
|
152
|
+
|
153
|
+
removeNoOptionsMessage() {
|
154
|
+
const existing = this.element.querySelector(".dropdown_no_options");
|
155
|
+
if (existing) {
|
156
|
+
existing.remove();
|
157
|
+
}
|
134
158
|
}
|
135
159
|
|
136
160
|
handleOptionClick(event) {
|
@@ -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,
|
data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx
ADDED
@@ -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.
|
@@ -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:
|
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:
|
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,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
checked: true,
|
19
19
|
value: "checkbox-value",
|
20
20
|
name: "main-checkbox-selectable",
|
21
|
-
|
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 %>
|