@poirazis/supercomponents-shared 1.2.16 → 1.2.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 (35) hide show
  1. package/dist/index.js +17785 -22317
  2. package/dist/index.umd.cjs +19 -19
  3. package/package.json +13 -13
  4. package/src/index.js +1 -0
  5. package/src/index.ts +1 -0
  6. package/src/lib/SuperButton/SuperButton.svelte +90 -43
  7. package/src/lib/SuperField/SuperField.svelte +2 -3
  8. package/src/lib/SuperForm/InnerForm.svelte +7 -8
  9. package/src/lib/SuperTable/SuperTable.css +13 -6
  10. package/src/lib/SuperTable/SuperTable.svelte +53 -38
  11. package/src/lib/SuperTable/constants.js +1 -1
  12. package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +34 -18
  13. package/src/lib/SuperTable/controls/SelectionColumn.svelte +6 -5
  14. package/src/lib/SuperTableCells/CellBoolean.svelte +52 -45
  15. package/src/lib/SuperTableCells/CellCommon.css +0 -5
  16. package/src/lib/SuperTableCells/CellDatetime.svelte +268 -120
  17. package/src/lib/SuperTableCells/CellLink.svelte +16 -7
  18. package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +28 -24
  19. package/src/lib/SuperTableCells/CellLinkPickerTree.svelte +22 -20
  20. package/src/lib/SuperTableCells/CellNumber.svelte +55 -53
  21. package/src/lib/SuperTableCells/CellOptions.svelte +60 -33
  22. package/src/lib/SuperTableCells/CellOptionsAdvanced.svelte +131 -129
  23. package/src/lib/SuperTableCells/CellSQLLink.svelte +35 -33
  24. package/src/lib/SuperTableCells/CellSQLLinkPicker.svelte +4 -7
  25. package/src/lib/SuperTableCells/CellString.svelte +49 -47
  26. package/src/lib/SuperTableCells/CellStringMask.svelte +41 -40
  27. package/src/lib/SuperTableColumn/SuperTableColumn.svelte +2 -0
  28. package/src/lib/SuperTableColumn/parts/SuperColumnBody.svelte +1 -0
  29. package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +44 -42
  30. package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +1 -1
  31. package/src/lib/SuperTabs/SuperTabs.svelte +33 -17
  32. package/src/lib/UI/elements/Checkbox.svelte +69 -11
  33. package/src/lib/UI/elements/Switch.svelte +162 -0
  34. package/src/lib/UI/elements/Textbox.svelte +210 -0
  35. package/src/lib/UI/elements/Tooltip.svelte +15 -43
@@ -12,6 +12,11 @@
12
12
  export let autofocus;
13
13
 
14
14
  let originalValue;
15
+ let anchor;
16
+ let picker;
17
+ let timePicker;
18
+ let open;
19
+ let selection = false;
15
20
 
16
21
  export let cellState = fsm("View", {
17
22
  "*": {
@@ -20,6 +25,10 @@
20
25
  },
21
26
  },
22
27
  View: {
28
+ _enter() {
29
+ open = false;
30
+ selection = false;
31
+ },
23
32
  focus() {
24
33
  if (!cellOptions.readonly) return "Editing";
25
34
  },
@@ -33,125 +42,176 @@
33
42
  _exit() {
34
43
  dispatch("exitedit");
35
44
  },
45
+ toggle(e) {
46
+ open = !open;
47
+ },
36
48
  handleKeyboard(e) {
37
49
  if (e.keyCode == 32) {
38
50
  e.stopPropagation();
39
51
  e.preventDefault();
40
52
  open = !open;
41
53
  }
54
+
55
+ if (e.code == "Delete" || e.code == "Backspace") {
56
+ e.stopPropagation();
57
+ e.preventDefault();
58
+ value = null;
59
+ dispatch("change", value);
60
+ }
42
61
  },
43
62
  focusout(e) {
44
63
  const isInPicker = picker?.contains(e.relatedTarget);
45
64
  const isInTimePicker = timePicker?.contains(e.relatedTarget);
46
65
 
66
+ if (isInPicker || isInTimePicker) return;
67
+
47
68
  if (!isInPicker && !isInTimePicker) {
48
69
  open = false;
49
- if (value != originalValue) {
50
- dispatch("change", value);
70
+ let outputValue = innerDate.toISOString();
71
+ if (!currentShowTime) {
72
+ outputValue = innerDate.toLocaleDateString("en-CA"); // YYYY-MM-DD format without time
51
73
  }
74
+
75
+ if (ignoreTimeZone) {
76
+ outputValue = innerDate.toISOString().slice(0, -1);
77
+ }
78
+
79
+ if (selection) dispatch("change", outputValue);
52
80
  return "View";
53
81
  }
54
82
  },
83
+ submit() {
84
+ dispatch("change", innerDate.toISOString());
85
+ return "View";
86
+ },
55
87
  cancel() {
56
- value = Array.isArray(originalValue)
57
- ? [...originalValue]
58
- : originalValue;
88
+ value = originalValue;
59
89
  return "View";
60
90
  },
61
91
  },
62
92
  });
63
93
 
64
- let anchor;
65
- let picker;
66
- let timePicker;
67
- let open;
68
-
69
94
  // Current date format and showTime - extracted to ensure reactivity
70
95
  $: currentDateFormat = cellOptions?.dateFormat;
71
96
  $: currentShowTime = cellOptions?.showTime;
97
+ $: ignoreTimeZone = cellOptions?.ignoreTimezone;
98
+ $: show24HTime = cellOptions?.show24HTime;
99
+ $: innerDate = parseValueToDate(value);
100
+ $: timeValue = innerDate.toLocaleTimeString("en-US", {
101
+ hour12: !show24HTime,
102
+ hour: "2-digit",
103
+ minute: "2-digit",
104
+ });
72
105
 
73
- // Time value (format: HH:mm)
74
- $: timeValue = currentShowTime && value ? getTimeFromValue() : "00:00";
75
- $: innerDate = value ? new Date(value) : new Date();
106
+ // Helper function to create a Date object that properly handles UTC when ignoreTimezone is true
107
+ function parseValueToDate(valueStr) {
108
+ if (!valueStr) return new Date();
109
+ if (valueStr instanceof Date) {
110
+ valueStr = valueStr;
111
+ }
76
112
 
77
- // Extract time from current value if it exists
78
- function getTimeFromValue() {
79
- if (!value) return "00:00";
80
- const date = new Date(value);
81
- return `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
113
+ return new Date(valueStr);
82
114
  }
83
115
 
84
- // Date formatting helper function
85
- function formatDate(date, dateFormat) {
86
- if (!date) return "";
87
-
88
- if (!dateFormat || dateFormat === "default") {
89
- return date?.toDateString();
90
- }
116
+ // Parse 12-hour time format to 24-hour format
117
+ function parse12HourTime(timeStr) {
118
+ const match = timeStr.match(/(\d{1,2}):(\d{2})\s*(AM|PM)/i);
119
+ if (!match) return null;
120
+ let hours = parseInt(match[1]);
121
+ const minutes = parseInt(match[2]);
122
+ const ampm = match[3].toUpperCase();
91
123
 
92
- // Manual formatting for specific formats to ensure exact order
93
- if (dateFormat === "MM/DD/YYYY") {
94
- return `${(date.getMonth() + 1).toString().padStart(2, "0")}/${date.getDate().toString().padStart(2, "0")}/${date.getFullYear()}`;
95
- }
124
+ if (ampm === "PM" && hours !== 12) hours += 12;
125
+ if (ampm === "AM" && hours === 12) hours = 0;
96
126
 
97
- if (dateFormat === "DD/MM/YYYY") {
98
- return `${date.getDate().toString().padStart(2, "0")}/${(date.getMonth() + 1).toString().padStart(2, "0")}/${date.getFullYear()}`;
99
- }
127
+ return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
128
+ }
100
129
 
101
- if (dateFormat === "YYYY-MM-DD") {
102
- return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
103
- }
130
+ // Format date/datetime helper function
131
+ // Only applies formatting - timezone handling is done in parseValueToDate
132
+ // If showTime is false (default), returns formatted date only
133
+ // If showTime is true, returns formatted date + time
134
+ function formatDateTime(date, dateFormat, showTime = false) {
135
+ if (!date) return "";
104
136
 
105
- // For shorter formats, still use locale-specific formatting
106
- const options = {
107
- "MMM DD, YYYY": {
108
- month: "short",
109
- day: "numeric",
110
- year: "numeric",
111
- timeZone: "UTC",
112
- },
113
- "DD MMM YYYY": {
114
- day: "numeric",
115
- month: "short",
116
- year: "numeric",
117
- timeZone: "UTC",
118
- },
119
- };
137
+ // Format the date part
138
+ let dateResult = "";
120
139
 
121
- const formatOption = options[dateFormat];
122
- if (formatOption) {
123
- return date.toLocaleDateString("en-US", formatOption);
140
+ if (!dateFormat || dateFormat === "default") {
141
+ dateResult = date?.toDateString();
142
+ } else {
143
+ // Use local methods to format - timezone is already handled by parseValueToDate
144
+ const month = date.getMonth();
145
+ const dayOfMonth = date.getDate();
146
+ const year = date.getFullYear();
147
+
148
+ // Manual formatting for specific formats to ensure exact order
149
+ if (dateFormat === "MM/DD/YYYY") {
150
+ dateResult = `${(month + 1).toString().padStart(2, "0")}/${dayOfMonth.toString().padStart(2, "0")}/${year}`;
151
+ } else if (dateFormat === "DD/MM/YYYY") {
152
+ dateResult = `${dayOfMonth.toString().padStart(2, "0")}/${(month + 1).toString().padStart(2, "0")}/${year}`;
153
+ } else if (dateFormat === "YYYY-MM-DD") {
154
+ dateResult = `${year}-${(month + 1).toString().padStart(2, "0")}-${dayOfMonth.toString().padStart(2, "0")}`;
155
+ } else {
156
+ // For shorter formats, use locale-specific formatting
157
+ const options = {
158
+ "MMM DD, YYYY": {
159
+ month: "short",
160
+ day: "numeric",
161
+ year: "numeric",
162
+ },
163
+ "DD MMM YYYY": {
164
+ day: "numeric",
165
+ month: "short",
166
+ year: "numeric",
167
+ },
168
+ };
169
+
170
+ const formatOption = options[dateFormat];
171
+ if (formatOption) {
172
+ dateResult = date.toLocaleDateString("en-US", formatOption);
173
+ } else {
174
+ // Fallback to default
175
+ dateResult = date?.toDateString();
176
+ }
177
+ }
124
178
  }
125
179
 
126
- // Fallback to default
127
- return date?.toDateString();
128
- }
129
-
130
- // DateTime formatting helper function
131
- function formatDateTime(date, dateFormat, showTime) {
132
- if (!date) return "";
133
-
180
+ // If not showing time, return just the formatted date
134
181
  if (!showTime) {
135
- return formatDate(date, dateFormat);
182
+ return dateResult;
136
183
  }
137
184
 
138
- const formattedDate = formatDate(date, dateFormat);
139
- const timeString = `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
185
+ // Format the time part when showTime is true (using local time)
186
+ let hours = date.getHours();
187
+ let minutes = date.getMinutes();
188
+
189
+ // Format based on show24HTime
190
+ let timeString;
191
+ if (show24HTime) {
192
+ timeString = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
193
+ } else {
194
+ const ampm = hours >= 12 ? "PM" : "AM";
195
+ const display12h = hours % 12 || 12;
196
+ timeString = `${display12h.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")} ${ampm}`;
197
+ }
140
198
 
141
- return `${formattedDate} ${timeString}`;
199
+ return `${dateResult} ${timeString}`;
142
200
  }
143
201
 
144
202
  $: formattedValue =
145
- cellOptions.template && value
146
- ? processStringSync(cellOptions.template, { value })
147
- : value
148
- ? formatDate(innerDate, currentDateFormat)
149
- : undefined;
203
+ cellOptions.template && value && value != "" && value != null
204
+ ? processStringSync(cellOptions.template, {
205
+ value: innerDate,
206
+ })
207
+ : (value && value != "" && value != null) || selection
208
+ ? formatDateTime(innerDate, currentDateFormat, currentShowTime)
209
+ : "";
150
210
 
151
211
  $: placeholder = cellOptions?.placeholder || "";
152
212
  $: inEdit = $cellState == "Editing";
153
213
  $: inline = cellOptions.role == "inlineInpur";
154
- $: isDirty = inEdit && originalValue != value;
214
+ $: isDirty = inEdit && true;
155
215
 
156
216
  onMount(() => {
157
217
  if (autofocus)
@@ -161,20 +221,72 @@
161
221
  }, 30);
162
222
  });
163
223
 
164
- // Handle time picker changes
224
+ // Handle Start button - set time to beginning of day (00:00 or 12:00 AM)
225
+ const handleStartTime = () => {
226
+ const startTime = show24HTime ? "00:00" : "12:00 AM";
227
+ timeValue = startTime;
228
+
229
+ innerDate.setHours(0, 0, 0, 0);
230
+ innerDate = innerDate;
231
+ selection = true;
232
+ anchor?.focus();
233
+ };
234
+
235
+ // Handle End button - set time to end of day (23:59 or 11:59 PM)
236
+ const handleEndTime = () => {
237
+ const endTime = show24HTime ? "23:59" : "11:59 PM";
238
+ timeValue = endTime;
239
+
240
+ innerDate.setHours(23, 59, 0, 0);
241
+ innerDate = innerDate;
242
+ selection = true;
243
+ anchor?.focus();
244
+ };
245
+
246
+ // Handle Now button - set both date and time to current date/time
247
+ const handleNowTime = () => {
248
+ innerDate = new Date();
249
+ selection = true;
250
+ anchor?.focus();
251
+ };
252
+
253
+ // Handle Clear button - clear the value
254
+ const handleClearValue = () => {
255
+ cellState.submit();
256
+ };
257
+
258
+ // Handle time picker changes - only affects the time, not timezone
165
259
  const handleTimeChange = (e) => {
166
- if (!value || !currentShowTime) return;
260
+ if (!currentShowTime) return;
261
+ selection = true;
167
262
 
168
263
  const newTime = e.target.value;
169
- const currentDate = new Date(value);
170
- const [hours, minutes] = newTime.split(":").map(Number);
264
+ // Convert 12-hour format to 24-hour if needed
265
+ const time24h = show24HTime ? newTime : parse12HourTime(newTime);
266
+ if (!time24h) return;
267
+
268
+ const [hours, minutes] = time24h.split(":").map(Number);
269
+
270
+ innerDate.setHours(hours, minutes, 0, 0);
271
+ };
171
272
 
172
- // Update the date with the new time
173
- currentDate.setHours(hours, minutes, 0, 0);
174
- value = currentDate.toISOString();
273
+ const handleDateChange = (e) => {
274
+ const newDate = e.detail;
275
+ selection = true;
276
+
277
+ if (currentShowTime) {
278
+ // Preserve the time from the current innerDate when appending to the selected date
279
+ newDate.setHours(
280
+ innerDate.getHours(),
281
+ innerDate.getMinutes(),
282
+ innerDate.getSeconds(),
283
+ innerDate.getMilliseconds(),
284
+ );
285
+ }
175
286
 
176
- // Keep the popover open for time changes
177
- dispatch("change", value);
287
+ innerDate = newDate;
288
+ anchor?.focus();
289
+ open = false;
178
290
  };
179
291
  </script>
180
292
 
@@ -197,45 +309,45 @@
197
309
  style:color={cellOptions.color}
198
310
  style:background={cellOptions.background}
199
311
  on:focus={cellState.focus}
200
- on:keypress={cellState.handleKeyboard}
312
+ on:keydown={cellState.handleKeyboard}
201
313
  on:focusout={cellState.focusout}
314
+ on:mousedown={cellState.toggle}
202
315
  >
203
- {#if cellOptions.icon}
204
- <i class={cellOptions.icon + " field-icon"}></i>
205
- {/if}
206
-
207
- {#if inEdit}
208
- <div
209
- class="editor"
210
- class:placeholder={!formattedValue}
211
- on:click={() => (open = !open)}
212
- >
213
- <span>{formattedValue || placeholder}</span>
214
- <i
215
- class="ri-calendar-line"
216
- style="font-size: 16px; justify-self: flex-end"
217
- ></i>
218
- </div>
219
- {:else}
220
- <div
221
- class="value"
222
- class:placeholder={!formattedValue}
223
- style:justify-content={cellOptions.align}
224
- >
225
- <span>
226
- {formattedValue || placeholder}
227
- </span>
228
- </div>
229
- {/if}
316
+ {#key $cellState}
317
+ {#if cellOptions.icon}
318
+ <i class={cellOptions.icon + " field-icon"}></i>
319
+ {/if}
320
+
321
+ {#if inEdit}
322
+ <div class="editor" class:placeholder={!formattedValue}>
323
+ <span>{formattedValue || placeholder}</span>
324
+ <i
325
+ class="ri-calendar-line"
326
+ style="font-size: 16px; justify-self: flex-end"
327
+ ></i>
328
+ </div>
329
+ {:else}
330
+ <div
331
+ class="value"
332
+ class:placeholder={!formattedValue}
333
+ style:justify-content={cellOptions.align}
334
+ >
335
+ <span>
336
+ {value ? formattedValue : placeholder}
337
+ </span>
338
+ </div>
339
+ {/if}
340
+ {/key}
230
341
  </div>
231
342
 
232
343
  {#if inEdit}
233
344
  <SuperPopover
234
345
  {anchor}
235
- dismissible={false}
236
346
  {open}
347
+ ignoreAnchor
237
348
  align="right"
238
349
  maxHeight={400}
350
+ on:close={cellState.focusout}
239
351
  >
240
352
  <div
241
353
  bind:this={picker}
@@ -244,26 +356,34 @@
244
356
  style:--date-picker-foreground="var(--spectrum-global-color-gray-800)"
245
357
  style:--date-picker-selected-background="var(--accent-color)"
246
358
  >
247
- <DatePicker
248
- bind:value={innerDate}
249
- on:select={(e) => {
250
- value = e.detail;
251
- anchor?.focus();
252
- open = false;
253
- }}
254
- />
359
+ <DatePicker value={innerDate} on:select={handleDateChange} />
255
360
 
256
361
  {#if currentShowTime}
257
362
  <div class="time-section">
258
363
  <!-- svelte-ignore a11y-label-has-associated-control -->
259
364
  <input
260
365
  bind:this={timePicker}
261
- type="time"
366
+ type="text"
367
+ placeholder={show24HTime ? "HH:MM" : "HH:MM AM/PM"}
262
368
  bind:value={timeValue}
263
369
  on:change={handleTimeChange}
370
+ on:focusout={cellState.focusout}
264
371
  class="time-input"
265
- step="900"
266
372
  />
373
+ <div class="time-buttons">
374
+ <button class="time-button start-button" on:click={handleStartTime}
375
+ >Start</button
376
+ >
377
+ <button class="time-button end-button" on:click={handleEndTime}
378
+ >End</button
379
+ >
380
+ <button class="time-button now-button" on:click={handleNowTime}
381
+ >Now</button
382
+ >
383
+ <button class="time-button clear-button" on:click={handleClearValue}
384
+ >Select</button
385
+ >
386
+ </div>
267
387
  </div>
268
388
  {/if}
269
389
  </div>
@@ -283,7 +403,35 @@
283
403
  .time-section {
284
404
  display: flex;
285
405
  flex-direction: column;
286
- gap: 4px;
406
+ gap: 8px;
407
+ }
408
+
409
+ .time-buttons {
410
+ display: flex;
411
+ gap: 6px;
412
+ }
413
+
414
+ .time-button {
415
+ flex: 1;
416
+ padding: 6px 12px;
417
+ border: 1px solid var(--spectrum-global-color-gray-300);
418
+ border-radius: 4px;
419
+ background: var(--spectrum-global-color-gray-50);
420
+ color: var(--spectrum-global-color-gray-800);
421
+ font-size: 13px;
422
+ font-weight: 500;
423
+ cursor: pointer;
424
+ transition: all 0.15s ease;
425
+ }
426
+
427
+ .time-button:hover {
428
+ background: var(--spectrum-global-color-gray-100);
429
+ border-color: var(--spectrum-global-color-gray-400);
430
+ }
431
+
432
+ .time-button:active {
433
+ background: var(--spectrum-global-color-gray-200);
434
+ border-color: var(--spectrum-global-color-gray-500);
287
435
  }
288
436
 
289
437
  .time-label {
@@ -145,7 +145,13 @@
145
145
 
146
146
  if (singleSelect) {
147
147
  editorState.close();
148
- anchor.focus();
148
+ }
149
+
150
+ if (cellOptions.debounced) {
151
+ dispatch(
152
+ "change",
153
+ returnSingle && localValue ? localValue[0] : localValue,
154
+ );
149
155
  }
150
156
  };
151
157
 
@@ -193,7 +199,7 @@
193
199
  class:open-popup={$editorState == "Open"}
194
200
  style:color={cellOptions.color}
195
201
  style:background={cellOptions.background}
196
- on:focusin={cellState.focus}
202
+ on:focus={cellState.focus}
197
203
  on:keydown|self={handleKeyboard}
198
204
  on:focusout={cellState.focusout}
199
205
  on:mousedown={cellState.toggle}
@@ -203,14 +209,12 @@
203
209
  {/if}
204
210
 
205
211
  <div class="value" class:placeholder={localValue?.length < 1}>
206
- {#if localValue?.length < 1}
207
- <span> {placeholder} </span>
208
- {:else if simpleView}
212
+ {#if simpleView}
209
213
  <span>
210
214
  {#if cellOptions.role == "formInput" && localValue.length > 1}
211
215
  ({localValue.length})
212
216
  {/if}
213
- {localValue.map((v) => v.primaryDisplay).join(", ")}
217
+ {localValue.map((v) => v.primaryDisplay).join(", ") || placeholder}
214
218
  </span>
215
219
  {:else}
216
220
  <div
@@ -221,7 +225,7 @@
221
225
  class:withCount={localValue.length > 5}
222
226
  class:inEdit
223
227
  >
224
- {#each localValue as val, idx}
228
+ {#each localValue as val, idx (val)}
225
229
  {#if idx < 5}
226
230
  <div
227
231
  class="item"
@@ -238,6 +242,11 @@
238
242
  </div>
239
243
  {/if}
240
244
  {/each}
245
+
246
+ {#if localValue.length == 0}
247
+ <span>{placeholder}</span>
248
+ {/if}
249
+
241
250
  {#if localValue.length > 5}
242
251
  <span class="count">
243
252
  (+ {localValue.length - 5})
@@ -265,34 +265,38 @@
265
265
  <div class="list" bind:this={listElement} on:scroll={handleScroll}>
266
266
  <div class="options">
267
267
  {#key localValue}
268
- {#if $fetch?.rows?.length || ($fetch?.loading && !$fetch?.loaded)}
269
- {#each $fetch?.rows || [] as row, idx (idx)}
270
- <div
271
- class="option"
272
- class:selected={rowSelected(row)}
273
- class:highlighted={focusIdx == idx}
274
- on:mouseenter={() => (focusIdx = idx)}
275
- on:mouseleave={() => (focusIdx = -1)}
276
- on:mousedown|preventDefault|stopPropagation={selectRow(row)}
277
- >
278
- {row[primaryDisplay]}
279
- <i class="ri-check-line"></i>
280
- </div>
281
- {/each}
282
- {#if $fetch?.loading && $fetch.loaded}
268
+ {#key $fetch?.rows}
269
+ {#if $fetch?.rows?.length || ($fetch?.loading && !$fetch?.loaded)}
270
+ {#each $fetch?.rows || [] as row, idx (idx)}
271
+ <div
272
+ class="option"
273
+ class:selected={rowSelected(row)}
274
+ class:highlighted={focusIdx == idx}
275
+ on:mouseenter={() => (focusIdx = idx)}
276
+ on:mouseleave={() => (focusIdx = -1)}
277
+ on:mousedown|preventDefault|stopPropagation={selectRow(
278
+ row,
279
+ )}
280
+ >
281
+ {row[primaryDisplay]}
282
+ <i class="ri-check-line"></i>
283
+ </div>
284
+ {/each}
285
+ {#if $fetch?.loading && $fetch.loaded}
286
+ <div class="option loading">
287
+ <i class="ri-loader-2-line rotating"></i>
288
+ Loading more...
289
+ </div>
290
+ {/if}
291
+ {:else if $fetch?.loading}
283
292
  <div class="option loading">
284
293
  <i class="ri-loader-2-line rotating"></i>
285
- Loading more...
294
+ Loading...
286
295
  </div>
296
+ {:else}
297
+ <div class="option">No Results Found</div>
287
298
  {/if}
288
- {:else if $fetch?.loading}
289
- <div class="option loading">
290
- <i class="ri-loader-2-line rotating"></i>
291
- Loading...
292
- </div>
293
- {:else}
294
- <div class="option">No Results Found</div>
295
- {/if}
299
+ {/key}
296
300
  {/key}
297
301
  </div>
298
302
  </div>