@poirazis/supercomponents-shared 1.2.11 → 1.2.13

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 (34) hide show
  1. package/dist/index.js +11081 -10997
  2. package/dist/index.umd.cjs +13 -13
  3. package/package.json +1 -1
  4. package/src/lib/SuperField/SuperField.svelte +1 -1
  5. package/src/lib/SuperForm/InnerForm.svelte +68 -19
  6. package/src/lib/SuperForm/SuperForm.svelte +13 -3
  7. package/src/lib/SuperTable/SuperTable.css +9 -6
  8. package/src/lib/SuperTable/SuperTable.svelte +207 -193
  9. package/src/lib/SuperTable/controls/ColumnsSection.svelte +11 -19
  10. package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +4 -4
  11. package/src/lib/SuperTable/controls/SelectionColumn.svelte +9 -10
  12. package/src/lib/SuperTable/overlays/AddNewRowOverlay.svelte +1 -1
  13. package/src/lib/SuperTableCells/CellAttachmentExpanded.svelte +0 -1
  14. package/src/lib/SuperTableCells/CellAttachmentSlider.svelte +0 -1
  15. package/src/lib/SuperTableCells/CellBoolean.svelte +0 -1
  16. package/src/lib/SuperTableCells/CellCommon.css +60 -88
  17. package/src/lib/SuperTableCells/CellDateRange.svelte +6 -32
  18. package/src/lib/SuperTableCells/CellDatetime.svelte +3 -4
  19. package/src/lib/SuperTableCells/CellJSON.svelte +1 -4
  20. package/src/lib/SuperTableCells/CellLink.svelte +22 -21
  21. package/src/lib/SuperTableCells/CellLinkAdvanced.svelte +3 -7
  22. package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +7 -4
  23. package/src/lib/SuperTableCells/CellNumber.svelte +18 -23
  24. package/src/lib/SuperTableCells/CellOptions.svelte +39 -37
  25. package/src/lib/SuperTableCells/CellSQLLink.svelte +85 -66
  26. package/src/lib/SuperTableCells/CellSQLLinkPicker.svelte +66 -36
  27. package/src/lib/SuperTableCells/CellString.svelte +9 -25
  28. package/src/lib/SuperTableCells/CellStringMask.svelte +119 -26
  29. package/src/lib/SuperTableCells/CellStringSimple.svelte +6 -8
  30. package/src/lib/SuperTableColumn/SuperTableColumn.svelte +10 -10
  31. package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +4 -1
  32. package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +25 -21
  33. package/src/lib/SuperTabs/SuperTabs.svelte +28 -23
  34. package/src/lib/SuperTable/controls/SuperTableWelcome.svelte +0 -58
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { createEventDispatcher, getContext } from "svelte";
2
+ import { getContext, createEventDispatcher } from "svelte";
3
3
  import fsm from "svelte-fsm";
4
4
  import SuperPopover from "../SuperPopover/SuperPopover.svelte";
5
5
  import CellLinkPickerSelect from "./CellLinkPickerSelect.svelte";
@@ -50,15 +50,17 @@
50
50
  dispatch("exitedit");
51
51
  },
52
52
  focusout(e) {
53
- if (
54
- anchor?.contains(e?.relatedTarget) ||
55
- popup?.contains(e?.relatedTarget)
56
- )
57
- return;
58
-
53
+ if (popup?.contains(e?.relatedTarget)) return;
59
54
  this.submit();
60
55
  },
61
-
56
+ popupfocusout(e) {
57
+ if (anchor != e?.relatedTarget) {
58
+ this.submit();
59
+ }
60
+ },
61
+ toggle(e) {
62
+ editorState.toggle();
63
+ },
62
64
  clear() {
63
65
  localValue = [];
64
66
  },
@@ -66,14 +68,14 @@
66
68
  if (isDirty)
67
69
  dispatch(
68
70
  "change",
69
- returnSingle && localValue ? localValue[0] : localValue
71
+ returnSingle && localValue ? localValue[0] : localValue,
70
72
  );
71
73
 
72
74
  return "View";
73
75
  },
74
- cancel() {
76
+ cancel(e) {
75
77
  localValue = JSON.parse(originalValue);
76
- anchor?.blur();
78
+ anchor.blur();
77
79
  return "View";
78
80
  },
79
81
  },
@@ -176,7 +178,7 @@
176
178
  <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
177
179
  <!-- svelte-ignore a11y-no-static-element-interactions -->
178
180
  <div
179
- class="superCell"
181
+ class="superCell has-popup"
180
182
  tabindex={cellOptions?.disabled ? -1 : 0}
181
183
  bind:this={anchor}
182
184
  class:isDirty={isDirty && cellOptions.showDirty}
@@ -188,12 +190,13 @@
188
190
  class:disabled={cellOptions.disabled}
189
191
  class:readonly
190
192
  class:error={cellOptions.error}
193
+ class:open-popup={$editorState == "Open"}
191
194
  style:color={cellOptions.color}
192
195
  style:background={cellOptions.background}
193
- on:mousedown={editorState.toggle}
194
196
  on:focusin={cellState.focus}
195
197
  on:keydown|self={handleKeyboard}
196
198
  on:focusout={cellState.focusout}
199
+ on:mousedown={cellState.toggle}
197
200
  >
198
201
  {#if cellOptions?.icon}
199
202
  <i class={cellOptions.icon + " field-icon"}></i>
@@ -221,7 +224,9 @@
221
224
  }
222
225
  : null}
223
226
  >
224
- <i class={valueIcon}></i>
227
+ {#if isUser}
228
+ <i class={valueIcon}></i>
229
+ {/if}
225
230
  <span>{val.primaryDisplay}</span>
226
231
  </div>
227
232
  {/if}
@@ -247,16 +252,11 @@
247
252
  </div>
248
253
 
249
254
  {#if inEdit}
250
- <SuperPopover
251
- {anchor}
252
- useAnchorWidth
253
- open={$editorState == "Open"}
254
- on:close={cellState.cancel}
255
- bind:popup
256
- >
255
+ <SuperPopover {anchor} useAnchorWidth open={$editorState == "Open"}>
257
256
  <!-- svelte-ignore a11y-no-static-element-interactions -->
258
257
  <div
259
258
  class="picker-container"
259
+ bind:this={popup}
260
260
  on:keydown={(e) => {
261
261
  if (e.key == "Escape" || e.key == "Tab") {
262
262
  anchor.focus();
@@ -288,6 +288,7 @@
288
288
  {search}
289
289
  wide={cellOptions.wide && !singleSelect}
290
290
  on:change={handleChange}
291
+ on:focusout={cellState.popupfocusout}
291
292
  />
292
293
  {/if}
293
294
  </div>
@@ -58,7 +58,7 @@
58
58
  if (isDirty)
59
59
  dispatch(
60
60
  "change",
61
- returnSingle && localValue ? localValue[0] : localValue
61
+ returnSingle && localValue ? localValue[0] : localValue,
62
62
  );
63
63
  editorState.close();
64
64
  return "View";
@@ -178,14 +178,10 @@
178
178
  on:mousedown={editorState.toggle}
179
179
  >
180
180
  {#if cellOptions?.icon}
181
- <i class={cellOptions.icon + " icon"}></i>
181
+ <i class={cellOptions.icon + " field-icon"}></i>
182
182
  {/if}
183
183
 
184
- <div
185
- class="value"
186
- class:with-icon={cellOptions?.icon}
187
- class:placeholder={localValue?.length < 1}
188
- >
184
+ <div class="value" class:placeholder={localValue?.length < 1}>
189
185
  {#if localValue?.length < 1}
190
186
  <span>
191
187
  {cellOptions.placeholder ?? null}
@@ -76,7 +76,7 @@
76
76
  const unselectRow = (val) => {
77
77
  localValue.splice(
78
78
  localValue.findIndex((e) => e._id === val._id),
79
- 1
79
+ 1,
80
80
  );
81
81
  localValue = localValue;
82
82
  dispatch("change", localValue);
@@ -132,7 +132,9 @@
132
132
  };
133
133
 
134
134
  const handleNavigation = (e) => {
135
- if (e.key == "ArrowDown") {
135
+ if (e.key == "Escape") {
136
+ dispatch("close");
137
+ } else if (e.key == "ArrowDown") {
136
138
  e.preventDefault();
137
139
  focusIdx += 1;
138
140
  if (focusIdx > $fetch.rows.length - 1) focusIdx = 0;
@@ -191,6 +193,7 @@
191
193
  : "Search"}
192
194
  on:input={handleSearch}
193
195
  on:keydown={handleNavigation}
196
+ on:focusout
194
197
  />
195
198
  </div>
196
199
 
@@ -209,7 +212,7 @@
209
212
  on:mouseenter={() => (focusIdx = idx)}
210
213
  on:mouseleave={() => (focusIdx = -1)}
211
214
  on:mousedown|preventDefault|stopPropagation={selectRow(
212
- row
215
+ row,
213
216
  )}
214
217
  >
215
218
  {row[primaryDisplay]}
@@ -243,7 +246,7 @@
243
246
  transition:fly={{ x: -20, duration: 130 }}
244
247
  class="option wide selected"
245
248
  on:mousedown|stopPropagation|preventDefault={unselectRow(
246
- val
249
+ val,
247
250
  )}
248
251
  >
249
252
  {val.primaryDisplay}
@@ -7,18 +7,11 @@
7
7
  } from "svelte";
8
8
  import fsm from "svelte-fsm";
9
9
 
10
- /**
11
- * @typedef {import('./types.js').CellOptions} CellOptions
12
- * @typedef {import('./types.js').CellApi} CellApi
13
- */
14
-
15
10
  const { processStringSync } = getContext("sdk");
16
11
  const context = getContext("context");
17
12
  const dispatch = createEventDispatcher();
18
13
 
19
- /** @type {number | null} */
20
14
  export let value;
21
- /** @type {CellOptions} */
22
15
  export let cellOptions = {};
23
16
  export let autofocus = false;
24
17
 
@@ -48,15 +41,10 @@
48
41
  decimals,
49
42
  thousandsSeparator,
50
43
  role,
44
+ calculated,
51
45
  } = cellOptions ?? {});
52
46
 
53
47
  // Helper function to format number with thousands separator
54
- /**
55
- * @param {number | string | null | undefined} num
56
- * @param {string | undefined} separator
57
- * @param {number | undefined} decimals
58
- * @returns {string}
59
- */
60
48
  function formatNumber(num, separator, decimals) {
61
49
  // Parse string to number if needed
62
50
  const parsedNum = typeof num === "string" ? parseFloat(num) : num;
@@ -90,11 +78,12 @@
90
78
  $: formattedValue = template
91
79
  ? processStringSync(template, {
92
80
  ...$context,
93
- value,
81
+ value: formatNumber(displayValue, thousandsSeparator, decimals),
94
82
  })
95
83
  : formatNumber(displayValue, thousandsSeparator, decimals);
96
84
 
97
85
  $: stepValue = stepSize ?? 1;
86
+ $: clearValue = cellOptions.clearValue && cellOptions.role != "tableCell";
98
87
 
99
88
  // Reset when value changes externally
100
89
  $: cellState.reset(value);
@@ -119,7 +108,7 @@
119
108
  return state;
120
109
  },
121
110
  focus() {
122
- if (!readonly && !disabled) return "Editing";
111
+ if (!readonly && !disabled && !calculated) return "Editing";
123
112
  },
124
113
  },
125
114
  Editing: {
@@ -275,7 +264,6 @@
275
264
  },
276
265
  });
277
266
 
278
- /** @type {CellApi} */
279
267
  export const cellApi = {
280
268
  focus: () => cellState.focus(),
281
269
  reset: () => cellState.reset(value),
@@ -320,7 +308,7 @@
320
308
  class:formInput={role == "formInput"}
321
309
  style:color
322
310
  style:background
323
- tabIndex={disabled ? -1 : 0}
311
+ tabIndex={disabled ? -1 : (cellOptions.order ?? 0)}
324
312
  on:focusin={cellState.focus}
325
313
  >
326
314
  {#if icon}
@@ -344,12 +332,15 @@
344
332
  on:wheel={(e) => cellState.handleWheel(e)}
345
333
  use:focus
346
334
  />
335
+
347
336
  <!-- svelte-ignore a11y-no-static-element-interactions -->
348
337
  <i
349
- class="ri-close-line clear-icon visible"
338
+ class="ri-close-line clear-icon"
339
+ class:visible={clearValue}
350
340
  on:mousedown|preventDefault|stopPropagation={cellState.clear}
351
341
  >
352
342
  </i>
343
+
353
344
  {#if showStepper}
354
345
  <div class="controls">
355
346
  <!-- svelte-ignore a11y-no-static-element-interactions -->
@@ -369,7 +360,6 @@
369
360
  {:else}
370
361
  <div
371
362
  class="value"
372
- style:padding-right={"12px"}
373
363
  class:placeholder={!value && value !== 0}
374
364
  style:justify-content={cellOptions.align ?? "flex-end"}
375
365
  >
@@ -380,22 +370,27 @@
380
370
 
381
371
  <style>
382
372
  .controls {
373
+ height: 100%;
383
374
  display: flex;
384
375
  flex-direction: row;
376
+ align-items: stretch;
385
377
  gap: 0.25rem;
386
- padding-right: 0.5rem;
387
- margin-left: -0.25rem;
378
+ padding: 0.25rem 0rem;
388
379
  }
389
380
 
390
381
  .controls i {
382
+ display: flex;
383
+ align-items: center;
384
+ justify-content: center;
391
385
  cursor: pointer;
392
- padding: 0.15rem;
386
+ padding: 0.25rem;
393
387
  background-color: var(--spectrum-global-color-gray-100);
394
388
  border-radius: 0.25rem;
395
389
  transition: all 0.2s ease-in-out;
396
390
  }
397
391
 
398
392
  .controls i:hover {
399
- background-color: var(--spectrum-global-color-gray-200);
393
+ background-color: var(--spectrum-global-color-gray-300);
394
+ color: var(--spectrum-global-color-gray-900);
400
395
  }
401
396
  </style>
@@ -106,6 +106,7 @@
106
106
  View: {
107
107
  _enter() {
108
108
  searchTerm = null;
109
+ editorState.filterOptions();
109
110
  },
110
111
  focus(e) {
111
112
  if (!readonly && !disabled) {
@@ -115,23 +116,22 @@
115
116
  },
116
117
  Editing: {
117
118
  _enter() {
119
+ editorState.open();
118
120
  originalValue = JSON.stringify(
119
- Array.isArray(value) ? value : value ? [value] : []
121
+ Array.isArray(value) ? value : value ? [value] : [],
120
122
  );
121
123
  inputValue = multi ? "" : labels[localValue[0]] || localValue[0] || "";
122
- // Open the popup if the focus in came from a TAB
123
- editorState.open();
124
+
124
125
  dispatch("enteredit");
125
126
  },
126
127
  _exit() {
127
128
  editorState.close();
128
- editorState.filterOptions();
129
129
  dispatch("exitedit");
130
130
  },
131
+ toggle(e) {
132
+ editorState.toggle();
133
+ },
131
134
  focusout(e) {
132
- // If the focus is moving to the search input inside the popup, ignore
133
- if (anchor.contains(e.relatedTarget)) return;
134
-
135
135
  dispatch("focusout");
136
136
 
137
137
  // For debounced inputs, dispatch the current value immediately on focusout
@@ -144,6 +144,12 @@
144
144
 
145
145
  return "View";
146
146
  },
147
+ popupfocusout(e) {
148
+ if (anchor != e?.relatedTarget) {
149
+ this.submit();
150
+ return "View";
151
+ }
152
+ },
147
153
  submit() {
148
154
  if (isDirty && !cellOptions.debounce) {
149
155
  if (multi) dispatch("change", localValue);
@@ -230,7 +236,7 @@
230
236
  // Client-side filtering for non-datasource
231
237
  if (term) {
232
238
  filteredOptions = $options.filter((x) =>
233
- x?.toLocaleLowerCase().startsWith(term.toLocaleLowerCase())
239
+ x?.toLocaleLowerCase().startsWith(term.toLocaleLowerCase()),
234
240
  );
235
241
  } else {
236
242
  filteredOptions = $options;
@@ -344,11 +350,8 @@
344
350
  searchTerm = null;
345
351
  focusedOptionIdx = -1;
346
352
  },
347
- toggle(e) {
348
- if (inEdit) {
349
- e.preventDefault();
350
- return "Open";
351
- }
353
+ toggle() {
354
+ return "Open";
352
355
  },
353
356
  open() {
354
357
  return "Open";
@@ -403,7 +406,7 @@
403
406
  $options.forEach(
404
407
  (option, index) =>
405
408
  (obj[option] =
406
- optionColors[option] ?? colorsArray[index % colorsArray.length])
409
+ optionColors[option] ?? colorsArray[index % colorsArray.length]),
407
410
  );
408
411
  return obj;
409
412
  });
@@ -441,7 +444,7 @@
441
444
  ];
442
445
 
443
446
  let originalValue = JSON.stringify(
444
- Array.isArray(value) ? value : value ? [value] : []
447
+ Array.isArray(value) ? value : value ? [value] : [],
445
448
  );
446
449
 
447
450
  $: ({
@@ -492,7 +495,7 @@
492
495
  iconColumn,
493
496
  colorColumn,
494
497
  $dataSourceStore,
495
- customOptions
498
+ customOptions,
496
499
  );
497
500
 
498
501
  // We always keep an internal value as an array
@@ -505,6 +508,8 @@
505
508
  $: isDirty = inEdit && originalValue !== JSON.stringify(localValue);
506
509
  $: inEdit = $cellState == "Editing";
507
510
  $: pills = optionsViewMode == "pills";
511
+ $: bullets = optionsViewMode == "bullets";
512
+
508
513
  $: multi =
509
514
  fieldSchema && fieldSchema.type ? fieldSchema.type == "array" : multi;
510
515
 
@@ -542,11 +547,12 @@
542
547
  class:inline={role == "inlineInput"}
543
548
  class:tableCell={role == "tableCell"}
544
549
  class:formInput={role == "formInput"}
545
- style:cursor={inEdit ? "pointer" : "default"}
550
+ class:has-popup={controlType == "select"}
551
+ class:open-popup={open}
546
552
  on:focusin={cellState.focus}
547
553
  on:focusout={cellState.focusout}
548
554
  on:keydown={editorState.handleKeyboard}
549
- on:mousedown={editorState.toggle}
555
+ on:mousedown={cellState.toggle}
550
556
  >
551
557
  {#if icon}
552
558
  <i class={icon + " field-icon"} class:active={searchTerm}></i>
@@ -593,7 +599,7 @@
593
599
  use:focus
594
600
  {placeholder}
595
601
  />
596
- <div class="action-icon" on:click={editorState.toggle}>
602
+ <div class="control-icon" on:click={editorState.toggle}>
597
603
  <i class="ph ph-caret-down"></i>
598
604
  </div>
599
605
  {:else}
@@ -612,7 +618,7 @@
612
618
  <div
613
619
  class="items"
614
620
  class:pills
615
- class:colorText={optionsViewMode == "colorText"}
621
+ class:bullets
616
622
  style:justify-content={cellOptions.align ?? "flex-start"}
617
623
  >
618
624
  {#each localValue as val, idx (val)}
@@ -621,7 +627,7 @@
621
627
  style:--option-color={$colors[val] ||
622
628
  colorsArray[idx % colorsArray.length]}
623
629
  >
624
- <i class={"ph-fill ph-square"}></i>
630
+ <div class="loope"></div>
625
631
  <span> {isObjects ? "JSON" : labels[val] || val} </span>
626
632
  </div>
627
633
  {/each}
@@ -629,7 +635,7 @@
629
635
  {/if}
630
636
  </div>
631
637
  {#if !readonly && (role == "formInput" || inEdit)}
632
- <i class="ph ph-caret-down control-icon"></i>
638
+ <i class="ph ph-caret-down control-icon" on:mousedown></i>
633
639
  {/if}
634
640
  {/if}
635
641
  </div>
@@ -772,21 +778,6 @@
772
778
  font-style: italic;
773
779
  }
774
780
 
775
- .action-icon {
776
- height: 100%;
777
- display: flex;
778
- justify-content: center;
779
- align-items: center;
780
- border-left: 1px solid var(--spectrum-global-color-blue-500);
781
- min-width: 2rem;
782
- font-size: 16px;
783
- }
784
- .action-icon:hover {
785
- cursor: pointer;
786
- background-color: var(--spectrum-global-color-gray-75);
787
- font-weight: 800;
788
- }
789
-
790
781
  .search-icon {
791
782
  font-size: 16px;
792
783
  color: var(--spectrum-global-color-gray-500);
@@ -813,4 +804,15 @@
813
804
  width: 100%;
814
805
  overflow: hidden;
815
806
  }
807
+
808
+ .loope {
809
+ width: 14px;
810
+ height: 14px;
811
+ border-radius: 2px;
812
+ background-color: var(
813
+ --option-color,
814
+ var(--spectrum-global-color-gray-300)
815
+ );
816
+ flex-shrink: 0;
817
+ }
816
818
  </style>