@fieldia/viewer 0.10.0 → 0.12.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 +6 -4
- package/bundle/fieldia.js.map +4 -4
- package/package.json +3 -3
- package/src/lib/attachment-preview.d.mts +27 -0
- package/src/lib/attachment-preview.d.ts +27 -0
- package/src/lib/attachment-preview.js +89 -0
- package/src/lib/attachment-preview.js.map +1 -0
- package/src/lib/attachment-preview.mjs +86 -0
- package/src/lib/attachment-preview.mjs.map +1 -0
- package/src/lib/dialog.d.mts +31 -2
- package/src/lib/dialog.d.ts +31 -2
- package/src/lib/dialog.js +158 -30
- package/src/lib/dialog.js.map +1 -1
- package/src/lib/dialog.mjs +155 -30
- package/src/lib/dialog.mjs.map +1 -1
- package/src/lib/hotkeys.d.mts +11 -0
- package/src/lib/hotkeys.d.ts +11 -0
- package/src/lib/hotkeys.js +34 -0
- package/src/lib/hotkeys.js.map +1 -0
- package/src/lib/hotkeys.mjs +30 -0
- package/src/lib/hotkeys.mjs.map +1 -0
- package/src/lib/labels.d.mts +39 -0
- package/src/lib/labels.d.ts +39 -0
- package/src/lib/labels.js +23 -0
- package/src/lib/labels.js.map +1 -1
- package/src/lib/labels.mjs +23 -0
- package/src/lib/labels.mjs.map +1 -1
- package/src/lib/list.d.mts +5 -2
- package/src/lib/list.d.ts +5 -2
- package/src/lib/list.js +6 -6
- package/src/lib/list.js.map +1 -1
- package/src/lib/list.mjs +6 -6
- package/src/lib/list.mjs.map +1 -1
- package/src/lib/locales/ar.js +23 -0
- package/src/lib/locales/ar.js.map +1 -1
- package/src/lib/locales/ar.mjs +23 -0
- package/src/lib/locales/ar.mjs.map +1 -1
- package/src/lib/locales/de.js +23 -0
- package/src/lib/locales/de.js.map +1 -1
- package/src/lib/locales/de.mjs +23 -0
- package/src/lib/locales/de.mjs.map +1 -1
- package/src/lib/locales/fr.js +23 -0
- package/src/lib/locales/fr.js.map +1 -1
- package/src/lib/locales/fr.mjs +23 -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 +30 -0
- package/src/lib/open.d.ts +30 -0
- package/src/lib/open.js +92 -0
- package/src/lib/open.js.map +1 -0
- package/src/lib/open.mjs +89 -0
- package/src/lib/open.mjs.map +1 -0
- package/src/lib/place.d.mts +2 -0
- package/src/lib/place.d.ts +2 -0
- package/src/lib/place.js.map +1 -1
- package/src/lib/place.mjs.map +1 -1
- package/src/lib/record-bar.d.mts +56 -0
- package/src/lib/record-bar.d.ts +56 -0
- package/src/lib/record-bar.js +237 -0
- package/src/lib/record-bar.js.map +1 -0
- package/src/lib/record-bar.mjs +234 -0
- package/src/lib/record-bar.mjs.map +1 -0
- package/src/lib/record-styles.d.mts +9 -0
- package/src/lib/record-styles.d.ts +9 -0
- package/src/lib/record-styles.js +83 -0
- package/src/lib/record-styles.js.map +1 -0
- package/src/lib/record-styles.mjs +79 -0
- package/src/lib/record-styles.mjs.map +1 -0
- package/src/lib/related.d.mts +26 -3
- package/src/lib/related.d.ts +26 -3
- package/src/lib/related.js +37 -10
- package/src/lib/related.js.map +1 -1
- package/src/lib/related.mjs +36 -10
- package/src/lib/related.mjs.map +1 -1
- package/src/lib/say.d.mts +11 -0
- package/src/lib/say.d.ts +11 -0
- package/src/lib/say.js +61 -0
- package/src/lib/say.js.map +1 -0
- package/src/lib/say.mjs +58 -0
- package/src/lib/say.mjs.map +1 -0
- package/src/lib/tab-strip.d.mts +17 -0
- package/src/lib/tab-strip.d.ts +17 -0
- package/src/lib/tab-strip.js +51 -0
- package/src/lib/tab-strip.js.map +1 -0
- package/src/lib/tab-strip.mjs +48 -0
- package/src/lib/tab-strip.mjs.map +1 -0
- package/src/lib/value-words.d.mts +10 -0
- package/src/lib/value-words.d.ts +10 -0
- package/src/lib/value-words.js +38 -0
- package/src/lib/value-words.js.map +1 -0
- package/src/lib/value-words.mjs +35 -0
- package/src/lib/value-words.mjs.map +1 -0
- package/src/lib/viewer.d.mts +54 -5
- package/src/lib/viewer.d.ts +54 -5
- package/src/lib/viewer.js +924 -297
- package/src/lib/viewer.js.map +1 -1
- package/src/lib/viewer.mjs +926 -299
- package/src/lib/viewer.mjs.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldia/viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Mount a Fieldia page in any web page: plain DOM, no framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://fieldia.dev",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"./package.json": "./package.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@fieldia/core": "0.
|
|
31
|
-
"@fieldia/widgets": "0.
|
|
30
|
+
"@fieldia/core": "0.12.0",
|
|
31
|
+
"@fieldia/widgets": "0.12.0",
|
|
32
32
|
"tslib": "^2.8.1"
|
|
33
33
|
},
|
|
34
34
|
"sideEffects": false,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AttachmentPreview, DataSource, Form, FormState, Page } from '@fieldia/core';
|
|
2
|
+
import { type El } from './dom.mjs';
|
|
3
|
+
import type { ViewerLabels } from './labels.mjs';
|
|
4
|
+
/** What the preview beside a sheet needs of the viewer that draws it. */
|
|
5
|
+
export interface PreviewContext {
|
|
6
|
+
doc: Document;
|
|
7
|
+
el: El;
|
|
8
|
+
form: Form;
|
|
9
|
+
page: Page;
|
|
10
|
+
node: AttachmentPreview;
|
|
11
|
+
dataSource: DataSource | undefined;
|
|
12
|
+
labels: ViewerLabels;
|
|
13
|
+
fill(template: string, values: Record<string, string | number>): string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The record's main attachment beside its sheet, as Flectra's
|
|
17
|
+
* o_attachment_preview: a PDF in the browser's own viewer or a picture, with
|
|
18
|
+
* Previous and Next when it has several, and a link that opens it on its own.
|
|
19
|
+
* From a file field of the page, or the data source's `attachments` of the
|
|
20
|
+
* record — asked again when the form shows another record, and after a save.
|
|
21
|
+
* Hidden while there is nothing to show.
|
|
22
|
+
*/
|
|
23
|
+
export declare function attachmentPreview(context: PreviewContext): {
|
|
24
|
+
element: HTMLElement;
|
|
25
|
+
update(state: FormState): void;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AttachmentPreview, DataSource, Form, FormState, Page } from '@fieldia/core';
|
|
2
|
+
import { type El } from './dom';
|
|
3
|
+
import type { ViewerLabels } from './labels';
|
|
4
|
+
/** What the preview beside a sheet needs of the viewer that draws it. */
|
|
5
|
+
export interface PreviewContext {
|
|
6
|
+
doc: Document;
|
|
7
|
+
el: El;
|
|
8
|
+
form: Form;
|
|
9
|
+
page: Page;
|
|
10
|
+
node: AttachmentPreview;
|
|
11
|
+
dataSource: DataSource | undefined;
|
|
12
|
+
labels: ViewerLabels;
|
|
13
|
+
fill(template: string, values: Record<string, string | number>): string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The record's main attachment beside its sheet, as Flectra's
|
|
17
|
+
* o_attachment_preview: a PDF in the browser's own viewer or a picture, with
|
|
18
|
+
* Previous and Next when it has several, and a link that opens it on its own.
|
|
19
|
+
* From a file field of the page, or the data source's `attachments` of the
|
|
20
|
+
* record — asked again when the form shows another record, and after a save.
|
|
21
|
+
* Hidden while there is nothing to show.
|
|
22
|
+
*/
|
|
23
|
+
export declare function attachmentPreview(context: PreviewContext): {
|
|
24
|
+
element: HTMLElement;
|
|
25
|
+
update(state: FormState): void;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachmentPreview = attachmentPreview;
|
|
4
|
+
const widgets_1 = require("@fieldia/widgets");
|
|
5
|
+
const dom_1 = require("./dom");
|
|
6
|
+
/** A file the browser shows itself: a picture or a PDF. */
|
|
7
|
+
const showable = (file) => /^image\//.test(file.type) || /pdf/i.test(file.type) || /\.pdf$/i.test(file.name);
|
|
8
|
+
const filesOf = (value) => (Array.isArray(value) ? value : value ? [value] : []).filter((file) => file && typeof file === 'object' && 'name' in file);
|
|
9
|
+
/**
|
|
10
|
+
* The record's main attachment beside its sheet, as Flectra's
|
|
11
|
+
* o_attachment_preview: a PDF in the browser's own viewer or a picture, with
|
|
12
|
+
* Previous and Next when it has several, and a link that opens it on its own.
|
|
13
|
+
* From a file field of the page, or the data source's `attachments` of the
|
|
14
|
+
* record — asked again when the form shows another record, and after a save.
|
|
15
|
+
* Hidden while there is nothing to show.
|
|
16
|
+
*/
|
|
17
|
+
function attachmentPreview(context) {
|
|
18
|
+
const { el, form, labels, node } = context;
|
|
19
|
+
const name = el('span', { class: 'fd-attachment-name', dir: 'auto' });
|
|
20
|
+
const count = el('span', { class: 'fd-attachment-count', dir: 'ltr' });
|
|
21
|
+
const previous = el('button', { type: 'button', class: 'fd-button fd-record-step', 'aria-label': labels.previousAttachment }, el('span', { 'aria-hidden': 'true', class: 'fd-record-arrow' }, '‹'));
|
|
22
|
+
const next = el('button', { type: 'button', class: 'fd-button fd-record-step', 'aria-label': labels.nextAttachment }, el('span', { 'aria-hidden': 'true', class: 'fd-record-arrow' }, '›'));
|
|
23
|
+
const open = el('a', { class: 'fd-button fd-button-link fd-attachment-open', target: '_blank', rel: 'noopener' }, labels.openAttachment);
|
|
24
|
+
const body = el('div', { class: 'fd-attachment-body' });
|
|
25
|
+
const element = el('aside', { class: 'fd-attachment-preview', hidden: '' }, el('div', { class: 'fd-attachment-head' }, name, count, previous, next, open), body);
|
|
26
|
+
let files = [];
|
|
27
|
+
let at = 0;
|
|
28
|
+
let shown = null;
|
|
29
|
+
/** The record the attachments were asked for, and the latest ask: an older answer is let go. */
|
|
30
|
+
let askedFor;
|
|
31
|
+
let asks = 0;
|
|
32
|
+
let status;
|
|
33
|
+
let held;
|
|
34
|
+
function draw() {
|
|
35
|
+
shown?.free();
|
|
36
|
+
shown = null;
|
|
37
|
+
const file = files[at];
|
|
38
|
+
if (!file)
|
|
39
|
+
return body.replaceChildren();
|
|
40
|
+
const made = (0, widgets_1.fileShown)(context.doc, file);
|
|
41
|
+
shown = made;
|
|
42
|
+
body.replaceChildren(...(made ? [made.element] : []));
|
|
43
|
+
(0, dom_1.setText)(name, file.name);
|
|
44
|
+
(0, dom_1.setText)(count, files.length > 1 ? context.fill(labels.recordAt, { n: at + 1, total: files.length }) : '');
|
|
45
|
+
(0, dom_1.setHidden)(previous, files.length < 2);
|
|
46
|
+
(0, dom_1.setHidden)(next, files.length < 2);
|
|
47
|
+
(0, dom_1.setAttr)(open, 'href', made?.url ?? null);
|
|
48
|
+
(0, dom_1.setAttr)(element, 'aria-label', context.fill(labels.attachment, { name: file.name }));
|
|
49
|
+
}
|
|
50
|
+
const step = (by) => {
|
|
51
|
+
at = (at + by + files.length) % files.length;
|
|
52
|
+
draw();
|
|
53
|
+
};
|
|
54
|
+
previous.addEventListener('click', () => step(-1));
|
|
55
|
+
next.addEventListener('click', () => step(1));
|
|
56
|
+
const take = (found) => {
|
|
57
|
+
files = found.filter(showable);
|
|
58
|
+
at = 0;
|
|
59
|
+
draw();
|
|
60
|
+
show();
|
|
61
|
+
};
|
|
62
|
+
const show = () => (0, dom_1.setHidden)(element, form.node('#preview').invisible || !files.length);
|
|
63
|
+
function ask(state) {
|
|
64
|
+
const source = context.dataSource;
|
|
65
|
+
const ask = ++asks;
|
|
66
|
+
askedFor = state.recordId;
|
|
67
|
+
if (state.recordId == null || !source?.attachments || context.page.data.kind !== 'record')
|
|
68
|
+
return take([]);
|
|
69
|
+
source.attachments({ model: context.page.data.model, id: state.recordId, fields: context.page.fields }).then((found) => ask === asks && take(found), () => ask === asks && take([]));
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
element,
|
|
73
|
+
update(state) {
|
|
74
|
+
if (node.field) {
|
|
75
|
+
const value = state.values[node.field];
|
|
76
|
+
if (value !== held) {
|
|
77
|
+
held = value;
|
|
78
|
+
take(filesOf(value));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (state.status !== 'loading' && state.status !== 'idle' && (state.recordId !== askedFor || (state.status === 'saved' && status !== 'saved')))
|
|
82
|
+
ask(state);
|
|
83
|
+
status = state.status;
|
|
84
|
+
show();
|
|
85
|
+
},
|
|
86
|
+
destroy: () => shown?.free(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=attachment-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-preview.js","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/attachment-preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { fileShown } from '@fieldia/widgets';
|
|
2
|
+
import { setAttr, setHidden, setText } from './dom.mjs';
|
|
3
|
+
/** A file the browser shows itself: a picture or a PDF. */
|
|
4
|
+
const showable = (file) => /^image\//.test(file.type) || /pdf/i.test(file.type) || /\.pdf$/i.test(file.name);
|
|
5
|
+
const filesOf = (value) => (Array.isArray(value) ? value : value ? [value] : []).filter((file) => file && typeof file === 'object' && 'name' in file);
|
|
6
|
+
/**
|
|
7
|
+
* The record's main attachment beside its sheet, as Flectra's
|
|
8
|
+
* o_attachment_preview: a PDF in the browser's own viewer or a picture, with
|
|
9
|
+
* Previous and Next when it has several, and a link that opens it on its own.
|
|
10
|
+
* From a file field of the page, or the data source's `attachments` of the
|
|
11
|
+
* record — asked again when the form shows another record, and after a save.
|
|
12
|
+
* Hidden while there is nothing to show.
|
|
13
|
+
*/
|
|
14
|
+
export function attachmentPreview(context) {
|
|
15
|
+
const { el, form, labels, node } = context;
|
|
16
|
+
const name = el('span', { class: 'fd-attachment-name', dir: 'auto' });
|
|
17
|
+
const count = el('span', { class: 'fd-attachment-count', dir: 'ltr' });
|
|
18
|
+
const previous = el('button', { type: 'button', class: 'fd-button fd-record-step', 'aria-label': labels.previousAttachment }, el('span', { 'aria-hidden': 'true', class: 'fd-record-arrow' }, '‹'));
|
|
19
|
+
const next = el('button', { type: 'button', class: 'fd-button fd-record-step', 'aria-label': labels.nextAttachment }, el('span', { 'aria-hidden': 'true', class: 'fd-record-arrow' }, '›'));
|
|
20
|
+
const open = el('a', { class: 'fd-button fd-button-link fd-attachment-open', target: '_blank', rel: 'noopener' }, labels.openAttachment);
|
|
21
|
+
const body = el('div', { class: 'fd-attachment-body' });
|
|
22
|
+
const element = el('aside', { class: 'fd-attachment-preview', hidden: '' }, el('div', { class: 'fd-attachment-head' }, name, count, previous, next, open), body);
|
|
23
|
+
let files = [];
|
|
24
|
+
let at = 0;
|
|
25
|
+
let shown = null;
|
|
26
|
+
/** The record the attachments were asked for, and the latest ask: an older answer is let go. */
|
|
27
|
+
let askedFor;
|
|
28
|
+
let asks = 0;
|
|
29
|
+
let status;
|
|
30
|
+
let held;
|
|
31
|
+
function draw() {
|
|
32
|
+
shown?.free();
|
|
33
|
+
shown = null;
|
|
34
|
+
const file = files[at];
|
|
35
|
+
if (!file)
|
|
36
|
+
return body.replaceChildren();
|
|
37
|
+
const made = fileShown(context.doc, file);
|
|
38
|
+
shown = made;
|
|
39
|
+
body.replaceChildren(...(made ? [made.element] : []));
|
|
40
|
+
setText(name, file.name);
|
|
41
|
+
setText(count, files.length > 1 ? context.fill(labels.recordAt, { n: at + 1, total: files.length }) : '');
|
|
42
|
+
setHidden(previous, files.length < 2);
|
|
43
|
+
setHidden(next, files.length < 2);
|
|
44
|
+
setAttr(open, 'href', made?.url ?? null);
|
|
45
|
+
setAttr(element, 'aria-label', context.fill(labels.attachment, { name: file.name }));
|
|
46
|
+
}
|
|
47
|
+
const step = (by) => {
|
|
48
|
+
at = (at + by + files.length) % files.length;
|
|
49
|
+
draw();
|
|
50
|
+
};
|
|
51
|
+
previous.addEventListener('click', () => step(-1));
|
|
52
|
+
next.addEventListener('click', () => step(1));
|
|
53
|
+
const take = (found) => {
|
|
54
|
+
files = found.filter(showable);
|
|
55
|
+
at = 0;
|
|
56
|
+
draw();
|
|
57
|
+
show();
|
|
58
|
+
};
|
|
59
|
+
const show = () => setHidden(element, form.node('#preview').invisible || !files.length);
|
|
60
|
+
function ask(state) {
|
|
61
|
+
const source = context.dataSource;
|
|
62
|
+
const ask = ++asks;
|
|
63
|
+
askedFor = state.recordId;
|
|
64
|
+
if (state.recordId == null || !source?.attachments || context.page.data.kind !== 'record')
|
|
65
|
+
return take([]);
|
|
66
|
+
source.attachments({ model: context.page.data.model, id: state.recordId, fields: context.page.fields }).then((found) => ask === asks && take(found), () => ask === asks && take([]));
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
element,
|
|
70
|
+
update(state) {
|
|
71
|
+
if (node.field) {
|
|
72
|
+
const value = state.values[node.field];
|
|
73
|
+
if (value !== held) {
|
|
74
|
+
held = value;
|
|
75
|
+
take(filesOf(value));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (state.status !== 'loading' && state.status !== 'idle' && (state.recordId !== askedFor || (state.status === 'saved' && status !== 'saved')))
|
|
79
|
+
ask(state);
|
|
80
|
+
status = state.status;
|
|
81
|
+
show();
|
|
82
|
+
},
|
|
83
|
+
destroy: () => shown?.free(),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=attachment-preview.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-preview.mjs","sourceRoot":"","sources":["../../../../../libs/viewer/src/lib/attachment-preview.ts"],"names":[],"mappings":"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"}
|
package/src/lib/dialog.d.mts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { PageLook, RecordId, RelatedRecord, Values } from '@fieldia/core';
|
|
1
|
+
import type { PageLook, PanelSide, RecordId, RelatedRecord, Values } from '@fieldia/core';
|
|
2
2
|
import { type Skin, type ViewerOptions } from './viewer.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* A page in a dialog: a new related record, a line to edit, a quick task. The
|
|
5
5
|
* dialog saves (Save & Close) or closes without saving (Discard, ×, Escape);
|
|
6
6
|
* the page's own Save and Discard stay hidden. The focus moves into the dialog,
|
|
7
7
|
* Tab stays inside it, and the focus goes back where it was when it closes.
|
|
8
|
+
* A side panel (`openFormPanel`) is the same box at the edge of the screen.
|
|
8
9
|
*/
|
|
9
10
|
export interface FormDialogOptions extends ViewerOptions {
|
|
10
11
|
title: string;
|
|
@@ -26,12 +27,40 @@ export interface FormDialogOptions extends ViewerOptions {
|
|
|
26
27
|
look?: PageLook;
|
|
27
28
|
}
|
|
28
29
|
export interface FormDialogResult {
|
|
29
|
-
/** True when Save & Close was pressed and the form accepted. */
|
|
30
|
+
/** True when Save & Close (Done, in a panel in "values" mode) was pressed and the form accepted. */
|
|
30
31
|
saved: boolean;
|
|
31
32
|
recordId: RecordId | null;
|
|
32
33
|
values: Values;
|
|
33
34
|
}
|
|
35
|
+
/** A page in a side panel: the dialog's options, with the edge it comes from and its depth in place of a size. */
|
|
36
|
+
export interface FormPanelOptions extends Omit<FormDialogOptions, 'size'> {
|
|
37
|
+
/**
|
|
38
|
+
* The edge it comes from: `end` (the default: the end of the line, the right,
|
|
39
|
+
* or the left right to left) or `start`, as the page reads; or `left`,
|
|
40
|
+
* `right`, `top` or `bottom` of the screen, whatever the page's direction.
|
|
41
|
+
*/
|
|
42
|
+
side?: PanelSide;
|
|
43
|
+
/** A panel at the end, start, left or right: about 420, 560 (the default) or 720 pixels wide on a wide screen; the whole screen on a phone. */
|
|
44
|
+
width?: 'narrow' | 'medium' | 'wide';
|
|
45
|
+
/** A panel at the top or bottom, the whole width: about 40, 60 (the default) or 85 in a hundred of the screen's height; the whole screen on a phone. */
|
|
46
|
+
height?: 'short' | 'medium' | 'tall';
|
|
47
|
+
}
|
|
48
|
+
/** The first box to type or choose in, where a page opened takes the focus. */
|
|
49
|
+
export declare const FIRST_FIELD = "input:not([type=\"hidden\"]), select, textarea, [contenteditable=\"true\"]";
|
|
50
|
+
/** The box of the first field shown that takes the focus as the record opens (a node's `focus`), if there is one. */
|
|
51
|
+
export declare function focusField(scope: Element): HTMLElement | null;
|
|
34
52
|
export declare function openFormDialog(options: FormDialogOptions): Promise<FormDialogResult>;
|
|
53
|
+
/**
|
|
54
|
+
* A page in a side panel: the dialog's twin, at full height along the
|
|
55
|
+
* inline-end edge (the left, right to left) unless it names another `side` —
|
|
56
|
+
* the whole width along the top or the bottom — the page behind dimmed but in
|
|
57
|
+
* sight; a full-screen sheet on a phone, from above for the top, from below
|
|
58
|
+
* for the rest. It saves, or in "values" mode hands back its values with
|
|
59
|
+
* Done, as the dialog does; Escape and × ask first when there are changes to
|
|
60
|
+
* lose. A dialog opened from it sits above it, and a panel opened from it
|
|
61
|
+
* stacks over it, this one stepped back from its own edge.
|
|
62
|
+
*/
|
|
63
|
+
export declare function openFormPanel(options: FormPanelOptions): Promise<FormDialogResult>;
|
|
35
64
|
export interface SearchDialogOptions {
|
|
36
65
|
title: string;
|
|
37
66
|
/** Finds records for what is typed: the field's own search, filter and all. */
|
package/src/lib/dialog.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { PageLook, RecordId, RelatedRecord, Values } from '@fieldia/core';
|
|
1
|
+
import type { PageLook, PanelSide, RecordId, RelatedRecord, Values } from '@fieldia/core';
|
|
2
2
|
import { type Skin, type ViewerOptions } from './viewer';
|
|
3
3
|
/**
|
|
4
4
|
* A page in a dialog: a new related record, a line to edit, a quick task. The
|
|
5
5
|
* dialog saves (Save & Close) or closes without saving (Discard, ×, Escape);
|
|
6
6
|
* the page's own Save and Discard stay hidden. The focus moves into the dialog,
|
|
7
7
|
* Tab stays inside it, and the focus goes back where it was when it closes.
|
|
8
|
+
* A side panel (`openFormPanel`) is the same box at the edge of the screen.
|
|
8
9
|
*/
|
|
9
10
|
export interface FormDialogOptions extends ViewerOptions {
|
|
10
11
|
title: string;
|
|
@@ -26,12 +27,40 @@ export interface FormDialogOptions extends ViewerOptions {
|
|
|
26
27
|
look?: PageLook;
|
|
27
28
|
}
|
|
28
29
|
export interface FormDialogResult {
|
|
29
|
-
/** True when Save & Close was pressed and the form accepted. */
|
|
30
|
+
/** True when Save & Close (Done, in a panel in "values" mode) was pressed and the form accepted. */
|
|
30
31
|
saved: boolean;
|
|
31
32
|
recordId: RecordId | null;
|
|
32
33
|
values: Values;
|
|
33
34
|
}
|
|
35
|
+
/** A page in a side panel: the dialog's options, with the edge it comes from and its depth in place of a size. */
|
|
36
|
+
export interface FormPanelOptions extends Omit<FormDialogOptions, 'size'> {
|
|
37
|
+
/**
|
|
38
|
+
* The edge it comes from: `end` (the default: the end of the line, the right,
|
|
39
|
+
* or the left right to left) or `start`, as the page reads; or `left`,
|
|
40
|
+
* `right`, `top` or `bottom` of the screen, whatever the page's direction.
|
|
41
|
+
*/
|
|
42
|
+
side?: PanelSide;
|
|
43
|
+
/** A panel at the end, start, left or right: about 420, 560 (the default) or 720 pixels wide on a wide screen; the whole screen on a phone. */
|
|
44
|
+
width?: 'narrow' | 'medium' | 'wide';
|
|
45
|
+
/** A panel at the top or bottom, the whole width: about 40, 60 (the default) or 85 in a hundred of the screen's height; the whole screen on a phone. */
|
|
46
|
+
height?: 'short' | 'medium' | 'tall';
|
|
47
|
+
}
|
|
48
|
+
/** The first box to type or choose in, where a page opened takes the focus. */
|
|
49
|
+
export declare const FIRST_FIELD = "input:not([type=\"hidden\"]), select, textarea, [contenteditable=\"true\"]";
|
|
50
|
+
/** The box of the first field shown that takes the focus as the record opens (a node's `focus`), if there is one. */
|
|
51
|
+
export declare function focusField(scope: Element): HTMLElement | null;
|
|
34
52
|
export declare function openFormDialog(options: FormDialogOptions): Promise<FormDialogResult>;
|
|
53
|
+
/**
|
|
54
|
+
* A page in a side panel: the dialog's twin, at full height along the
|
|
55
|
+
* inline-end edge (the left, right to left) unless it names another `side` —
|
|
56
|
+
* the whole width along the top or the bottom — the page behind dimmed but in
|
|
57
|
+
* sight; a full-screen sheet on a phone, from above for the top, from below
|
|
58
|
+
* for the rest. It saves, or in "values" mode hands back its values with
|
|
59
|
+
* Done, as the dialog does; Escape and × ask first when there are changes to
|
|
60
|
+
* lose. A dialog opened from it sits above it, and a panel opened from it
|
|
61
|
+
* stacks over it, this one stepped back from its own edge.
|
|
62
|
+
*/
|
|
63
|
+
export declare function openFormPanel(options: FormPanelOptions): Promise<FormDialogResult>;
|
|
35
64
|
export interface SearchDialogOptions {
|
|
36
65
|
title: string;
|
|
37
66
|
/** Finds records for what is typed: the field's own search, filter and all. */
|