shadcn_phlexcomponents 0.1.18 → 0.1.19
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/README.md +321 -23
- data/app/javascript/controllers/accordion_controller.js +101 -90
- data/app/javascript/controllers/alert_dialog_controller.js +5 -4
- data/app/javascript/controllers/avatar_controller.js +12 -11
- data/app/javascript/controllers/checkbox_controller.js +26 -26
- data/app/javascript/controllers/collapsible_controller.js +35 -36
- data/app/javascript/controllers/combobox_controller.js +262 -231
- data/app/javascript/controllers/command_controller.js +205 -184
- data/app/javascript/controllers/date_picker_controller.js +252 -253
- data/app/javascript/controllers/date_range_picker_controller.js +189 -200
- data/app/javascript/controllers/dialog_controller.js +79 -78
- data/app/javascript/controllers/dropdown_menu_controller.js +229 -208
- data/app/javascript/controllers/dropdown_menu_sub_controller.js +111 -97
- data/app/javascript/controllers/form_field_controller.js +17 -16
- data/app/javascript/controllers/hover_card_controller.js +69 -71
- data/app/javascript/controllers/loading_button_controller.js +11 -10
- data/app/javascript/controllers/popover_controller.js +85 -78
- data/app/javascript/controllers/progress_controller.js +12 -11
- data/app/javascript/controllers/radio_group_controller.js +75 -74
- data/app/javascript/controllers/select_controller.js +247 -232
- data/app/javascript/controllers/sidebar_controller.js +26 -27
- data/app/javascript/controllers/sidebar_trigger_controller.js +12 -9
- data/app/javascript/controllers/slider_controller.js +74 -74
- data/app/javascript/controllers/switch_controller.js +23 -23
- data/app/javascript/controllers/tabs_controller.js +61 -61
- data/app/javascript/controllers/theme_switcher_controller.js +28 -27
- data/app/javascript/controllers/toast_container_controller.js +45 -31
- data/app/javascript/controllers/toast_controller.js +19 -18
- data/app/javascript/controllers/toggle_controller.js +17 -17
- data/app/javascript/controllers/toggle_group_controller.js +17 -17
- data/app/javascript/controllers/tooltip_controller.js +75 -77
- data/app/javascript/shadcn_phlexcomponents.js +27 -60
- data/app/javascript/utils/command.js +390 -334
- data/app/javascript/utils/floating_ui.js +139 -107
- data/app/javascript/utils/index.js +253 -190
- data/app/typescript/controllers/accordion_controller.ts +2 -0
- data/app/typescript/controllers/alert_dialog_controller.ts +2 -0
- data/app/typescript/controllers/avatar_controller.ts +2 -0
- data/app/typescript/controllers/checkbox_controller.ts +2 -0
- data/app/typescript/controllers/collapsible_controller.ts +2 -0
- data/app/typescript/controllers/combobox_controller.ts +2 -0
- data/app/typescript/controllers/command_controller.ts +2 -0
- data/app/typescript/controllers/date_picker_controller.ts +2 -0
- data/app/typescript/controllers/date_range_picker_controller.ts +2 -0
- data/app/typescript/controllers/dialog_controller.ts +2 -0
- data/app/typescript/controllers/dropdown_menu_controller.ts +2 -0
- data/app/typescript/controllers/dropdown_menu_sub_controller.ts +2 -0
- data/app/typescript/controllers/form_field_controller.ts +2 -0
- data/app/typescript/controllers/hover_card_controller.ts +2 -0
- data/app/typescript/controllers/loading_button_controller.ts +2 -0
- data/app/typescript/controllers/popover_controller.ts +2 -0
- data/app/typescript/controllers/progress_controller.ts +2 -0
- data/app/typescript/controllers/radio_group_controller.ts +2 -0
- data/app/typescript/controllers/select_controller.ts +2 -0
- data/app/typescript/controllers/slider_controller.ts +2 -0
- data/app/typescript/controllers/switch_controller.ts +2 -0
- data/app/typescript/controllers/tabs_controller.ts +2 -0
- data/app/typescript/controllers/theme_switcher_controller.ts +2 -0
- data/app/typescript/controllers/toast_container_controller.ts +2 -0
- data/app/typescript/controllers/toast_controller.ts +2 -0
- data/app/typescript/controllers/toggle_controller.ts +2 -0
- data/app/typescript/controllers/toggle_group_controller.ts +2 -0
- data/app/typescript/controllers/tooltip_controller.ts +2 -0
- data/app/typescript/shadcn_phlexcomponents.ts +27 -61
- data/app/typescript/utils/index.ts +7 -0
- data/lib/install/upgrade_shadcn_phlexcomponents.rb +28 -0
- data/lib/shadcn_phlexcomponents/components/accordion.rb +55 -12
- data/lib/shadcn_phlexcomponents/components/alert.rb +35 -16
- data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +52 -12
- data/lib/shadcn_phlexcomponents/components/aspect_ratio.rb +33 -2
- data/lib/shadcn_phlexcomponents/components/avatar.rb +24 -7
- data/lib/shadcn_phlexcomponents/components/badge.rb +23 -18
- data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +46 -6
- data/lib/shadcn_phlexcomponents/components/button.rb +32 -27
- data/lib/shadcn_phlexcomponents/components/card.rb +59 -10
- data/lib/shadcn_phlexcomponents/components/checkbox.rb +51 -30
- data/lib/shadcn_phlexcomponents/components/checkbox_group.rb +24 -4
- data/lib/shadcn_phlexcomponents/components/combobox.rb +212 -69
- data/lib/shadcn_phlexcomponents/components/command.rb +156 -52
- data/lib/shadcn_phlexcomponents/components/date_picker.rb +134 -48
- data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +20 -42
- data/lib/shadcn_phlexcomponents/components/dialog.rb +80 -26
- data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +74 -25
- data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +52 -24
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_error.rb +8 -1
- data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +3 -2
- data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +8 -1
- data/lib/shadcn_phlexcomponents/components/form/form_input.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_select.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/form.rb +22 -6
- data/lib/shadcn_phlexcomponents/components/hover_card.rb +48 -18
- data/lib/shadcn_phlexcomponents/components/input.rb +13 -8
- data/lib/shadcn_phlexcomponents/components/label.rb +9 -4
- data/lib/shadcn_phlexcomponents/components/link.rb +8 -1
- data/lib/shadcn_phlexcomponents/components/pagination.rb +34 -6
- data/lib/shadcn_phlexcomponents/components/popover.rb +43 -13
- data/lib/shadcn_phlexcomponents/components/progress.rb +37 -6
- data/lib/shadcn_phlexcomponents/components/radio_group.rb +41 -15
- data/lib/shadcn_phlexcomponents/components/select.rb +99 -42
- data/lib/shadcn_phlexcomponents/components/separator.rb +9 -4
- data/lib/shadcn_phlexcomponents/components/sheet.rb +87 -21
- data/lib/shadcn_phlexcomponents/components/skeleton.rb +8 -1
- data/lib/shadcn_phlexcomponents/components/switch.rb +45 -17
- data/lib/shadcn_phlexcomponents/components/table.rb +84 -17
- data/lib/shadcn_phlexcomponents/components/tabs.rb +36 -12
- data/lib/shadcn_phlexcomponents/components/textarea.rb +12 -7
- data/lib/shadcn_phlexcomponents/components/toast.rb +46 -20
- data/lib/shadcn_phlexcomponents/components/toast_container.rb +19 -14
- data/lib/shadcn_phlexcomponents/components/toggle.rb +28 -23
- data/lib/shadcn_phlexcomponents/components/tooltip.rb +49 -14
- data/lib/shadcn_phlexcomponents/configuration.rb +46 -0
- data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +28 -0
- data/lib/shadcn_phlexcomponents/version.rb +1 -1
- data/lib/shadcn_phlexcomponents.rb +12 -1
- data/lib/tasks/upgrade.rake +10 -0
- metadata +15 -14
- data/app/typescript/controllers/sidebar_controller.ts +0 -39
- data/app/typescript/controllers/sidebar_trigger_controller.ts +0 -21
@@ -2,224 +2,287 @@ const ANIMATION_OUT_DELAY = 100;
|
|
2
2
|
const ON_OPEN_FOCUS_DELAY = 100;
|
3
3
|
const ON_CLOSE_FOCUS_DELAY = 50;
|
4
4
|
const getScrollbarWidth = () => {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
// Create a temporary div container and append it into the body
|
6
|
+
const outer = document.createElement("div");
|
7
|
+
outer.style.visibility = "hidden";
|
8
|
+
outer.style.overflow = "scroll"; // force scrollbars
|
9
|
+
outer.style.width = "100px";
|
10
|
+
outer.style.position = "absolute";
|
11
|
+
outer.style.top = "-9999px";
|
12
|
+
document.body.appendChild(outer);
|
13
|
+
// Create an inner div and place it inside the outer div
|
14
|
+
const inner = document.createElement("div");
|
15
|
+
inner.style.width = "100%";
|
16
|
+
outer.appendChild(inner);
|
17
|
+
// Calculate the scrollbar width
|
18
|
+
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
|
19
|
+
// Clean up
|
20
|
+
outer.remove();
|
21
|
+
return scrollbarWidth;
|
22
22
|
};
|
23
23
|
const lockScroll = (contentId) => {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
if (window.innerHeight < document.documentElement.scrollHeight) {
|
25
|
+
document.body.dataset.scrollLocked = "1";
|
26
|
+
document.body.classList.add(
|
27
|
+
"data-[scroll-locked]:pointer-events-none",
|
28
|
+
"data-[scroll-locked]:!overflow-hidden",
|
29
|
+
"data-[scroll-locked]:!relative",
|
30
|
+
"data-[scroll-locked]:px-0",
|
31
|
+
"data-[scroll-locked]:pt-0",
|
32
|
+
"data-[scroll-locked]:ml-0",
|
33
|
+
"data-[scroll-locked]:mt-0",
|
34
|
+
);
|
35
|
+
document.body.style.marginRight = `${getScrollbarWidth()}px`;
|
36
|
+
const contentIdsString =
|
37
|
+
document.body.dataset.scrollLockedContentIds || "[]";
|
38
|
+
const contentIds = JSON.parse(contentIdsString);
|
39
|
+
contentIds.push(contentId);
|
40
|
+
document.body.dataset.scrollLockedContentIds = JSON.stringify(contentIds);
|
41
|
+
}
|
33
42
|
};
|
34
43
|
const unlockScroll = (contentId) => {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
const contentIdsString = document.body.dataset.scrollLockedContentIds || "[]";
|
45
|
+
const contentIds = JSON.parse(contentIdsString);
|
46
|
+
const newContentIds = contentIds.filter((id) => id !== contentId);
|
47
|
+
document.body.dataset.scrollLockedContentIds = JSON.stringify(newContentIds);
|
48
|
+
if (newContentIds.length === 0) {
|
49
|
+
delete document.body.dataset.scrollLocked;
|
50
|
+
document.body.classList.remove(
|
51
|
+
"data-[scroll-locked]:pointer-events-none",
|
52
|
+
"data-[scroll-locked]:!overflow-hidden",
|
53
|
+
"data-[scroll-locked]:!relative",
|
54
|
+
"data-[scroll-locked]:px-0",
|
55
|
+
"data-[scroll-locked]:pt-0",
|
56
|
+
"data-[scroll-locked]:ml-0",
|
57
|
+
"data-[scroll-locked]:mt-0",
|
58
|
+
);
|
59
|
+
document.body.style.marginRight = "";
|
60
|
+
}
|
44
61
|
};
|
45
62
|
const focusTrigger = (triggerTarget) => {
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
}, ON_CLOSE_FOCUS_DELAY);
|
63
|
+
setTimeout(() => {
|
64
|
+
if (triggerTarget.dataset.asChild === "false") {
|
65
|
+
const childElement = triggerTarget.firstElementChild;
|
66
|
+
if (childElement) {
|
67
|
+
childElement.focus();
|
68
|
+
}
|
69
|
+
} else {
|
70
|
+
triggerTarget.focus();
|
71
|
+
}
|
72
|
+
}, ON_CLOSE_FOCUS_DELAY);
|
57
73
|
};
|
58
74
|
const focusElement = (element) => {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
75
|
+
setTimeout(() => {
|
76
|
+
if (element) {
|
77
|
+
element.focus();
|
78
|
+
}
|
79
|
+
}, ON_OPEN_FOCUS_DELAY);
|
64
80
|
};
|
65
81
|
const getFocusableElements = (container) => {
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
if (trigger) {
|
81
|
-
if (setEqualWidth) {
|
82
|
-
const triggerWidth = trigger.offsetWidth;
|
83
|
-
const contentContainerWidth = contentContainer.offsetWidth;
|
84
|
-
if (contentContainerWidth < triggerWidth) {
|
85
|
-
contentContainer.style.width = `${triggerWidth}px`;
|
86
|
-
}
|
87
|
-
}
|
88
|
-
trigger.ariaExpanded = 'true';
|
89
|
-
trigger.dataset.state = 'open';
|
82
|
+
return Array.from(
|
83
|
+
container.querySelectorAll(
|
84
|
+
'button, [href], input:not([type="hidden"]), select:not([tabindex="-1"]), textarea, [tabindex]:not([tabindex="-1"])',
|
85
|
+
),
|
86
|
+
);
|
87
|
+
};
|
88
|
+
const getSameLevelItems = ({ content, items, closestContentSelector }) => {
|
89
|
+
const sameLevelItems = [];
|
90
|
+
items.forEach((i) => {
|
91
|
+
if (
|
92
|
+
i.closest(closestContentSelector) === content &&
|
93
|
+
i.dataset.disabled === undefined
|
94
|
+
) {
|
95
|
+
sameLevelItems.push(i);
|
90
96
|
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
97
|
+
});
|
98
|
+
return sameLevelItems;
|
99
|
+
};
|
100
|
+
const showContent = ({
|
101
|
+
trigger,
|
102
|
+
content,
|
103
|
+
contentContainer,
|
104
|
+
setEqualWidth,
|
105
|
+
overlay,
|
106
|
+
}) => {
|
107
|
+
contentContainer.style.display = "";
|
108
|
+
if (trigger) {
|
109
|
+
if (setEqualWidth) {
|
110
|
+
const triggerWidth = trigger.offsetWidth;
|
111
|
+
const contentContainerWidth = contentContainer.offsetWidth;
|
112
|
+
if (contentContainerWidth < triggerWidth) {
|
113
|
+
contentContainer.style.width = `${triggerWidth}px`;
|
114
|
+
}
|
96
115
|
}
|
116
|
+
trigger.ariaExpanded = "true";
|
117
|
+
trigger.dataset.state = "open";
|
118
|
+
}
|
119
|
+
content.dataset.state = "open";
|
120
|
+
if (overlay) {
|
121
|
+
overlay.style.display = "";
|
122
|
+
overlay.dataset.state = "open";
|
123
|
+
lockScroll(content.id);
|
124
|
+
}
|
97
125
|
};
|
98
|
-
const hideContent = ({ trigger, content, contentContainer, overlay
|
99
|
-
|
100
|
-
|
101
|
-
|
126
|
+
const hideContent = ({ trigger, content, contentContainer, overlay }) => {
|
127
|
+
if (trigger) {
|
128
|
+
trigger.ariaExpanded = "false";
|
129
|
+
trigger.dataset.state = "closed";
|
130
|
+
}
|
131
|
+
content.dataset.state = "closed";
|
132
|
+
setTimeout(() => {
|
133
|
+
contentContainer.style.display = "none";
|
134
|
+
if (overlay) {
|
135
|
+
overlay.style.display = "none";
|
136
|
+
overlay.dataset.state = "closed";
|
137
|
+
unlockScroll(content.id);
|
102
138
|
}
|
103
|
-
|
104
|
-
setTimeout(() => {
|
105
|
-
contentContainer.style.display = 'none';
|
106
|
-
if (overlay) {
|
107
|
-
overlay.style.display = 'none';
|
108
|
-
overlay.dataset.state = 'closed';
|
109
|
-
unlockScroll(content.id);
|
110
|
-
}
|
111
|
-
}, ANIMATION_OUT_DELAY);
|
139
|
+
}, ANIMATION_OUT_DELAY);
|
112
140
|
};
|
113
141
|
const getStimulusInstance = (controller, element) => {
|
114
|
-
|
115
|
-
|
116
|
-
|
142
|
+
if (!element) return;
|
143
|
+
return window.Stimulus.getControllerForElementAndIdentifier(
|
144
|
+
element,
|
145
|
+
controller,
|
146
|
+
);
|
117
147
|
};
|
118
148
|
const anyNestedComponentsOpen = (element) => {
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
149
|
+
const components = [];
|
150
|
+
const componentNames = [
|
151
|
+
"dialog",
|
152
|
+
"alert-dialog",
|
153
|
+
"dropdown-menu",
|
154
|
+
"popover",
|
155
|
+
"select",
|
156
|
+
"combobox",
|
157
|
+
"command",
|
158
|
+
"hover-card",
|
159
|
+
"tooltip",
|
160
|
+
"date-picker",
|
161
|
+
"date-range-picker",
|
162
|
+
];
|
163
|
+
componentNames.forEach((name) => {
|
164
|
+
const triggers = Array.from(
|
165
|
+
element.querySelectorAll(
|
166
|
+
`[data-shadcn-phlexcomponents="${name}-trigger"]`,
|
167
|
+
),
|
168
|
+
);
|
169
|
+
const controllerElements = Array.from(
|
170
|
+
element.querySelectorAll(`[data-controller="${name}"]`),
|
171
|
+
);
|
172
|
+
controllerElements.forEach((controller) => {
|
173
|
+
const stimulusInstance = getStimulusInstance(name, controller);
|
174
|
+
if (stimulusInstance) {
|
175
|
+
components.push(stimulusInstance);
|
176
|
+
}
|
177
|
+
});
|
178
|
+
triggers.forEach((trigger) => {
|
179
|
+
const stimulusInstance = getStimulusInstance(
|
180
|
+
name,
|
181
|
+
document.querySelector(`#${trigger.getAttribute("aria-controls")}`),
|
182
|
+
);
|
183
|
+
if (stimulusInstance) {
|
184
|
+
components.push(stimulusInstance);
|
185
|
+
}
|
148
186
|
});
|
149
|
-
|
187
|
+
});
|
188
|
+
return components.some((c) => c.isOpenValue);
|
150
189
|
};
|
151
190
|
const onClickOutside = (controller, event) => {
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
return;
|
158
|
-
controller.close();
|
191
|
+
const target = event.target;
|
192
|
+
// Let trigger handle state
|
193
|
+
if (target === controller.triggerTarget) return;
|
194
|
+
if (controller.triggerTarget.contains(target)) return;
|
195
|
+
controller.close();
|
159
196
|
};
|
160
197
|
const setGroupLabelsId = (controller) => {
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
};
|
168
|
-
const getNextEnabledIndex = ({ items, currentIndex, wrapAround, filterFn, }) => {
|
169
|
-
let newIndex = null;
|
170
|
-
if (filterFn) {
|
171
|
-
newIndex = items.findIndex((item, index) => index > currentIndex && filterFn(item));
|
172
|
-
if (newIndex === -1) {
|
173
|
-
newIndex = currentIndex;
|
174
|
-
}
|
175
|
-
}
|
176
|
-
else {
|
177
|
-
newIndex = currentIndex + 1;
|
198
|
+
controller.groupTargets.forEach((g) => {
|
199
|
+
const label = g.querySelector(
|
200
|
+
`[data-shadcn-phlexcomponents="${controller.identifier}-label"]`,
|
201
|
+
);
|
202
|
+
if (label) {
|
203
|
+
label.id = g.getAttribute("aria-labelledby");
|
178
204
|
}
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
205
|
+
});
|
206
|
+
};
|
207
|
+
const getNextEnabledIndex = ({ items, currentIndex, wrapAround, filterFn }) => {
|
208
|
+
let newIndex = null;
|
209
|
+
if (filterFn) {
|
210
|
+
newIndex = items.findIndex(
|
211
|
+
(item, index) => index > currentIndex && filterFn(item),
|
212
|
+
);
|
213
|
+
if (newIndex === -1) {
|
214
|
+
newIndex = currentIndex;
|
186
215
|
}
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if (
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
}
|
216
|
+
} else {
|
217
|
+
newIndex = currentIndex + 1;
|
218
|
+
}
|
219
|
+
if (newIndex > items.length - 1) {
|
220
|
+
if (wrapAround) {
|
221
|
+
newIndex = 0;
|
222
|
+
} else {
|
223
|
+
newIndex = items.length - 1;
|
196
224
|
}
|
197
|
-
|
198
|
-
|
225
|
+
}
|
226
|
+
return newIndex;
|
227
|
+
};
|
228
|
+
const getPreviousEnabledIndex = ({
|
229
|
+
items,
|
230
|
+
currentIndex,
|
231
|
+
wrapAround,
|
232
|
+
filterFn,
|
233
|
+
}) => {
|
234
|
+
let newIndex = null;
|
235
|
+
if (filterFn) {
|
236
|
+
newIndex = items.findLastIndex(
|
237
|
+
(item, index) => index < currentIndex && filterFn(item),
|
238
|
+
);
|
239
|
+
if (newIndex === -1) {
|
240
|
+
newIndex = currentIndex;
|
199
241
|
}
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
242
|
+
} else {
|
243
|
+
newIndex = currentIndex - 1;
|
244
|
+
}
|
245
|
+
if (newIndex < 0) {
|
246
|
+
if (wrapAround) {
|
247
|
+
newIndex = items.length - 1;
|
248
|
+
} else {
|
249
|
+
newIndex = 0;
|
207
250
|
}
|
208
|
-
|
251
|
+
}
|
252
|
+
return newIndex;
|
209
253
|
};
|
210
254
|
const handleTabNavigation = (element, event) => {
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
255
|
+
const focusableElements = getFocusableElements(element);
|
256
|
+
const firstElement = focusableElements[0];
|
257
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
258
|
+
// If Shift + Tab pressed on first element, go to last element
|
259
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
260
|
+
event.preventDefault();
|
261
|
+
lastElement.focus();
|
262
|
+
}
|
263
|
+
// If Tab pressed on last element, go to first element
|
264
|
+
else if (!event.shiftKey && document.activeElement === lastElement) {
|
265
|
+
event.preventDefault();
|
266
|
+
firstElement.focus();
|
267
|
+
}
|
268
|
+
};
|
269
|
+
export {
|
270
|
+
ANIMATION_OUT_DELAY,
|
271
|
+
ON_CLOSE_FOCUS_DELAY,
|
272
|
+
ON_OPEN_FOCUS_DELAY,
|
273
|
+
lockScroll,
|
274
|
+
unlockScroll,
|
275
|
+
focusTrigger,
|
276
|
+
focusElement,
|
277
|
+
getFocusableElements,
|
278
|
+
getSameLevelItems,
|
279
|
+
showContent,
|
280
|
+
hideContent,
|
281
|
+
getStimulusInstance,
|
282
|
+
anyNestedComponentsOpen,
|
283
|
+
onClickOutside,
|
284
|
+
setGroupLabelsId,
|
285
|
+
getNextEnabledIndex,
|
286
|
+
getPreviousEnabledIndex,
|
287
|
+
handleTabNavigation,
|
224
288
|
};
|
225
|
-
export { ANIMATION_OUT_DELAY, ON_CLOSE_FOCUS_DELAY, ON_OPEN_FOCUS_DELAY, lockScroll, unlockScroll, focusTrigger, focusElement, getFocusableElements, getSameLevelItems, showContent, hideContent, getStimulusInstance, anyNestedComponentsOpen, onClickOutside, setGroupLabelsId, getNextEnabledIndex, getPreviousEnabledIndex, handleTabNavigation, };
|
@@ -2,6 +2,8 @@ import { Controller } from '@hotwired/stimulus'
|
|
2
2
|
import { hideContent, showContent } from '../utils'
|
3
3
|
|
4
4
|
const CollapsibleController = class extends Controller {
|
5
|
+
static name = 'collapsible'
|
6
|
+
|
5
7
|
// targets
|
6
8
|
static targets = ['trigger', 'content']
|
7
9
|
declare readonly triggerTarget: HTMLElement
|
@@ -49,6 +49,8 @@ const focusItemByIndex = (
|
|
49
49
|
}
|
50
50
|
|
51
51
|
const DropdownMenuController = class extends Controller<HTMLElement> {
|
52
|
+
static name = 'dropdown-menu'
|
53
|
+
|
52
54
|
// targets
|
53
55
|
static targets = ['trigger', 'contentContainer', 'content', 'item']
|
54
56
|
declare readonly triggerTarget: HTMLElement
|
@@ -9,6 +9,8 @@ import {
|
|
9
9
|
} from '../utils'
|
10
10
|
|
11
11
|
const DropdownMenuSubController = class extends Controller<HTMLElement> {
|
12
|
+
static name = 'dropdown-menu-sub'
|
13
|
+
|
12
14
|
// targets
|
13
15
|
static targets = ['trigger', 'contentContainer', 'content']
|
14
16
|
declare readonly triggerTarget: HTMLElement
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
3
|
const FormFieldController = class extends Controller {
|
4
|
+
static name = 'form-field'
|
5
|
+
|
4
6
|
connect() {
|
5
7
|
const hintContainer = this.element.querySelector('[data-remove-label]')
|
6
8
|
const labelContainer = this.element.querySelector('[data-remove-hint]')
|
@@ -4,6 +4,8 @@ import { initFloatingUi } from '../utils/floating_ui'
|
|
4
4
|
import { showContent, hideContent } from '../utils'
|
5
5
|
|
6
6
|
const HoverCardController = class extends Controller<HTMLElement> {
|
7
|
+
static name = 'hover-card'
|
8
|
+
|
7
9
|
// targets
|
8
10
|
static targets = ['trigger', 'content', 'contentContainer']
|
9
11
|
declare readonly triggerTarget: HTMLElement
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
|
3
3
|
const RadioGroupController = class extends Controller<HTMLElement> {
|
4
|
+
static name = 'radio-group'
|
5
|
+
|
4
6
|
// targets
|
5
7
|
static targets = ['item', 'input', 'indicator']
|
6
8
|
declare readonly itemTargets: HTMLInputElement[]
|