@lavalogic/scoria 0.25.0 → 0.25.2

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.
@@ -31,11 +31,10 @@
31
31
  oninput,
32
32
 
33
33
  inputRef = $bindable(),
34
- 'data-type': dataType
34
+ 'data-type': dataType,
35
35
  }: NumberInputProps = $props();
36
36
 
37
- // HACK cannot alter signature because it's passed by a use: directive
38
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
37
+ // NOTE cannot alter signature because it's passed by a use: directive
39
38
  function numberValidator(_node: HTMLInputElement, _newValue: number | null) {
40
39
  return {
41
40
  update(newValue: number) {
@@ -43,7 +42,7 @@
43
42
  const overMaximum = max != undefined && max < newValue;
44
43
 
45
44
  value = isNaN(newValue) ? 0 : underMinimum ? min : overMaximum ? max : newValue;
46
- }
45
+ },
47
46
  };
48
47
  }
49
48
 
@@ -69,13 +68,18 @@
69
68
  >{labelTop}{#if optional}<i>&nbsp;- optional</i>{/if}</span
70
69
  >
71
70
  {#if variant === InputVariant.Default}
72
- <span class="border" class:invalid={isInvalid}
71
+ <span
72
+ class="border"
73
+ class:invalid={isInvalid}
73
74
  >{labelTop}{#if optional}<i>&nbsp;- optional</i>{/if}</span
74
75
  >
75
76
  {/if}
76
77
  {/if}
77
78
  <!-- style="--background-colour: {leftIcon?.backgroundColour ?? rightIcon?.backgroundColour};" -->
78
- <div class="icon-container" class:for-modal={variant == InputVariant.Modal}>
79
+ <div
80
+ class="icon-container"
81
+ class:for-modal={variant == InputVariant.Modal}
82
+ >
79
83
  {#if leftIcon}
80
84
  <Icon
81
85
  name={leftIcon.name}
@@ -128,8 +132,9 @@
128
132
  />
129
133
  {/if}
130
134
  {#if labelRight}
131
- <span class="right-label inset" class:for-modal={variant == InputVariant.Modal}
132
- >{labelRight}</span
135
+ <span
136
+ class="right-label inset"
137
+ class:for-modal={variant == InputVariant.Modal}>{labelRight}</span
133
138
  >
134
139
  {/if}
135
140
  </div>
@@ -46,29 +46,37 @@
46
46
  tableContext.focusStartIsBeingEdited
47
47
  );
48
48
 
49
+ function handleEditable(isEditable: boolean): Promise<void> {
50
+ if (isEditable) {
51
+ return tick().then(() => {
52
+ modalLock = true;
53
+ });
54
+ } else {
55
+ if (modalLock) {
56
+ return tick().then(() => {
57
+ if (!tableContext.singleClickEditing) {
58
+ tableContext.focusStartIsBeingEdited = false;
59
+ }
60
+ modalLock = false;
61
+ });
62
+ }
63
+
64
+ return Promise.resolve();
65
+ }
66
+ }
67
+
49
68
  $effect(() => {
50
69
  void editable;
51
70
  if (wantsToBeEdited) {
52
- editable
53
- .then((isEditable) => {
54
- if (isEditable) {
55
- return tick().then(() => {
56
- modalLock = true;
57
- });
58
- } else {
59
- if (modalLock) {
60
- return tick().then(() => {
61
- if (!tableContext.singleClickEditing) {
62
- tableContext.focusStartIsBeingEdited = false;
63
- }
64
- modalLock = false;
65
- });
66
- }
67
-
68
- return;
69
- }
70
- })
71
- .catch(devCatch);
71
+ if (editable instanceof Promise) {
72
+ editable
73
+ .then((isEditable) => {
74
+ return handleEditable(isEditable);
75
+ })
76
+ .catch(devCatch);
77
+ } else {
78
+ handleEditable(editable).catch(devCatch);
79
+ }
72
80
  } else {
73
81
  tick()
74
82
  .then(() => {
@@ -89,71 +89,40 @@
89
89
 
90
90
  let isBeingEdited = $state(false);
91
91
 
92
- /*
93
- $effect(() => {
94
- void editable;
95
- if (wantsToBeEdited) {
96
- if (editable) {
97
- tick()
98
- .then(() => {
99
- untrack(() => {
100
- isBeingEdited = true;
101
- });
102
- })
103
- .catch(devCatch);
104
- } else {
105
- tick()
106
- .then(() => {
107
- untrack(() => {
108
- tableContext.focusStartIsBeingEdited = false;
109
- });
110
- })
111
- .catch(devCatch);
112
- }
92
+ function handleIsEditable(isEditable: boolean): Promise<void> {
93
+ if (isEditable) {
94
+ return tick().then(() => {
95
+ isBeingEdited = true;
96
+ });
113
97
  } else {
114
98
  if (isBeingEdited) {
115
- tick()
99
+ return tick()
116
100
  .then(() => {
117
- untrack(() => {
118
- if (!tableContext.singleClickEditing) {
119
- tableContext.focusStartIsBeingEdited = false;
120
- }
101
+ if (!tableContext.singleClickEditing) {
102
+ tableContext.focusStartIsBeingEdited = false;
103
+ }
121
104
 
122
- isBeingEdited = false;
123
- });
105
+ isBeingEdited = false;
124
106
  })
125
107
  .catch(devCatch);
126
108
  }
127
109
  }
128
- });
129
- */
110
+ return Promise.resolve();
111
+ }
112
+
130
113
  $effect(() => {
131
114
  void editable;
132
115
  if (wantsToBeEdited) {
133
- editable
134
- .then((isEditable) => {
135
- if (isEditable) {
136
- return tick().then(() => {
137
- isBeingEdited = true;
138
- });
139
- } else {
140
- if (isBeingEdited) {
141
- return tick()
142
- .then(() => {
143
- if (!tableContext.singleClickEditing) {
144
- tableContext.focusStartIsBeingEdited = false;
145
- }
146
-
147
- isBeingEdited = false;
148
- })
149
- .catch(devCatch);
150
- }
151
- }
152
-
153
- return;
154
- })
116
+ if (editable instanceof Promise) {
117
+ editable
118
+ .then((isEditable) => {
119
+ return handleIsEditable(isEditable);
120
+ })
155
121
 
156
- .catch(devCatch);
122
+ .catch(devCatch);
123
+ } else {
124
+ handleIsEditable(editable).catch(devCatch);
125
+ }
157
126
  } else {
158
127
  tick()
159
128
  .then(() => {
@@ -34,13 +34,27 @@
34
34
  const keyOrPromise: RowIdType | Promise<RowIdType> = $derived(
35
35
  tableContext.selectionExtractor(cell.row.original)
36
36
  );
37
- const isSelectable = $derived(
37
+ const isSelectableMaybePromise = $derived(
38
38
  (cell.column.columnDef as RowSelectionDef<T>).isSelectable(
39
39
  cell.row.original,
40
40
  cell.row.originalIndex
41
41
  )
42
42
  );
43
43
 
44
+ let isSelectable = $state(false);
45
+
46
+ $effect(() => {
47
+ if (isSelectableMaybePromise instanceof Promise) {
48
+ isSelectableMaybePromise
49
+ .then((it) => {
50
+ isSelectable = it;
51
+ })
52
+ .catch(devCatch);
53
+ } else {
54
+ isSelectable = isSelectableMaybePromise;
55
+ }
56
+ });
57
+
44
58
  // Sync path (common): uses selectedItems.has(key) for per-key reactive tracking —
45
59
  // only this row's checkbox re-runs when its specific key changes.
46
60
  // Async path (rare): returns null and defers to _isSelectedAsync updated by the $effect below.
@@ -56,7 +70,9 @@
56
70
  let _isSelectedAsync: boolean = $state(false);
57
71
  $effect(() => {
58
72
  const k = keyOrPromise;
59
- if (!(k instanceof Promise)) { return; }
73
+ if (!(k instanceof Promise)) {
74
+ return;
75
+ }
60
76
  void tableContext.selectedItems.size; // re-run when selection changes
61
77
  k.then((key) => {
62
78
  _isSelectedAsync = tableContext.selectedItems.has(key);
@@ -51,33 +51,42 @@
51
51
  );
52
52
 
53
53
  let isBeingEdited = $derived(false);
54
+
55
+ function handleIsEditable(isEditable: boolean): Promise<void> {
56
+ if (isEditable) {
57
+ return tick().then(() => {
58
+ isBeingEdited = true;
59
+ });
60
+ } else {
61
+ if (isBeingEdited) {
62
+ return tick()
63
+ .then(() => {
64
+ if (!tableContext.singleClickEditing) {
65
+ tableContext.focusStartIsBeingEdited = false;
66
+ }
67
+
68
+ isBeingEdited = false;
69
+ })
70
+ .catch(devCatch);
71
+ }
72
+ }
73
+
74
+ return Promise.resolve();
75
+ }
76
+
54
77
  $effect(() => {
55
78
  void editable;
56
79
  if (wantsToBeEdited) {
57
- editable
58
- .then((isEditable) => {
59
- if (isEditable) {
60
- return tick().then(() => {
61
- isBeingEdited = true;
62
- });
63
- } else {
64
- if (isBeingEdited) {
65
- return tick()
66
- .then(() => {
67
- if (!tableContext.singleClickEditing) {
68
- tableContext.focusStartIsBeingEdited = false;
69
- }
70
-
71
- isBeingEdited = false;
72
- })
73
- .catch(devCatch);
74
- }
75
- }
76
-
77
- return;
78
- })
80
+ if (editable instanceof Promise) {
81
+ editable
82
+ .then((isEditable) => {
83
+ return handleIsEditable(isEditable);
84
+ })
79
85
 
80
- .catch(devCatch);
86
+ .catch(devCatch);
87
+ } else {
88
+ handleIsEditable(editable).catch(devCatch);
89
+ }
81
90
  } else {
82
91
  tick()
83
92
  .then(() => {
@@ -82,7 +82,7 @@ export function generateExampleItemColumnDefs(modal) {
82
82
  getDisplayValue: (item) => {
83
83
  return item.simulatedQuery?.value ?? null;
84
84
  },
85
- isEditable: () => Promise.resolve(true),
85
+ isEditable: () => true,
86
86
  id: 'simulatedQuery',
87
87
  query: async (_v, item) => {
88
88
  void item.someDate;
@@ -101,13 +101,13 @@ export function generateExampleItemColumnDefs(modal) {
101
101
  new TextInputDef({
102
102
  header: 'Name',
103
103
  id: 'name',
104
- isEditable: () => Promise.resolve(true),
104
+ isEditable: () => true,
105
105
  isValid,
106
106
  }),
107
107
  new NumberInputDef({
108
108
  header: 'Some Number',
109
109
  id: 'someNumber',
110
- isEditable: () => Promise.resolve(true),
110
+ isEditable: () => true,
111
111
  min: 0,
112
112
  max: 12345,
113
113
  isValid,
@@ -150,20 +150,20 @@ export function generateExampleItemColumnDefs(modal) {
150
150
  new DateInputDef({
151
151
  header: 'Some Date With Time',
152
152
  id: 'someDateWithTime',
153
- isEditable: () => Promise.resolve(true),
153
+ isEditable: () => true,
154
154
  showTime: true,
155
155
  isValid,
156
156
  }),
157
157
  new DateInputDef({
158
158
  header: 'Flo Date',
159
159
  id: 'floDate',
160
- isEditable: () => Promise.resolve(true),
160
+ isEditable: () => true,
161
161
  defaultHidden: true,
162
162
  }),
163
163
  new DateInputDef({
164
164
  header: 'Flo Date With Time',
165
165
  id: 'floDateWithTime',
166
- isEditable: () => Promise.resolve(true),
166
+ isEditable: () => true,
167
167
  defaultHidden: true,
168
168
  showTime: true,
169
169
  isValid,
@@ -194,7 +194,7 @@ export function generateExampleItemColumnDefs(modal) {
194
194
  ];
195
195
  },
196
196
  getDisplayValue: (item) => item.someSelect,
197
- isEditable: () => Promise.resolve(true),
197
+ isEditable: () => true,
198
198
  isValid,
199
199
  }),
200
200
  new BubbleDef({
@@ -17,7 +17,7 @@ export interface ColumnDefProps<T extends object, in FilterFnType, out OptionsTy
17
17
  defaultHidden?: boolean;
18
18
  minSize?: Pixels;
19
19
  width?: Pixels;
20
- isEditable?: (item: T, index: number) => Promise<boolean>;
20
+ isEditable?: (item: T, index: number) => boolean | Promise<boolean>;
21
21
  resizable?: boolean;
22
22
  isValid?: ValidationFn<T>;
23
23
  filterFn?: FilterFn<T, FilterFnType>;
@@ -57,7 +57,7 @@ export declare abstract class ColumnDef<T extends object, in FilterFnType = neve
57
57
  set filterValueType(v: FilterValueType | undefined);
58
58
  readonly getDisplayValue: ((item: T, index: number) => string | null | Promise<string | null>) | undefined;
59
59
  toJSON(): ColumnJSONRepresentation;
60
- readonly isEditable: (item: T, index: number) => Promise<boolean>;
60
+ readonly isEditable: (item: T, index: number) => boolean | Promise<boolean>;
61
61
  readonly resizable: boolean;
62
62
  readonly header: string | Snippet;
63
63
  readonly getOptions?: () => Array<SelectOption<OptionsType>> | Promise<Array<SelectOption<OptionsType>>>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lavalogic/scoria",
3
3
  "description": "Svelte components used for the FloWMS Web Frontend",
4
- "version": "0.25.0",
4
+ "version": "0.25.2",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },