shadcn_phlexcomponents 0.1.16 → 0.1.18

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/app/javascript/controllers/accordion_controller.js +90 -100
  3. data/app/javascript/controllers/alert_dialog_controller.js +4 -4
  4. data/app/javascript/controllers/avatar_controller.js +11 -11
  5. data/app/javascript/controllers/checkbox_controller.js +26 -25
  6. data/app/javascript/controllers/collapsible_controller.js +36 -34
  7. data/app/javascript/controllers/combobox_controller.js +231 -262
  8. data/app/javascript/controllers/command_controller.js +184 -204
  9. data/app/javascript/controllers/date_picker_controller.js +257 -240
  10. data/app/javascript/controllers/date_range_picker_controller.js +200 -188
  11. data/app/javascript/controllers/dialog_controller.js +78 -78
  12. data/app/javascript/controllers/dropdown_menu_controller.js +208 -228
  13. data/app/javascript/controllers/dropdown_menu_sub_controller.js +97 -110
  14. data/app/javascript/controllers/form_field_controller.js +16 -16
  15. data/app/javascript/controllers/hover_card_controller.js +71 -68
  16. data/app/javascript/controllers/loading_button_controller.js +10 -10
  17. data/app/javascript/controllers/popover_controller.js +78 -84
  18. data/app/javascript/controllers/progress_controller.js +11 -11
  19. data/app/javascript/controllers/radio_group_controller.js +74 -74
  20. data/app/javascript/controllers/select_controller.js +232 -246
  21. data/app/javascript/controllers/sidebar_controller.js +27 -26
  22. data/app/javascript/controllers/sidebar_trigger_controller.js +9 -12
  23. data/app/javascript/controllers/slider_controller.js +74 -73
  24. data/app/javascript/controllers/switch_controller.js +23 -22
  25. data/app/javascript/controllers/tabs_controller.js +61 -60
  26. data/app/javascript/controllers/theme_switcher_controller.js +27 -27
  27. data/app/javascript/controllers/toast_container_controller.js +31 -44
  28. data/app/javascript/controllers/toast_controller.js +18 -18
  29. data/app/javascript/controllers/toggle_controller.js +17 -16
  30. data/app/javascript/controllers/toggle_group_controller.js +17 -16
  31. data/app/javascript/controllers/tooltip_controller.js +77 -74
  32. data/app/javascript/shadcn_phlexcomponents.js +58 -58
  33. data/app/javascript/utils/command.js +334 -392
  34. data/app/javascript/utils/floating_ui.js +108 -147
  35. data/app/javascript/utils/index.js +190 -253
  36. data/app/stylesheets/date_picker.css +1 -1
  37. data/app/stylesheets/shadcn_phlexcomponents.css +173 -0
  38. data/app/typescript/controllers/combobox_controller.ts +0 -1
  39. data/app/typescript/controllers/date_picker_controller.ts +25 -7
  40. data/app/typescript/controllers/tooltip_controller.ts +1 -1
  41. data/app/typescript/utils/command.ts +0 -2
  42. data/app/typescript/utils/floating_ui.ts +11 -20
  43. data/app/typescript/utils/index.ts +0 -7
  44. data/lib/shadcn_phlexcomponents/components/accordion.rb +1 -1
  45. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +6 -6
  46. data/lib/shadcn_phlexcomponents/components/base.rb +2 -2
  47. data/lib/shadcn_phlexcomponents/components/combobox.rb +15 -19
  48. data/lib/shadcn_phlexcomponents/components/command.rb +13 -13
  49. data/lib/shadcn_phlexcomponents/components/date_picker.rb +18 -12
  50. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +7 -3
  51. data/lib/shadcn_phlexcomponents/components/dialog.rb +6 -6
  52. data/lib/shadcn_phlexcomponents/components/sheet.rb +7 -7
  53. data/lib/shadcn_phlexcomponents/components/toggle.rb +1 -1
  54. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  55. metadata +2 -1
@@ -1,448 +1,390 @@
1
- import { ComboboxController } from "../controllers/combobox_controller";
2
- import { getNextEnabledIndex, getPreviousEnabledIndex } from ".";
1
+ import { ComboboxController, } from '../controllers/combobox_controller';
2
+ import { getNextEnabledIndex, getPreviousEnabledIndex } from '.';
3
3
  const scrollToItem = (controller, index) => {
4
- const item = controller.filteredItems[index];
5
- const itemRect = item.getBoundingClientRect();
6
- const listContainerRect =
7
- controller.listContainerTarget.getBoundingClientRect();
8
- let newScrollTop = null;
9
- const maxScrollTop =
10
- controller.listContainerTarget.scrollHeight -
11
- controller.listContainerTarget.clientHeight;
12
- // scroll to bottom
13
- if (itemRect.bottom - listContainerRect.bottom > 0) {
14
- if (index === controller.filteredItems.length - 1) {
15
- newScrollTop = maxScrollTop;
16
- } else {
17
- newScrollTop =
18
- controller.listContainerTarget.scrollTop +
19
- (itemRect.bottom - listContainerRect.bottom);
4
+ const item = controller.filteredItems[index];
5
+ const itemRect = item.getBoundingClientRect();
6
+ const listContainerRect = controller.listContainerTarget.getBoundingClientRect();
7
+ let newScrollTop = null;
8
+ const maxScrollTop = controller.listContainerTarget.scrollHeight -
9
+ controller.listContainerTarget.clientHeight;
10
+ // scroll to bottom
11
+ if (itemRect.bottom - listContainerRect.bottom > 0) {
12
+ if (index === controller.filteredItems.length - 1) {
13
+ newScrollTop = maxScrollTop;
14
+ }
15
+ else {
16
+ newScrollTop =
17
+ controller.listContainerTarget.scrollTop +
18
+ (itemRect.bottom - listContainerRect.bottom);
19
+ }
20
20
  }
21
- } else if (listContainerRect.top - itemRect.top > 0) {
22
- // scroll to top
23
- if (index === 0) {
24
- newScrollTop = 0;
25
- } else {
26
- newScrollTop =
27
- controller.listContainerTarget.scrollTop -
28
- (listContainerRect.top - itemRect.top);
21
+ else if (listContainerRect.top - itemRect.top > 0) {
22
+ // scroll to top
23
+ if (index === 0) {
24
+ newScrollTop = 0;
25
+ }
26
+ else {
27
+ newScrollTop =
28
+ controller.listContainerTarget.scrollTop -
29
+ (listContainerRect.top - itemRect.top);
30
+ }
29
31
  }
30
- }
31
- if (newScrollTop !== null) {
32
- controller.scrollingViaKeyboard = true;
33
- if (newScrollTop >= 0 && newScrollTop <= maxScrollTop) {
34
- controller.listContainerTarget.scrollTop = newScrollTop;
32
+ if (newScrollTop !== null) {
33
+ controller.scrollingViaKeyboard = true;
34
+ if (newScrollTop >= 0 && newScrollTop <= maxScrollTop) {
35
+ controller.listContainerTarget.scrollTop = newScrollTop;
36
+ }
37
+ // Clear the flag after scroll settles
38
+ clearTimeout(controller.keyboardScrollTimeout);
39
+ controller.keyboardScrollTimeout = window.setTimeout(() => {
40
+ controller.scrollingViaKeyboard = false;
41
+ }, 200);
35
42
  }
36
- // Clear the flag after scroll settles
37
- clearTimeout(controller.keyboardScrollTimeout);
38
- controller.keyboardScrollTimeout = window.setTimeout(() => {
39
- controller.scrollingViaKeyboard = false;
40
- }, 200);
41
- }
42
43
  };
43
44
  const highlightItem = (controller, event = null, index = null) => {
44
- if (event !== null) {
45
- if (event instanceof KeyboardEvent) {
46
- const key = event.key;
47
- const item = controller.filteredItems.find(
48
- (i) => i.dataset.highlighted === "true",
49
- );
50
- if (item) {
51
- const index = controller.filteredItems.indexOf(item);
52
- let newIndex = 0;
53
- if (key === "ArrowUp") {
54
- newIndex = getPreviousEnabledIndex({
55
- items: controller.filteredItems,
56
- currentIndex: index,
57
- filterFn: (item) => item.dataset.disabled === undefined,
58
- wrapAround: false,
59
- });
60
- } else {
61
- newIndex = getNextEnabledIndex({
62
- items: controller.filteredItems,
63
- currentIndex: index,
64
- filterFn: (item) => item.dataset.disabled === undefined,
65
- wrapAround: false,
66
- });
45
+ if (event !== null) {
46
+ if (event instanceof KeyboardEvent) {
47
+ const key = event.key;
48
+ const item = controller.filteredItems.find((i) => i.dataset.highlighted === 'true');
49
+ if (item) {
50
+ const index = controller.filteredItems.indexOf(item);
51
+ let newIndex = 0;
52
+ if (key === 'ArrowUp') {
53
+ newIndex = getPreviousEnabledIndex({
54
+ items: controller.filteredItems,
55
+ currentIndex: index,
56
+ filterFn: (item) => item.dataset.disabled === undefined,
57
+ wrapAround: false,
58
+ });
59
+ }
60
+ else {
61
+ newIndex = getNextEnabledIndex({
62
+ items: controller.filteredItems,
63
+ currentIndex: index,
64
+ filterFn: (item) => item.dataset.disabled === undefined,
65
+ wrapAround: false,
66
+ });
67
+ }
68
+ controller.highlightItemByIndex(newIndex);
69
+ controller.scrollToItem(newIndex);
70
+ }
71
+ else {
72
+ if (key === 'ArrowUp') {
73
+ controller.highlightItemByIndex(controller.filteredItems.length - 1);
74
+ }
75
+ else {
76
+ controller.highlightItemByIndex(0);
77
+ }
78
+ }
67
79
  }
68
- controller.highlightItemByIndex(newIndex);
69
- controller.scrollToItem(newIndex);
70
- } else {
71
- if (key === "ArrowUp") {
72
- controller.highlightItemByIndex(controller.filteredItems.length - 1);
73
- } else {
74
- controller.highlightItemByIndex(0);
80
+ else {
81
+ // mouse event
82
+ if (controller.scrollingViaKeyboard) {
83
+ event.stopImmediatePropagation();
84
+ return;
85
+ }
86
+ else {
87
+ const item = event.currentTarget;
88
+ const index = controller.filteredItems.indexOf(item);
89
+ controller.highlightItemByIndex(index);
90
+ }
75
91
  }
76
- }
77
- } else {
78
- // mouse event
79
- if (controller.scrollingViaKeyboard) {
80
- event.stopImmediatePropagation();
81
- return;
82
- } else {
83
- const item = event.currentTarget;
84
- const index = controller.filteredItems.indexOf(item);
92
+ }
93
+ else if (index !== null) {
85
94
  controller.highlightItemByIndex(index);
86
- }
87
95
  }
88
- } else if (index !== null) {
89
- controller.highlightItemByIndex(index);
90
- }
91
96
  };
92
97
  const highlightItemByIndex = (controller, index) => {
93
- controller.filteredItems.forEach((item, i) => {
94
- if (i === index) {
95
- item.dataset.highlighted = "true";
96
- } else {
97
- item.dataset.highlighted = "false";
98
- }
99
- });
100
- };
101
- const filteredItemsChanged = (controller, filteredItemIndexes) => {
102
- if (controller.orderedItems) {
103
- const filteredItems = filteredItemIndexes.map(
104
- (i) => controller.orderedItems[i],
105
- );
106
- // 1. Toggle visibility of items
107
- controller.orderedItems.forEach((item) => {
108
- if (filteredItems.includes(item)) {
109
- item.ariaHidden = "false";
110
- item.classList.remove("hidden");
111
- } else {
112
- item.ariaHidden = "true";
113
- item.classList.add("hidden");
114
- }
115
- });
116
- // 2. Get groups based on order of filtered items
117
- const groupIds = filteredItems.map((item) => item.dataset.groupId);
118
- const uniqueGroupIds = [...new Set(groupIds)].filter(
119
- (groupId) => !!groupId,
120
- );
121
- const orderedGroups = uniqueGroupIds.map((groupId) => {
122
- return controller.listTarget.querySelector(
123
- `[aria-labelledby=${groupId}]`,
124
- );
125
- });
126
- // 3. Append items and groups based on filtered items
127
- const appendedGroupIds = [];
128
- filteredItems.forEach((item) => {
129
- const groupId = item.dataset.groupId;
130
- if (groupId) {
131
- const group = orderedGroups.find(
132
- (g) => g.getAttribute("aria-labelledby") === groupId,
133
- );
134
- if (group) {
135
- group.appendChild(item);
136
- if (!appendedGroupIds.includes(groupId)) {
137
- controller.listTarget.appendChild(group);
138
- appendedGroupIds.push(groupId);
139
- }
98
+ controller.filteredItems.forEach((item, i) => {
99
+ if (i === index) {
100
+ item.dataset.highlighted = 'true';
140
101
  }
141
- } else {
142
- controller.listTarget.appendChild(item);
143
- }
144
- });
145
- // 4. Toggle visibility of groups
146
- controller.groupTargets.forEach((group) => {
147
- const itemsCount = group.querySelectorAll(
148
- `[data-${controller.identifier}-target=item][aria-hidden=false]`,
149
- ).length;
150
- if (itemsCount > 0) {
151
- group.classList.remove("hidden");
152
- } else {
153
- group.classList.add("hidden");
154
- }
155
- });
156
- // 5. Move remote items to the end
157
- const remoteItems = Array.from(
158
- controller.element.querySelectorAll(
159
- `[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`,
160
- ),
161
- );
162
- remoteItems.forEach((i) => {
163
- const isInsideGroup =
164
- i.parentElement?.dataset?.shadcnPhlexcomponents ===
165
- `${controller.identifier}-group`;
166
- if (isInsideGroup) {
167
- const isRemoteGroup = i.parentElement.dataset.remote === "true";
168
- // Move group to last
169
- if (isRemoteGroup) {
170
- controller.listTarget.appendChild(i.parentElement);
102
+ else {
103
+ item.dataset.highlighted = 'false';
171
104
  }
172
- } else {
173
- // Move item to last
174
- controller.listTarget.appendChild(i);
175
- }
176
105
  });
177
- // 6. Assign filteredItems based on the order it is displayed in the DOM
178
- controller.filteredItems = Array.from(
179
- controller.listTarget.querySelectorAll(
180
- `[data-${controller.identifier}-target=item][aria-hidden=false]`,
181
- ),
182
- );
183
- // 7. Highlight first item
184
- controller.highlightItemByIndex(0);
185
- // 8. Toggle visibility of empty
186
- if (controller.isDirty && !controller.isLoading) {
187
- if (controller.filteredItems.length > 0) {
188
- hideEmpty(controller);
189
- } else {
190
- showEmpty(controller);
191
- }
106
+ };
107
+ const filteredItemsChanged = (controller, filteredItemIndexes) => {
108
+ if (controller.orderedItems) {
109
+ const filteredItems = filteredItemIndexes.map((i) => controller.orderedItems[i]);
110
+ // 1. Toggle visibility of items
111
+ controller.orderedItems.forEach((item) => {
112
+ if (filteredItems.includes(item)) {
113
+ item.ariaHidden = 'false';
114
+ item.classList.remove('hidden');
115
+ }
116
+ else {
117
+ item.ariaHidden = 'true';
118
+ item.classList.add('hidden');
119
+ }
120
+ });
121
+ // 2. Get groups based on order of filtered items
122
+ const groupIds = filteredItems.map((item) => item.dataset.groupId);
123
+ const uniqueGroupIds = [...new Set(groupIds)].filter((groupId) => !!groupId);
124
+ const orderedGroups = uniqueGroupIds.map((groupId) => {
125
+ return controller.listTarget.querySelector(`[aria-labelledby=${groupId}]`);
126
+ });
127
+ // 3. Append items and groups based on filtered items
128
+ const appendedGroupIds = [];
129
+ filteredItems.forEach((item) => {
130
+ const groupId = item.dataset.groupId;
131
+ if (groupId) {
132
+ const group = orderedGroups.find((g) => g.getAttribute('aria-labelledby') === groupId);
133
+ if (group) {
134
+ group.appendChild(item);
135
+ if (!appendedGroupIds.includes(groupId)) {
136
+ controller.listTarget.appendChild(group);
137
+ appendedGroupIds.push(groupId);
138
+ }
139
+ }
140
+ }
141
+ else {
142
+ controller.listTarget.appendChild(item);
143
+ }
144
+ });
145
+ // 4. Toggle visibility of groups
146
+ controller.groupTargets.forEach((group) => {
147
+ const itemsCount = group.querySelectorAll(`[data-${controller.identifier}-target=item][aria-hidden=false]`).length;
148
+ if (itemsCount > 0) {
149
+ group.classList.remove('hidden');
150
+ }
151
+ else {
152
+ group.classList.add('hidden');
153
+ }
154
+ });
155
+ // 5. Move remote items to the end
156
+ const remoteItems = Array.from(controller.element.querySelectorAll(`[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`));
157
+ remoteItems.forEach((i) => {
158
+ const isInsideGroup = i.parentElement?.dataset?.shadcnPhlexcomponents ===
159
+ `${controller.identifier}-group`;
160
+ if (isInsideGroup) {
161
+ const isRemoteGroup = i.parentElement.dataset.remote === 'true';
162
+ // Move group to last
163
+ if (isRemoteGroup) {
164
+ controller.listTarget.appendChild(i.parentElement);
165
+ }
166
+ }
167
+ else {
168
+ // Move item to last
169
+ controller.listTarget.appendChild(i);
170
+ }
171
+ });
172
+ // 6. Assign filteredItems based on the order it is displayed in the DOM
173
+ controller.filteredItems = Array.from(controller.listTarget.querySelectorAll(`[data-${controller.identifier}-target=item][aria-hidden=false]`));
174
+ // 7. Highlight first item
175
+ controller.highlightItemByIndex(0);
176
+ // 8. Toggle visibility of empty
177
+ if (controller.isDirty && !controller.isLoading) {
178
+ if (controller.filteredItems.length > 0) {
179
+ hideEmpty(controller);
180
+ }
181
+ else {
182
+ showEmpty(controller);
183
+ }
184
+ }
192
185
  }
193
- }
194
186
  };
195
187
  const setItemsGroupId = (controller) => {
196
- controller.itemTargets.forEach((item) => {
197
- const parent = item.parentElement;
198
- if (parent?.dataset[`${controller.identifier}Target`] === "group") {
199
- item.dataset.groupId = parent.getAttribute("aria-labelledby");
200
- }
201
- });
188
+ controller.itemTargets.forEach((item) => {
189
+ const parent = item.parentElement;
190
+ if (parent?.dataset[`${controller.identifier}Target`] === 'group') {
191
+ item.dataset.groupId = parent.getAttribute('aria-labelledby');
192
+ }
193
+ });
202
194
  };
203
195
  const search = (controller, event) => {
204
- const input = event.target;
205
- const value = input.value.trim();
206
- if (value.length > 0) {
207
- const results = controller.fuse.search(value);
208
- // Don't show disabled items when filtering
209
- let filteredItemIndexes = results.map((result) => result.refIndex);
210
- filteredItemIndexes = filteredItemIndexes.filter((index) => {
211
- const item = controller.orderedItems[index];
212
- return item.dataset.disabled === undefined;
213
- });
214
- if (controller.searchPath) {
215
- hideSelectedRemoteItems(controller);
216
- showLoading(controller);
217
- hideList(controller);
218
- hideEmpty(controller);
219
- controller.filteredItemIndexesValue = filteredItemIndexes;
220
- performRemoteSearch(controller, value);
221
- } else {
222
- controller.filteredItemIndexesValue = filteredItemIndexes;
196
+ const input = event.target;
197
+ const value = input.value.trim();
198
+ if (value.length > 0) {
199
+ const results = controller.fuse.search(value);
200
+ // Don't show disabled items when filtering
201
+ let filteredItemIndexes = results.map((result) => result.refIndex);
202
+ filteredItemIndexes = filteredItemIndexes.filter((index) => {
203
+ const item = controller.orderedItems[index];
204
+ return item.dataset.disabled === undefined;
205
+ });
206
+ if (controller.searchPath) {
207
+ hideSelectedRemoteItems(controller);
208
+ showLoading(controller);
209
+ hideList(controller);
210
+ hideEmpty(controller);
211
+ controller.filteredItemIndexesValue = filteredItemIndexes;
212
+ performRemoteSearch(controller, value);
213
+ }
214
+ else {
215
+ controller.filteredItemIndexesValue = filteredItemIndexes;
216
+ }
223
217
  }
224
- } else {
225
- if (controller.searchPath) {
226
- showSelectedRemoteItems(controller);
218
+ else {
219
+ if (controller.searchPath) {
220
+ showSelectedRemoteItems(controller);
221
+ }
222
+ controller.filteredItemIndexesValue = Array.from({ length: controller.orderedItems.length }, (_, i) => i);
227
223
  }
228
- controller.filteredItemIndexesValue = Array.from(
229
- { length: controller.orderedItems.length },
230
- (_, i) => i,
231
- );
232
- }
233
224
  };
234
225
  const performRemoteSearch = async (controller, query) => {
235
- // Cancel previous request
236
- if (controller.abortController) {
237
- controller.abortController.abort();
238
- }
239
- // Create new abort controller
240
- controller.abortController = new AbortController();
241
- try {
242
- const response = await fetch(`${controller.searchPath}?q=${query}`, {
243
- signal: controller.abortController.signal,
244
- headers: {
245
- Accept: "application/json",
246
- "Content-Type": "application/json",
247
- },
248
- });
249
- if (!response.ok) {
250
- throw new Error(`HTTP error! status: ${response.status}`);
226
+ // Cancel previous request
227
+ if (controller.abortController) {
228
+ controller.abortController.abort();
229
+ }
230
+ // Create new abort controller
231
+ controller.abortController = new AbortController();
232
+ try {
233
+ const response = await fetch(`${controller.searchPath}?q=${query}`, {
234
+ signal: controller.abortController.signal,
235
+ headers: {
236
+ Accept: 'application/json',
237
+ 'Content-Type': 'application/json',
238
+ },
239
+ });
240
+ if (!response.ok) {
241
+ throw new Error(`HTTP error! status: ${response.status}`);
242
+ }
243
+ const data = await response.json();
244
+ renderRemoteResults(controller, data);
245
+ showList(controller);
246
+ }
247
+ catch (error) {
248
+ if (error instanceof Error && error.name !== 'AbortError') {
249
+ console.error('Remote search error:', error);
250
+ showError(controller);
251
+ }
251
252
  }
252
- const data = await response.json();
253
- renderRemoteResults(controller, data);
254
- showList(controller);
255
- } catch (error) {
256
- if (error instanceof Error && error.name !== "AbortError") {
257
- console.error("Remote search error:", error);
258
- showError(controller);
253
+ finally {
254
+ hideLoading(controller);
259
255
  }
260
- } finally {
261
- hideLoading(controller);
262
- }
263
256
  };
264
257
  const renderRemoteResults = (controller, data) => {
265
- console.log("data", data);
266
- data.forEach((item) => {
267
- const tempDiv = document.createElement("div");
268
- tempDiv.innerHTML = item.html;
269
- const itemEl = tempDiv.firstElementChild;
270
- itemEl.dataset.remote = "true";
271
- itemEl.ariaHidden = "false";
272
- if (controller instanceof ComboboxController) {
273
- // Don't append same item
274
- if (controller.selectedValue === itemEl.dataset.value) {
275
- const item = controller.itemTargets.find(
276
- (i) => i.dataset.value === controller.selectedValue,
277
- );
278
- if (item) {
279
- item.classList.remove("hidden");
280
- item.ariaHidden = "false";
258
+ data.forEach((item) => {
259
+ const tempDiv = document.createElement('div');
260
+ tempDiv.innerHTML = item.html;
261
+ const itemEl = tempDiv.firstElementChild;
262
+ itemEl.dataset.remote = 'true';
263
+ itemEl.ariaHidden = 'false';
264
+ if (controller instanceof ComboboxController) {
265
+ // Don't append same item
266
+ if (controller.selectedValue === itemEl.dataset.value) {
267
+ const item = controller.itemTargets.find((i) => i.dataset.value === controller.selectedValue);
268
+ if (item) {
269
+ item.classList.remove('hidden');
270
+ item.ariaHidden = 'false';
271
+ }
272
+ return;
273
+ }
281
274
  }
282
- return;
283
- }
275
+ const group = item.group;
276
+ if (group) {
277
+ const groupEl = controller.groupTargets.find((g) => {
278
+ const label = g.querySelector(`[data-shadcn-phlexcomponents="${controller.identifier}-label"]`);
279
+ if (!label)
280
+ return false;
281
+ return label.textContent === group;
282
+ });
283
+ if (groupEl) {
284
+ groupEl.classList.remove('hidden');
285
+ groupEl.append(itemEl);
286
+ }
287
+ else {
288
+ const template = controller.element.querySelector('template');
289
+ const clone = template.content.cloneNode(true);
290
+ const groupEl = clone.querySelector(`[data-shadcn-phlexcomponents="${controller.identifier}-group"]`);
291
+ const groupId = crypto.randomUUID();
292
+ const label = clone.querySelector(`[data-shadcn-phlexcomponents="${controller.identifier}-label"]`);
293
+ label.textContent = group;
294
+ label.id = groupId;
295
+ groupEl.setAttribute('aria-labelledby', groupId);
296
+ groupEl.dataset.remote = 'true';
297
+ groupEl.append(itemEl);
298
+ controller.listTarget.append(clone);
299
+ }
300
+ }
301
+ else {
302
+ controller.listTarget.append(itemEl);
303
+ }
304
+ });
305
+ // Update filtered items for keyboard navigation
306
+ controller.filteredItems = Array.from(controller.listTarget.querySelectorAll(`[data-${controller.identifier}-target="item"][aria-hidden=false]`));
307
+ controller.highlightItemByIndex(0);
308
+ if (controller.filteredItems.length > 0) {
309
+ hideEmpty(controller);
284
310
  }
285
- const group = item.group;
286
- if (group) {
287
- const groupEl = controller.groupTargets.find((g) => {
288
- const label = g.querySelector(
289
- `[data-shadcn-phlexcomponents="${controller.identifier}-label"]`,
290
- );
291
- if (!label) return false;
292
- return label.textContent === group;
293
- });
294
- if (groupEl) {
295
- groupEl.classList.remove("hidden");
296
- groupEl.append(itemEl);
297
- } else {
298
- const template = controller.element.querySelector("template");
299
- const clone = template.content.cloneNode(true);
300
- const groupEl = clone.querySelector(
301
- `[data-shadcn-phlexcomponents="${controller.identifier}-group"]`,
302
- );
303
- const groupId = crypto.randomUUID();
304
- const label = clone.querySelector(
305
- `[data-shadcn-phlexcomponents="${controller.identifier}-label"]`,
306
- );
307
- label.textContent = group;
308
- label.id = groupId;
309
- groupEl.setAttribute("aria-labelledby", groupId);
310
- groupEl.dataset.remote = "true";
311
- groupEl.append(itemEl);
312
- controller.listTarget.append(clone);
313
- }
314
- } else {
315
- controller.listTarget.append(itemEl);
311
+ else {
312
+ showEmpty(controller);
316
313
  }
317
- });
318
- // Update filtered items for keyboard navigation
319
- controller.filteredItems = Array.from(
320
- controller.listTarget.querySelectorAll(
321
- `[data-${controller.identifier}-target="item"][aria-hidden=false]`,
322
- ),
323
- );
324
- controller.highlightItemByIndex(0);
325
- console.log("controller.filteredItems", controller.filteredItems);
326
- if (controller.filteredItems.length > 0) {
327
- hideEmpty(controller);
328
- } else {
329
- showEmpty(controller);
330
- }
331
314
  };
332
315
  const clearRemoteResults = (controller) => {
333
- const remoteGroups = Array.from(
334
- controller.element.querySelectorAll(
335
- `[data-shadcn-phlexcomponents="${controller.identifier}-group"][data-remote='true']`,
336
- ),
337
- );
338
- remoteGroups.forEach((g) => {
339
- const containsSelected = g.querySelector('[aria-selected="true"]');
340
- if (!containsSelected) {
341
- g.remove();
342
- }
343
- });
344
- const remoteItems = Array.from(
345
- controller.element.querySelectorAll(
346
- `[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']:not([aria-selected="true"])`,
347
- ),
348
- );
349
- remoteItems.forEach((i) => i.remove());
316
+ const remoteGroups = Array.from(controller.element.querySelectorAll(`[data-shadcn-phlexcomponents="${controller.identifier}-group"][data-remote='true']`));
317
+ remoteGroups.forEach((g) => {
318
+ const containsSelected = g.querySelector('[aria-selected="true"]');
319
+ if (!containsSelected) {
320
+ g.remove();
321
+ }
322
+ });
323
+ const remoteItems = Array.from(controller.element.querySelectorAll(`[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']:not([aria-selected="true"])`));
324
+ remoteItems.forEach((i) => i.remove());
350
325
  };
351
326
  const resetState = (controller) => {
352
- controller.searchInputTarget.value = "";
353
- if (controller.searchPath) {
354
- clearRemoteResults(controller);
355
- showSelectedRemoteItems(controller);
356
- }
357
- controller.filteredItemIndexesValue = Array.from(
358
- { length: controller.orderedItems.length },
359
- (_, i) => i,
360
- );
327
+ controller.searchInputTarget.value = '';
328
+ if (controller.searchPath) {
329
+ clearRemoteResults(controller);
330
+ showSelectedRemoteItems(controller);
331
+ }
332
+ controller.filteredItemIndexesValue = Array.from({ length: controller.orderedItems.length }, (_, i) => i);
361
333
  };
362
334
  const showLoading = (controller) => {
363
- controller.isLoading = true;
364
- controller.loadingTarget.classList.remove("hidden");
335
+ controller.isLoading = true;
336
+ controller.loadingTarget.classList.remove('hidden');
365
337
  };
366
338
  const hideLoading = (controller) => {
367
- controller.isLoading = false;
368
- controller.loadingTarget.classList.add("hidden");
339
+ controller.isLoading = false;
340
+ controller.loadingTarget.classList.add('hidden');
369
341
  };
370
342
  const showList = (controller) => {
371
- controller.listTarget.classList.remove("hidden");
343
+ controller.listTarget.classList.remove('hidden');
372
344
  };
373
345
  const hideList = (controller) => {
374
- controller.listTarget.classList.add("hidden");
346
+ controller.listTarget.classList.add('hidden');
375
347
  };
376
348
  const showError = (controller) => {
377
- controller.errorTarget.classList.remove("hidden");
349
+ controller.errorTarget.classList.remove('hidden');
378
350
  };
379
351
  const hideError = (controller) => {
380
- controller.errorTarget.classList.add("hidden");
352
+ controller.errorTarget.classList.add('hidden');
381
353
  };
382
354
  const showEmpty = (controller) => {
383
- controller.emptyTarget.classList.remove("hidden");
355
+ controller.emptyTarget.classList.remove('hidden');
384
356
  };
385
357
  const hideEmpty = (controller) => {
386
- controller.emptyTarget.classList.add("hidden");
358
+ controller.emptyTarget.classList.add('hidden');
387
359
  };
388
360
  const showSelectedRemoteItems = (controller) => {
389
- const remoteItems = Array.from(
390
- controller.element.querySelectorAll(
391
- `[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`,
392
- ),
393
- );
394
- remoteItems.forEach((i) => {
395
- const isInsideGroup =
396
- i.parentElement?.dataset?.shadcnPhlexcomponents ===
397
- `${controller.identifier}-group`;
398
- if (isInsideGroup) {
399
- const isRemoteGroup = i.parentElement.dataset.remote === "true";
400
- if (isRemoteGroup) {
401
- i.parentElement.classList.remove("hidden");
402
- }
403
- }
404
- i.ariaHidden = "false";
405
- i.classList.remove("hidden");
406
- });
361
+ const remoteItems = Array.from(controller.element.querySelectorAll(`[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`));
362
+ remoteItems.forEach((i) => {
363
+ const isInsideGroup = i.parentElement?.dataset?.shadcnPhlexcomponents ===
364
+ `${controller.identifier}-group`;
365
+ if (isInsideGroup) {
366
+ const isRemoteGroup = i.parentElement.dataset.remote === 'true';
367
+ if (isRemoteGroup) {
368
+ i.parentElement.classList.remove('hidden');
369
+ }
370
+ }
371
+ i.ariaHidden = 'false';
372
+ i.classList.remove('hidden');
373
+ });
407
374
  };
408
375
  const hideSelectedRemoteItems = (controller) => {
409
- const remoteItems = Array.from(
410
- controller.element.querySelectorAll(
411
- `[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`,
412
- ),
413
- );
414
- remoteItems.forEach((i) => {
415
- const isInsideGroup =
416
- i.parentElement?.dataset?.shadcnPhlexcomponents ===
417
- `${controller.identifier}-group`;
418
- if (isInsideGroup) {
419
- const isRemoteGroup = i.parentElement.dataset.remote === "true";
420
- if (isRemoteGroup) {
421
- i.parentElement.classList.add("hidden");
422
- }
423
- }
424
- i.ariaHidden = "true";
425
- i.classList.add("hidden");
426
- });
427
- };
428
- export {
429
- scrollToItem,
430
- highlightItem,
431
- highlightItemByIndex,
432
- filteredItemsChanged,
433
- setItemsGroupId,
434
- search,
435
- performRemoteSearch,
436
- clearRemoteResults,
437
- resetState,
438
- showLoading,
439
- hideLoading,
440
- showList,
441
- hideList,
442
- showError,
443
- hideError,
444
- showEmpty,
445
- hideEmpty,
446
- showSelectedRemoteItems,
447
- hideSelectedRemoteItems,
376
+ const remoteItems = Array.from(controller.element.querySelectorAll(`[data-shadcn-phlexcomponents="${controller.identifier}-item"][data-remote='true']`));
377
+ remoteItems.forEach((i) => {
378
+ const isInsideGroup = i.parentElement?.dataset?.shadcnPhlexcomponents ===
379
+ `${controller.identifier}-group`;
380
+ if (isInsideGroup) {
381
+ const isRemoteGroup = i.parentElement.dataset.remote === 'true';
382
+ if (isRemoteGroup) {
383
+ i.parentElement.classList.add('hidden');
384
+ }
385
+ }
386
+ i.ariaHidden = 'true';
387
+ i.classList.add('hidden');
388
+ });
448
389
  };
390
+ export { scrollToItem, highlightItem, highlightItemByIndex, filteredItemsChanged, setItemsGroupId, search, performRemoteSearch, clearRemoteResults, resetState, showLoading, hideLoading, showList, hideList, showError, hideError, showEmpty, hideEmpty, showSelectedRemoteItems, hideSelectedRemoteItems, };