runeforge 0.0.49 → 0.0.51
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.
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
async function navList() {
|
|
143
|
-
await goto('?');
|
|
143
|
+
await goto(lastListState.search || '?');
|
|
144
144
|
}
|
|
145
145
|
async function navCreate() {
|
|
146
146
|
await goto('?view=create');
|
|
@@ -154,15 +154,22 @@
|
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
let lastListState = $state<{ data: T[]; search: string }>({ data: [], search: '' });
|
|
158
|
+
$effect(() => {
|
|
159
|
+
if (!creating && !reading && !editing) {
|
|
160
|
+
lastListState = { data: entityData, search: page.url.search };
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
157
164
|
// "Save and continue" on the Update form: jumps to editing the record that
|
|
158
|
-
// follows the current one in the
|
|
165
|
+
// follows the current one in the last loaded list, falling back to
|
|
159
166
|
// re-editing the same instance when it's the last one (or isn't found).
|
|
160
167
|
function nextInstance(current: T): T {
|
|
161
168
|
const currentId = (current as Record<string, unknown>)[idKey];
|
|
162
|
-
const idx =
|
|
169
|
+
const idx = lastListState.data.findIndex(
|
|
163
170
|
(item) => (item as Record<string, unknown>)[idKey] === currentId
|
|
164
171
|
);
|
|
165
|
-
return (idx !== -1 ?
|
|
172
|
+
return (idx !== -1 ? lastListState.data[idx + 1] : undefined) ?? current;
|
|
166
173
|
}
|
|
167
174
|
async function navContinueEdit() {
|
|
168
175
|
if (!singleInstance) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const formatBoolean: (trueLabel?: string, falseLabel?: string) => () => (value: boolean) => string;
|
|
2
|
-
export declare const formatDatetime: (format?: string) => (() => (value: Date) => string);
|
|
2
|
+
export declare const formatDatetime: (format?: string, timeZone?: string) => (() => (value: Date) => string);
|
|
3
3
|
export declare function formatTruncateTextUpTo(maxLength: number): () => (value: string) => string;
|
|
4
4
|
export declare function formatInstance<T extends Record<string, unknown>>(attribute: keyof T & string, instances: T[], urlPath: string, idKey?: keyof T & string): (value: unknown) => string;
|
|
@@ -8,7 +8,36 @@ const TOKENS = {
|
|
|
8
8
|
MM: (d) => String(d.getMinutes()).padStart(2, '0'),
|
|
9
9
|
ss: (d) => String(d.getSeconds()).padStart(2, '0')
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
// Same tokens, read from Intl.DateTimeFormat parts instead of local Date
|
|
12
|
+
// getters, so the result depends only on `timeZone` — never on the
|
|
13
|
+
// environment (SSR host vs. browser) running the code.
|
|
14
|
+
function tokensFor(d, timeZone) {
|
|
15
|
+
const parts = new Intl.DateTimeFormat('en-US', {
|
|
16
|
+
timeZone,
|
|
17
|
+
year: 'numeric',
|
|
18
|
+
month: '2-digit',
|
|
19
|
+
day: '2-digit',
|
|
20
|
+
hour: '2-digit',
|
|
21
|
+
minute: '2-digit',
|
|
22
|
+
second: '2-digit',
|
|
23
|
+
hourCycle: 'h23'
|
|
24
|
+
}).formatToParts(d);
|
|
25
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? '';
|
|
26
|
+
return {
|
|
27
|
+
dd: get('day'),
|
|
28
|
+
mm: get('month'),
|
|
29
|
+
YYYY: get('year'),
|
|
30
|
+
HH: get('hour'),
|
|
31
|
+
MM: get('minute'),
|
|
32
|
+
ss: get('second')
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// `timeZone` is an IANA zone name (e.g. 'America/Argentina/Buenos_Aires').
|
|
36
|
+
// Omit it to keep formatting in whichever timezone the running environment
|
|
37
|
+
// is in — this differs between SSR (server) and CSR (browser) and will
|
|
38
|
+
// render the same instant differently depending on where it runs, so pass
|
|
39
|
+
// an explicit `timeZone` for any value that must display consistently.
|
|
40
|
+
export const formatDatetime = (format = 'dd/mm/YYYY HH:MM', timeZone) => {
|
|
12
41
|
const fmt = (value) => {
|
|
13
42
|
// `null`/`undefined`/`''` (an unset field) must render blank, not epoch 0
|
|
14
43
|
// — `new Date(null)` is 1970-01-01, a "valid" Date whose getTime() isn't
|
|
@@ -18,7 +47,8 @@ export const formatDatetime = (format = 'dd/mm/YYYY HH:MM') => {
|
|
|
18
47
|
const d = new Date(value);
|
|
19
48
|
if (isNaN(d.getTime()))
|
|
20
49
|
return '';
|
|
21
|
-
|
|
50
|
+
const tokens = timeZone ? tokensFor(d, timeZone) : null;
|
|
51
|
+
return format.replace(/dd|mm|YYYY|HH|MM|ss/g, (token) => tokens ? tokens[token] : TOKENS[token](d));
|
|
22
52
|
};
|
|
23
53
|
return () => fmt;
|
|
24
54
|
};
|