@poirazis/supercomponents-shared 1.2.15 → 1.2.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 (37) hide show
  1. package/dist/index.js +17704 -22252
  2. package/dist/index.umd.cjs +19 -18
  3. package/package.json +11 -11
  4. package/src/lib/SuperButton/SuperButton.svelte +65 -35
  5. package/src/lib/SuperField/SuperField.svelte +8 -11
  6. package/src/lib/SuperForm/InnerForm.svelte +14 -8
  7. package/src/lib/SuperForm/SuperForm.svelte +5 -5
  8. package/src/lib/SuperPopover/SuperPopover.svelte +1 -1
  9. package/src/lib/SuperTable/SuperTable.css +13 -6
  10. package/src/lib/SuperTable/SuperTable.svelte +28 -19
  11. package/src/lib/SuperTable/constants.js +1 -1
  12. package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +33 -17
  13. package/src/lib/SuperTable/controls/SelectionColumn.svelte +2 -2
  14. package/src/lib/SuperTableCells/CellBoolean.svelte +52 -45
  15. package/src/lib/SuperTableCells/CellCommon.css +97 -35
  16. package/src/lib/SuperTableCells/CellDatetime.svelte +267 -120
  17. package/src/lib/SuperTableCells/CellLink.svelte +22 -13
  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 +356 -246
  22. package/src/lib/SuperTableCells/CellOptionsAdvanced.svelte +199 -180
  23. package/src/lib/SuperTableCells/CellSQLLink.svelte +32 -32
  24. package/src/lib/SuperTableCells/CellSQLLinkPicker.svelte +2 -7
  25. package/src/lib/SuperTableCells/CellSkeleton.svelte +1 -1
  26. package/src/lib/SuperTableCells/CellString.svelte +62 -80
  27. package/src/lib/SuperTableCells/CellStringMask.svelte +41 -40
  28. package/src/lib/SuperTableCells/CellStringSimple.svelte +1 -4
  29. package/src/lib/SuperTableColumn/SuperTableColumn.svelte +3 -1
  30. package/src/lib/SuperTableColumn/parts/SuperColumnBody.svelte +3 -0
  31. package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +44 -42
  32. package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +2 -4
  33. package/src/lib/SuperTabs/SuperTabs.svelte +33 -17
  34. package/src/lib/UI/elements/Checkbox.svelte +68 -10
  35. package/src/lib/UI/elements/Switch.svelte +162 -0
  36. package/src/lib/UI/elements/Tooltip.svelte +15 -43
  37. package/src/lib/SuperTableCells/JSDOC_GUIDE.md +0 -869
@@ -2,7 +2,6 @@
2
2
  import { getContext, createEventDispatcher, onMount, tick } from "svelte";
3
3
  import SuperPopover from "../SuperPopover/SuperPopover.svelte";
4
4
  import "./CellCommon.css";
5
-
6
5
  import fsm from "svelte-fsm";
7
6
 
8
7
  const dispatch = createEventDispatcher();
@@ -18,159 +17,62 @@
18
17
  let editor;
19
18
  let optionsList;
20
19
  let options = memo([]);
21
- let labels = {};
20
+ let labels = memo({});
22
21
  let optionColors = {};
23
22
  let filteredOptions = [];
24
23
  let focusedOptionIdx = -1;
25
24
  let timer;
26
25
  let localValue = [];
27
26
 
28
- let searchTerm = "";
29
- let inputValue = "";
30
- let isInitialLoad = false;
27
+ let searchTerm = null;
28
+ let inputValue = null;
31
29
  let initLimit = 15;
30
+ let fetch;
31
+ let loading = false;
32
+ let optionsSource = "schema";
33
+
34
+ // Handle Options from Data Source
35
+ const dataSourceStore = memo(cellOptions?.datasource);
36
+ $: dataSourceStore.set(cellOptions.datasource);
37
+
38
+ $: ({
39
+ controlType,
40
+ optionsSource,
41
+ limit,
42
+ sortColumn,
43
+ sortOrder,
44
+ valueColumn,
45
+ labelColumn,
46
+ iconColumn,
47
+ colorColumn,
48
+ customOptions,
49
+ optionsViewMode,
50
+ role,
51
+ readonly,
52
+ disabled,
53
+ error,
54
+ color,
55
+ background,
56
+ filter,
57
+ pickerWidth,
58
+ } = cellOptions);
32
59
 
33
60
  const createFetch = (datasource) => {
34
- if (optionsSource != "data") return memo({});
61
+ defaultQuery = QueryUtils.buildQuery(cellOptions.filter || []);
62
+ initLimit = limit || 15;
63
+
35
64
  return fetchData({
36
65
  API,
37
66
  datasource,
38
67
  options: {
68
+ query: defaultQuery,
39
69
  sortColumn: cellOptions.sortColumn,
40
70
  sortOrder: cellOptions.sortOrder,
41
- limit: initLimit,
71
+ limit,
42
72
  },
43
73
  });
44
74
  };
45
75
 
46
- export const cellState = fsm("Loading", {
47
- "*": {
48
- goTo(state) {
49
- return state;
50
- },
51
- refresh() {
52
- $options = [];
53
- return "Loading";
54
- },
55
- loadSchemaOptions() {
56
- optionColors = fieldSchema?.optionColors || {};
57
- $options = fieldSchema?.constraints?.inclusion || [];
58
- labels = {};
59
- filteredOptions = $options;
60
- },
61
- loadDataOptions(rows) {
62
- $options = [];
63
- labels = {};
64
- if (rows && rows.length) {
65
- rows.forEach((row) => {
66
- $options.push(row[valueColumn]?.toString());
67
- labels[row[valueColumn]] = row[labelColumn || valueColumn];
68
- if (colorColumn) optionColors[row[valueColumn]] = row[colorColumn];
69
- });
70
- }
71
- $options = $options;
72
- filteredOptions = $options;
73
- if (isInitialLoad) isInitialLoad = false;
74
- },
75
- loadCustomOptions() {
76
- if (customOptions?.length) {
77
- customOptions.forEach((row) => {
78
- $options.push(row.value || row);
79
- labels[row.value] = row.label || row;
80
- });
81
- }
82
- $options = $options;
83
- },
84
- },
85
- Loading: {
86
- _enter() {
87
- if (cellOptions.optionsSource != "data") return "View";
88
- },
89
- _exit() {
90
- if (cellOptions.optionsSource == "custom") this.loadCustomOptions();
91
- else if (optionsSource == "data") this.loadDataOptions($fetch?.rows);
92
- else this.loadSchemaOptions();
93
-
94
- filteredOptions = $options;
95
- },
96
- syncFetch(fetch) {
97
- if (fetch?.loaded) {
98
- return cellOptions.initialState || "View";
99
- }
100
- },
101
- focus(e) {
102
- if (!cellOptions.readonly && !cellOptions.disabled) {
103
- return "Editing";
104
- }
105
- },
106
- },
107
- View: {
108
- _enter() {
109
- searchTerm = null;
110
- editorState.filterOptions();
111
- },
112
- focus(e) {
113
- if (!readonly && !disabled) {
114
- return "Editing";
115
- }
116
- },
117
- },
118
- Editing: {
119
- _enter() {
120
- editorState.open();
121
- originalValue = JSON.stringify(
122
- Array.isArray(value) ? value : value ? [value] : [],
123
- );
124
- inputValue = multi ? "" : labels[localValue[0]] || localValue[0] || "";
125
-
126
- dispatch("enteredit");
127
- },
128
- _exit() {
129
- editorState.close();
130
- dispatch("exitedit");
131
- },
132
- toggle(e) {
133
- editorState.toggle();
134
- },
135
- focusout(e) {
136
- dispatch("focusout");
137
-
138
- // For debounced inputs, dispatch the current value immediately on focusout
139
- if (cellOptions.debounce && isDirty) {
140
- clearTimeout(timer);
141
- dispatch("change", multi ? localValue : localValue[0]);
142
- } else {
143
- this.submit();
144
- }
145
-
146
- return "View";
147
- },
148
- popupfocusout(e) {
149
- if (anchor != e?.relatedTarget) {
150
- this.submit();
151
- return "View";
152
- }
153
- },
154
- submit() {
155
- if (isDirty && !cellOptions.debounce) {
156
- if (multi) dispatch("change", localValue);
157
- else dispatch("change", localValue[0]);
158
- }
159
- },
160
- clear() {
161
- localValue = [];
162
- anchor?.focus();
163
- if (cellOptions.debounce) dispatch("change", null);
164
- },
165
- cancel() {
166
- localValue = JSON.parse(originalValue);
167
- searchTerm = null;
168
- anchor?.blur();
169
- return "View";
170
- },
171
- },
172
- });
173
-
174
76
  const editorState = fsm("Closed", {
175
77
  "*": {
176
78
  toggleOption(idx) {
@@ -189,13 +91,21 @@
189
91
  if (localValue[0] == option) localValue.length = 0;
190
92
  else localValue[0] = option;
191
93
 
192
- inputValue = labels[localValue[0]] || localValue[0] || "";
94
+ localValue = [...localValue];
95
+
96
+ inputValue = $labels[localValue[0]] || localValue[0] || "";
193
97
  }
194
98
 
195
99
  if (cellOptions.debounce) {
196
100
  clearTimeout(timer);
197
101
  timer = setTimeout(() => {
198
102
  dispatch("change", multi ? localValue : localValue[0]);
103
+ dispatch(
104
+ "labelChange",
105
+ multi
106
+ ? localValue.map((val) => $labels[val] || val)
107
+ : $labels[localValue[0]] || localValue[0],
108
+ );
199
109
  }, cellOptions.debounce ?? 0);
200
110
  }
201
111
 
@@ -211,44 +121,77 @@
211
121
  }
212
122
  },
213
123
  filterOptions(term) {
214
- if (cellOptions.optionsSource == "data") {
124
+ if (optionsSource == "data") {
215
125
  // For datasource, update the fetch with filter
216
- let appliedFilter = [];
217
- if (term) {
218
- appliedFilter = [
219
- ...(cellOptions.filter || []),
220
- {
221
- field: labelColumn || valueColumn,
222
- type: "string",
223
- operator: "fuzzy",
224
- value: term,
225
- valueType: "Value",
226
- },
227
- ];
126
+ let appliedFilter = {};
127
+
128
+ // Start with base filter or create new one
129
+ if (
130
+ filter &&
131
+ typeof filter === "object" &&
132
+ Object.keys(filter).length > 0
133
+ ) {
134
+ appliedFilter = JSON.parse(JSON.stringify(filter)); // Deep clone
228
135
  } else {
229
- appliedFilter = cellOptions.filter || [];
136
+ // Create a base filter object
137
+ appliedFilter = {
138
+ logicalOperator: "all",
139
+ onEmptyFilter: "all",
140
+ groups: [],
141
+ };
230
142
  }
143
+
144
+ // Add search term as a new filter group if provided
145
+ if (term != null && term.trim() !== "") {
146
+ const searchFilterGroup = {
147
+ logicalOperator: "any",
148
+ filters: [
149
+ {
150
+ valueType: "Value",
151
+ field: labelColumn || valueColumn,
152
+ type: "string",
153
+ constraints: {
154
+ type: "string",
155
+ length: {},
156
+ presence: false,
157
+ },
158
+ operator: "fuzzy",
159
+ noValue: false,
160
+ value: term,
161
+ },
162
+ ],
163
+ };
164
+
165
+ // Add the search filter group
166
+ if (!appliedFilter.groups) {
167
+ appliedFilter.groups = [];
168
+ }
169
+ appliedFilter.groups.push(searchFilterGroup);
170
+ }
171
+
172
+ const query = QueryUtils.buildQuery(appliedFilter);
231
173
  fetch?.update({
232
- query: QueryUtils.buildQuery(appliedFilter),
174
+ query,
233
175
  });
234
- // Keep filteredOptions in sync
235
- filteredOptions = $options;
236
176
  } else {
237
177
  // Client-side filtering for non-datasource
238
178
  if (term) {
239
179
  filteredOptions = $options.filter((x) =>
240
- x?.toLocaleLowerCase().startsWith(term.toLocaleLowerCase()),
180
+ x?.toLocaleLowerCase().includes(term.toLocaleLowerCase()),
241
181
  );
242
182
  } else {
243
183
  filteredOptions = $options;
244
184
  }
245
185
  }
246
186
  },
187
+ clearFilter() {
188
+ searchTerm = null;
189
+ this.filterOptions();
190
+ },
247
191
  },
248
192
  Open: {
249
193
  _enter() {
250
194
  searchTerm = "";
251
- this.filterOptions();
252
195
  focusedOptionIdx = -1;
253
196
  },
254
197
  toggle() {
@@ -347,10 +290,7 @@
347
290
  },
348
291
  },
349
292
  Closed: {
350
- _enter() {
351
- searchTerm = null;
352
- focusedOptionIdx = -1;
353
- },
293
+ _enter() {},
354
294
  toggle() {
355
295
  return "Open";
356
296
  },
@@ -402,6 +342,190 @@
402
342
  },
403
343
  });
404
344
 
345
+ export const cellState = fsm("View", {
346
+ "*": {
347
+ goTo(state) {
348
+ return state;
349
+ },
350
+ refresh() {
351
+ $options = [];
352
+ optionColors = {};
353
+ $labels = {};
354
+ filteredOptions = [];
355
+ if (optionsSource != "data") {
356
+ this.loadOptions(optionsSource);
357
+ }
358
+ return optionsSource == "data" ? "Loading" : "View";
359
+ },
360
+ reload() {
361
+ this.loadOptions(optionsSource);
362
+ },
363
+ loadSchemaOptions() {
364
+ try {
365
+ optionColors = fieldSchema?.optionColors || {};
366
+ $options = fieldSchema?.constraints?.inclusion || [];
367
+ $labels = {};
368
+ filteredOptions = $options;
369
+ } catch (e) {}
370
+ },
371
+ loadDataOptions(rows) {
372
+ $options = [];
373
+ $labels = {};
374
+ let primaryDisplay = labelColumn || labelColumn;
375
+ if (rows && rows.length) {
376
+ rows.forEach((row) => {
377
+ $options.push(row[valueColumn]);
378
+ $labels[row[valueColumn]] = row[primaryDisplay];
379
+ if (colorColumn) optionColors[row[valueColumn]] = row[colorColumn];
380
+ });
381
+ }
382
+
383
+ $options = $options;
384
+ filteredOptions = $options;
385
+ },
386
+ loadCustomOptions() {
387
+ $options = [];
388
+ $labels = {};
389
+ if (customOptions?.length) {
390
+ customOptions.forEach((row) => {
391
+ $options.push(row.value || row);
392
+ $labels[row.value] = row.label || row;
393
+ });
394
+ }
395
+ $options = $options;
396
+ filteredOptions = $options;
397
+ },
398
+ loadOptions(src) {
399
+ if (src == "data") {
400
+ this.loadDataOptions($fetch?.rows);
401
+ } else if (src == "custom") {
402
+ this.loadCustomOptions();
403
+ } else {
404
+ this.loadSchemaOptions();
405
+ }
406
+ },
407
+ },
408
+ Loading: {
409
+ _enter() {
410
+ fetch = createFetch($dataSourceStore);
411
+ loading = true;
412
+ },
413
+ _exit() {
414
+ loading = false;
415
+ },
416
+ refresh() {},
417
+ reload() {},
418
+ syncFetch(fetch) {
419
+ if (fetch?.loaded) {
420
+ return cellOptions.initialState || "View";
421
+ }
422
+ },
423
+ focus(e) {
424
+ if (!cellOptions.readonly && !cellOptions.disabled) {
425
+ return "Editing";
426
+ }
427
+ },
428
+ },
429
+ View: {
430
+ _enter() {
431
+ searchTerm = null;
432
+ editorState.filterOptions();
433
+ },
434
+ toggle(e) {
435
+ if (cellOptions.disabled || cellOptions.readonly) return;
436
+ return "Editing";
437
+ },
438
+ focus(e) {
439
+ if (!readonly && !disabled) {
440
+ return "Editing";
441
+ }
442
+ },
443
+ },
444
+ Editing: {
445
+ _enter() {
446
+ editorState.open();
447
+
448
+ setTimeout(() => {
449
+ editor?.focus();
450
+ }, 30);
451
+ originalValue = JSON.stringify(
452
+ Array.isArray(value) ? value : value ? [value] : [],
453
+ );
454
+ inputValue = multi ? "" : $labels[localValue[0]] || localValue[0] || "";
455
+
456
+ dispatch("enteredit");
457
+ },
458
+ _exit() {
459
+ searchTerm = null;
460
+ inputValue = null;
461
+ editorState.close();
462
+ dispatch("exitedit");
463
+ },
464
+ toggle(e) {
465
+ if (!inputSelect && searchTerm) {
466
+ return;
467
+ }
468
+ e.preventDefault();
469
+ editorState.toggle();
470
+ },
471
+ focusout(e) {
472
+ if (anchor.contains(e.relatedTarget)) {
473
+ return;
474
+ }
475
+
476
+ if (cellOptions.debounce && isDirty) {
477
+ clearTimeout(timer);
478
+ dispatch("change", multi ? localValue : localValue[0]);
479
+ dispatch(
480
+ "labelChange",
481
+ multi
482
+ ? localValue.map((val) => $labels[val] || val)
483
+ : $labels[localValue[0]] || localValue[0],
484
+ );
485
+ } else {
486
+ this.submit();
487
+ }
488
+ dispatch("focusout");
489
+ return "View";
490
+ },
491
+ popupfocusout(e) {
492
+ if (anchor != e?.relatedTarget) {
493
+ this.submit();
494
+ return "View";
495
+ }
496
+ },
497
+ submit() {
498
+ if (isDirty && !cellOptions.debounce) {
499
+ if (multi) dispatch("change", localValue);
500
+ else dispatch("change", localValue[0]);
501
+
502
+ if (multi) {
503
+ dispatch(
504
+ "labelChange",
505
+ localValue.map((val) => $labels[val] || val),
506
+ );
507
+ } else {
508
+ dispatch("labelChange", $labels[localValue[0]] || localValue[0]);
509
+ }
510
+ }
511
+ },
512
+ clear() {
513
+ localValue = [];
514
+ anchor?.focus();
515
+ if (cellOptions.debounce) {
516
+ dispatch("change", null);
517
+ dispatch("labelChange", null);
518
+ }
519
+ },
520
+ cancel() {
521
+ localValue = JSON.parse(originalValue);
522
+ searchTerm = null;
523
+ anchor?.blur();
524
+ return "View";
525
+ },
526
+ },
527
+ });
528
+
405
529
  const colors = derivedMemo(options, ($options) => {
406
530
  let obj = {};
407
531
  $options.forEach(
@@ -448,54 +572,23 @@
448
572
  Array.isArray(value) ? value : value ? [value] : [],
449
573
  );
450
574
 
451
- $: ({
452
- controlType,
453
- optionsSource,
454
- valueColumn,
455
- labelColumn,
456
- iconColumn,
457
- colorColumn,
458
- customOptions,
459
- optionsViewMode,
460
- role,
461
- readonly,
462
- disabled,
463
- error,
464
- color,
465
- background,
466
- } = cellOptions);
467
-
468
- // Handle Options from Data Source
469
- const dataSourceStore = memo(cellOptions?.datasource ?? {});
470
- $: dataSourceStore.set(cellOptions.datasource);
471
- $: fetch = createFetch($dataSourceStore);
472
- $: if (optionsSource == "data") {
473
- initLimit = 15;
474
- isInitialLoad = true;
475
- }
476
- $: query = QueryUtils.buildQuery(cellOptions.filter);
477
575
  $: inputSelect = controlType == "inputSelect";
478
576
 
479
- $: if (optionsSource == "data")
480
- fetch?.update?.({
481
- query,
482
- sortColumn: cellOptions.sortColumn,
483
- sortOrder: cellOptions.sortOrder,
484
- limit: initLimit,
485
- });
577
+ $: defaultQuery = QueryUtils.buildQuery(filter || []);
578
+ $: fetch?.update?.({ query: defaultQuery });
486
579
 
487
580
  $: cellState.syncFetch($fetch);
488
581
  $: cellState.loadDataOptions($fetch?.rows);
489
582
 
490
583
  // React to property changes
491
- $: cellState.refresh(
584
+ $: cellState.refresh($dataSourceStore, optionsSource);
585
+
586
+ $: cellState.reload(
492
587
  fieldSchema,
493
- optionsSource,
494
588
  labelColumn,
495
589
  valueColumn,
496
590
  iconColumn,
497
591
  colorColumn,
498
- $dataSourceStore,
499
592
  customOptions,
500
593
  );
501
594
 
@@ -510,18 +603,15 @@
510
603
  $: inEdit = $cellState == "Editing";
511
604
  $: pills = optionsViewMode == "pills";
512
605
  $: bullets = optionsViewMode == "bullets";
606
+ $: plaintext = optionsViewMode == "text";
513
607
 
514
608
  $: multi =
515
609
  fieldSchema && fieldSchema.type ? fieldSchema.type == "array" : multi;
516
610
 
517
- $: placeholder = disabled || readonly ? "" : cellOptions.placeholder || "";
611
+ $: placeholder = cellOptions.placeholder || "";
518
612
  $: icon = searchTerm && isEmpty ? "ph ph-magnifying-glass" : cellOptions.icon;
519
613
  $: open = $editorState == "Open";
520
614
 
521
- const focus = (node) => {
522
- node?.focus();
523
- };
524
-
525
615
  onMount(() => {
526
616
  if (autofocus)
527
617
  setTimeout(() => {
@@ -543,15 +633,15 @@
543
633
  class:disabled
544
634
  class:readonly
545
635
  class:error
546
- style:color
547
- style:background
548
636
  class:inline={role == "inlineInput"}
549
637
  class:tableCell={role == "tableCell"}
550
638
  class:formInput={role == "formInput"}
551
639
  class:has-popup={controlType == "select"}
552
640
  class:open-popup={open}
641
+ style:color
642
+ style:background
553
643
  on:focusin={cellState.focus}
554
- on:focusout={cellState.focusout}
644
+ on:focusout={controlType != "inputSelect" ? cellState.focusout : undefined}
555
645
  on:keydown={editorState.handleKeyboard}
556
646
  on:mousedown={cellState.toggle}
557
647
  >
@@ -581,7 +671,7 @@
581
671
  {#if pills}
582
672
  <div class="loope"></div>
583
673
  {/if}
584
- <span> {labels[val] || val} </span>
674
+ <span> {$labels[val] || val} </span>
585
675
  </div>
586
676
  {/each}
587
677
  </div>
@@ -597,46 +687,55 @@
597
687
  if (!multi) localValue[0] = e.target.value?.trim();
598
688
  editorState.filterOptions(e.target.value);
599
689
  }}
600
- use:focus
690
+ on:focusout={cellState.focusout}
601
691
  {placeholder}
602
692
  />
603
- <div class="control-icon" on:click={editorState.toggle}>
693
+ <div
694
+ class="control-icon"
695
+ style:border-left="1px solid var(--spectrum-global-color-blue-400)"
696
+ style:padding-left="0.75rem"
697
+ >
604
698
  <i class="ph ph-caret-down"></i>
605
699
  </div>
606
700
  {:else}
607
701
  <div class="value" class:placeholder={isEmpty && !searchTerm}>
608
- {#if isEmpty && !open}
609
- <span>{searchTerm || placeholder}</span>
610
- {:else if isEmpty && open}
611
- <span>{searchTerm || "Type to search..."}</span>
612
- {:else if optionsViewMode == "text"}
613
- <span>
614
- {multi || localValue.length > 1
615
- ? localValue.join(", ")
616
- : labels[localValue[0]] || localValue[0]}
617
- </span>
618
- {:else}
619
- <div
620
- class="items"
621
- class:pills
622
- class:bullets
623
- style:justify-content={cellOptions.align ?? "flex-start"}
624
- >
625
- {#each localValue as val, idx (val)}
626
- <div
627
- class="item"
628
- style:--option-color={$colors[val] ||
629
- colorsArray[idx % colorsArray.length]}
630
- >
631
- <div class="loope"></div>
632
- <span> {isObjects ? "JSON" : labels[val] || val} </span>
633
- </div>
634
- {/each}
635
- </div>
636
- {/if}
702
+ {#key isEmpty}
703
+ {#if localValue?.length < 1}
704
+ {#if open}
705
+ {searchTerm ? searchTerm : "Type to search..."}
706
+ {:else}
707
+ {loading ? "Loading..." : placeholder}
708
+ {/if}
709
+ {:else}
710
+ <div
711
+ class="items"
712
+ class:pills
713
+ class:bullets
714
+ style:justify-content={cellOptions.align ?? "flex-start"}
715
+ >
716
+ {#if plaintext}
717
+ {#each localValue as val, idx (val)}
718
+ {$labels[val] || val}
719
+ {idx < localValue.length - 1 ? ", " : ""}
720
+ {/each}
721
+ {:else}
722
+ {#each localValue as val, idx (val)}
723
+ <div
724
+ class="item"
725
+ style:--option-color={$colors[val] ||
726
+ colorsArray[idx % colorsArray.length]}
727
+ >
728
+ <div class="loope"></div>
729
+ <span> {isObjects ? "JSON" : $labels[val] || val} </span>
730
+ </div>
731
+ {/each}
732
+ {/if}
733
+ </div>
734
+ {/if}
735
+ {/key}
637
736
  </div>
638
737
  {#if !readonly && (role == "formInput" || inEdit)}
639
- <i class="ph ph-caret-down control-icon" on:mousedown></i>
738
+ <i class="ph ph-caret-down control-icon"></i>
640
739
  {/if}
641
740
  {/if}
642
741
  </div>
@@ -644,9 +743,16 @@
644
743
  <!-- svelte-ignore a11y-no-static-element-interactions -->
645
744
  <!-- svelte-ignore a11y-click-events-have-key-events -->
646
745
  {#if inEdit}
647
- <SuperPopover {anchor} useAnchorWidth maxHeight={250} {open}>
746
+ <SuperPopover
747
+ {anchor}
748
+ useAnchorWidth
749
+ minWidth={pickerWidth}
750
+ align="left"
751
+ maxHeight={250}
752
+ {open}
753
+ >
648
754
  <div class="picker" on:mousedown|stopPropagation|preventDefault>
649
- {#if searchTerm && !isEmpty}
755
+ {#if searchTerm && !inputSelect && !isEmpty}
650
756
  <div class="searchControl">
651
757
  <i
652
758
  class="search-icon ph ph-magnifying-glass"
@@ -662,12 +768,14 @@
662
768
  on:mouseleave={() => (focusedOptionIdx = -1)}
663
769
  on:scroll={optionsSource == "data" ? editorState.handleScroll : null}
664
770
  >
665
- {#if optionsSource == "data" && $fetch?.loading && !$fetch?.rows?.length}
771
+ {#if $fetch?.loading && !$fetch?.loaded}
666
772
  <div class="option loading">
667
773
  <i class="ph ph-spinner spin"></i>
668
774
  Loading...
669
775
  </div>
670
- {:else if filteredOptions?.length}
776
+ {/if}
777
+
778
+ {#if filteredOptions?.length}
671
779
  {#each filteredOptions as option, idx (idx)}
672
780
  <div
673
781
  class="option"
@@ -686,18 +794,20 @@
686
794
  : "ph-fill ph-square"}
687
795
  style:color={$colors[option]}
688
796
  ></i>
689
- {labels[option] || option}
797
+ {$labels[option] || option}
690
798
  </span>
691
799
  <i class="ph ph-check"></i>
692
800
  </div>
693
801
  {/each}
694
- {#if optionsSource == "data" && $fetch?.loading}
802
+ {#if $fetch?.loading}
695
803
  <div class="option loading">
696
804
  <i class="ph ph-spinner spin"></i>
697
805
  Loading more...
698
806
  </div>
699
807
  {/if}
700
- {:else}
808
+ {/if}
809
+
810
+ {#if filteredOptions?.length === 0 && $fetch.loaded}
701
811
  <div class="option">
702
812
  <span>
703
813
  <i class="ri-close-line"></i>
@@ -714,7 +824,7 @@
714
824
  .searchControl {
715
825
  display: flex;
716
826
  align-items: center;
717
- height: 2rem;
827
+ min-height: 2rem;
718
828
  border-bottom: 1px solid var(--spectrum-global-color-gray-300);
719
829
  }
720
830
  .options {
@@ -727,13 +837,13 @@
727
837
  }
728
838
 
729
839
  .option {
730
- min-height: 1.75rem;
840
+ min-height: 1.85rem;
731
841
  display: flex;
732
842
  gap: 0.5rem;
733
843
  align-items: center;
734
844
  justify-content: space-between;
735
845
  cursor: pointer;
736
- padding: 0 0.5rem;
846
+ padding: 0rem 0.5rem;
737
847
 
738
848
  &.selected {
739
849
  color: var(--spectrum-global-color-gray-800);