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.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +321 -23
  3. data/app/javascript/controllers/accordion_controller.js +101 -90
  4. data/app/javascript/controllers/alert_dialog_controller.js +5 -4
  5. data/app/javascript/controllers/avatar_controller.js +12 -11
  6. data/app/javascript/controllers/checkbox_controller.js +26 -26
  7. data/app/javascript/controllers/collapsible_controller.js +35 -36
  8. data/app/javascript/controllers/combobox_controller.js +262 -231
  9. data/app/javascript/controllers/command_controller.js +205 -184
  10. data/app/javascript/controllers/date_picker_controller.js +252 -253
  11. data/app/javascript/controllers/date_range_picker_controller.js +189 -200
  12. data/app/javascript/controllers/dialog_controller.js +79 -78
  13. data/app/javascript/controllers/dropdown_menu_controller.js +229 -208
  14. data/app/javascript/controllers/dropdown_menu_sub_controller.js +111 -97
  15. data/app/javascript/controllers/form_field_controller.js +17 -16
  16. data/app/javascript/controllers/hover_card_controller.js +69 -71
  17. data/app/javascript/controllers/loading_button_controller.js +11 -10
  18. data/app/javascript/controllers/popover_controller.js +85 -78
  19. data/app/javascript/controllers/progress_controller.js +12 -11
  20. data/app/javascript/controllers/radio_group_controller.js +75 -74
  21. data/app/javascript/controllers/select_controller.js +247 -232
  22. data/app/javascript/controllers/sidebar_controller.js +26 -27
  23. data/app/javascript/controllers/sidebar_trigger_controller.js +12 -9
  24. data/app/javascript/controllers/slider_controller.js +74 -74
  25. data/app/javascript/controllers/switch_controller.js +23 -23
  26. data/app/javascript/controllers/tabs_controller.js +61 -61
  27. data/app/javascript/controllers/theme_switcher_controller.js +28 -27
  28. data/app/javascript/controllers/toast_container_controller.js +45 -31
  29. data/app/javascript/controllers/toast_controller.js +19 -18
  30. data/app/javascript/controllers/toggle_controller.js +17 -17
  31. data/app/javascript/controllers/toggle_group_controller.js +17 -17
  32. data/app/javascript/controllers/tooltip_controller.js +75 -77
  33. data/app/javascript/shadcn_phlexcomponents.js +27 -60
  34. data/app/javascript/utils/command.js +390 -334
  35. data/app/javascript/utils/floating_ui.js +139 -107
  36. data/app/javascript/utils/index.js +253 -190
  37. data/app/typescript/controllers/accordion_controller.ts +2 -0
  38. data/app/typescript/controllers/alert_dialog_controller.ts +2 -0
  39. data/app/typescript/controllers/avatar_controller.ts +2 -0
  40. data/app/typescript/controllers/checkbox_controller.ts +2 -0
  41. data/app/typescript/controllers/collapsible_controller.ts +2 -0
  42. data/app/typescript/controllers/combobox_controller.ts +2 -0
  43. data/app/typescript/controllers/command_controller.ts +2 -0
  44. data/app/typescript/controllers/date_picker_controller.ts +2 -0
  45. data/app/typescript/controllers/date_range_picker_controller.ts +2 -0
  46. data/app/typescript/controllers/dialog_controller.ts +2 -0
  47. data/app/typescript/controllers/dropdown_menu_controller.ts +2 -0
  48. data/app/typescript/controllers/dropdown_menu_sub_controller.ts +2 -0
  49. data/app/typescript/controllers/form_field_controller.ts +2 -0
  50. data/app/typescript/controllers/hover_card_controller.ts +2 -0
  51. data/app/typescript/controllers/loading_button_controller.ts +2 -0
  52. data/app/typescript/controllers/popover_controller.ts +2 -0
  53. data/app/typescript/controllers/progress_controller.ts +2 -0
  54. data/app/typescript/controllers/radio_group_controller.ts +2 -0
  55. data/app/typescript/controllers/select_controller.ts +2 -0
  56. data/app/typescript/controllers/slider_controller.ts +2 -0
  57. data/app/typescript/controllers/switch_controller.ts +2 -0
  58. data/app/typescript/controllers/tabs_controller.ts +2 -0
  59. data/app/typescript/controllers/theme_switcher_controller.ts +2 -0
  60. data/app/typescript/controllers/toast_container_controller.ts +2 -0
  61. data/app/typescript/controllers/toast_controller.ts +2 -0
  62. data/app/typescript/controllers/toggle_controller.ts +2 -0
  63. data/app/typescript/controllers/toggle_group_controller.ts +2 -0
  64. data/app/typescript/controllers/tooltip_controller.ts +2 -0
  65. data/app/typescript/shadcn_phlexcomponents.ts +27 -61
  66. data/app/typescript/utils/index.ts +7 -0
  67. data/lib/install/upgrade_shadcn_phlexcomponents.rb +28 -0
  68. data/lib/shadcn_phlexcomponents/components/accordion.rb +55 -12
  69. data/lib/shadcn_phlexcomponents/components/alert.rb +35 -16
  70. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +52 -12
  71. data/lib/shadcn_phlexcomponents/components/aspect_ratio.rb +33 -2
  72. data/lib/shadcn_phlexcomponents/components/avatar.rb +24 -7
  73. data/lib/shadcn_phlexcomponents/components/badge.rb +23 -18
  74. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +46 -6
  75. data/lib/shadcn_phlexcomponents/components/button.rb +32 -27
  76. data/lib/shadcn_phlexcomponents/components/card.rb +59 -10
  77. data/lib/shadcn_phlexcomponents/components/checkbox.rb +51 -30
  78. data/lib/shadcn_phlexcomponents/components/checkbox_group.rb +24 -4
  79. data/lib/shadcn_phlexcomponents/components/combobox.rb +212 -69
  80. data/lib/shadcn_phlexcomponents/components/command.rb +156 -52
  81. data/lib/shadcn_phlexcomponents/components/date_picker.rb +134 -48
  82. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +20 -42
  83. data/lib/shadcn_phlexcomponents/components/dialog.rb +80 -26
  84. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +74 -25
  85. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +52 -24
  86. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +1 -1
  87. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +1 -1
  88. data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +1 -1
  89. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +1 -1
  90. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +1 -1
  91. data/lib/shadcn_phlexcomponents/components/form/form_error.rb +8 -1
  92. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +3 -2
  93. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +8 -1
  94. data/lib/shadcn_phlexcomponents/components/form/form_input.rb +1 -1
  95. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +1 -1
  96. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +1 -1
  97. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +1 -1
  98. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +1 -1
  99. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +1 -1
  100. data/lib/shadcn_phlexcomponents/components/form.rb +22 -6
  101. data/lib/shadcn_phlexcomponents/components/hover_card.rb +48 -18
  102. data/lib/shadcn_phlexcomponents/components/input.rb +13 -8
  103. data/lib/shadcn_phlexcomponents/components/label.rb +9 -4
  104. data/lib/shadcn_phlexcomponents/components/link.rb +8 -1
  105. data/lib/shadcn_phlexcomponents/components/pagination.rb +34 -6
  106. data/lib/shadcn_phlexcomponents/components/popover.rb +43 -13
  107. data/lib/shadcn_phlexcomponents/components/progress.rb +37 -6
  108. data/lib/shadcn_phlexcomponents/components/radio_group.rb +41 -15
  109. data/lib/shadcn_phlexcomponents/components/select.rb +99 -42
  110. data/lib/shadcn_phlexcomponents/components/separator.rb +9 -4
  111. data/lib/shadcn_phlexcomponents/components/sheet.rb +87 -21
  112. data/lib/shadcn_phlexcomponents/components/skeleton.rb +8 -1
  113. data/lib/shadcn_phlexcomponents/components/switch.rb +45 -17
  114. data/lib/shadcn_phlexcomponents/components/table.rb +84 -17
  115. data/lib/shadcn_phlexcomponents/components/tabs.rb +36 -12
  116. data/lib/shadcn_phlexcomponents/components/textarea.rb +12 -7
  117. data/lib/shadcn_phlexcomponents/components/toast.rb +46 -20
  118. data/lib/shadcn_phlexcomponents/components/toast_container.rb +19 -14
  119. data/lib/shadcn_phlexcomponents/components/toggle.rb +28 -23
  120. data/lib/shadcn_phlexcomponents/components/tooltip.rb +49 -14
  121. data/lib/shadcn_phlexcomponents/configuration.rb +46 -0
  122. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +28 -0
  123. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  124. data/lib/shadcn_phlexcomponents.rb +12 -1
  125. data/lib/tasks/upgrade.rake +10 -0
  126. metadata +15 -14
  127. data/app/typescript/controllers/sidebar_controller.ts +0 -39
  128. 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
- // 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;
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
- if (window.innerHeight < document.documentElement.scrollHeight) {
25
- document.body.dataset.scrollLocked = '1';
26
- document.body.classList.add('data-[scroll-locked]:pointer-events-none', 'data-[scroll-locked]:!overflow-hidden', 'data-[scroll-locked]:!relative', 'data-[scroll-locked]:px-0', 'data-[scroll-locked]:pt-0', 'data-[scroll-locked]:ml-0', 'data-[scroll-locked]:mt-0');
27
- document.body.style.marginRight = `${getScrollbarWidth()}px`;
28
- const contentIdsString = document.body.dataset.scrollLockedContentIds || '[]';
29
- const contentIds = JSON.parse(contentIdsString);
30
- contentIds.push(contentId);
31
- document.body.dataset.scrollLockedContentIds = JSON.stringify(contentIds);
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
- const contentIdsString = document.body.dataset.scrollLockedContentIds || '[]';
36
- const contentIds = JSON.parse(contentIdsString);
37
- const newContentIds = contentIds.filter((id) => id !== contentId);
38
- document.body.dataset.scrollLockedContentIds = JSON.stringify(newContentIds);
39
- if (newContentIds.length === 0) {
40
- delete document.body.dataset.scrollLocked;
41
- document.body.classList.remove('data-[scroll-locked]:pointer-events-none', 'data-[scroll-locked]:!overflow-hidden', 'data-[scroll-locked]:!relative', 'data-[scroll-locked]:px-0', 'data-[scroll-locked]:pt-0', 'data-[scroll-locked]:ml-0', 'data-[scroll-locked]:mt-0');
42
- document.body.style.marginRight = '';
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
- setTimeout(() => {
47
- if (triggerTarget.dataset.asChild === 'false') {
48
- const childElement = triggerTarget.firstElementChild;
49
- if (childElement) {
50
- childElement.focus();
51
- }
52
- }
53
- else {
54
- triggerTarget.focus();
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
- setTimeout(() => {
60
- if (element) {
61
- element.focus();
62
- }
63
- }, ON_OPEN_FOCUS_DELAY);
75
+ setTimeout(() => {
76
+ if (element) {
77
+ element.focus();
78
+ }
79
+ }, ON_OPEN_FOCUS_DELAY);
64
80
  };
65
81
  const getFocusableElements = (container) => {
66
- return Array.from(container.querySelectorAll('button, [href], input:not([type="hidden"]), select:not([tabindex="-1"]), textarea, [tabindex]:not([tabindex="-1"])'));
67
- };
68
- const getSameLevelItems = ({ content, items, closestContentSelector, }) => {
69
- const sameLevelItems = [];
70
- items.forEach((i) => {
71
- if (i.closest(closestContentSelector) === content &&
72
- i.dataset.disabled === undefined) {
73
- sameLevelItems.push(i);
74
- }
75
- });
76
- return sameLevelItems;
77
- };
78
- const showContent = ({ trigger, content, contentContainer, setEqualWidth, overlay, }) => {
79
- contentContainer.style.display = '';
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
- content.dataset.state = 'open';
92
- if (overlay) {
93
- overlay.style.display = '';
94
- overlay.dataset.state = 'open';
95
- lockScroll(content.id);
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
- if (trigger) {
100
- trigger.ariaExpanded = 'false';
101
- trigger.dataset.state = 'closed';
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
- content.dataset.state = 'closed';
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
- if (!element)
115
- return;
116
- return window.Stimulus.getControllerForElementAndIdentifier(element, controller);
142
+ if (!element) return;
143
+ return window.Stimulus.getControllerForElementAndIdentifier(
144
+ element,
145
+ controller,
146
+ );
117
147
  };
118
148
  const anyNestedComponentsOpen = (element) => {
119
- const components = [];
120
- const componentNames = [
121
- 'dialog',
122
- 'alert-dialog',
123
- 'dropdown-menu',
124
- 'popover',
125
- 'select',
126
- 'combobox',
127
- 'command',
128
- 'hover-card',
129
- 'tooltip',
130
- 'date-picker',
131
- 'date-range-picker',
132
- ];
133
- componentNames.forEach((name) => {
134
- const triggers = Array.from(element.querySelectorAll(`[data-shadcn-phlexcomponents="${name}-trigger"]`));
135
- const controllerElements = Array.from(element.querySelectorAll(`[data-controller="${name}"]`));
136
- controllerElements.forEach((controller) => {
137
- const stimulusInstance = getStimulusInstance(name, controller);
138
- if (stimulusInstance) {
139
- components.push(stimulusInstance);
140
- }
141
- });
142
- triggers.forEach((trigger) => {
143
- const stimulusInstance = getStimulusInstance(name, document.querySelector(`#${trigger.getAttribute('aria-controls')}`));
144
- if (stimulusInstance) {
145
- components.push(stimulusInstance);
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
- return components.some((c) => c.isOpenValue);
187
+ });
188
+ return components.some((c) => c.isOpenValue);
150
189
  };
151
190
  const onClickOutside = (controller, event) => {
152
- const target = event.target;
153
- // Let trigger handle state
154
- if (target === controller.triggerTarget)
155
- return;
156
- if (controller.triggerTarget.contains(target))
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
- controller.groupTargets.forEach((g) => {
162
- const label = g.querySelector(`[data-shadcn-phlexcomponents="${controller.identifier}-label"]`);
163
- if (label) {
164
- label.id = g.getAttribute('aria-labelledby');
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
- if (newIndex > items.length - 1) {
180
- if (wrapAround) {
181
- newIndex = 0;
182
- }
183
- else {
184
- newIndex = items.length - 1;
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
- return newIndex;
188
- };
189
- const getPreviousEnabledIndex = ({ items, currentIndex, wrapAround, filterFn, }) => {
190
- let newIndex = null;
191
- if (filterFn) {
192
- newIndex = items.findLastIndex((item, index) => index < currentIndex && filterFn(item));
193
- if (newIndex === -1) {
194
- newIndex = currentIndex;
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
- else {
198
- newIndex = currentIndex - 1;
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
- if (newIndex < 0) {
201
- if (wrapAround) {
202
- newIndex = items.length - 1;
203
- }
204
- else {
205
- newIndex = 0;
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
- return newIndex;
251
+ }
252
+ return newIndex;
209
253
  };
210
254
  const handleTabNavigation = (element, event) => {
211
- const focusableElements = getFocusableElements(element);
212
- const firstElement = focusableElements[0];
213
- const lastElement = focusableElements[focusableElements.length - 1];
214
- // If Shift + Tab pressed on first element, go to last element
215
- if (event.shiftKey && document.activeElement === firstElement) {
216
- event.preventDefault();
217
- lastElement.focus();
218
- }
219
- // If Tab pressed on last element, go to first element
220
- else if (!event.shiftKey && document.activeElement === lastElement) {
221
- event.preventDefault();
222
- firstElement.focus();
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, };
@@ -7,6 +7,8 @@ import {
7
7
  } from '../utils'
8
8
 
9
9
  const AccordionController = class extends Controller<HTMLElement> {
10
+ static name = 'accordion'
11
+
10
12
  // targets
11
13
  static targets = ['item', 'trigger', 'content']
12
14
  declare itemTargets: HTMLElement[]
@@ -1,6 +1,8 @@
1
1
  import { DialogController } from './dialog_controller'
2
2
 
3
3
  const AlertDialogController = class extends DialogController {
4
+ static name = 'alert-dialog'
5
+
4
6
  protected onDOMClick() {
5
7
  return
6
8
  }
@@ -1,6 +1,8 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  const AvatarController = class extends Controller {
4
+ static name = 'avatar'
5
+
4
6
  // targets
5
7
  static targets = ['image', 'fallback']
6
8
  declare readonly imageTarget: HTMLElement
@@ -1,6 +1,8 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  const CheckboxController = class extends Controller<HTMLElement> {
4
+ static name = 'checkbox'
5
+
4
6
  // targets
5
7
  static targets = ['input', 'indicator']
6
8
  declare readonly inputTarget: HTMLInputElement
@@ -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
@@ -25,6 +25,8 @@ import {
25
25
  import { useClickOutside, useDebounce } from 'stimulus-use'
26
26
 
27
27
  const ComboboxController = class extends Controller<HTMLElement> {
28
+ static name = 'combobox'
29
+
28
30
  // targets
29
31
  static targets = [
30
32
  'trigger',
@@ -31,6 +31,8 @@ declare global {
31
31
  }
32
32
 
33
33
  const CommandController = class extends Controller<HTMLElement> {
34
+ static name = 'command'
35
+
34
36
  // targets
35
37
  static targets = [
36
38
  'trigger',
@@ -28,6 +28,8 @@ const isSmallScreen = () => {
28
28
  const DAYJS_FORMAT = 'YYYY-MM-DD'
29
29
 
30
30
  const DatePickerController = class extends Controller<HTMLElement> {
31
+ static name = 'date-picker'
32
+
31
33
  // targets
32
34
  static targets = [
33
35
  'trigger',
@@ -10,6 +10,8 @@ const DELIMITER = ' - '
10
10
  const DAYJS_FORMAT = 'YYYY-MM-DD'
11
11
 
12
12
  const DateRangePickerController = class extends DatePickerController {
13
+ static name = 'date-range-picker'
14
+
13
15
  // targets
14
16
  static targets = [
15
17
  'trigger',
@@ -10,6 +10,8 @@ import {
10
10
  } from '../utils'
11
11
 
12
12
  const DialogController = class extends Controller<HTMLElement> {
13
+ static name = 'dialog'
14
+
13
15
  // targets
14
16
  static targets = ['trigger', 'content', 'overlay']
15
17
  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 LoadingButtonController = class extends Controller<HTMLButtonElement> {
4
+ static name = 'loading-button'
5
+
4
6
  connect() {
5
7
  const el = this.element
6
8
  const form = el.closest('form')
@@ -12,6 +12,8 @@ import {
12
12
  } from '../utils'
13
13
 
14
14
  const PopoverController = class extends Controller<HTMLElement> {
15
+ static name = 'popover'
16
+
15
17
  // targets
16
18
  static targets = ['trigger', 'contentContainer', 'content']
17
19
  declare readonly triggerTarget: HTMLElement
@@ -1,6 +1,8 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  const ProgressController = class extends Controller {
4
+ static name = 'progress'
5
+
4
6
  // targets
5
7
  static targets = ['indicator']
6
8
  declare readonly indicatorTarget: 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[]