@studiocms/ui 0.4.0 → 0.4.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.
- package/dist/components/Accordion/accordion.d.ts +1 -1
- package/dist/components/Accordion/accordion.js +68 -65
- package/dist/components/Checkbox/checkbox.d.ts +1 -2
- package/dist/components/Checkbox/checkbox.js +22 -19
- package/dist/components/Progress/progress.d.ts +1 -1
- package/dist/components/Progress/progress.js +11 -8
- package/dist/components/RadioGroup/radiogroup.d.ts +1 -1
- package/dist/components/RadioGroup/radiogroup.js +48 -45
- package/dist/components/SearchSelect/searchselect.d.ts +1 -1
- package/dist/components/SearchSelect/searchselect.js +156 -153
- package/dist/components/Tabs/tabs.d.ts +1 -1
- package/dist/components/Tabs/tabs.js +77 -74
- package/dist/components/Toggle/toggle.d.ts +1 -2
- package/dist/components/Toggle/toggle.js +22 -19
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare function loadAccordions(): void;
|
|
@@ -1,70 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
content.classList.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const open = item.dataset.open === "true";
|
|
18
|
-
if (open) {
|
|
19
|
-
item.classList.add("active");
|
|
20
|
-
content.style.maxHeight = `${contentBoundingBox.height}px`;
|
|
21
|
-
}
|
|
22
|
-
const toggleElement = () => {
|
|
23
|
-
if (!multipleOpen) {
|
|
24
|
-
for (const otherItem of items) {
|
|
25
|
-
if (otherItem !== item) {
|
|
26
|
-
otherItem.classList.remove("active");
|
|
27
|
-
const otherContent = otherItem.querySelector(".sui-accordion-details");
|
|
28
|
-
if (otherContent) {
|
|
29
|
-
otherContent.style.maxHeight = "0";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
function loadAccordions() {
|
|
2
|
+
const allAccordions = document.querySelectorAll(".sui-accordion");
|
|
3
|
+
for (const accordion of allAccordions) {
|
|
4
|
+
const multipleOpen = accordion.dataset.multiple === "true";
|
|
5
|
+
const items = accordion.querySelectorAll(".sui-accordion-item");
|
|
6
|
+
for (const item of items) {
|
|
7
|
+
const summary = item.querySelector(".sui-accordion-summary");
|
|
8
|
+
const content = item.querySelector(".sui-accordion-details");
|
|
9
|
+
if (!content || !summary) continue;
|
|
10
|
+
const itemWidth = item.getBoundingClientRect().width;
|
|
11
|
+
content.style.width = `${itemWidth - 36}px`;
|
|
12
|
+
let contentBoundingBox = content.getBoundingClientRect();
|
|
13
|
+
content.style.width = "auto";
|
|
14
|
+
if (content.classList.contains("initial")) {
|
|
15
|
+
content.classList.remove("initial");
|
|
16
|
+
content.classList.add("active");
|
|
33
17
|
}
|
|
34
|
-
item.
|
|
35
|
-
if (
|
|
18
|
+
const open = item.dataset.open === "true";
|
|
19
|
+
if (open) {
|
|
20
|
+
item.classList.add("active");
|
|
36
21
|
content.style.maxHeight = `${contentBoundingBox.height}px`;
|
|
37
|
-
} else {
|
|
38
|
-
content.style.maxHeight = "0";
|
|
39
|
-
content.classList.remove("open");
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
summary.addEventListener("click", toggleElement);
|
|
43
|
-
summary.addEventListener("keydown", (event) => {
|
|
44
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
45
|
-
toggleElement();
|
|
46
22
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
23
|
+
const toggleElement = () => {
|
|
24
|
+
if (!multipleOpen) {
|
|
25
|
+
for (const otherItem of items) {
|
|
26
|
+
if (otherItem !== item) {
|
|
27
|
+
otherItem.classList.remove("active");
|
|
28
|
+
const otherContent = otherItem.querySelector(".sui-accordion-details");
|
|
29
|
+
if (otherContent) {
|
|
30
|
+
otherContent.style.maxHeight = "0";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
item.classList.toggle("active");
|
|
36
|
+
if (item.classList.contains("active")) {
|
|
37
|
+
content.style.maxHeight = `${contentBoundingBox.height}px`;
|
|
38
|
+
} else {
|
|
39
|
+
content.style.maxHeight = "0";
|
|
40
|
+
content.classList.remove("open");
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
summary.addEventListener("click", toggleElement);
|
|
44
|
+
summary.addEventListener("keydown", (event) => {
|
|
45
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
46
|
+
toggleElement();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
let resetting = false;
|
|
50
|
+
window.addEventListener("resize", async () => {
|
|
51
|
+
if (item.classList.contains("active")) {
|
|
52
|
+
content.style.maxHeight = "none";
|
|
53
|
+
contentBoundingBox = content.getBoundingClientRect();
|
|
54
|
+
content.style.maxHeight = `${contentBoundingBox.height}px`;
|
|
55
|
+
} else if (!resetting) {
|
|
56
|
+
resetting = true;
|
|
57
|
+
content.classList.remove("active");
|
|
58
|
+
content.classList.add("initial");
|
|
59
|
+
const itemWidth2 = item.getBoundingClientRect().width;
|
|
60
|
+
content.style.width = `${itemWidth2 - 36}px`;
|
|
61
|
+
content.style.maxHeight = "none";
|
|
62
|
+
contentBoundingBox = content.getBoundingClientRect();
|
|
63
|
+
content.style.width = "auto";
|
|
64
|
+
content.style.maxHeight = "0";
|
|
65
|
+
content.classList.add("active");
|
|
66
|
+
content.classList.remove("initial");
|
|
67
|
+
resetting = false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
69
71
|
}
|
|
70
72
|
}
|
|
73
|
+
document.addEventListener("astro:page-load", loadAccordions);
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
declare
|
|
2
|
-
declare const allCheckbox: NodeListOf<HTMLInputElement>;
|
|
1
|
+
declare function loadCheckboxes(): void;
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
box.
|
|
19
|
-
|
|
1
|
+
function loadCheckboxes() {
|
|
2
|
+
const allElements = document.querySelectorAll(".sui-checkmark-container");
|
|
3
|
+
const allCheckbox = document.querySelectorAll(".sui-checkbox");
|
|
4
|
+
for (const element of allElements) {
|
|
5
|
+
if (element.dataset.initialized) continue;
|
|
6
|
+
element.dataset.initialized = "true";
|
|
7
|
+
element.addEventListener("keydown", (e) => {
|
|
8
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
const checkbox = element.querySelector(".sui-checkbox");
|
|
11
|
+
if (!checkbox) return;
|
|
12
|
+
checkbox.click();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
for (const box of allCheckbox) {
|
|
16
|
+
if (box.dataset.initialized) continue;
|
|
17
|
+
box.dataset.initialized = "true";
|
|
18
|
+
box.addEventListener("change", (e) => {
|
|
19
|
+
box.parentElement.ariaChecked = e.target.checked ? "true" : "false";
|
|
20
|
+
});
|
|
21
|
+
}
|
|
20
22
|
}
|
|
23
|
+
document.addEventListener("astro:page-load", loadCheckboxes);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare function loadProgressBars(): void;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
function loadProgressBars() {
|
|
2
|
+
const allBars = document.querySelectorAll(".sui-progress");
|
|
3
|
+
for (const bar of allBars) {
|
|
4
|
+
const value = bar.dataset.value;
|
|
5
|
+
const max = bar.dataset.max;
|
|
6
|
+
const progress = bar.firstElementChild;
|
|
7
|
+
if (value && max) {
|
|
8
|
+
const percent = Math.round(Number.parseInt(value, 10) / Number.parseInt(max, 10) * 100);
|
|
9
|
+
progress.style.width = `${percent}%`;
|
|
10
|
+
}
|
|
9
11
|
}
|
|
10
12
|
}
|
|
13
|
+
document.addEventListener("astro:page-load", loadProgressBars);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare function loadRadioGroups(): void;
|
|
@@ -1,48 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
e.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
e.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
e.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
1
|
+
function loadRadioGroups() {
|
|
2
|
+
const AllRadioGroupContainers = document.querySelectorAll(".sui-radio-container");
|
|
3
|
+
for (const element of AllRadioGroupContainers) {
|
|
4
|
+
if (element.dataset.initialized) continue;
|
|
5
|
+
element.dataset.initialized = "true";
|
|
6
|
+
const radioBoxes = element.querySelectorAll(".sui-radio-box");
|
|
7
|
+
let i = 0;
|
|
8
|
+
for (const radioBox of radioBoxes) {
|
|
9
|
+
radioBox.addEventListener("keydown", (e) => {
|
|
10
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
11
|
+
e.preventDefault();
|
|
12
|
+
const input = e.target.parentElement.parentElement.querySelector(".sui-radio-toggle");
|
|
13
|
+
if (input.disabled) return;
|
|
14
|
+
input.checked = true;
|
|
15
|
+
}
|
|
16
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
let nextRadioBox;
|
|
19
|
+
radioBoxes.forEach((box, index) => {
|
|
20
|
+
if (box === radioBox) nextRadioBox = radioBoxes[index + 1];
|
|
21
|
+
});
|
|
22
|
+
if (!nextRadioBox) return;
|
|
23
|
+
radioBox.tabIndex = -1;
|
|
24
|
+
nextRadioBox.tabIndex = 0;
|
|
25
|
+
nextRadioBox.focus();
|
|
26
|
+
nextRadioBox.click();
|
|
27
|
+
}
|
|
28
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
let previousRadioBox;
|
|
31
|
+
radioBoxes.forEach((box, index) => {
|
|
32
|
+
if (box === radioBox) previousRadioBox = radioBoxes[index - 1];
|
|
33
|
+
});
|
|
34
|
+
if (!previousRadioBox) return;
|
|
35
|
+
radioBox.tabIndex = -1;
|
|
36
|
+
previousRadioBox.tabIndex = 0;
|
|
37
|
+
previousRadioBox.focus();
|
|
38
|
+
previousRadioBox.click();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
element.addEventListener("keydown", (e) => {
|
|
44
|
+
if (e.key !== "Enter") return;
|
|
45
|
+
const checkbox = element.querySelector(".sui-checkbox");
|
|
46
|
+
if (!checkbox) return;
|
|
47
|
+
checkbox.click();
|
|
39
48
|
});
|
|
40
|
-
i++;
|
|
41
49
|
}
|
|
42
|
-
element.addEventListener("keydown", (e) => {
|
|
43
|
-
if (e.key !== "Enter") return;
|
|
44
|
-
const checkbox = element.querySelector(".sui-checkbox");
|
|
45
|
-
if (!checkbox) return;
|
|
46
|
-
checkbox.click();
|
|
47
|
-
});
|
|
48
50
|
}
|
|
51
|
+
document.addEventListener("astro:page-load", loadRadioGroups);
|
|
@@ -1,166 +1,169 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
function loadSearchSelects() {
|
|
2
|
+
const allSearchSelects = document.querySelectorAll(".sui-search-select-label");
|
|
3
|
+
for (const container of allSearchSelects) {
|
|
4
|
+
let hideOnClickOutside2 = function(element) {
|
|
5
|
+
const outsideClickListener = (event) => {
|
|
6
|
+
if (!element.contains(event.target) && isVisible(element) && active === true) {
|
|
7
|
+
dropdown.classList.remove("active", "above");
|
|
8
|
+
active = false;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
document.addEventListener("click", outsideClickListener);
|
|
12
|
+
}, constructOptionsBasedOnOptions2 = function(options2) {
|
|
13
|
+
dropdown.innerHTML = "";
|
|
14
|
+
if (options2.length === 0) {
|
|
15
|
+
const element = document.createElement("li");
|
|
16
|
+
element.classList.add("empty-search-results");
|
|
17
|
+
element.textContent = "No results found.";
|
|
18
|
+
dropdown.appendChild(element);
|
|
19
|
+
}
|
|
20
|
+
let i = 0;
|
|
21
|
+
for (const option of options2) {
|
|
22
|
+
const element = document.createElement("li");
|
|
23
|
+
element.classList.add(
|
|
24
|
+
...[
|
|
25
|
+
"sui-search-select-option",
|
|
26
|
+
option.disabled && "disabled",
|
|
27
|
+
focusIndex === i && "focused"
|
|
28
|
+
].filter((x) => typeof x === "string")
|
|
29
|
+
);
|
|
30
|
+
element.role = "option";
|
|
31
|
+
element.value = Number.parseInt(option.value);
|
|
32
|
+
element.id = "";
|
|
33
|
+
element.dataset.optionIndex = i.toString();
|
|
34
|
+
element.dataset.value = option.value;
|
|
35
|
+
element.textContent = option.label;
|
|
36
|
+
element.addEventListener("click", (e) => handleSelection(e, element));
|
|
37
|
+
dropdown.appendChild(element);
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
optionElements = container.querySelectorAll("li");
|
|
41
|
+
};
|
|
42
|
+
var hideOnClickOutside = hideOnClickOutside2, constructOptionsBasedOnOptions = constructOptionsBasedOnOptions2;
|
|
43
|
+
const hiddenSelect = container.querySelector("select");
|
|
44
|
+
const searchWrapper = container.querySelector(".sui-search-input-wrapper");
|
|
45
|
+
const searchInput = searchWrapper.querySelector("input");
|
|
46
|
+
const dropdown = container.querySelector(".sui-search-select-dropdown");
|
|
47
|
+
let optionElements = container.querySelectorAll("li");
|
|
48
|
+
let active = false;
|
|
49
|
+
const options = JSON.parse(container.dataset.options);
|
|
50
|
+
const id = container.dataset.id;
|
|
51
|
+
let filteredOptions = options;
|
|
52
|
+
searchWrapper.addEventListener("click", () => {
|
|
53
|
+
const { bottom, left, right, width, x, y, height } = searchWrapper.getBoundingClientRect();
|
|
54
|
+
const optionHeight = 36;
|
|
55
|
+
const totalBorderSize = 2;
|
|
56
|
+
const margin = 4;
|
|
57
|
+
const dropdownHeight = options.length * optionHeight + totalBorderSize + margin;
|
|
58
|
+
const CustomRect = {
|
|
59
|
+
top: bottom + margin,
|
|
60
|
+
left,
|
|
61
|
+
right,
|
|
62
|
+
bottom: bottom + margin + dropdownHeight,
|
|
63
|
+
width,
|
|
64
|
+
height: dropdownHeight,
|
|
65
|
+
x,
|
|
66
|
+
y: y + height + margin
|
|
67
|
+
};
|
|
68
|
+
if (active) {
|
|
69
|
+
searchInput.ariaExpanded = "false";
|
|
6
70
|
dropdown.classList.remove("active", "above");
|
|
7
71
|
active = false;
|
|
72
|
+
return;
|
|
8
73
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (options2.length === 0) {
|
|
14
|
-
const element = document.createElement("li");
|
|
15
|
-
element.classList.add("empty-search-results");
|
|
16
|
-
element.textContent = "No results found.";
|
|
17
|
-
dropdown.appendChild(element);
|
|
18
|
-
}
|
|
19
|
-
let i = 0;
|
|
20
|
-
for (const option of options2) {
|
|
21
|
-
const element = document.createElement("li");
|
|
22
|
-
element.classList.add(
|
|
23
|
-
...[
|
|
24
|
-
"sui-search-select-option",
|
|
25
|
-
option.disabled && "disabled",
|
|
26
|
-
focusIndex === i && "focused"
|
|
27
|
-
].filter((x) => typeof x === "string")
|
|
28
|
-
);
|
|
29
|
-
element.role = "option";
|
|
30
|
-
element.value = Number.parseInt(option.value);
|
|
31
|
-
element.id = "";
|
|
32
|
-
element.dataset.optionIndex = i.toString();
|
|
33
|
-
element.dataset.value = option.value;
|
|
34
|
-
element.textContent = option.label;
|
|
35
|
-
element.addEventListener("click", (e) => handleSelection(e, element));
|
|
36
|
-
dropdown.appendChild(element);
|
|
37
|
-
i++;
|
|
38
|
-
}
|
|
39
|
-
optionElements = container.querySelectorAll("li");
|
|
40
|
-
};
|
|
41
|
-
var hideOnClickOutside2 = hideOnClickOutside, constructOptionsBasedOnOptions2 = constructOptionsBasedOnOptions;
|
|
42
|
-
const hiddenSelect = container.querySelector("select");
|
|
43
|
-
const searchWrapper = container.querySelector(".sui-search-input-wrapper");
|
|
44
|
-
const searchInput = searchWrapper.querySelector("input");
|
|
45
|
-
const dropdown = container.querySelector(".sui-search-select-dropdown");
|
|
46
|
-
let optionElements = container.querySelectorAll("li");
|
|
47
|
-
let active = false;
|
|
48
|
-
const options = JSON.parse(container.dataset.options);
|
|
49
|
-
const id = container.dataset.id;
|
|
50
|
-
let filteredOptions = options;
|
|
51
|
-
searchWrapper.addEventListener("click", () => {
|
|
52
|
-
const { bottom, left, right, width, x, y, height } = searchWrapper.getBoundingClientRect();
|
|
53
|
-
const optionHeight = 36;
|
|
54
|
-
const totalBorderSize = 2;
|
|
55
|
-
const margin = 4;
|
|
56
|
-
const dropdownHeight = options.length * optionHeight + totalBorderSize + margin;
|
|
57
|
-
const CustomRect = {
|
|
58
|
-
top: bottom + margin,
|
|
59
|
-
left,
|
|
60
|
-
right,
|
|
61
|
-
bottom: bottom + margin + dropdownHeight,
|
|
62
|
-
width,
|
|
63
|
-
height: dropdownHeight,
|
|
64
|
-
x,
|
|
65
|
-
y: y + height + margin
|
|
66
|
-
};
|
|
67
|
-
if (active) {
|
|
68
|
-
searchInput.ariaExpanded = "false";
|
|
69
|
-
dropdown.classList.remove("active", "above");
|
|
70
|
-
active = false;
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
active = true;
|
|
74
|
-
searchInput.ariaExpanded = "true";
|
|
75
|
-
if (CustomRect.top >= 0 && CustomRect.left >= 0 && CustomRect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && CustomRect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
|
|
76
|
-
dropdown.classList.add("active");
|
|
77
|
-
} else {
|
|
78
|
-
dropdown.classList.add("active", "above");
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
const handleSelection = (e, option) => {
|
|
82
|
-
e.stopImmediatePropagation();
|
|
83
|
-
if (option.id === `${id}-selected` || !id) return;
|
|
84
|
-
const currentlySelected = document.getElementById(`${id}-selected`);
|
|
85
|
-
if (currentlySelected) {
|
|
86
|
-
currentlySelected.classList.remove("selected");
|
|
87
|
-
currentlySelected.id = "";
|
|
88
|
-
}
|
|
89
|
-
option.id = `${id}-selected`;
|
|
90
|
-
option.classList.add("selected");
|
|
91
|
-
const index = options.findIndex((x) => x.value === option.dataset.value);
|
|
92
|
-
focusIndex = index;
|
|
93
|
-
const opt = options[index];
|
|
94
|
-
hiddenSelect.value = opt.value;
|
|
95
|
-
searchInput.placeholder = opt.label;
|
|
96
|
-
dropdown.classList.remove("active", "above");
|
|
97
|
-
searchInput.value = "";
|
|
98
|
-
filteredOptions = options;
|
|
99
|
-
constructOptionsBasedOnOptions(options);
|
|
100
|
-
active = false;
|
|
101
|
-
};
|
|
102
|
-
for (const option of optionElements) {
|
|
103
|
-
option.addEventListener("click", (e) => handleSelection(e, option));
|
|
104
|
-
}
|
|
105
|
-
window.addEventListener("scroll", () => {
|
|
106
|
-
dropdown.classList.remove("active", "above");
|
|
107
|
-
active = false;
|
|
108
|
-
});
|
|
109
|
-
hideOnClickOutside(container);
|
|
110
|
-
const isVisible = (elem) => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);
|
|
111
|
-
let focusIndex = 0;
|
|
112
|
-
const recomputeOptions = () => {
|
|
113
|
-
for (const entry of optionElements) {
|
|
114
|
-
if (Number.parseInt(entry.dataset.optionIndex) === focusIndex) {
|
|
115
|
-
entry.classList.add("focused");
|
|
74
|
+
active = true;
|
|
75
|
+
searchInput.ariaExpanded = "true";
|
|
76
|
+
if (CustomRect.top >= 0 && CustomRect.left >= 0 && CustomRect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && CustomRect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
|
|
77
|
+
dropdown.classList.add("active");
|
|
116
78
|
} else {
|
|
117
|
-
|
|
79
|
+
dropdown.classList.add("active", "above");
|
|
118
80
|
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
searchInput.addEventListener("keydown", (e) => {
|
|
122
|
-
if (e.key === "Escape") {
|
|
123
|
-
e.preventDefault();
|
|
81
|
+
});
|
|
82
|
+
const handleSelection = (e, option) => {
|
|
124
83
|
e.stopImmediatePropagation();
|
|
125
|
-
|
|
84
|
+
if (option.id === `${id}-selected` || !id) return;
|
|
85
|
+
const currentlySelected = document.getElementById(`${id}-selected`);
|
|
86
|
+
if (currentlySelected) {
|
|
87
|
+
currentlySelected.classList.remove("selected");
|
|
88
|
+
currentlySelected.id = "";
|
|
89
|
+
}
|
|
90
|
+
option.id = `${id}-selected`;
|
|
91
|
+
option.classList.add("selected");
|
|
92
|
+
const index = options.findIndex((x) => x.value === option.dataset.value);
|
|
93
|
+
focusIndex = index;
|
|
94
|
+
const opt = options[index];
|
|
95
|
+
hiddenSelect.value = opt.value;
|
|
96
|
+
searchInput.placeholder = opt.label;
|
|
126
97
|
dropdown.classList.remove("active", "above");
|
|
127
|
-
searchInput.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
recomputeOptions();
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
if (e.key === "ArrowDown" && focusIndex + 1 < filteredOptions.filter((x) => !x.disabled).length) {
|
|
138
|
-
e.preventDefault();
|
|
139
|
-
e.stopImmediatePropagation();
|
|
140
|
-
focusIndex++;
|
|
141
|
-
recomputeOptions();
|
|
142
|
-
return;
|
|
98
|
+
searchInput.value = "";
|
|
99
|
+
filteredOptions = options;
|
|
100
|
+
constructOptionsBasedOnOptions2(options);
|
|
101
|
+
active = false;
|
|
102
|
+
};
|
|
103
|
+
for (const option of optionElements) {
|
|
104
|
+
option.addEventListener("click", (e) => handleSelection(e, option));
|
|
143
105
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
106
|
+
window.addEventListener("scroll", () => {
|
|
107
|
+
dropdown.classList.remove("active", "above");
|
|
108
|
+
active = false;
|
|
109
|
+
});
|
|
110
|
+
hideOnClickOutside2(container);
|
|
111
|
+
const isVisible = (elem) => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);
|
|
112
|
+
let focusIndex = 0;
|
|
113
|
+
const recomputeOptions = () => {
|
|
147
114
|
for (const entry of optionElements) {
|
|
148
115
|
if (Number.parseInt(entry.dataset.optionIndex) === focusIndex) {
|
|
149
|
-
entry.
|
|
116
|
+
entry.classList.add("focused");
|
|
117
|
+
} else {
|
|
118
|
+
entry.classList.remove("focused");
|
|
150
119
|
}
|
|
151
120
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
121
|
+
};
|
|
122
|
+
searchInput.addEventListener("keydown", (e) => {
|
|
123
|
+
if (e.key === "Escape") {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
e.stopImmediatePropagation();
|
|
126
|
+
active = false;
|
|
127
|
+
dropdown.classList.remove("active", "above");
|
|
128
|
+
searchInput.blur();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (e.key === "ArrowUp" && focusIndex > 0) {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
e.stopImmediatePropagation();
|
|
134
|
+
focusIndex--;
|
|
135
|
+
recomputeOptions();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (e.key === "ArrowDown" && focusIndex + 1 < filteredOptions.filter((x) => !x.disabled).length) {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
e.stopImmediatePropagation();
|
|
141
|
+
focusIndex++;
|
|
142
|
+
recomputeOptions();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (e.key === "Enter") {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
e.stopImmediatePropagation();
|
|
148
|
+
for (const entry of optionElements) {
|
|
149
|
+
if (Number.parseInt(entry.dataset.optionIndex) === focusIndex) {
|
|
150
|
+
entry.click();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
searchInput.addEventListener("keyup", (e) => {
|
|
157
|
+
if (["Enter", "ArrowUp", "ArrowDown"].includes(e.key)) return;
|
|
158
|
+
if (searchInput.value.trim().length === 0) {
|
|
159
|
+
constructOptionsBasedOnOptions2(options);
|
|
160
|
+
filteredOptions = options;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
filteredOptions = options.filter((x) => x.label.includes(searchInput.value));
|
|
164
|
+
focusIndex = 0;
|
|
165
|
+
constructOptionsBasedOnOptions2(filteredOptions);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
166
168
|
}
|
|
169
|
+
document.addEventListener("astro:page-load", loadSearchSelects);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare function loadTabs(): void;
|
|
@@ -1,82 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
function loadTabs() {
|
|
2
|
+
const allTabContainers = document.querySelectorAll(".sui-tabs-container");
|
|
3
|
+
for (const tabContainer of allTabContainers) {
|
|
4
|
+
const storage = tabContainer.dataset.storageStrategy;
|
|
5
|
+
const syncKey = tabContainer.dataset.syncKey;
|
|
6
|
+
const storageLayer = storage === "session" ? sessionStorage : localStorage;
|
|
7
|
+
const constructCustomEvent = (tabIndex, uniqueId) => {
|
|
8
|
+
return new CustomEvent(`sui-tab-switch:${syncKey}`, {
|
|
9
|
+
detail: {
|
|
10
|
+
tabIndex,
|
|
11
|
+
uniqueId
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const switchTab = (target, container, originatedFromSync = false) => {
|
|
16
|
+
const activeChildren = container.querySelectorAll(".active");
|
|
17
|
+
for (const child of activeChildren) {
|
|
18
|
+
child.tabIndex = -1;
|
|
19
|
+
child.classList.remove("active");
|
|
11
20
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
child.classList.remove("active");
|
|
19
|
-
}
|
|
20
|
-
const newActiveTab = target;
|
|
21
|
-
newActiveTab.classList.add("active");
|
|
22
|
-
newActiveTab.tabIndex = 0;
|
|
23
|
-
const newActiveTabContentId = newActiveTab.dataset.tabChild;
|
|
24
|
-
const newActiveTabContent = container.querySelector(
|
|
25
|
-
`sui-tab-item[data-tab-id="${newActiveTabContentId}"]`
|
|
26
|
-
);
|
|
27
|
-
newActiveTabContent.classList.add("active");
|
|
28
|
-
if (syncKey && !originatedFromSync) {
|
|
29
|
-
const tabIndex = Array.prototype.indexOf.call(
|
|
30
|
-
newActiveTab.parentElement.children,
|
|
31
|
-
newActiveTab
|
|
21
|
+
const newActiveTab = target;
|
|
22
|
+
newActiveTab.classList.add("active");
|
|
23
|
+
newActiveTab.tabIndex = 0;
|
|
24
|
+
const newActiveTabContentId = newActiveTab.dataset.tabChild;
|
|
25
|
+
const newActiveTabContent = container.querySelector(
|
|
26
|
+
`sui-tab-item[data-tab-id="${newActiveTabContentId}"]`
|
|
32
27
|
);
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
newActiveTabContent.classList.add("active");
|
|
29
|
+
if (syncKey && !originatedFromSync) {
|
|
30
|
+
const tabIndex = Array.prototype.indexOf.call(
|
|
31
|
+
newActiveTab.parentElement.children,
|
|
32
|
+
newActiveTab
|
|
33
|
+
);
|
|
34
|
+
storageLayer.setItem(syncKey, tabIndex.toString());
|
|
35
|
+
document.dispatchEvent(constructCustomEvent(tabIndex, container.dataset.uniqueId));
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const tabHeaders = tabContainer.querySelectorAll(".sui-tab-header");
|
|
39
|
+
for (const tab of tabHeaders) {
|
|
40
|
+
tab.addEventListener("click", (e) => switchTab(e.target, tabContainer));
|
|
41
|
+
tab.addEventListener("keydown", (e) => {
|
|
42
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
|
|
43
|
+
const activeTabIndex = Array.prototype.indexOf.call(tab.parentElement.children, tab);
|
|
44
|
+
const nextTabIndex = e.key === "ArrowLeft" ? activeTabIndex - 1 : activeTabIndex + 1;
|
|
45
|
+
if (nextTabIndex >= 0 && nextTabIndex < tab.parentElement.children.length) {
|
|
46
|
+
tab.tabIndex = -1;
|
|
47
|
+
const nextTab = tab.parentElement.children[nextTabIndex];
|
|
48
|
+
nextTab.tabIndex = 0;
|
|
49
|
+
nextTab.click();
|
|
50
|
+
nextTab.focus();
|
|
51
|
+
} else if (nextTabIndex < 0) {
|
|
52
|
+
tab.tabIndex = -1;
|
|
53
|
+
const lastTab = tab.parentElement.children[tab.parentElement.children.length - 1];
|
|
54
|
+
lastTab.tabIndex = 0;
|
|
55
|
+
lastTab.click();
|
|
56
|
+
lastTab.focus();
|
|
57
|
+
} else {
|
|
58
|
+
tab.tabIndex = -1;
|
|
59
|
+
const firstTab = tab.parentElement.children[0];
|
|
60
|
+
firstTab.tabIndex = 0;
|
|
61
|
+
firstTab.click();
|
|
62
|
+
firstTab.focus();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
35
66
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const activeTabIndex = Array.prototype.indexOf.call(tab.parentElement.children, tab);
|
|
43
|
-
const nextTabIndex = e.key === "ArrowLeft" ? activeTabIndex - 1 : activeTabIndex + 1;
|
|
44
|
-
if (nextTabIndex >= 0 && nextTabIndex < tab.parentElement.children.length) {
|
|
45
|
-
tab.tabIndex = -1;
|
|
46
|
-
const nextTab = tab.parentElement.children[nextTabIndex];
|
|
47
|
-
nextTab.tabIndex = 0;
|
|
48
|
-
nextTab.click();
|
|
49
|
-
nextTab.focus();
|
|
50
|
-
} else if (nextTabIndex < 0) {
|
|
51
|
-
tab.tabIndex = -1;
|
|
52
|
-
const lastTab = tab.parentElement.children[tab.parentElement.children.length - 1];
|
|
53
|
-
lastTab.tabIndex = 0;
|
|
54
|
-
lastTab.click();
|
|
55
|
-
lastTab.focus();
|
|
56
|
-
} else {
|
|
57
|
-
tab.tabIndex = -1;
|
|
58
|
-
const firstTab = tab.parentElement.children[0];
|
|
59
|
-
firstTab.tabIndex = 0;
|
|
60
|
-
firstTab.click();
|
|
61
|
-
firstTab.focus();
|
|
67
|
+
if (syncKey) {
|
|
68
|
+
const activeTabIndex = storageLayer.getItem(syncKey);
|
|
69
|
+
if (activeTabIndex) {
|
|
70
|
+
const activeTab = tabContainer.querySelector(`#${syncKey}-${activeTabIndex}`);
|
|
71
|
+
if (activeTab) {
|
|
72
|
+
activeTab.click();
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
activeTab.click();
|
|
72
|
-
}
|
|
75
|
+
document.addEventListener(`sui-tab-switch:${syncKey}`, (e) => {
|
|
76
|
+
const event = e;
|
|
77
|
+
const { tabIndex, uniqueId } = event.detail;
|
|
78
|
+
if (uniqueId === tabContainer.dataset.uniqueId) return;
|
|
79
|
+
const newTab = tabContainer.querySelector(`#${syncKey}-${tabIndex}`);
|
|
80
|
+
switchTab(newTab, tabContainer, true);
|
|
81
|
+
});
|
|
73
82
|
}
|
|
74
|
-
document.addEventListener(`sui-tab-switch:${syncKey}`, (e) => {
|
|
75
|
-
const event = e;
|
|
76
|
-
const { tabIndex, uniqueId } = event.detail;
|
|
77
|
-
if (uniqueId === tabContainer.dataset.uniqueId) return;
|
|
78
|
-
const newTab = tabContainer.querySelector(`#${syncKey}-${tabIndex}`);
|
|
79
|
-
switchTab(newTab, tabContainer, true);
|
|
80
|
-
});
|
|
81
83
|
}
|
|
82
84
|
}
|
|
85
|
+
document.addEventListener("astro:page-load", loadTabs);
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
declare
|
|
2
|
-
declare const allToggles: NodeListOf<HTMLInputElement>;
|
|
1
|
+
declare function loadToggles(): void;
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
box.
|
|
19
|
-
|
|
1
|
+
function loadToggles() {
|
|
2
|
+
const allToggleElements = document.querySelectorAll(".sui-toggle-container");
|
|
3
|
+
const allToggles = document.querySelectorAll(".sui-toggle-checkbox");
|
|
4
|
+
for (const element of allToggleElements) {
|
|
5
|
+
if (element.dataset.initialized) continue;
|
|
6
|
+
element.dataset.initialized = "true";
|
|
7
|
+
element.addEventListener("keydown", (e) => {
|
|
8
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
const checkbox = element.querySelector(".sui-toggle-checkbox");
|
|
11
|
+
if (!checkbox) return;
|
|
12
|
+
checkbox.click();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
for (const box of allToggles) {
|
|
16
|
+
if (box.dataset.initialized) continue;
|
|
17
|
+
box.dataset.initialized = "true";
|
|
18
|
+
box.addEventListener("change", (e) => {
|
|
19
|
+
box.previousSibling.ariaChecked = e.target.checked ? "true" : "false";
|
|
20
|
+
});
|
|
21
|
+
}
|
|
20
22
|
}
|
|
23
|
+
document.addEventListener("astro:page-load", loadToggles);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studiocms/ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "The UI library for StudioCMS. Includes the layouts & components we use to build StudioCMS.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
],
|
|
27
27
|
"homepage": "https://ui.studiocms.dev",
|
|
28
28
|
"publishConfig": {
|
|
29
|
-
"access": "public"
|
|
29
|
+
"access": "public",
|
|
30
|
+
"provenance": true
|
|
30
31
|
},
|
|
31
32
|
"sideEffects": false,
|
|
32
33
|
"files": [
|
|
33
|
-
"dist"
|
|
34
|
-
"assets"
|
|
34
|
+
"dist"
|
|
35
35
|
],
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"type": "module",
|