@fieldia/viewer 0.10.0 → 0.11.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 +126 -1
- package/bundle/fieldia.ar.js +2 -2
- package/bundle/fieldia.ar.js.map +2 -2
- package/bundle/fieldia.de.js +2 -2
- package/bundle/fieldia.de.js.map +2 -2
- package/bundle/fieldia.fr.js +2 -2
- package/bundle/fieldia.fr.js.map +2 -2
- package/bundle/fieldia.js +4 -4
- package/bundle/fieldia.js.map +4 -4
- package/package.json +3 -3
- package/src/lib/dialog.d.mts +29 -2
- package/src/lib/dialog.d.ts +29 -2
- package/src/lib/dialog.js +94 -27
- package/src/lib/dialog.js.map +1 -1
- package/src/lib/dialog.mjs +92 -27
- package/src/lib/dialog.mjs.map +1 -1
- package/src/lib/labels.d.mts +14 -0
- package/src/lib/labels.d.ts +14 -0
- package/src/lib/labels.js +6 -0
- package/src/lib/labels.js.map +1 -1
- package/src/lib/labels.mjs +6 -0
- package/src/lib/labels.mjs.map +1 -1
- package/src/lib/list.d.mts +3 -2
- package/src/lib/list.d.ts +3 -2
- package/src/lib/list.js +5 -5
- package/src/lib/list.js.map +1 -1
- package/src/lib/list.mjs +5 -5
- package/src/lib/list.mjs.map +1 -1
- package/src/lib/locales/ar.js +6 -0
- package/src/lib/locales/ar.js.map +1 -1
- package/src/lib/locales/ar.mjs +6 -0
- package/src/lib/locales/ar.mjs.map +1 -1
- package/src/lib/locales/de.js +6 -0
- package/src/lib/locales/de.js.map +1 -1
- package/src/lib/locales/de.mjs +6 -0
- package/src/lib/locales/de.mjs.map +1 -1
- package/src/lib/locales/fr.js +6 -0
- package/src/lib/locales/fr.js.map +1 -1
- package/src/lib/locales/fr.mjs +6 -0
- package/src/lib/locales/fr.mjs.map +1 -1
- package/src/lib/look.d.mts +7 -3
- package/src/lib/look.d.ts +7 -3
- package/src/lib/look.js +72 -15
- package/src/lib/look.js.map +1 -1
- package/src/lib/look.mjs +72 -15
- package/src/lib/look.mjs.map +1 -1
- package/src/lib/open.d.mts +24 -0
- package/src/lib/open.d.ts +24 -0
- package/src/lib/open.js +81 -0
- package/src/lib/open.js.map +1 -0
- package/src/lib/open.mjs +78 -0
- package/src/lib/open.mjs.map +1 -0
- package/src/lib/related.d.mts +19 -0
- package/src/lib/related.d.ts +19 -0
- package/src/lib/related.js +15 -2
- package/src/lib/related.js.map +1 -1
- package/src/lib/related.mjs +14 -2
- package/src/lib/related.mjs.map +1 -1
- package/src/lib/say.d.mts +9 -0
- package/src/lib/say.d.ts +9 -0
- package/src/lib/say.js +45 -0
- package/src/lib/say.js.map +1 -0
- package/src/lib/say.mjs +42 -0
- package/src/lib/say.mjs.map +1 -0
- package/src/lib/viewer.d.mts +33 -5
- package/src/lib/viewer.d.ts +33 -5
- package/src/lib/viewer.js +464 -279
- package/src/lib/viewer.js.map +1 -1
- package/src/lib/viewer.mjs +465 -280
- package/src/lib/viewer.mjs.map +1 -1
package/src/lib/look.d.ts
CHANGED
|
@@ -13,9 +13,13 @@ export interface AccentShades {
|
|
|
13
13
|
/**
|
|
14
14
|
* The accent, and what goes with it in either scheme. Each is moved, in small
|
|
15
15
|
* steps and only as far as it has to be, until words in it and on it read at
|
|
16
|
-
* 4.5:1 — darker on a light page, lighter on a dark one
|
|
17
|
-
* shades are mixed from these
|
|
16
|
+
* 4.5:1 — darker on a light page, lighter on a dark one — on the page and on
|
|
17
|
+
* any `grounds` of its parts. The softer and hover shades are mixed from these
|
|
18
|
+
* by the stylesheet.
|
|
18
19
|
*/
|
|
19
|
-
export declare function accentShades(hex: string
|
|
20
|
+
export declare function accentShades(hex: string, grounds?: {
|
|
21
|
+
light: string[];
|
|
22
|
+
dark: string[];
|
|
23
|
+
}): AccentShades;
|
|
20
24
|
/** Put the page's look on the form's root. */
|
|
21
25
|
export declare function applyLook(root: HTMLElement, look: PageLook | undefined): void;
|
package/src/lib/look.js
CHANGED
|
@@ -8,7 +8,9 @@ exports.applyLook = applyLook;
|
|
|
8
8
|
* font, room, corners, labels and colour scheme becomes attributes and tokens
|
|
9
9
|
* on the form's root, and the stylesheet turns them into the form's own
|
|
10
10
|
* colours and sizes — so every widget follows, in either skin, light or dark.
|
|
11
|
-
* A
|
|
11
|
+
* A look for a kind of part (text boxes, choices, groups, buttons, tables)
|
|
12
|
+
* becomes tokens of that kind, worn by it alone. A page with no look is left
|
|
13
|
+
* exactly as its skin draws it.
|
|
12
14
|
*/
|
|
13
15
|
/** Words written on a light accent, and on the dark page's accent. */
|
|
14
16
|
const INK = '#111418';
|
|
@@ -37,30 +39,84 @@ function contrast(a, b) {
|
|
|
37
39
|
const textOn = (hex) => (contrast(hex, '#ffffff') >= READABLE ? '#ffffff' : INK);
|
|
38
40
|
/** On a dark page the accent is light: whichever of ink or white reads better on it. */
|
|
39
41
|
const textOnDark = (hex) => (contrast(hex, INK) >= contrast(hex, '#ffffff') ? INK : '#ffffff');
|
|
40
|
-
/** A colour taken towards
|
|
41
|
-
const
|
|
42
|
-
/** A colour taken towards black by `amount` (0 to 1). */
|
|
43
|
-
const darken = (hex, amount) => toHex(channels(hex).map((c) => c * (1 - amount)));
|
|
42
|
+
/** A colour taken towards another by `amount` (0 to 1). */
|
|
43
|
+
const towards = (hex, to, amount) => toHex(channels(hex).map((c, i) => c + (channels(to)[i] - c) * amount));
|
|
44
44
|
/** The accent's softer shade on a surface, as the stylesheet mixes it: 12% of the accent. */
|
|
45
|
-
const softOn = (hex, surface) =>
|
|
45
|
+
const softOn = (hex, surface) => towards(surface, hex, 0.12);
|
|
46
46
|
/** Reads as words on a surface, on the lightest ground there, and on its own softer shade (a picked tab, a chip). */
|
|
47
47
|
const readsOn = (hex, grounds) => [...grounds, softOn(hex, grounds[0])].every((ground) => contrast(hex, ground) >= READABLE);
|
|
48
|
+
/** A colour moved towards `to` in small steps, only as far as it has to be, until it `reads`; at worst it is `to`. */
|
|
49
|
+
function moved(hex, to, reads) {
|
|
50
|
+
let colour = hex;
|
|
51
|
+
for (let step = 1; step <= 40 && !reads(colour); step++)
|
|
52
|
+
colour = towards(hex, to, step / 40);
|
|
53
|
+
return colour;
|
|
54
|
+
}
|
|
48
55
|
/**
|
|
49
56
|
* The accent, and what goes with it in either scheme. Each is moved, in small
|
|
50
57
|
* steps and only as far as it has to be, until words in it and on it read at
|
|
51
|
-
* 4.5:1 — darker on a light page, lighter on a dark one
|
|
52
|
-
* shades are mixed from these
|
|
58
|
+
* 4.5:1 — darker on a light page, lighter on a dark one — on the page and on
|
|
59
|
+
* any `grounds` of its parts. The softer and hover shades are mixed from these
|
|
60
|
+
* by the stylesheet.
|
|
53
61
|
*/
|
|
54
|
-
function accentShades(hex) {
|
|
62
|
+
function accentShades(hex, grounds = { light: [], dark: [] }) {
|
|
55
63
|
const given = hex.toLowerCase();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
accent = darken(given, step / 40);
|
|
59
|
-
let dark = given;
|
|
60
|
-
for (let step = 1; step <= 40 && !readsOn(dark, [DARK_SURFACE]); step++)
|
|
61
|
-
dark = lighten(given, step / 40);
|
|
64
|
+
const accent = moved(given, '#000000', (colour) => readsOn(colour, ['#ffffff', LIGHT_GROUND, ...grounds.light]));
|
|
65
|
+
const dark = moved(given, '#ffffff', (colour) => readsOn(colour, [DARK_SURFACE, ...grounds.dark]));
|
|
62
66
|
return { accent, accentText: textOn(accent), dark, darkText: textOnDark(dark) };
|
|
63
67
|
}
|
|
68
|
+
/** Each scheme's words that every ground of a part must keep readable: its text, muted words and errors. */
|
|
69
|
+
const LIGHT_WORDS = ['#212529', '#636976', '#c63c3d'];
|
|
70
|
+
const DARK_WORDS = ['#e8eaed', '#a3a9b2', '#ff8a7a'];
|
|
71
|
+
/** The skins' own accent where the page names none: outlined's, the lighter of the two, which has the most to read on. */
|
|
72
|
+
const SKIN_ACCENT = { accent: '#1365d9', dark: '#5aa2ff' };
|
|
73
|
+
/** What a part's settings are called on the form, `data-inputs="bg radius"`, and in its tokens, `--fd-inputs-bg`. */
|
|
74
|
+
const NAMES = { background: 'bg', border: 'border', corners: 'radius', textSize: 'size', accent: 'accent' };
|
|
75
|
+
const SIZES = { small: '13px', large: '16px' };
|
|
76
|
+
/** The corners of a box, and of a group, in pixels: the page's own (`data-corners`) for each. */
|
|
77
|
+
const RADII = { square: [0, 0], soft: [6, 10], round: [12, 16] };
|
|
78
|
+
/**
|
|
79
|
+
* A look for each kind of part, as its own tokens on the form, each worked out
|
|
80
|
+
* for the page's scheme (both, for auto, as `light-dark()`): a ground moved
|
|
81
|
+
* until the page's words and accent read on it — lighter on a light page,
|
|
82
|
+
* towards the dark surface on a dark one; an accent moved until words in it
|
|
83
|
+
* and on it read, on the page and on every ground given; an edge as given.
|
|
84
|
+
*/
|
|
85
|
+
function applyParts(root, look) {
|
|
86
|
+
const wear = (light, dark) => (look.scheme === 'dark' ? dark : look.scheme === 'auto' ? `light-dark(${light}, ${dark})` : light);
|
|
87
|
+
const page = look.accent ? accentShades(look.accent) : SKIN_ACCENT;
|
|
88
|
+
const parts = Object.entries(look.parts ?? {});
|
|
89
|
+
const set = (kind, name, value) => root.style.setProperty(`--fd-${kind}-${name}`, value);
|
|
90
|
+
// The grounds first: every accent has to read on each of them.
|
|
91
|
+
const grounds = { light: [], dark: [] };
|
|
92
|
+
const readsAll = (words) => (colour) => words.every((word) => contrast(word, colour) >= READABLE);
|
|
93
|
+
for (const [kind, part] of parts) {
|
|
94
|
+
const given = part.background?.toLowerCase();
|
|
95
|
+
if (!given)
|
|
96
|
+
continue;
|
|
97
|
+
const light = moved(given, '#ffffff', readsAll([...LIGHT_WORDS, page.accent]));
|
|
98
|
+
const dark = moved(given, DARK_SURFACE, readsAll([...DARK_WORDS, page.dark]));
|
|
99
|
+
grounds.light.push(light);
|
|
100
|
+
grounds.dark.push(dark);
|
|
101
|
+
set(kind, 'bg', wear(light, dark));
|
|
102
|
+
}
|
|
103
|
+
for (const [kind, part] of parts) {
|
|
104
|
+
const names = Object.keys(NAMES).filter((name) => part[name]).map((name) => NAMES[name]);
|
|
105
|
+
if (names.length)
|
|
106
|
+
root.setAttribute(`data-${kind}`, names.join(' '));
|
|
107
|
+
if (part.border)
|
|
108
|
+
set(kind, 'border', part.border);
|
|
109
|
+
if (part.corners)
|
|
110
|
+
set(kind, 'radius', `${RADII[part.corners][kind === 'groups' ? 1 : 0]}px`);
|
|
111
|
+
if (part.textSize)
|
|
112
|
+
set(kind, 'size', SIZES[part.textSize]);
|
|
113
|
+
if (part.accent) {
|
|
114
|
+
const shades = accentShades(part.accent, grounds);
|
|
115
|
+
set(kind, 'accent', wear(shades.accent, shades.dark));
|
|
116
|
+
set(kind, 'accent-text', wear(shades.accentText, shades.darkText));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
64
120
|
/** Put the page's look on the form's root. */
|
|
65
121
|
function applyLook(root, look) {
|
|
66
122
|
if (!look)
|
|
@@ -80,5 +136,6 @@ function applyLook(root, look) {
|
|
|
80
136
|
root.style.setProperty('--fd-look-accent-dark', shades.dark);
|
|
81
137
|
root.style.setProperty('--fd-look-accent-dark-text', shades.darkText);
|
|
82
138
|
}
|
|
139
|
+
applyParts(root, look);
|
|
83
140
|
}
|
|
84
141
|
//# sourceMappingURL=look.js.map
|
package/src/lib/look.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"look.js","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/look.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"look.js","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/look.ts"],"names":[],"mappings":"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"}
|
package/src/lib/look.mjs
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* font, room, corners, labels and colour scheme becomes attributes and tokens
|
|
4
4
|
* on the form's root, and the stylesheet turns them into the form's own
|
|
5
5
|
* colours and sizes — so every widget follows, in either skin, light or dark.
|
|
6
|
-
* A
|
|
6
|
+
* A look for a kind of part (text boxes, choices, groups, buttons, tables)
|
|
7
|
+
* becomes tokens of that kind, worn by it alone. A page with no look is left
|
|
8
|
+
* exactly as its skin draws it.
|
|
7
9
|
*/
|
|
8
10
|
/** Words written on a light accent, and on the dark page's accent. */
|
|
9
11
|
const INK = '#111418';
|
|
@@ -32,30 +34,84 @@ export function contrast(a, b) {
|
|
|
32
34
|
const textOn = (hex) => (contrast(hex, '#ffffff') >= READABLE ? '#ffffff' : INK);
|
|
33
35
|
/** On a dark page the accent is light: whichever of ink or white reads better on it. */
|
|
34
36
|
const textOnDark = (hex) => (contrast(hex, INK) >= contrast(hex, '#ffffff') ? INK : '#ffffff');
|
|
35
|
-
/** A colour taken towards
|
|
36
|
-
const
|
|
37
|
-
/** A colour taken towards black by `amount` (0 to 1). */
|
|
38
|
-
const darken = (hex, amount) => toHex(channels(hex).map((c) => c * (1 - amount)));
|
|
37
|
+
/** A colour taken towards another by `amount` (0 to 1). */
|
|
38
|
+
const towards = (hex, to, amount) => toHex(channels(hex).map((c, i) => c + (channels(to)[i] - c) * amount));
|
|
39
39
|
/** The accent's softer shade on a surface, as the stylesheet mixes it: 12% of the accent. */
|
|
40
|
-
const softOn = (hex, surface) =>
|
|
40
|
+
const softOn = (hex, surface) => towards(surface, hex, 0.12);
|
|
41
41
|
/** Reads as words on a surface, on the lightest ground there, and on its own softer shade (a picked tab, a chip). */
|
|
42
42
|
const readsOn = (hex, grounds) => [...grounds, softOn(hex, grounds[0])].every((ground) => contrast(hex, ground) >= READABLE);
|
|
43
|
+
/** A colour moved towards `to` in small steps, only as far as it has to be, until it `reads`; at worst it is `to`. */
|
|
44
|
+
function moved(hex, to, reads) {
|
|
45
|
+
let colour = hex;
|
|
46
|
+
for (let step = 1; step <= 40 && !reads(colour); step++)
|
|
47
|
+
colour = towards(hex, to, step / 40);
|
|
48
|
+
return colour;
|
|
49
|
+
}
|
|
43
50
|
/**
|
|
44
51
|
* The accent, and what goes with it in either scheme. Each is moved, in small
|
|
45
52
|
* steps and only as far as it has to be, until words in it and on it read at
|
|
46
|
-
* 4.5:1 — darker on a light page, lighter on a dark one
|
|
47
|
-
* shades are mixed from these
|
|
53
|
+
* 4.5:1 — darker on a light page, lighter on a dark one — on the page and on
|
|
54
|
+
* any `grounds` of its parts. The softer and hover shades are mixed from these
|
|
55
|
+
* by the stylesheet.
|
|
48
56
|
*/
|
|
49
|
-
export function accentShades(hex) {
|
|
57
|
+
export function accentShades(hex, grounds = { light: [], dark: [] }) {
|
|
50
58
|
const given = hex.toLowerCase();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
accent = darken(given, step / 40);
|
|
54
|
-
let dark = given;
|
|
55
|
-
for (let step = 1; step <= 40 && !readsOn(dark, [DARK_SURFACE]); step++)
|
|
56
|
-
dark = lighten(given, step / 40);
|
|
59
|
+
const accent = moved(given, '#000000', (colour) => readsOn(colour, ['#ffffff', LIGHT_GROUND, ...grounds.light]));
|
|
60
|
+
const dark = moved(given, '#ffffff', (colour) => readsOn(colour, [DARK_SURFACE, ...grounds.dark]));
|
|
57
61
|
return { accent, accentText: textOn(accent), dark, darkText: textOnDark(dark) };
|
|
58
62
|
}
|
|
63
|
+
/** Each scheme's words that every ground of a part must keep readable: its text, muted words and errors. */
|
|
64
|
+
const LIGHT_WORDS = ['#212529', '#636976', '#c63c3d'];
|
|
65
|
+
const DARK_WORDS = ['#e8eaed', '#a3a9b2', '#ff8a7a'];
|
|
66
|
+
/** The skins' own accent where the page names none: outlined's, the lighter of the two, which has the most to read on. */
|
|
67
|
+
const SKIN_ACCENT = { accent: '#1365d9', dark: '#5aa2ff' };
|
|
68
|
+
/** What a part's settings are called on the form, `data-inputs="bg radius"`, and in its tokens, `--fd-inputs-bg`. */
|
|
69
|
+
const NAMES = { background: 'bg', border: 'border', corners: 'radius', textSize: 'size', accent: 'accent' };
|
|
70
|
+
const SIZES = { small: '13px', large: '16px' };
|
|
71
|
+
/** The corners of a box, and of a group, in pixels: the page's own (`data-corners`) for each. */
|
|
72
|
+
const RADII = { square: [0, 0], soft: [6, 10], round: [12, 16] };
|
|
73
|
+
/**
|
|
74
|
+
* A look for each kind of part, as its own tokens on the form, each worked out
|
|
75
|
+
* for the page's scheme (both, for auto, as `light-dark()`): a ground moved
|
|
76
|
+
* until the page's words and accent read on it — lighter on a light page,
|
|
77
|
+
* towards the dark surface on a dark one; an accent moved until words in it
|
|
78
|
+
* and on it read, on the page and on every ground given; an edge as given.
|
|
79
|
+
*/
|
|
80
|
+
function applyParts(root, look) {
|
|
81
|
+
const wear = (light, dark) => (look.scheme === 'dark' ? dark : look.scheme === 'auto' ? `light-dark(${light}, ${dark})` : light);
|
|
82
|
+
const page = look.accent ? accentShades(look.accent) : SKIN_ACCENT;
|
|
83
|
+
const parts = Object.entries(look.parts ?? {});
|
|
84
|
+
const set = (kind, name, value) => root.style.setProperty(`--fd-${kind}-${name}`, value);
|
|
85
|
+
// The grounds first: every accent has to read on each of them.
|
|
86
|
+
const grounds = { light: [], dark: [] };
|
|
87
|
+
const readsAll = (words) => (colour) => words.every((word) => contrast(word, colour) >= READABLE);
|
|
88
|
+
for (const [kind, part] of parts) {
|
|
89
|
+
const given = part.background?.toLowerCase();
|
|
90
|
+
if (!given)
|
|
91
|
+
continue;
|
|
92
|
+
const light = moved(given, '#ffffff', readsAll([...LIGHT_WORDS, page.accent]));
|
|
93
|
+
const dark = moved(given, DARK_SURFACE, readsAll([...DARK_WORDS, page.dark]));
|
|
94
|
+
grounds.light.push(light);
|
|
95
|
+
grounds.dark.push(dark);
|
|
96
|
+
set(kind, 'bg', wear(light, dark));
|
|
97
|
+
}
|
|
98
|
+
for (const [kind, part] of parts) {
|
|
99
|
+
const names = Object.keys(NAMES).filter((name) => part[name]).map((name) => NAMES[name]);
|
|
100
|
+
if (names.length)
|
|
101
|
+
root.setAttribute(`data-${kind}`, names.join(' '));
|
|
102
|
+
if (part.border)
|
|
103
|
+
set(kind, 'border', part.border);
|
|
104
|
+
if (part.corners)
|
|
105
|
+
set(kind, 'radius', `${RADII[part.corners][kind === 'groups' ? 1 : 0]}px`);
|
|
106
|
+
if (part.textSize)
|
|
107
|
+
set(kind, 'size', SIZES[part.textSize]);
|
|
108
|
+
if (part.accent) {
|
|
109
|
+
const shades = accentShades(part.accent, grounds);
|
|
110
|
+
set(kind, 'accent', wear(shades.accent, shades.dark));
|
|
111
|
+
set(kind, 'accent-text', wear(shades.accentText, shades.darkText));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
59
115
|
/** Put the page's look on the form's root. */
|
|
60
116
|
export function applyLook(root, look) {
|
|
61
117
|
if (!look)
|
|
@@ -75,5 +131,6 @@ export function applyLook(root, look) {
|
|
|
75
131
|
root.style.setProperty('--fd-look-accent-dark', shades.dark);
|
|
76
132
|
root.style.setProperty('--fd-look-accent-dark-text', shades.darkText);
|
|
77
133
|
}
|
|
134
|
+
applyParts(root, look);
|
|
78
135
|
}
|
|
79
136
|
//# sourceMappingURL=look.mjs.map
|
package/src/lib/look.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"look.mjs","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/look.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"look.mjs","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/look.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OpenRequest, OpenResult, Page } from '@fieldia/core';
|
|
2
|
+
import { type ViewerOptions } from './viewer.mjs';
|
|
3
|
+
/** What opening a page needs of the viewer that opens it. */
|
|
4
|
+
export interface Opener {
|
|
5
|
+
options: ViewerOptions;
|
|
6
|
+
/** The element the viewer is in: a page opened in its place goes there. */
|
|
7
|
+
place: HTMLElement;
|
|
8
|
+
/** The viewer's own form element, which steps aside meanwhile. */
|
|
9
|
+
root: HTMLElement;
|
|
10
|
+
/** The page's title as the viewer shows it: in its language, through the app's translator. */
|
|
11
|
+
title(page: Page): string;
|
|
12
|
+
/** "Back", in the page's language. */
|
|
13
|
+
back: string;
|
|
14
|
+
/** Why a page cannot be opened: the app has none by that id. */
|
|
15
|
+
missing(page: string): string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Open a page as a step asks, for the viewer's host: the app's own way first
|
|
19
|
+
* (`onOpen`), else found through `pages` and opened in a dialog, a side panel
|
|
20
|
+
* (from the side the step names) or this form's place — with the same data
|
|
21
|
+
* source, pages, words and look.
|
|
22
|
+
* Resolves with how it ended; the saved record named by its page's title field.
|
|
23
|
+
*/
|
|
24
|
+
export declare function openPage(opener: Opener, request: OpenRequest): Promise<OpenResult>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OpenRequest, OpenResult, Page } from '@fieldia/core';
|
|
2
|
+
import { type ViewerOptions } from './viewer';
|
|
3
|
+
/** What opening a page needs of the viewer that opens it. */
|
|
4
|
+
export interface Opener {
|
|
5
|
+
options: ViewerOptions;
|
|
6
|
+
/** The element the viewer is in: a page opened in its place goes there. */
|
|
7
|
+
place: HTMLElement;
|
|
8
|
+
/** The viewer's own form element, which steps aside meanwhile. */
|
|
9
|
+
root: HTMLElement;
|
|
10
|
+
/** The page's title as the viewer shows it: in its language, through the app's translator. */
|
|
11
|
+
title(page: Page): string;
|
|
12
|
+
/** "Back", in the page's language. */
|
|
13
|
+
back: string;
|
|
14
|
+
/** Why a page cannot be opened: the app has none by that id. */
|
|
15
|
+
missing(page: string): string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Open a page as a step asks, for the viewer's host: the app's own way first
|
|
19
|
+
* (`onOpen`), else found through `pages` and opened in a dialog, a side panel
|
|
20
|
+
* (from the side the step names) or this form's place — with the same data
|
|
21
|
+
* source, pages, words and look.
|
|
22
|
+
* Resolves with how it ended; the saved record named by its page's title field.
|
|
23
|
+
*/
|
|
24
|
+
export declare function openPage(opener: Opener, request: OpenRequest): Promise<OpenResult>;
|
package/src/lib/open.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openPage = openPage;
|
|
4
|
+
const dialog_1 = require("./dialog");
|
|
5
|
+
const related_1 = require("./related");
|
|
6
|
+
const viewer_1 = require("./viewer");
|
|
7
|
+
/**
|
|
8
|
+
* Open a page as a step asks, for the viewer's host: the app's own way first
|
|
9
|
+
* (`onOpen`), else found through `pages` and opened in a dialog, a side panel
|
|
10
|
+
* (from the side the step names) or this form's place — with the same data
|
|
11
|
+
* source, pages, words and look.
|
|
12
|
+
* Resolves with how it ended; the saved record named by its page's title field.
|
|
13
|
+
*/
|
|
14
|
+
async function openPage(opener, request) {
|
|
15
|
+
const { options } = opener;
|
|
16
|
+
const theirs = options.onOpen?.(request);
|
|
17
|
+
if (theirs)
|
|
18
|
+
return theirs;
|
|
19
|
+
const found = await (0, related_1.findPage)(options, request.version === undefined ? { id: request.page } : { id: request.page, version: request.version });
|
|
20
|
+
if (!found)
|
|
21
|
+
throw new Error(opener.missing(request.page));
|
|
22
|
+
// It wears the look of the page that opened it, unless it has one of its own.
|
|
23
|
+
const look = options.page.look;
|
|
24
|
+
const shared = {
|
|
25
|
+
...options,
|
|
26
|
+
page: look && !found.look ? { ...found, look } : found,
|
|
27
|
+
form: undefined,
|
|
28
|
+
recordId: request.recordId ?? null,
|
|
29
|
+
values: request.values,
|
|
30
|
+
// What belongs to the page that opened it alone.
|
|
31
|
+
drafts: undefined,
|
|
32
|
+
autosave: undefined,
|
|
33
|
+
readonly: undefined,
|
|
34
|
+
editSwitch: undefined,
|
|
35
|
+
saveStatus: undefined,
|
|
36
|
+
};
|
|
37
|
+
const title = request.title ?? opener.title(found);
|
|
38
|
+
const result = request.as === 'page' ? await inPlace(opener, shared)
|
|
39
|
+
: request.as === 'panel' ? await (0, dialog_1.openFormPanel)({ ...shared, title, side: request.side })
|
|
40
|
+
: await (0, dialog_1.openFormDialog)({ ...shared, title, size: found.layout.type === 'sheet' ? 'large' : 'medium' });
|
|
41
|
+
const name = (0, related_1.nameFieldOf)(found);
|
|
42
|
+
const label = name ? result.values[name] : undefined;
|
|
43
|
+
return { ...result, ...(typeof label === 'string' && label ? { label } : {}) };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A page in this form's place, with Back over it. Saved or sent — once its own
|
|
47
|
+
* after-save steps have run — it gives way back to this form, as it was, and
|
|
48
|
+
* the run goes on; Back, or a `close` step inside it, returns without.
|
|
49
|
+
*/
|
|
50
|
+
function inPlace(opener, options) {
|
|
51
|
+
const { place, root } = opener;
|
|
52
|
+
const doc = place.ownerDocument;
|
|
53
|
+
const from = doc.activeElement;
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
let done = false;
|
|
56
|
+
const end = (saved) => {
|
|
57
|
+
if (done)
|
|
58
|
+
return;
|
|
59
|
+
done = true;
|
|
60
|
+
const state = opened.form.getState();
|
|
61
|
+
opened.destroy();
|
|
62
|
+
root.hidden = false;
|
|
63
|
+
if (from?.isConnected)
|
|
64
|
+
from.focus();
|
|
65
|
+
resolve({ saved, recordId: state.recordId ?? null, values: state.values });
|
|
66
|
+
};
|
|
67
|
+
root.hidden = true;
|
|
68
|
+
const opened = (0, viewer_1.mountViewer)(place, { ...options, host: { ...options.host, close: () => end(false) } });
|
|
69
|
+
const back = doc.createElement('button');
|
|
70
|
+
back.type = 'button';
|
|
71
|
+
back.className = 'fd-button fd-button-link fd-back';
|
|
72
|
+
back.textContent = opener.back;
|
|
73
|
+
back.addEventListener('click', () => end(false));
|
|
74
|
+
opened.element.prepend(back);
|
|
75
|
+
const leave = () => void opened.form.settled().then(() => end(true));
|
|
76
|
+
opened.on('save', leave);
|
|
77
|
+
opened.on('send', leave);
|
|
78
|
+
(opened.element.querySelector(dialog_1.FIRST_FIELD) ?? back).focus();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/open.ts"],"names":[],"mappings":"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"}
|
package/src/lib/open.mjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { FIRST_FIELD, openFormDialog, openFormPanel } from './dialog.mjs';
|
|
2
|
+
import { findPage, nameFieldOf } from './related.mjs';
|
|
3
|
+
import { mountViewer } from './viewer.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Open a page as a step asks, for the viewer's host: the app's own way first
|
|
6
|
+
* (`onOpen`), else found through `pages` and opened in a dialog, a side panel
|
|
7
|
+
* (from the side the step names) or this form's place — with the same data
|
|
8
|
+
* source, pages, words and look.
|
|
9
|
+
* Resolves with how it ended; the saved record named by its page's title field.
|
|
10
|
+
*/
|
|
11
|
+
export async function openPage(opener, request) {
|
|
12
|
+
const { options } = opener;
|
|
13
|
+
const theirs = options.onOpen?.(request);
|
|
14
|
+
if (theirs)
|
|
15
|
+
return theirs;
|
|
16
|
+
const found = await findPage(options, request.version === undefined ? { id: request.page } : { id: request.page, version: request.version });
|
|
17
|
+
if (!found)
|
|
18
|
+
throw new Error(opener.missing(request.page));
|
|
19
|
+
// It wears the look of the page that opened it, unless it has one of its own.
|
|
20
|
+
const look = options.page.look;
|
|
21
|
+
const shared = {
|
|
22
|
+
...options,
|
|
23
|
+
page: look && !found.look ? { ...found, look } : found,
|
|
24
|
+
form: undefined,
|
|
25
|
+
recordId: request.recordId ?? null,
|
|
26
|
+
values: request.values,
|
|
27
|
+
// What belongs to the page that opened it alone.
|
|
28
|
+
drafts: undefined,
|
|
29
|
+
autosave: undefined,
|
|
30
|
+
readonly: undefined,
|
|
31
|
+
editSwitch: undefined,
|
|
32
|
+
saveStatus: undefined,
|
|
33
|
+
};
|
|
34
|
+
const title = request.title ?? opener.title(found);
|
|
35
|
+
const result = request.as === 'page' ? await inPlace(opener, shared)
|
|
36
|
+
: request.as === 'panel' ? await openFormPanel({ ...shared, title, side: request.side })
|
|
37
|
+
: await openFormDialog({ ...shared, title, size: found.layout.type === 'sheet' ? 'large' : 'medium' });
|
|
38
|
+
const name = nameFieldOf(found);
|
|
39
|
+
const label = name ? result.values[name] : undefined;
|
|
40
|
+
return { ...result, ...(typeof label === 'string' && label ? { label } : {}) };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A page in this form's place, with Back over it. Saved or sent — once its own
|
|
44
|
+
* after-save steps have run — it gives way back to this form, as it was, and
|
|
45
|
+
* the run goes on; Back, or a `close` step inside it, returns without.
|
|
46
|
+
*/
|
|
47
|
+
function inPlace(opener, options) {
|
|
48
|
+
const { place, root } = opener;
|
|
49
|
+
const doc = place.ownerDocument;
|
|
50
|
+
const from = doc.activeElement;
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
let done = false;
|
|
53
|
+
const end = (saved) => {
|
|
54
|
+
if (done)
|
|
55
|
+
return;
|
|
56
|
+
done = true;
|
|
57
|
+
const state = opened.form.getState();
|
|
58
|
+
opened.destroy();
|
|
59
|
+
root.hidden = false;
|
|
60
|
+
if (from?.isConnected)
|
|
61
|
+
from.focus();
|
|
62
|
+
resolve({ saved, recordId: state.recordId ?? null, values: state.values });
|
|
63
|
+
};
|
|
64
|
+
root.hidden = true;
|
|
65
|
+
const opened = mountViewer(place, { ...options, host: { ...options.host, close: () => end(false) } });
|
|
66
|
+
const back = doc.createElement('button');
|
|
67
|
+
back.type = 'button';
|
|
68
|
+
back.className = 'fd-button fd-button-link fd-back';
|
|
69
|
+
back.textContent = opener.back;
|
|
70
|
+
back.addEventListener('click', () => end(false));
|
|
71
|
+
opened.element.prepend(back);
|
|
72
|
+
const leave = () => void opened.form.settled().then(() => end(true));
|
|
73
|
+
opened.on('save', leave);
|
|
74
|
+
opened.on('send', leave);
|
|
75
|
+
(opened.element.querySelector(FIRST_FIELD) ?? back).focus();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=open.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.mjs","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/open.ts"],"names":[],"mappings":"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"}
|
package/src/lib/related.d.mts
CHANGED
|
@@ -3,5 +3,24 @@ import type { WidgetDialogs } from '@fieldia/widgets';
|
|
|
3
3
|
import type { ViewerOptions } from './viewer.mjs';
|
|
4
4
|
/** The field a page's records are named by: its title, or "name", or its first line of text. */
|
|
5
5
|
export declare function nameFieldOf(page: Page): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* What a part asks the app's pages for: the page for a model, to show a
|
|
8
|
+
* linked record in a dialog; or a saved page by its id — and the version it
|
|
9
|
+
* keeps to, when it keeps to one — to draw a saved form placed in another.
|
|
10
|
+
*/
|
|
11
|
+
export type PageRequest = {
|
|
12
|
+
model: string;
|
|
13
|
+
} | {
|
|
14
|
+
id: string;
|
|
15
|
+
version?: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The app's pages: a record of them by key — a model, a page's id, or
|
|
19
|
+
* `id@version` for a version kept to — or a function asked for each, which
|
|
20
|
+
* may answer at once or with a promise.
|
|
21
|
+
*/
|
|
22
|
+
export type PageFinder = Record<string, Page> | ((request: PageRequest) => Page | null | undefined | Promise<Page | null | undefined>);
|
|
23
|
+
/** The page the app gives for a request: from `pages`, and for a model from `relatedPages` after it. A promise when it answers later. */
|
|
24
|
+
export declare function findPage(options: Pick<ViewerOptions, 'pages' | 'relatedPages'>, request: PageRequest): Page | null | Promise<Page | null>;
|
|
6
25
|
/** The dialogs a page's widgets may open, made from the viewer's own options. */
|
|
7
26
|
export declare function pageDialogs(options: ViewerOptions): WidgetDialogs;
|
package/src/lib/related.d.ts
CHANGED
|
@@ -3,5 +3,24 @@ import type { WidgetDialogs } from '@fieldia/widgets';
|
|
|
3
3
|
import type { ViewerOptions } from './viewer';
|
|
4
4
|
/** The field a page's records are named by: its title, or "name", or its first line of text. */
|
|
5
5
|
export declare function nameFieldOf(page: Page): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* What a part asks the app's pages for: the page for a model, to show a
|
|
8
|
+
* linked record in a dialog; or a saved page by its id — and the version it
|
|
9
|
+
* keeps to, when it keeps to one — to draw a saved form placed in another.
|
|
10
|
+
*/
|
|
11
|
+
export type PageRequest = {
|
|
12
|
+
model: string;
|
|
13
|
+
} | {
|
|
14
|
+
id: string;
|
|
15
|
+
version?: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The app's pages: a record of them by key — a model, a page's id, or
|
|
19
|
+
* `id@version` for a version kept to — or a function asked for each, which
|
|
20
|
+
* may answer at once or with a promise.
|
|
21
|
+
*/
|
|
22
|
+
export type PageFinder = Record<string, Page> | ((request: PageRequest) => Page | null | undefined | Promise<Page | null | undefined>);
|
|
23
|
+
/** The page the app gives for a request: from `pages`, and for a model from `relatedPages` after it. A promise when it answers later. */
|
|
24
|
+
export declare function findPage(options: Pick<ViewerOptions, 'pages' | 'relatedPages'>, request: PageRequest): Page | null | Promise<Page | null>;
|
|
6
25
|
/** The dialogs a page's widgets may open, made from the viewer's own options. */
|
|
7
26
|
export declare function pageDialogs(options: ViewerOptions): WidgetDialogs;
|