@lavalogic/scoria 0.37.23 → 0.37.25
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.
|
@@ -24,6 +24,37 @@
|
|
|
24
24
|
cell.column.columnDef.getDisplayValue?.(cell.row.original, cell.row.originalIndex) ?? value
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
+
/** For Date-typed display columns, expose both the local-time and UTC
|
|
28
|
+
* representations of the raw accessor value as a multi-line tooltip.
|
|
29
|
+
* The cell's body shows the locale-formatted value (via
|
|
30
|
+
* `getDisplayValue`); the title attribute below lets users hover to
|
|
31
|
+
* see Local + UTC side-by-side without expanding the column. */
|
|
32
|
+
const dateTooltip: string | undefined = $derived.by(() => {
|
|
33
|
+
if (cell.column.columnDef.filterValueType !== 'Date') {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
if (value == null || value === '' || value instanceof Promise) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
let d: Date | undefined;
|
|
40
|
+
if (value instanceof Date) {
|
|
41
|
+
d = value;
|
|
42
|
+
} else if (typeof value === 'string' || typeof value === 'number') {
|
|
43
|
+
const parsed = new Date(value);
|
|
44
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
45
|
+
d = parsed;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (d == null) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
// Use `toLocaleString` for both lines so the visual format matches
|
|
52
|
+
// (only the time zone differs). The `timeZone: 'UTC'` override on
|
|
53
|
+
// the second call renders the same date / time but reinterpreted
|
|
54
|
+
// in UTC, which is what the user expects to see on hover.
|
|
55
|
+
return `Local: ${d.toLocaleString()}\nUTC: ${d.toLocaleString(undefined, { timeZone: 'UTC' })}`;
|
|
56
|
+
});
|
|
57
|
+
|
|
27
58
|
const tableContext = getContext<TableContext<T, RowIdType>>(TableContext.identifier);
|
|
28
59
|
|
|
29
60
|
const options: Array<SelectOption<unknown>> = $derived(
|
|
@@ -106,6 +137,7 @@
|
|
|
106
137
|
class:has-modal={!!modalComponent}
|
|
107
138
|
tabIndex={hasValue ? 0 : undefined}
|
|
108
139
|
class="focusable"
|
|
140
|
+
title={dateTooltip}
|
|
109
141
|
style={focusDetails.outline}
|
|
110
142
|
class:multifocus={hasValue && focusDetails.isMultiFocused}
|
|
111
143
|
class:multifocus-start={hasValue && focusDetails.isMultiFocusStart}
|
|
@@ -325,26 +325,33 @@ export function createColumnFactory() {
|
|
|
325
325
|
: opts.filterValueType === 'String'
|
|
326
326
|
? 'text'
|
|
327
327
|
: 'display';
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
328
|
+
// For Date-typed display columns, leave the accessor returning
|
|
329
|
+
// the raw Date / ISO string (filter / sort logic still operates
|
|
330
|
+
// on the raw value) and surface the formatted local-time
|
|
331
|
+
// string via `getDisplayValue`. The cell renders
|
|
332
|
+
// `getDisplayValue` for visible text and reads the raw value
|
|
333
|
+
// from `accessorFn` to compose the hover tooltip showing both
|
|
334
|
+
// the local-time and UTC representations.
|
|
334
335
|
const rawValue = opts.value;
|
|
335
|
-
const valueAccessor =
|
|
336
|
+
const valueAccessor = rawValue;
|
|
337
|
+
const dateDisplayValue = opts.filterValueType === 'Date'
|
|
336
338
|
? (row, index) => {
|
|
337
339
|
const v = rawValue(row, index);
|
|
338
340
|
if (v instanceof Promise) {
|
|
339
|
-
return v.then(
|
|
341
|
+
return v.then((resolved) => {
|
|
342
|
+
const formatted = formatLocaleDate(resolved);
|
|
343
|
+
return formatted == null ? null : String(formatted);
|
|
344
|
+
});
|
|
340
345
|
}
|
|
341
|
-
|
|
346
|
+
const formatted = formatLocaleDate(v);
|
|
347
|
+
return formatted == null ? null : String(formatted);
|
|
342
348
|
}
|
|
343
|
-
:
|
|
349
|
+
: undefined;
|
|
344
350
|
const def = new DisplayDef({
|
|
345
351
|
id,
|
|
346
352
|
...commonProps(opts, inferredKind),
|
|
347
353
|
accessorFn: valueAccessor,
|
|
354
|
+
getDisplayValue: dateDisplayValue,
|
|
348
355
|
modal: opts.modal,
|
|
349
356
|
// Display columns have no implicit filter type (unlike the
|
|
350
357
|
// typed kinds where the factory pins one based on the
|
|
@@ -146,6 +146,10 @@ export function attachDropdownPortal(options) {
|
|
|
146
146
|
}
|
|
147
147
|
originalParent = dropdown.parentNode;
|
|
148
148
|
originalNextSibling = dropdown.nextSibling;
|
|
149
|
+
// Clear any `display: none` left over from a previous portalIn
|
|
150
|
+
// (see the defensive hide there) so the dropdown is visible
|
|
151
|
+
// once teleported into the new host.
|
|
152
|
+
dropdown.style.display = '';
|
|
149
153
|
// Append the dropdown to the nearest open native `<dialog>` ancestor
|
|
150
154
|
// when one exists, otherwise to `document.body`. A `<dialog>` opened
|
|
151
155
|
// via `showModal()` renders in the browser's top layer, which sits
|
|
@@ -200,6 +204,18 @@ export function attachDropdownPortal(options) {
|
|
|
200
204
|
dropdown.style.maxHeight = '';
|
|
201
205
|
dropdown.style.zIndex = '';
|
|
202
206
|
dropdown.removeAttribute('data-scoria-portal-dropdown');
|
|
207
|
+
// Defensive: if Svelecte left the dropdown without its own
|
|
208
|
+
// `display: none` (e.g. on certain transition-cancel race paths
|
|
209
|
+
// the open/close class flip and the inline style update arrive
|
|
210
|
+
// out of order), the dropdown would now be `position: static;
|
|
211
|
+
// display: block` in `document.body` and contribute its option
|
|
212
|
+
// list's height to the body scroll size - which is what surfaces
|
|
213
|
+
// as a stray page-level vertical scrollbar after toggling a
|
|
214
|
+
// select. Force `display: none` here; Svelecte will restore the
|
|
215
|
+
// inline style on next open via its own class-driven render.
|
|
216
|
+
if (!dropdown.classList.contains('is-open')) {
|
|
217
|
+
dropdown.style.display = 'none';
|
|
218
|
+
}
|
|
203
219
|
if (originalParent != null) {
|
|
204
220
|
if (originalNextSibling != null && originalNextSibling.parentNode === originalParent) {
|
|
205
221
|
originalParent.insertBefore(dropdown, originalNextSibling);
|