@fieldia/core 0.23.0 → 0.25.0
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.
- package/README.md +211 -3
- package/package.json +1 -1
- package/schema/page.schema.json +1051 -325
- package/src/index.d.mts +9 -2
- package/src/index.d.ts +9 -2
- package/src/index.js +31 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +12 -2
- package/src/index.mjs.map +1 -1
- package/src/lib/format/actions.d.mts +31 -1
- package/src/lib/format/actions.d.ts +31 -1
- package/src/lib/format/actions.js +1 -0
- package/src/lib/format/actions.js.map +1 -1
- package/src/lib/format/actions.mjs +1 -0
- package/src/lib/format/actions.mjs.map +1 -1
- package/src/lib/format/autofill-group.d.mts +12 -0
- package/src/lib/format/autofill-group.d.ts +12 -0
- package/src/lib/format/autofill-group.js +23 -0
- package/src/lib/format/autofill-group.js.map +1 -0
- package/src/lib/format/autofill-group.mjs +19 -0
- package/src/lib/format/autofill-group.mjs.map +1 -0
- package/src/lib/format/autofill.d.mts +14 -0
- package/src/lib/format/autofill.d.ts +14 -0
- package/src/lib/format/autofill.js +54 -0
- package/src/lib/format/autofill.js.map +1 -0
- package/src/lib/format/autofill.mjs +48 -0
- package/src/lib/format/autofill.mjs.map +1 -0
- package/src/lib/format/bulk-edit.d.mts +18 -0
- package/src/lib/format/bulk-edit.d.ts +18 -0
- package/src/lib/format/bulk-edit.js +26 -0
- package/src/lib/format/bulk-edit.js.map +1 -0
- package/src/lib/format/bulk-edit.mjs +21 -0
- package/src/lib/format/bulk-edit.mjs.map +1 -0
- package/src/lib/format/duplicate-kinds.d.mts +10 -0
- package/src/lib/format/duplicate-kinds.d.ts +10 -0
- package/src/lib/format/duplicate-kinds.js +14 -0
- package/src/lib/format/duplicate-kinds.js.map +1 -0
- package/src/lib/format/duplicate-kinds.mjs +10 -0
- package/src/lib/format/duplicate-kinds.mjs.map +1 -0
- package/src/lib/format/duplicates.d.mts +22 -0
- package/src/lib/format/duplicates.d.ts +22 -0
- package/src/lib/format/duplicates.js +24 -0
- package/src/lib/format/duplicates.js.map +1 -0
- package/src/lib/format/duplicates.mjs +21 -0
- package/src/lib/format/duplicates.mjs.map +1 -0
- package/src/lib/format/field.d.mts +291 -34
- package/src/lib/format/field.d.ts +291 -34
- package/src/lib/format/field.js +19 -4
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +17 -2
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/import-fields.d.mts +18 -0
- package/src/lib/format/import-fields.d.ts +18 -0
- package/src/lib/format/import-fields.js +26 -0
- package/src/lib/format/import-fields.js.map +1 -0
- package/src/lib/format/import-fields.mjs +21 -0
- package/src/lib/format/import-fields.mjs.map +1 -0
- package/src/lib/format/layout.d.mts +7357 -3127
- package/src/lib/format/layout.d.ts +7357 -3127
- package/src/lib/format/layout.js +108 -32
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +107 -32
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/layout.types.d.mts +5 -2
- package/src/lib/format/layout.types.d.ts +5 -2
- package/src/lib/format/page.d.mts +1080 -106
- package/src/lib/format/page.d.ts +1080 -106
- package/src/lib/format/page.js +25 -0
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +26 -1
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/phone.d.mts +27 -0
- package/src/lib/format/phone.d.ts +27 -0
- package/src/lib/format/phone.js +43 -0
- package/src/lib/format/phone.js.map +1 -0
- package/src/lib/format/phone.mjs +39 -0
- package/src/lib/format/phone.mjs.map +1 -0
- package/src/lib/format/references.d.mts +39 -0
- package/src/lib/format/references.d.ts +39 -0
- package/src/lib/format/references.js +263 -20
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +263 -20
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/slots-options.d.mts +26 -0
- package/src/lib/format/slots-options.d.ts +26 -0
- package/src/lib/format/slots-options.js +35 -0
- package/src/lib/format/slots-options.js.map +1 -0
- package/src/lib/format/slots-options.mjs +31 -0
- package/src/lib/format/slots-options.mjs.map +1 -0
- package/src/lib/format/translate.js +8 -4
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +8 -4
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/format/upgrade.d.mts +8 -3
- package/src/lib/format/upgrade.d.ts +8 -3
- package/src/lib/format/upgrade.js +8 -3
- package/src/lib/format/upgrade.js.map +1 -1
- package/src/lib/format/upgrade.mjs +8 -3
- package/src/lib/format/upgrade.mjs.map +1 -1
- package/src/lib/format/version.d.mts +2 -2
- package/src/lib/format/version.d.ts +2 -2
- package/src/lib/format/version.js +2 -2
- package/src/lib/format/version.js.map +1 -1
- package/src/lib/format/version.mjs +2 -2
- package/src/lib/format/version.mjs.map +1 -1
- package/src/lib/format/zoned.d.mts +8 -0
- package/src/lib/format/zoned.d.ts +8 -0
- package/src/lib/format/zoned.js +36 -0
- package/src/lib/format/zoned.js.map +1 -0
- package/src/lib/format/zoned.mjs +33 -0
- package/src/lib/format/zoned.mjs.map +1 -0
- package/src/lib/record/check.d.mts +6 -1
- package/src/lib/record/check.d.ts +6 -1
- package/src/lib/record/check.js +12 -4
- package/src/lib/record/check.js.map +1 -1
- package/src/lib/record/check.mjs +12 -4
- package/src/lib/record/check.mjs.map +1 -1
- package/src/lib/record/data-source.d.mts +309 -3
- package/src/lib/record/data-source.d.ts +309 -3
- package/src/lib/record/data-source.js +16 -0
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs +15 -0
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/form.d.mts +116 -25
- package/src/lib/record/form.d.ts +116 -25
- package/src/lib/record/form.js +457 -78
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +457 -78
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/input-rules.d.mts +51 -9
- package/src/lib/record/input-rules.d.ts +51 -9
- package/src/lib/record/input-rules.js +119 -20
- package/src/lib/record/input-rules.js.map +1 -1
- package/src/lib/record/input-rules.mjs +118 -19
- package/src/lib/record/input-rules.mjs.map +1 -1
- package/src/lib/record/inputs.js +4 -2
- package/src/lib/record/inputs.js.map +1 -1
- package/src/lib/record/inputs.mjs +4 -2
- package/src/lib/record/inputs.mjs.map +1 -1
- package/src/lib/record/limits.d.mts +1 -1
- package/src/lib/record/limits.d.ts +1 -1
- package/src/lib/record/limits.js +4 -2
- package/src/lib/record/limits.js.map +1 -1
- package/src/lib/record/limits.mjs +4 -2
- package/src/lib/record/limits.mjs.map +1 -1
- package/src/lib/record/locales/ar.js +3 -2
- package/src/lib/record/locales/ar.js.map +1 -1
- package/src/lib/record/locales/ar.mjs +3 -2
- package/src/lib/record/locales/ar.mjs.map +1 -1
- package/src/lib/record/locales/de.js +3 -2
- package/src/lib/record/locales/de.js.map +1 -1
- package/src/lib/record/locales/de.mjs +3 -2
- package/src/lib/record/locales/de.mjs.map +1 -1
- package/src/lib/record/locales/fr.js +3 -2
- package/src/lib/record/locales/fr.js.map +1 -1
- package/src/lib/record/locales/fr.mjs +3 -2
- package/src/lib/record/locales/fr.mjs.map +1 -1
- package/src/lib/record/memory-data-source.d.mts +20 -2
- package/src/lib/record/memory-data-source.d.ts +20 -2
- package/src/lib/record/memory-data-source.js +153 -35
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +154 -36
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/memory-duplicates.d.mts +19 -0
- package/src/lib/record/memory-duplicates.d.ts +19 -0
- package/src/lib/record/memory-duplicates.js +78 -0
- package/src/lib/record/memory-duplicates.js.map +1 -0
- package/src/lib/record/memory-duplicates.mjs +74 -0
- package/src/lib/record/memory-duplicates.mjs.map +1 -0
- package/src/lib/record/memory-schedules.d.mts +45 -0
- package/src/lib/record/memory-schedules.d.ts +45 -0
- package/src/lib/record/memory-schedules.js +81 -0
- package/src/lib/record/memory-schedules.js.map +1 -0
- package/src/lib/record/memory-schedules.mjs +78 -0
- package/src/lib/record/memory-schedules.mjs.map +1 -0
- package/src/lib/record/messages.d.mts +3 -1
- package/src/lib/record/messages.d.ts +3 -1
- package/src/lib/record/messages.js +3 -2
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +3 -2
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/periods.d.mts +47 -0
- package/src/lib/record/periods.d.ts +47 -0
- package/src/lib/record/periods.js +86 -0
- package/src/lib/record/periods.js.map +1 -0
- package/src/lib/record/periods.mjs +79 -0
- package/src/lib/record/periods.mjs.map +1 -0
- package/src/lib/record/rules.js +5 -6
- package/src/lib/record/rules.js.map +1 -1
- package/src/lib/record/rules.mjs +5 -6
- package/src/lib/record/rules.mjs.map +1 -1
- package/src/lib/record/run.d.mts +75 -9
- package/src/lib/record/run.d.ts +75 -9
- package/src/lib/record/run.js +169 -26
- package/src/lib/record/run.js.map +1 -1
- package/src/lib/record/run.mjs +170 -27
- package/src/lib/record/run.mjs.map +1 -1
- package/src/lib/record/search.d.mts +13 -3
- package/src/lib/record/search.d.ts +13 -3
- package/src/lib/record/search.js +11 -4
- package/src/lib/record/search.js.map +1 -1
- package/src/lib/record/search.mjs +11 -4
- package/src/lib/record/search.mjs.map +1 -1
- package/src/lib/record/waits.d.mts +32 -0
- package/src/lib/record/waits.d.ts +32 -0
- package/src/lib/record/waits.js +89 -0
- package/src/lib/record/waits.js.map +1 -0
- package/src/lib/record/waits.mjs +85 -0
- package/src/lib/record/waits.mjs.map +1 -0
- package/src/lib/record/zones.d.mts +57 -0
- package/src/lib/record/zones.d.ts +57 -0
- package/src/lib/record/zones.js +147 -0
- package/src/lib/record/zones.js.map +1 -0
- package/src/lib/record/zones.mjs +132 -0
- package/src/lib/record/zones.mjs.map +1 -0
- package/src/runtime.d.mts +19 -9
- package/src/runtime.d.ts +19 -9
- package/src/runtime.js +37 -2
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +9 -2
- package/src/runtime.mjs.map +1 -1
|
@@ -58,8 +58,12 @@ export function suggestions(typed, page, list, words = { searchFor: 'Search {fie
|
|
|
58
58
|
};
|
|
59
59
|
return found.map((s, i) => ({ s, i })).sort((a, b) => rank(a.s) - rank(b.s) || a.i - b.i).map(({ s }) => s);
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
62
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The filter a list's facets make: the values of one field any of them, named filters any of them, the facets all
|
|
63
|
+
* together. A period — a named filter's, a custom filter's — is counted by `periods`, as the list counts days (its
|
|
64
|
+
* clock, its week, its time zone); a custom filter without it keeps what it was counted as.
|
|
65
|
+
*/
|
|
66
|
+
export function facetsToFilter(facets, list, periods) {
|
|
63
67
|
const filter = [];
|
|
64
68
|
for (const facet of facets) {
|
|
65
69
|
if (facet.kind === 'field') {
|
|
@@ -68,14 +72,17 @@ export function facetsToFilter(facets, list) {
|
|
|
68
72
|
}
|
|
69
73
|
else if (facet.kind === 'filters') {
|
|
70
74
|
// A list's own filters have no valueFrom: their conditions are already values.
|
|
71
|
-
const chosen = facet.ids
|
|
75
|
+
const chosen = facet.ids
|
|
76
|
+
.map((id) => list.filters?.find((f) => f.id === id))
|
|
77
|
+
.map((named) => [...(named?.filter ?? []), ...(named?.period && periods ? periods(named.period) : [])])
|
|
78
|
+
.filter((items) => items.length);
|
|
72
79
|
if (chosen.length === 1)
|
|
73
80
|
filter.push(...chosen[0]);
|
|
74
81
|
else if (chosen.length > 1)
|
|
75
82
|
filter.push({ any: chosen.map((items) => (items.length === 1 ? items[0] : { all: items })) });
|
|
76
83
|
}
|
|
77
84
|
else if (facet.kind === 'custom') {
|
|
78
|
-
filter.push(...facet.filter);
|
|
85
|
+
filter.push(...(facet.period && periods ? periods(facet.period) : facet.filter));
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
88
|
return filter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/search.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"search.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Page } from '../format/page.mjs';
|
|
2
|
+
import type { UnreadText } from './form.mjs';
|
|
3
|
+
import { type Values } from './values.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* What a value worked out from others waits for, while one of them holds text that does not read: the field, and on
|
|
6
|
+
* a table of lines the line — numbered as people count lines, sections and notes not counted — and its cell.
|
|
7
|
+
*/
|
|
8
|
+
export interface WaitsFor {
|
|
9
|
+
/** The field holding the text, or the table whose line holds it. */
|
|
10
|
+
readonly field: string;
|
|
11
|
+
/** The line, from 1: items only. Left out for a field of the record's own. */
|
|
12
|
+
readonly line?: number;
|
|
13
|
+
/** The line's cell holding the text. */
|
|
14
|
+
readonly column?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Which fields of a page each of its values worked out from others is worked out from — what it waits for while one
|
|
18
|
+
* of them holds text that does not read, as a number worked out on a line waits for its line's cells and the table's
|
|
19
|
+
* total for its lines (0.24). The page's own `compute`: the fields it reads, and what each of those it reads that is
|
|
20
|
+
* worked out reads in turn — a sum over a table's lines waits for those lines. The app's (`appWorksOut`, a source
|
|
21
|
+
* with an onchange): an amount no one types in (read-only), which the app works out as the lines change, from any
|
|
22
|
+
* table of lines the page has — a sales order's Untaxed, Taxes and Total, its tax totals. A line's own form (`asLine`:
|
|
23
|
+
* a line opened in its dialog) is the line the table's rule reads: a number on it no one types in waits for any of
|
|
24
|
+
* its fields a person types in, as its cell in the table does. Fields worked out from nothing that can hold such text
|
|
25
|
+
* are left out.
|
|
26
|
+
*/
|
|
27
|
+
export declare function workedOutFrom(page: Page, appWorksOut: boolean, asLine?: boolean): Map<string, readonly string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* The first of `from` holding text that does not read, in the page's order: a field's own, or a table's line's cell
|
|
30
|
+
* (the first line holding one, as people count lines). Null when none does.
|
|
31
|
+
*/
|
|
32
|
+
export declare function waitingOn(page: Page, from: readonly string[], values: Readonly<Values>, unread: Readonly<Record<string, UnreadText>>): WaitsFor | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Page } from '../format/page';
|
|
2
|
+
import type { UnreadText } from './form';
|
|
3
|
+
import { type Values } from './values';
|
|
4
|
+
/**
|
|
5
|
+
* What a value worked out from others waits for, while one of them holds text that does not read: the field, and on
|
|
6
|
+
* a table of lines the line — numbered as people count lines, sections and notes not counted — and its cell.
|
|
7
|
+
*/
|
|
8
|
+
export interface WaitsFor {
|
|
9
|
+
/** The field holding the text, or the table whose line holds it. */
|
|
10
|
+
readonly field: string;
|
|
11
|
+
/** The line, from 1: items only. Left out for a field of the record's own. */
|
|
12
|
+
readonly line?: number;
|
|
13
|
+
/** The line's cell holding the text. */
|
|
14
|
+
readonly column?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Which fields of a page each of its values worked out from others is worked out from — what it waits for while one
|
|
18
|
+
* of them holds text that does not read, as a number worked out on a line waits for its line's cells and the table's
|
|
19
|
+
* total for its lines (0.24). The page's own `compute`: the fields it reads, and what each of those it reads that is
|
|
20
|
+
* worked out reads in turn — a sum over a table's lines waits for those lines. The app's (`appWorksOut`, a source
|
|
21
|
+
* with an onchange): an amount no one types in (read-only), which the app works out as the lines change, from any
|
|
22
|
+
* table of lines the page has — a sales order's Untaxed, Taxes and Total, its tax totals. A line's own form (`asLine`:
|
|
23
|
+
* a line opened in its dialog) is the line the table's rule reads: a number on it no one types in waits for any of
|
|
24
|
+
* its fields a person types in, as its cell in the table does. Fields worked out from nothing that can hold such text
|
|
25
|
+
* are left out.
|
|
26
|
+
*/
|
|
27
|
+
export declare function workedOutFrom(page: Page, appWorksOut: boolean, asLine?: boolean): Map<string, readonly string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* The first of `from` holding text that does not read, in the page's order: a field's own, or a table's line's cell
|
|
30
|
+
* (the first line holding one, as people count lines). Null when none does.
|
|
31
|
+
*/
|
|
32
|
+
export declare function waitingOn(page: Page, from: readonly string[], values: Readonly<Values>, unread: Readonly<Record<string, UnreadText>>): WaitsFor | null;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.workedOutFrom = workedOutFrom;
|
|
4
|
+
exports.waitingOn = waitingOn;
|
|
5
|
+
const expression_1 = require("../expression/expression");
|
|
6
|
+
const values_1 = require("./values");
|
|
7
|
+
/** Kinds of value an app works out from a record's lines: amounts, and totals kept whole (Flectra's tax_totals). */
|
|
8
|
+
const WORKED_OUT = new Set(['integer', 'float', 'monetary', 'json']);
|
|
9
|
+
/** The numbers a line works out, which wait for its cells (0.24's rule for a table's cells). */
|
|
10
|
+
const NUMBERS = new Set(['integer', 'float', 'monetary']);
|
|
11
|
+
/**
|
|
12
|
+
* Which fields of a page each of its values worked out from others is worked out from — what it waits for while one
|
|
13
|
+
* of them holds text that does not read, as a number worked out on a line waits for its line's cells and the table's
|
|
14
|
+
* total for its lines (0.24). The page's own `compute`: the fields it reads, and what each of those it reads that is
|
|
15
|
+
* worked out reads in turn — a sum over a table's lines waits for those lines. The app's (`appWorksOut`, a source
|
|
16
|
+
* with an onchange): an amount no one types in (read-only), which the app works out as the lines change, from any
|
|
17
|
+
* table of lines the page has — a sales order's Untaxed, Taxes and Total, its tax totals. A line's own form (`asLine`:
|
|
18
|
+
* a line opened in its dialog) is the line the table's rule reads: a number on it no one types in waits for any of
|
|
19
|
+
* its fields a person types in, as its cell in the table does. Fields worked out from nothing that can hold such text
|
|
20
|
+
* are left out.
|
|
21
|
+
*/
|
|
22
|
+
function workedOutFrom(page, appWorksOut, asLine = false) {
|
|
23
|
+
const tables = Object.keys(page.fields).filter((name) => page.fields[name].type === 'one2many');
|
|
24
|
+
const typed = Object.keys(page.fields).filter((name) => page.fields[name].readonly !== true && page.fields[name].compute === undefined);
|
|
25
|
+
const reads = new Map();
|
|
26
|
+
for (const [name, def] of Object.entries(page.fields)) {
|
|
27
|
+
if (def.type === 'one2many')
|
|
28
|
+
continue;
|
|
29
|
+
if (asLine && NUMBERS.has(def.type) && (def.readonly === true || def.compute !== undefined))
|
|
30
|
+
reads.set(name, typed);
|
|
31
|
+
else if (def.compute !== undefined) {
|
|
32
|
+
try {
|
|
33
|
+
reads.set(name, (0, expression_1.compileExpression)(def.compute).fields.filter((one) => one !== name && one in page.fields));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// An expression that does not read is refused by the page's checks; it works nothing out here.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (appWorksOut && def.readonly === true && WORKED_OUT.has(def.type) && tables.length)
|
|
40
|
+
reads.set(name, tables);
|
|
41
|
+
}
|
|
42
|
+
const found = new Map();
|
|
43
|
+
/** What a value is worked out from, read through the values worked out it reads. */
|
|
44
|
+
const sources = (name, seen) => {
|
|
45
|
+
seen.add(name);
|
|
46
|
+
const all = (reads.get(name) ?? []).flatMap((one) => (seen.has(one) ? [] : [one, ...(reads.has(one) ? sources(one, seen) : [])]));
|
|
47
|
+
return [...new Set(all)];
|
|
48
|
+
};
|
|
49
|
+
// What holds text a person typed: a field they type in, or a table's lines — never a value worked out.
|
|
50
|
+
for (const name of reads.keys()) {
|
|
51
|
+
const from = sources(name, new Set()).filter((one) => !reads.has(one));
|
|
52
|
+
if (from.length)
|
|
53
|
+
found.set(name, from);
|
|
54
|
+
}
|
|
55
|
+
return found;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The first of `from` holding text that does not read, in the page's order: a field's own, or a table's line's cell
|
|
59
|
+
* (the first line holding one, as people count lines). Null when none does.
|
|
60
|
+
*/
|
|
61
|
+
function waitingOn(page, from, values, unread) {
|
|
62
|
+
const paths = Object.keys(unread);
|
|
63
|
+
if (!paths.length)
|
|
64
|
+
return null;
|
|
65
|
+
for (const field of from) {
|
|
66
|
+
const def = page.fields[field];
|
|
67
|
+
if (!def)
|
|
68
|
+
continue;
|
|
69
|
+
if (def.type !== 'one2many') {
|
|
70
|
+
if (unread[field])
|
|
71
|
+
return { field };
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const held = paths.filter((path) => path.startsWith(`${field}.`));
|
|
75
|
+
if (!held.length)
|
|
76
|
+
continue;
|
|
77
|
+
let n = 0;
|
|
78
|
+
for (const line of values[field] ?? []) {
|
|
79
|
+
if ((0, values_1.lineKind)(def, line.values) !== null)
|
|
80
|
+
continue;
|
|
81
|
+
n++;
|
|
82
|
+
const cell = held.find((path) => path.startsWith(`${field}.${line.key}.`));
|
|
83
|
+
if (cell)
|
|
84
|
+
return { field, line: n, column: cell.slice(field.length + line.key.length + 2).split('.')[0] };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=waits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waits.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/waits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { compileExpression } from '../expression/expression.mjs';
|
|
2
|
+
import { lineKind } from './values.mjs';
|
|
3
|
+
/** Kinds of value an app works out from a record's lines: amounts, and totals kept whole (Flectra's tax_totals). */
|
|
4
|
+
const WORKED_OUT = new Set(['integer', 'float', 'monetary', 'json']);
|
|
5
|
+
/** The numbers a line works out, which wait for its cells (0.24's rule for a table's cells). */
|
|
6
|
+
const NUMBERS = new Set(['integer', 'float', 'monetary']);
|
|
7
|
+
/**
|
|
8
|
+
* Which fields of a page each of its values worked out from others is worked out from — what it waits for while one
|
|
9
|
+
* of them holds text that does not read, as a number worked out on a line waits for its line's cells and the table's
|
|
10
|
+
* total for its lines (0.24). The page's own `compute`: the fields it reads, and what each of those it reads that is
|
|
11
|
+
* worked out reads in turn — a sum over a table's lines waits for those lines. The app's (`appWorksOut`, a source
|
|
12
|
+
* with an onchange): an amount no one types in (read-only), which the app works out as the lines change, from any
|
|
13
|
+
* table of lines the page has — a sales order's Untaxed, Taxes and Total, its tax totals. A line's own form (`asLine`:
|
|
14
|
+
* a line opened in its dialog) is the line the table's rule reads: a number on it no one types in waits for any of
|
|
15
|
+
* its fields a person types in, as its cell in the table does. Fields worked out from nothing that can hold such text
|
|
16
|
+
* are left out.
|
|
17
|
+
*/
|
|
18
|
+
export function workedOutFrom(page, appWorksOut, asLine = false) {
|
|
19
|
+
const tables = Object.keys(page.fields).filter((name) => page.fields[name].type === 'one2many');
|
|
20
|
+
const typed = Object.keys(page.fields).filter((name) => page.fields[name].readonly !== true && page.fields[name].compute === undefined);
|
|
21
|
+
const reads = new Map();
|
|
22
|
+
for (const [name, def] of Object.entries(page.fields)) {
|
|
23
|
+
if (def.type === 'one2many')
|
|
24
|
+
continue;
|
|
25
|
+
if (asLine && NUMBERS.has(def.type) && (def.readonly === true || def.compute !== undefined))
|
|
26
|
+
reads.set(name, typed);
|
|
27
|
+
else if (def.compute !== undefined) {
|
|
28
|
+
try {
|
|
29
|
+
reads.set(name, compileExpression(def.compute).fields.filter((one) => one !== name && one in page.fields));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// An expression that does not read is refused by the page's checks; it works nothing out here.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (appWorksOut && def.readonly === true && WORKED_OUT.has(def.type) && tables.length)
|
|
36
|
+
reads.set(name, tables);
|
|
37
|
+
}
|
|
38
|
+
const found = new Map();
|
|
39
|
+
/** What a value is worked out from, read through the values worked out it reads. */
|
|
40
|
+
const sources = (name, seen) => {
|
|
41
|
+
seen.add(name);
|
|
42
|
+
const all = (reads.get(name) ?? []).flatMap((one) => (seen.has(one) ? [] : [one, ...(reads.has(one) ? sources(one, seen) : [])]));
|
|
43
|
+
return [...new Set(all)];
|
|
44
|
+
};
|
|
45
|
+
// What holds text a person typed: a field they type in, or a table's lines — never a value worked out.
|
|
46
|
+
for (const name of reads.keys()) {
|
|
47
|
+
const from = sources(name, new Set()).filter((one) => !reads.has(one));
|
|
48
|
+
if (from.length)
|
|
49
|
+
found.set(name, from);
|
|
50
|
+
}
|
|
51
|
+
return found;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The first of `from` holding text that does not read, in the page's order: a field's own, or a table's line's cell
|
|
55
|
+
* (the first line holding one, as people count lines). Null when none does.
|
|
56
|
+
*/
|
|
57
|
+
export function waitingOn(page, from, values, unread) {
|
|
58
|
+
const paths = Object.keys(unread);
|
|
59
|
+
if (!paths.length)
|
|
60
|
+
return null;
|
|
61
|
+
for (const field of from) {
|
|
62
|
+
const def = page.fields[field];
|
|
63
|
+
if (!def)
|
|
64
|
+
continue;
|
|
65
|
+
if (def.type !== 'one2many') {
|
|
66
|
+
if (unread[field])
|
|
67
|
+
return { field };
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const held = paths.filter((path) => path.startsWith(`${field}.`));
|
|
71
|
+
if (!held.length)
|
|
72
|
+
continue;
|
|
73
|
+
let n = 0;
|
|
74
|
+
for (const line of values[field] ?? []) {
|
|
75
|
+
if (lineKind(def, line.values) !== null)
|
|
76
|
+
continue;
|
|
77
|
+
n++;
|
|
78
|
+
const cell = held.find((path) => path.startsWith(`${field}.${line.key}.`));
|
|
79
|
+
if (cell)
|
|
80
|
+
return { field, line: n, column: cell.slice(field.length + line.key.length + 2).split('.')[0] };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=waits.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waits.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/waits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time zones, by their IANA names ("Africa/Cairo", "Europe/Berlin"): a page's
|
|
3
|
+
* `timeZone`, or a date and time field's own. A date and time is kept as an
|
|
4
|
+
* instant (written in UTC, 2026-10-15T12:30:00.000Z, as Fieldia always kept
|
|
5
|
+
* one; an instant written with its offset is read the same) and shown, typed
|
|
6
|
+
* and counted by its day in its zone — the browser's own where none is named.
|
|
7
|
+
* Made from Intl alone, so no zone's rules are carried in the code.
|
|
8
|
+
*
|
|
9
|
+
* On a day the clocks change, a time on the clock may not exist (the hour they
|
|
10
|
+
* skip) or exist twice (the hour they repeat): `instantsAt` gives none, or
|
|
11
|
+
* both, and what reads a typed time says so — it is never moved in silence.
|
|
12
|
+
*/
|
|
13
|
+
/** A day and a time on the clock in some zone, to the minute. */
|
|
14
|
+
export interface WallTime {
|
|
15
|
+
year: number;
|
|
16
|
+
/** 1 to 12. */
|
|
17
|
+
month: number;
|
|
18
|
+
day: number;
|
|
19
|
+
hour: number;
|
|
20
|
+
minute: number;
|
|
21
|
+
}
|
|
22
|
+
/** Whether a name is a time zone the browser knows, by its IANA name: "Africa/Cairo", "UTC". Never an offset. */
|
|
23
|
+
export declare function isTimeZone(name: unknown): name is string;
|
|
24
|
+
/** The browser's own time zone, by its IANA name. */
|
|
25
|
+
export declare function ownZone(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether a zone keeps the browser's own clock: the same time through the year, in winter and summer — the browser's
|
|
28
|
+
* zone by any of its names ("Asia/Calcutta", "Asia/Kolkata"), or a neighbour on the same clock. Asked once a zone.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isOwnZone(zone: string): boolean;
|
|
31
|
+
/** The clock in `zone` at an instant (in ms), to the minute: the browser's own clock without one. */
|
|
32
|
+
export declare function wallTime(at: number, zone?: string): WallTime;
|
|
33
|
+
/** A day as a date field keeps it: 2026-10-15. */
|
|
34
|
+
export declare const wallDay: (wall: WallTime) => string;
|
|
35
|
+
/** A clock's time: 14:30. */
|
|
36
|
+
export declare const wallClock: (wall: WallTime) => string;
|
|
37
|
+
/** A wall time as the date readers write one: 2026-10-15T14:30. */
|
|
38
|
+
export declare const wallText: (wall: WallTime) => string;
|
|
39
|
+
/** A wall time read back from yyyy-mm-dd and, after a T, HH:MM (midnight without). */
|
|
40
|
+
export declare function wallOf(text: string): WallTime | null;
|
|
41
|
+
/** Minutes the zone's clock is ahead of UTC at an instant: 180 in Cairo's summer, -240 in New York's. */
|
|
42
|
+
export declare function zoneOffset(at: number, zone?: string): number;
|
|
43
|
+
/**
|
|
44
|
+
* The instants a time on the clock is in a zone, earliest first: one; none in the hour the clocks skip as they go
|
|
45
|
+
* forward; two in the hour they repeat as they go back. The browser's own zone without one.
|
|
46
|
+
*/
|
|
47
|
+
export declare function instantsAt(wall: WallTime, zone?: string): number[];
|
|
48
|
+
/** The day an instant falls on in a zone, 2026-10-15: the browser's own without one. */
|
|
49
|
+
export declare function dayIn(at: number | Date, zone?: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* The clocks' change that skips a time on the clock, which `instantsAt` found none of: the time they went forward
|
|
52
|
+
* from and the time they went to (02:00 → 03:00), or null where nothing was skipped.
|
|
53
|
+
*/
|
|
54
|
+
export declare function clocksSkip(wall: WallTime, zone?: string): {
|
|
55
|
+
from: WallTime;
|
|
56
|
+
to: WallTime;
|
|
57
|
+
} | null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time zones, by their IANA names ("Africa/Cairo", "Europe/Berlin"): a page's
|
|
3
|
+
* `timeZone`, or a date and time field's own. A date and time is kept as an
|
|
4
|
+
* instant (written in UTC, 2026-10-15T12:30:00.000Z, as Fieldia always kept
|
|
5
|
+
* one; an instant written with its offset is read the same) and shown, typed
|
|
6
|
+
* and counted by its day in its zone — the browser's own where none is named.
|
|
7
|
+
* Made from Intl alone, so no zone's rules are carried in the code.
|
|
8
|
+
*
|
|
9
|
+
* On a day the clocks change, a time on the clock may not exist (the hour they
|
|
10
|
+
* skip) or exist twice (the hour they repeat): `instantsAt` gives none, or
|
|
11
|
+
* both, and what reads a typed time says so — it is never moved in silence.
|
|
12
|
+
*/
|
|
13
|
+
/** A day and a time on the clock in some zone, to the minute. */
|
|
14
|
+
export interface WallTime {
|
|
15
|
+
year: number;
|
|
16
|
+
/** 1 to 12. */
|
|
17
|
+
month: number;
|
|
18
|
+
day: number;
|
|
19
|
+
hour: number;
|
|
20
|
+
minute: number;
|
|
21
|
+
}
|
|
22
|
+
/** Whether a name is a time zone the browser knows, by its IANA name: "Africa/Cairo", "UTC". Never an offset. */
|
|
23
|
+
export declare function isTimeZone(name: unknown): name is string;
|
|
24
|
+
/** The browser's own time zone, by its IANA name. */
|
|
25
|
+
export declare function ownZone(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether a zone keeps the browser's own clock: the same time through the year, in winter and summer — the browser's
|
|
28
|
+
* zone by any of its names ("Asia/Calcutta", "Asia/Kolkata"), or a neighbour on the same clock. Asked once a zone.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isOwnZone(zone: string): boolean;
|
|
31
|
+
/** The clock in `zone` at an instant (in ms), to the minute: the browser's own clock without one. */
|
|
32
|
+
export declare function wallTime(at: number, zone?: string): WallTime;
|
|
33
|
+
/** A day as a date field keeps it: 2026-10-15. */
|
|
34
|
+
export declare const wallDay: (wall: WallTime) => string;
|
|
35
|
+
/** A clock's time: 14:30. */
|
|
36
|
+
export declare const wallClock: (wall: WallTime) => string;
|
|
37
|
+
/** A wall time as the date readers write one: 2026-10-15T14:30. */
|
|
38
|
+
export declare const wallText: (wall: WallTime) => string;
|
|
39
|
+
/** A wall time read back from yyyy-mm-dd and, after a T, HH:MM (midnight without). */
|
|
40
|
+
export declare function wallOf(text: string): WallTime | null;
|
|
41
|
+
/** Minutes the zone's clock is ahead of UTC at an instant: 180 in Cairo's summer, -240 in New York's. */
|
|
42
|
+
export declare function zoneOffset(at: number, zone?: string): number;
|
|
43
|
+
/**
|
|
44
|
+
* The instants a time on the clock is in a zone, earliest first: one; none in the hour the clocks skip as they go
|
|
45
|
+
* forward; two in the hour they repeat as they go back. The browser's own zone without one.
|
|
46
|
+
*/
|
|
47
|
+
export declare function instantsAt(wall: WallTime, zone?: string): number[];
|
|
48
|
+
/** The day an instant falls on in a zone, 2026-10-15: the browser's own without one. */
|
|
49
|
+
export declare function dayIn(at: number | Date, zone?: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* The clocks' change that skips a time on the clock, which `instantsAt` found none of: the time they went forward
|
|
52
|
+
* from and the time they went to (02:00 → 03:00), or null where nothing was skipped.
|
|
53
|
+
*/
|
|
54
|
+
export declare function clocksSkip(wall: WallTime, zone?: string): {
|
|
55
|
+
from: WallTime;
|
|
56
|
+
to: WallTime;
|
|
57
|
+
} | null;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Time zones, by their IANA names ("Africa/Cairo", "Europe/Berlin"): a page's
|
|
4
|
+
* `timeZone`, or a date and time field's own. A date and time is kept as an
|
|
5
|
+
* instant (written in UTC, 2026-10-15T12:30:00.000Z, as Fieldia always kept
|
|
6
|
+
* one; an instant written with its offset is read the same) and shown, typed
|
|
7
|
+
* and counted by its day in its zone — the browser's own where none is named.
|
|
8
|
+
* Made from Intl alone, so no zone's rules are carried in the code.
|
|
9
|
+
*
|
|
10
|
+
* On a day the clocks change, a time on the clock may not exist (the hour they
|
|
11
|
+
* skip) or exist twice (the hour they repeat): `instantsAt` gives none, or
|
|
12
|
+
* both, and what reads a typed time says so — it is never moved in silence.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.wallText = exports.wallClock = exports.wallDay = void 0;
|
|
16
|
+
exports.isTimeZone = isTimeZone;
|
|
17
|
+
exports.ownZone = ownZone;
|
|
18
|
+
exports.isOwnZone = isOwnZone;
|
|
19
|
+
exports.wallTime = wallTime;
|
|
20
|
+
exports.wallOf = wallOf;
|
|
21
|
+
exports.zoneOffset = zoneOffset;
|
|
22
|
+
exports.instantsAt = instantsAt;
|
|
23
|
+
exports.dayIn = dayIn;
|
|
24
|
+
exports.clocksSkip = clocksSkip;
|
|
25
|
+
const MINUTE = 60000;
|
|
26
|
+
const clocks = new Map();
|
|
27
|
+
/** The clock of a zone, read in parts: Intl's, the Gregorian calendar, 24 hours, Latin digits. */
|
|
28
|
+
function clockOf(zone) {
|
|
29
|
+
let clock = clocks.get(zone);
|
|
30
|
+
if (!clock) {
|
|
31
|
+
clock = new Intl.DateTimeFormat('en-US', { timeZone: zone, calendar: 'gregory', numberingSystem: 'latn', hourCycle: 'h23', year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' });
|
|
32
|
+
clocks.set(zone, clock);
|
|
33
|
+
}
|
|
34
|
+
return clock;
|
|
35
|
+
}
|
|
36
|
+
/** Whether a name is a time zone the browser knows, by its IANA name: "Africa/Cairo", "UTC". Never an offset. */
|
|
37
|
+
function isTimeZone(name) {
|
|
38
|
+
if (typeof name !== 'string' || !/^[A-Za-z][\w+-]*(\/[\w+-]+)*$/.test(name))
|
|
39
|
+
return false;
|
|
40
|
+
try {
|
|
41
|
+
clockOf(name);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** The browser's own time zone, by its IANA name. */
|
|
49
|
+
function ownZone() {
|
|
50
|
+
return new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
51
|
+
}
|
|
52
|
+
const own = new Map();
|
|
53
|
+
/**
|
|
54
|
+
* Whether a zone keeps the browser's own clock: the same time through the year, in winter and summer — the browser's
|
|
55
|
+
* zone by any of its names ("Asia/Calcutta", "Asia/Kolkata"), or a neighbour on the same clock. Asked once a zone.
|
|
56
|
+
*/
|
|
57
|
+
function isOwnZone(zone) {
|
|
58
|
+
let same = own.get(zone);
|
|
59
|
+
if (same === undefined) {
|
|
60
|
+
const year = new Date().getFullYear();
|
|
61
|
+
same = [0, 3, 6, 9].every((month) => zoneOffset(Date.UTC(year, month, 15), zone) === zoneOffset(Date.UTC(year, month, 15)));
|
|
62
|
+
own.set(zone, same);
|
|
63
|
+
}
|
|
64
|
+
return same;
|
|
65
|
+
}
|
|
66
|
+
/** The clock in `zone` at an instant (in ms), to the minute: the browser's own clock without one. */
|
|
67
|
+
function wallTime(at, zone) {
|
|
68
|
+
if (!zone) {
|
|
69
|
+
const d = new Date(at);
|
|
70
|
+
return { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate(), hour: d.getHours(), minute: d.getMinutes() };
|
|
71
|
+
}
|
|
72
|
+
const read = {};
|
|
73
|
+
for (const part of clockOf(zone).formatToParts(at))
|
|
74
|
+
read[part.type] = Number(part.value);
|
|
75
|
+
return { year: read['year'], month: read['month'], day: read['day'], hour: read['hour'] % 24, minute: read['minute'] };
|
|
76
|
+
}
|
|
77
|
+
const pad = (n, width = 2) => String(n).padStart(width, '0');
|
|
78
|
+
/** A day as a date field keeps it: 2026-10-15. */
|
|
79
|
+
const wallDay = (wall) => `${pad(wall.year, 4)}-${pad(wall.month)}-${pad(wall.day)}`;
|
|
80
|
+
exports.wallDay = wallDay;
|
|
81
|
+
/** A clock's time: 14:30. */
|
|
82
|
+
const wallClock = (wall) => `${pad(wall.hour)}:${pad(wall.minute)}`;
|
|
83
|
+
exports.wallClock = wallClock;
|
|
84
|
+
/** A wall time as the date readers write one: 2026-10-15T14:30. */
|
|
85
|
+
const wallText = (wall) => `${(0, exports.wallDay)(wall)}T${(0, exports.wallClock)(wall)}`;
|
|
86
|
+
exports.wallText = wallText;
|
|
87
|
+
/** A wall time read back from yyyy-mm-dd and, after a T, HH:MM (midnight without). */
|
|
88
|
+
function wallOf(text) {
|
|
89
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}))?/.exec(text);
|
|
90
|
+
return m ? { year: Number(m[1]), month: Number(m[2]), day: Number(m[3]), hour: Number(m[4] ?? 0), minute: Number(m[5] ?? 0) } : null;
|
|
91
|
+
}
|
|
92
|
+
/** A wall time as if it were UTC, in ms: what the zone's offset is added to. */
|
|
93
|
+
const asUtc = (wall) => Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour, wall.minute);
|
|
94
|
+
/** The minute an instant falls in. */
|
|
95
|
+
const floorMinute = (at) => Math.floor(at / MINUTE) * MINUTE;
|
|
96
|
+
/** Minutes the zone's clock is ahead of UTC at an instant: 180 in Cairo's summer, -240 in New York's. */
|
|
97
|
+
function zoneOffset(at, zone) {
|
|
98
|
+
return Math.round((asUtc(wallTime(at, zone)) - floorMinute(at)) / MINUTE);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The instants a time on the clock is in a zone, earliest first: one; none in the hour the clocks skip as they go
|
|
102
|
+
* forward; two in the hour they repeat as they go back. The browser's own zone without one.
|
|
103
|
+
*/
|
|
104
|
+
function instantsAt(wall, zone) {
|
|
105
|
+
const local = asUtc(wall);
|
|
106
|
+
const found = new Set();
|
|
107
|
+
// The zone's offsets a day either side: what the clock is ahead by before a change near it and after.
|
|
108
|
+
for (const probe of [local - 86400000, local, local + 86400000]) {
|
|
109
|
+
const at = local - zoneOffset(probe, zone) * MINUTE;
|
|
110
|
+
if (asUtc(wallTime(at, zone)) === local)
|
|
111
|
+
found.add(at);
|
|
112
|
+
}
|
|
113
|
+
return [...found].sort((a, b) => a - b);
|
|
114
|
+
}
|
|
115
|
+
/** The day an instant falls on in a zone, 2026-10-15: the browser's own without one. */
|
|
116
|
+
function dayIn(at, zone) {
|
|
117
|
+
return (0, exports.wallDay)(wallTime(typeof at === 'number' ? at : at.getTime(), zone));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The clocks' change that skips a time on the clock, which `instantsAt` found none of: the time they went forward
|
|
121
|
+
* from and the time they went to (02:00 → 03:00), or null where nothing was skipped.
|
|
122
|
+
*/
|
|
123
|
+
function clocksSkip(wall, zone) {
|
|
124
|
+
const local = asUtc(wall);
|
|
125
|
+
const before = zoneOffset(local - 86400000, zone);
|
|
126
|
+
const after = zoneOffset(local + 86400000, zone);
|
|
127
|
+
if (after <= before || instantsAt(wall, zone).length)
|
|
128
|
+
return null;
|
|
129
|
+
// The change is between the instant the time would be at the later offset and at the earlier: its first minute.
|
|
130
|
+
let low = local - after * MINUTE;
|
|
131
|
+
let high = local - before * MINUTE;
|
|
132
|
+
while (high - low > MINUTE) {
|
|
133
|
+
const middle = floorMinute((low + high) / 2);
|
|
134
|
+
if (zoneOffset(middle, zone) === after)
|
|
135
|
+
high = middle;
|
|
136
|
+
else
|
|
137
|
+
low = middle;
|
|
138
|
+
}
|
|
139
|
+
// Its first minute at the later offset: the clock read it at the earlier one just before, and reads it at the later.
|
|
140
|
+
return { from: utcWall(high + before * MINUTE), to: utcWall(high + after * MINUTE) };
|
|
141
|
+
}
|
|
142
|
+
/** A number of ms read as a UTC clock's parts: the inverse of asUtc. */
|
|
143
|
+
function utcWall(ms) {
|
|
144
|
+
const d = new Date(ms);
|
|
145
|
+
return { year: d.getUTCFullYear(), month: d.getUTCMonth() + 1, day: d.getUTCDate(), hour: d.getUTCHours(), minute: d.getUTCMinutes() };
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=zones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zones.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/zones.ts"],"names":[],"mappings":"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"}
|