@poirazis/supercomponents-shared 1.0.11 → 1.0.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.
@@ -3,6 +3,7 @@
3
3
  import fsm from "svelte-fsm";
4
4
  import { writable } from "svelte/store";
5
5
 
6
+ import "./SuperTable.css";
6
7
  import {
7
8
  sizingMap,
8
9
  defaultOperatorMap,
@@ -290,11 +291,14 @@
290
291
  $: cumulativeHeights = derivedMemo(
291
292
  [stbRowMetadata, stbSettings],
292
293
  ([$meta, $settings]) => {
293
- const defaultRowHeight = $settings.appearance?.rowHeight || 36; // Fallback if undefined
294
+ const defaultRowHeight = $settings.appearance?.rowHeight || 36;
294
295
  return $meta.map((_, i) =>
295
296
  $meta
296
297
  .slice(0, i + 1)
297
- .reduce((sum, meta) => sum + (meta.height || defaultRowHeight), 0)
298
+ .reduce(
299
+ (sum, meta) => sum + Math.max(meta.height || defaultRowHeight, 0),
300
+ 0
301
+ )
298
302
  );
299
303
  }
300
304
  );
@@ -647,10 +651,8 @@
647
651
  init() {
648
652
  return "Init";
649
653
  },
650
- async refresh() {
651
- if (stbData.loaded) await stbData?.refresh();
652
- this.enrichRows();
653
- this.calculateRowBoundaries();
654
+ refresh() {
655
+ stbData?.refresh();
654
656
  },
655
657
  enrichRows() {},
656
658
  scrollToTop() {
@@ -703,11 +705,10 @@
703
705
  if (!rows?.length || !viewport || !$cumulativeHeights.length) return;
704
706
 
705
707
  const defaultRowHeight = $stbSettings.appearance.rowHeight;
706
- let start = $stbVisibleRows?.length ? $stbVisibleRows[0] - 1 : 0;
707
- start = Math.max(0, start); // Ensure start doesn't go negative
708
- let end = 0;
708
+ let start = 0,
709
+ end = rows.length;
709
710
 
710
- // Find start index using cumulativeHeights
711
+ // Find start index
711
712
  for (let i = 0; i < rows.length; i++) {
712
713
  if ($cumulativeHeights[i] > $stbScrollPos) {
713
714
  start = i;
@@ -715,45 +716,30 @@
715
716
  }
716
717
  }
717
718
 
718
- // Find end index using cumulativeHeights
719
+ // Find end index
719
720
  for (let i = start; i < rows.length; i++) {
720
- if (
721
- $cumulativeHeights[i] >=
722
- $stbScrollPos + maxBodyHeight - defaultRowHeight
723
- ) {
721
+ if ($cumulativeHeights[i] >= $stbScrollPos + maxBodyHeight) {
724
722
  end = i + 1;
725
723
  break;
726
724
  }
727
725
  }
728
726
 
729
- // Ensure all rows are included when at the bottom
730
- end = end || rows.length;
731
-
732
727
  // Update visible rows
733
728
  $stbVisibleRows = $stbData?.rows
734
- ?.slice(start, end)
729
+ .slice(start, end)
735
730
  .map((_, i) => i + start);
736
731
 
737
- // Calculate scroll offset for rendering
732
+ // Calculate scroll offset
738
733
  const startHeight = start > 0 ? $cumulativeHeights[start - 1] : 0;
739
734
  $stbScrollOffset = $stbScrollPos - startHeight;
740
735
 
741
- // Ensure offset doesn't exceed bounds at the end
742
- if ($stbScrollPos >= scrollHeight - maxBodyHeight) {
743
- $stbScrollPos = Math.max(0, scrollHeight - maxBodyHeight);
744
- $stbScrollOffset = Math.min(
745
- $stbScrollOffset,
746
- maxBodyHeight - defaultRowHeight
747
- );
748
- }
749
-
750
- // Fetch more rows if nearing the end of loaded data
736
+ // Fetch more rows if nearing the end
751
737
  if (fetchOnScroll && rows.length > 0) {
752
738
  const loadedHeight = $cumulativeHeights[rows.length - 1];
753
739
  const remainingHeight =
754
740
  loadedHeight - ($stbScrollPos + maxBodyHeight);
755
- if (remainingHeight < maxBodyHeight && rows.length == _limit) {
756
- stbState.fetchMoreRows.debounce(200, 100); // Debounced fetch call
741
+ if (remainingHeight < maxBodyHeight && rows.length === _limit) {
742
+ stbState.fetchMoreRows.debounce(200, 100); // Debounced fetch
757
743
  }
758
744
  }
759
745
  },
@@ -769,11 +755,7 @@
769
755
  scrollHeight > maxBodyHeight
770
756
  ? $stbScrollPos / (scrollHeight - maxBodyHeight)
771
757
  : 0;
772
- $stbScrollOffset = Math.floor(
773
- $stbScrollPos % $stbSettings.appearance.rowHeight
774
- );
775
-
776
- this.calculateRowBoundaries.debounce(1);
758
+ window.requestAnimationFrame(() => this.calculateRowBoundaries());
777
759
  },
778
760
  handleWheel(e) {
779
761
  if ($stbState == "Inserting") {
@@ -1194,8 +1176,6 @@
1194
1176
  $: console.log("Table Filters : ", stbColumnFilters);
1195
1177
  $: console.log("Table Settings : ", $stbSettings);
1196
1178
  */
1197
-
1198
- $: console.log($stbSchema);
1199
1179
  </script>
1200
1180
 
1201
1181
  <!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -205,6 +205,8 @@
205
205
  color: var(--spectrum-global-color-gray-800);
206
206
  border: 1px solid var(--spectrum-global-color-gray-300);
207
207
  background: var(--spectrum-global-color-gray-50);
208
+ min-height: 2rem;
209
+ max-height: 2rem;
208
210
 
209
211
  &:focus-within {
210
212
  border: 1px solid var(--spectrum-global-color-blue-400) !important;
@@ -180,7 +180,6 @@
180
180
  class:readonly
181
181
  on:click={!readonly
182
182
  ? () => {
183
- console.log(open);
184
183
  open = !open;
185
184
  }
186
185
  : null}
@@ -1,104 +1,119 @@
1
- <script>
2
- import { createEventDispatcher, getContext, onMount } from "svelte";
1
+ <script lang="ts">
2
+ import {
3
+ createEventDispatcher,
4
+ getContext,
5
+ onDestroy,
6
+ onMount,
7
+ } from "svelte";
3
8
  import fsm from "svelte-fsm";
4
9
 
5
10
  const { processStringSync } = getContext("sdk");
6
11
  const context = getContext("context");
7
12
  const dispatch = createEventDispatcher();
8
13
 
9
- export let value;
10
- export let formattedValue;
11
- export let cellOptions;
12
- export let autofocus;
14
+ export let value: number | null;
15
+ export let formattedValue: string | undefined;
16
+ export let cellOptions: any;
17
+ export let autofocus: boolean;
13
18
 
14
- let originalValue = value;
15
- let inEdit;
16
- let localValue = value;
17
- let editor;
18
-
19
- $: inEdit = $cellState == "Editing";
20
- $: inline = cellOptions.role == "inlineInput";
21
- $: isDirty = inEdit && originalValue != localValue;
22
- $: formattedValue = cellOptions.template
23
- ? processStringSync(cellOptions.template, {
24
- ...$context,
25
- value: localValue,
26
- })
27
- : undefined;
28
-
29
- $: placeholder =
30
- cellOptions.readonly || cellOptions.disabled
31
- ? ""
32
- : cellOptions.placeholder || "";
19
+ let originalValue: number | null = value;
20
+ let inEdit: boolean;
21
+ let localValue: number | null = value;
22
+ let editor: HTMLInputElement;
23
+ let lastEdit: Date | undefined;
24
+ let timer: ReturnType<typeof setTimeout>;
33
25
 
34
26
  export let cellState = fsm(cellOptions.initialState ?? "View", {
35
27
  "*": {
36
- goTo(state) {
28
+ goTo(state: string) {
37
29
  return state;
38
30
  },
31
+ reset() {
32
+ localValue = value;
33
+ lastEdit = undefined;
34
+ return "View";
35
+ },
39
36
  },
40
37
  View: {
38
+ _enter() {
39
+ localValue = value;
40
+ },
41
41
  focus() {
42
42
  if (!cellOptions.readonly && !cellOptions.disabled) return "Editing";
43
43
  },
44
44
  },
45
- Hovered: {
46
- cancel: () => {
47
- return "View";
48
- },
49
- },
50
- Focused: {
51
- unfocus() {
52
- return "View";
53
- },
54
- },
55
- Error: { check: "View" },
56
45
  Editing: {
57
46
  _enter() {
58
- originalValue = localValue;
47
+ originalValue = value;
59
48
  editor?.focus();
60
49
  dispatch("enteredit");
61
50
  },
62
51
  _exit() {
52
+ originalValue = undefined;
63
53
  dispatch("exitedit");
64
- },
65
- focusout() {
66
- if (isDirty && !cellOptions.debounce) dispatch("change", localValue);
67
-
68
54
  dispatch("focusout");
69
- return "View";
70
55
  },
71
56
  clear() {
72
57
  if (cellOptions.debounce) dispatch("change", null);
58
+ lastEdit = new Date();
73
59
  localValue = null;
74
60
  },
61
+ focusout(e: FocusEvent) {
62
+ this.submit();
63
+ },
64
+ submit() {
65
+ if (isDirty) {
66
+ dispatch("change", localValue);
67
+ }
68
+ return "View";
69
+ },
75
70
  cancel() {
76
71
  value = originalValue;
72
+ dispatch("cancel");
73
+ return "View";
74
+ },
75
+ debounce(e: KeyboardEvent) {
76
+ if ((e.key.length === 1 && e.key !== "." && isNaN(Number(e.key)) && !e.ctrlKey) ||
77
+ e.keyCode == 32 ||
78
+ (e.key === "." && e.target.value.toString().indexOf(".") > -1)) {
79
+ e.preventDefault();
80
+ return;
81
+ }
82
+ localValue = Number(e.target.value);
83
+ lastEdit = new Date();
84
+ if (cellOptions?.debounce) {
85
+ clearTimeout(timer);
86
+ timer = setTimeout(() => {
87
+ dispatch("change", localValue);
88
+ }, cellOptions.debounce ?? 0);
89
+ }
90
+ },
91
+ handleKeyboard(e: KeyboardEvent) {
92
+ if (e.key == "Enter") this.submit();
93
+ if (e.key == "Escape") this.cancel();
77
94
  },
78
95
  },
79
96
  });
80
97
 
81
- let timer;
82
- const debounce = (e) => {
83
- // Abort Invalid Keys
84
- if (
85
- (e.key.length === 1 && e.key !== "." && isNaN(e.key) && !e.ctrlKey) ||
86
- e.keyCode == 32 ||
87
- (e.key === "." && e.target.value.toString().indexOf(".") > -1)
88
- ) {
89
- e.preventDefault();
90
- return;
91
- }
92
- if (cellOptions.debounce) {
93
- clearTimeout(timer);
94
- timer = setTimeout(() => {
95
- dispatch("change", localValue);
96
- }, cellOptions.debounce ?? 0);
97
- }
98
- };
98
+ $: inEdit = $cellState == "Editing";
99
+ $: inline = cellOptions.role == "inlineInput";
100
+ $: isDirty = inEdit && originalValue != localValue;
101
+ $: formattedValue = cellOptions.template
102
+ ? processStringSync(cellOptions.template, {
103
+ ...$context,
104
+ value: localValue,
105
+ })
106
+ : undefined;
107
+
108
+ $: placeholder =
109
+ cellOptions.readonly || cellOptions.disabled
110
+ ? ""
111
+ : cellOptions.placeholder || "";
99
112
 
100
- function focus(element) {
101
- setTimeout(element?.focus(), 10);
113
+ $: cellState.reset(value);
114
+
115
+ function focus(element: HTMLElement) {
116
+ setTimeout(() => element?.focus(), 10);
102
117
  }
103
118
 
104
119
  onMount(() => {
@@ -108,6 +123,11 @@
108
123
  editor?.focus();
109
124
  }, 30);
110
125
  });
126
+
127
+ onDestroy(() => {
128
+ clearTimeout(timer);
129
+ cellState.reset();
130
+ });
111
131
  </script>
112
132
 
113
133
  <!-- svelte-ignore a11y-no-static-element-interactions -->
@@ -148,8 +168,9 @@
148
168
  : "right "}
149
169
  placeholder={cellOptions?.placeholder}
150
170
  bind:value={localValue}
151
- on:keydown={(e) => debounce(e)}
152
- on:focusout={cellState.focusout}
171
+ on:keydown={(e) => cellState.debounce(e)}
172
+ on:focusout={(e) => cellState.focusout(e)}
173
+ on:keyup={(e) => cellState.handleKeyboard(e)}
153
174
  use:focus
154
175
  />
155
176
  <i class="ri-close-line clearIcon" on:mousedown|self={cellState.clear}> </i>
@@ -1,5 +1,10 @@
1
1
  <script>
2
- import { createEventDispatcher, getContext, onMount } from "svelte";
2
+ import {
3
+ createEventDispatcher,
4
+ getContext,
5
+ onMount,
6
+ onDestroy,
7
+ } from "svelte";
3
8
  import fsm from "svelte-fsm";
4
9
  const dispatch = createEventDispatcher();
5
10
  const { processStringSync } = getContext("sdk");
@@ -28,6 +33,7 @@
28
33
  reset() {
29
34
  localValue = value;
30
35
  lastEdit = undefined;
36
+ return "View";
31
37
  },
32
38
  },
33
39
  View: {
@@ -109,6 +115,19 @@
109
115
  cellState.focus();
110
116
  }, 50);
111
117
  });
118
+
119
+ onDestroy(() => {
120
+ clearTimeout(timer);
121
+ cellState.reset();
122
+ });
123
+
124
+ $: if (inEdit)
125
+ console.log(
126
+ "Entering edit mode for cell",
127
+ value,
128
+ localValue,
129
+ originalValue
130
+ );
112
131
  </script>
113
132
 
114
133
  <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
@@ -11,11 +11,11 @@
11
11
  };
12
12
 
13
13
  $: formattedValue =
14
- !formattedValue && cellOptions?.template
14
+ cellOptions?.template
15
15
  ? processStringSync(cellOptions.template, {
16
16
  value,
17
17
  })
18
- : formattedValue;
18
+ : undefined;;
19
19
 
20
20
  $: placeholder =
21
21
  cellOptions.readonly || cellOptions.disabled
@@ -1,7 +1,13 @@
1
1
  <script>
2
- import { getContext, createEventDispatcher, onMount, tick } from "svelte";
2
+ import {
3
+ getContext,
4
+ createEventDispatcher,
5
+ onMount,
6
+ tick,
7
+ onDestroy,
8
+ } from "svelte";
3
9
 
4
- const { Provider, processStringSync, ContextScopes } = getContext("sdk");
10
+ const { Provider, ContextScopes } = getContext("sdk");
5
11
 
6
12
  const dispatch = createEventDispatcher();
7
13
  const columnSettings = getContext("stColumnOptions");
@@ -10,6 +16,7 @@
10
16
  const rowMetadata = getContext("stbRowMetadata");
11
17
  const stbHovered = getContext("stbHovered");
12
18
  const stbSelected = getContext("stbSelected");
19
+ const stbEditing = getContext("stbEditing");
13
20
  const stbAPI = getContext("stbAPI");
14
21
  const stbState = getContext("stbState");
15
22
  const stbMenuID = getContext("stbMenuID");
@@ -34,12 +41,6 @@
34
41
  $: isSelected = $stbSelected.includes(id);
35
42
  $: hasChildren = $columnSettings.hasChildren > 0;
36
43
 
37
- const getCellValue = (value) => {
38
- return $columnSettings.template
39
- ? processStringSync($columnSettings.template, { value })
40
- : undefined;
41
- };
42
-
43
44
  const patchRow = async (change) => {
44
45
  let patch = {
45
46
  ...row,
@@ -88,6 +89,12 @@
88
89
  } else return obj[path] ?? undefined;
89
90
  };
90
91
  onMount(() => (mounted = $columnSettings.superColumn));
92
+
93
+ onDestroy(() => {
94
+ if ($stbEditing == index) {
95
+ columnState.exitedit();
96
+ }
97
+ });
91
98
  </script>
92
99
 
93
100
  <!-- svelte-ignore a11y-click-events-have-key-events -->
File without changes