@fieldia/designer 0.27.0 → 0.29.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 +23 -0
- package/package.json +4 -4
- package/src/lib/approval-settings.d.mts +13 -0
- package/src/lib/approval-settings.d.ts +13 -0
- package/src/lib/approval-settings.js +49 -0
- package/src/lib/approval-settings.js.map +1 -0
- package/src/lib/approval-settings.mjs +46 -0
- package/src/lib/approval-settings.mjs.map +1 -0
- package/src/lib/assist-settings.d.mts +12 -0
- package/src/lib/assist-settings.d.ts +12 -0
- package/src/lib/assist-settings.js +64 -0
- package/src/lib/assist-settings.js.map +1 -0
- package/src/lib/assist-settings.mjs +61 -0
- package/src/lib/assist-settings.mjs.map +1 -0
- package/src/lib/bottom-bar.d.mts +22 -0
- package/src/lib/bottom-bar.d.ts +22 -0
- package/src/lib/bottom-bar.js +99 -0
- package/src/lib/bottom-bar.js.map +1 -0
- package/src/lib/bottom-bar.mjs +93 -0
- package/src/lib/bottom-bar.mjs.map +1 -0
- package/src/lib/designer.d.mts +21 -0
- package/src/lib/designer.d.ts +21 -0
- package/src/lib/designer.js +96 -0
- package/src/lib/designer.js.map +1 -1
- package/src/lib/designer.mjs +96 -0
- package/src/lib/designer.mjs.map +1 -1
- package/src/lib/icons.js +2 -0
- package/src/lib/icons.js.map +1 -1
- package/src/lib/icons.mjs +2 -0
- package/src/lib/icons.mjs.map +1 -1
- package/src/lib/inline-settings.js +9 -2
- package/src/lib/inline-settings.js.map +1 -1
- package/src/lib/inline-settings.mjs +9 -2
- package/src/lib/inline-settings.mjs.map +1 -1
- package/src/lib/input-changes.js +11 -0
- package/src/lib/input-changes.js.map +1 -1
- package/src/lib/input-changes.mjs +11 -0
- package/src/lib/input-changes.mjs.map +1 -1
- package/src/lib/input-commands.d.mts +11 -0
- package/src/lib/input-commands.d.ts +11 -0
- package/src/lib/input-commands.js +58 -0
- package/src/lib/input-commands.js.map +1 -1
- package/src/lib/input-commands.mjs +58 -0
- package/src/lib/input-commands.mjs.map +1 -1
- package/src/lib/kind-settings-inputs.d.mts +2 -0
- package/src/lib/kind-settings-inputs.d.ts +2 -0
- package/src/lib/kind-settings-inputs.js +97 -0
- package/src/lib/kind-settings-inputs.js.map +1 -1
- package/src/lib/kind-settings-inputs.mjs +96 -0
- package/src/lib/kind-settings-inputs.mjs.map +1 -1
- package/src/lib/kind-settings-structures.d.mts +2 -2
- package/src/lib/kind-settings-structures.d.ts +2 -2
- package/src/lib/kind-settings-structures.js +34 -0
- package/src/lib/kind-settings-structures.js.map +1 -1
- package/src/lib/kind-settings-structures.mjs +34 -0
- package/src/lib/kind-settings-structures.mjs.map +1 -1
- package/src/lib/kinds.js +6 -1
- package/src/lib/kinds.js.map +1 -1
- package/src/lib/kinds.mjs +6 -1
- package/src/lib/kinds.mjs.map +1 -1
- package/src/lib/list-commands.d.mts +4 -0
- package/src/lib/list-commands.d.ts +4 -0
- package/src/lib/list-commands.js +11 -0
- package/src/lib/list-commands.js.map +1 -1
- package/src/lib/list-commands.mjs +12 -1
- package/src/lib/list-commands.mjs.map +1 -1
- package/src/lib/list-properties.js +19 -1
- package/src/lib/list-properties.js.map +1 -1
- package/src/lib/list-properties.mjs +19 -1
- package/src/lib/list-properties.mjs.map +1 -1
- package/src/lib/locales/ar/changes.js +12 -0
- package/src/lib/locales/ar/changes.js.map +1 -1
- package/src/lib/locales/ar/changes.mjs +12 -0
- package/src/lib/locales/ar/changes.mjs.map +1 -1
- package/src/lib/locales/ar/kinds.js +1 -0
- package/src/lib/locales/ar/kinds.js.map +1 -1
- package/src/lib/locales/ar/kinds.mjs +1 -0
- package/src/lib/locales/ar/kinds.mjs.map +1 -1
- package/src/lib/locales/ar/list.js +4 -0
- package/src/lib/locales/ar/list.js.map +1 -1
- package/src/lib/locales/ar/list.mjs +4 -0
- package/src/lib/locales/ar/list.mjs.map +1 -1
- package/src/lib/locales/ar/panel.js +31 -0
- package/src/lib/locales/ar/panel.js.map +1 -1
- package/src/lib/locales/ar/panel.mjs +31 -0
- package/src/lib/locales/ar/panel.mjs.map +1 -1
- package/src/lib/locales/ar/questions.js +15 -0
- package/src/lib/locales/ar/questions.js.map +1 -1
- package/src/lib/locales/ar/questions.mjs +15 -0
- package/src/lib/locales/ar/questions.mjs.map +1 -1
- package/src/lib/locales/ar/refusals.js +10 -0
- package/src/lib/locales/ar/refusals.js.map +1 -1
- package/src/lib/locales/ar/refusals.mjs +10 -0
- package/src/lib/locales/ar/refusals.mjs.map +1 -1
- package/src/lib/locales/ar/settings-changes.js +9 -0
- package/src/lib/locales/ar/settings-changes.js.map +1 -1
- package/src/lib/locales/ar/settings-changes.mjs +9 -0
- package/src/lib/locales/ar/settings-changes.mjs.map +1 -1
- package/src/lib/locales/en/changes.d.mts +12 -0
- package/src/lib/locales/en/changes.d.ts +12 -0
- package/src/lib/locales/en/changes.js +13 -0
- package/src/lib/locales/en/changes.js.map +1 -1
- package/src/lib/locales/en/changes.mjs +13 -0
- package/src/lib/locales/en/changes.mjs.map +1 -1
- package/src/lib/locales/en/index.d.mts +70 -0
- package/src/lib/locales/en/index.d.ts +70 -0
- package/src/lib/locales/en/kinds.d.mts +1 -0
- package/src/lib/locales/en/kinds.d.ts +1 -0
- package/src/lib/locales/en/kinds.js +1 -0
- package/src/lib/locales/en/kinds.js.map +1 -1
- package/src/lib/locales/en/kinds.mjs +1 -0
- package/src/lib/locales/en/kinds.mjs.map +1 -1
- package/src/lib/locales/en/list.d.mts +4 -0
- package/src/lib/locales/en/list.d.ts +4 -0
- package/src/lib/locales/en/list.js +4 -0
- package/src/lib/locales/en/list.js.map +1 -1
- package/src/lib/locales/en/list.mjs +4 -0
- package/src/lib/locales/en/list.mjs.map +1 -1
- package/src/lib/locales/en/panel.d.mts +23 -0
- package/src/lib/locales/en/panel.d.ts +23 -0
- package/src/lib/locales/en/panel.js +25 -0
- package/src/lib/locales/en/panel.js.map +1 -1
- package/src/lib/locales/en/panel.mjs +25 -0
- package/src/lib/locales/en/panel.mjs.map +1 -1
- package/src/lib/locales/en/questions.d.mts +17 -0
- package/src/lib/locales/en/questions.d.ts +17 -0
- package/src/lib/locales/en/questions.js +17 -0
- package/src/lib/locales/en/questions.js.map +1 -1
- package/src/lib/locales/en/questions.mjs +17 -0
- package/src/lib/locales/en/questions.mjs.map +1 -1
- package/src/lib/locales/en/refusals.d.mts +10 -0
- package/src/lib/locales/en/refusals.d.ts +10 -0
- package/src/lib/locales/en/refusals.js +11 -0
- package/src/lib/locales/en/refusals.js.map +1 -1
- package/src/lib/locales/en/refusals.mjs +11 -0
- package/src/lib/locales/en/refusals.mjs.map +1 -1
- package/src/lib/locales/en/settings-changes.d.mts +7 -0
- package/src/lib/locales/en/settings-changes.d.ts +7 -0
- package/src/lib/locales/en/settings-changes.js +10 -0
- package/src/lib/locales/en/settings-changes.js.map +1 -1
- package/src/lib/locales/en/settings-changes.mjs +10 -0
- package/src/lib/locales/en/settings-changes.mjs.map +1 -1
- package/src/lib/page-checks.js +21 -2
- package/src/lib/page-checks.js.map +1 -1
- package/src/lib/page-checks.mjs +21 -2
- package/src/lib/page-checks.mjs.map +1 -1
- package/src/lib/panel-field.js +24 -1
- package/src/lib/panel-field.js.map +1 -1
- package/src/lib/panel-field.mjs +24 -1
- package/src/lib/panel-field.mjs.map +1 -1
- package/src/lib/panel-page.js +9 -1
- package/src/lib/panel-page.js.map +1 -1
- package/src/lib/panel-page.mjs +9 -1
- package/src/lib/panel-page.mjs.map +1 -1
- package/src/lib/styles-kinds.d.mts +1 -1
- package/src/lib/styles-kinds.d.ts +1 -1
- package/src/lib/styles-kinds.js +7 -0
- package/src/lib/styles-kinds.js.map +1 -1
- package/src/lib/styles-kinds.mjs +7 -0
- package/src/lib/styles-kinds.mjs.map +1 -1
- package/src/lib/styles.d.mts +1 -1
- package/src/lib/styles.d.ts +1 -1
- package/src/lib/styles.js +4 -2
- package/src/lib/styles.js.map +1 -1
- package/src/lib/styles.mjs +4 -2
- package/src/lib/styles.mjs.map +1 -1
- package/src/lib/survey-editor.js +19 -0
- package/src/lib/survey-editor.js.map +1 -1
- package/src/lib/survey-editor.mjs +19 -0
- package/src/lib/survey-editor.mjs.map +1 -1
- package/src/lib/table-commands.d.mts +1 -1
- package/src/lib/table-commands.d.ts +1 -1
- package/src/lib/table-panel.js +3 -2
- package/src/lib/table-panel.js.map +1 -1
- package/src/lib/table-panel.mjs +3 -2
- package/src/lib/table-panel.mjs.map +1 -1
- package/src/lib/toolbox.js +1 -1
- package/src/lib/toolbox.js.map +1 -1
- package/src/lib/toolbox.mjs +1 -1
- package/src/lib/toolbox.mjs.map +1 -1
- package/src/lib/try-drawer.js +7 -0
- package/src/lib/try-drawer.js.map +1 -1
- package/src/lib/try-drawer.mjs +7 -0
- package/src/lib/try-drawer.mjs.map +1 -1
package/README.md
CHANGED
|
@@ -120,6 +120,29 @@ close before the open, or limits on a record's screen, are refused in words),
|
|
|
120
120
|
`designer.setContinueLater(on)` and `designer.setOptionDetails(id, index, {
|
|
121
121
|
seats })` the rest; Publish lists each change.
|
|
122
122
|
|
|
123
|
+
## Approvals on a record's screen
|
|
124
|
+
|
|
125
|
+
With nothing picked, a record's screen's Rules tab offers **Approvals** — its
|
|
126
|
+
records wait for approval as the app's data source says — and once it is on,
|
|
127
|
+
**Locked while it waits** and **Open while it waits**: a tick for each field
|
|
128
|
+
that stays open while a record waits for a decision, every other one locked.
|
|
129
|
+
`designer.setApproval({ on, open, lock })` sets them (`on: false` takes the
|
|
130
|
+
setting away; `lock: false` leaves none open to name; a form of responses or a
|
|
131
|
+
list is refused in words); a field taken away goes from those left open, and
|
|
132
|
+
Publish lists each change.
|
|
133
|
+
|
|
134
|
+
## A text typed in several languages
|
|
135
|
+
|
|
136
|
+
A short answer's, a paragraph's or formatted text's own settings offer *Typed in
|
|
137
|
+
several languages*: on, it is typed in the page's language and English (or Arabic,
|
|
138
|
+
on an English page), its languages as chips — one added from the common ones, one
|
|
139
|
+
taken away while three or more are kept — and, while it is required, *Required in*,
|
|
140
|
+
the languages a required answer is typed in (none refused). `setLanguages(id,
|
|
141
|
+
["ar", "en"] | null)` and `setRequiredIn(id, ["en"] | null)` are the commands; a
|
|
142
|
+
model's field keeps the model's, and a field made a paragraph or formatted text
|
|
143
|
+
keeps its languages. Publish says what changed: "“Title”: typed in Arabic and
|
|
144
|
+
English".
|
|
145
|
+
|
|
123
146
|
## Trying a field's rules
|
|
124
147
|
|
|
125
148
|
Under a field's answer rules — on the panel's Rules tab, and in a survey
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldia/designer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Build Fieldia pages without writing JSON: an editing model with undo and versions, a survey editor, and a canvas.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://fieldia.dev",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"./package.json": "./package.json"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@fieldia/core": "0.
|
|
48
|
-
"@fieldia/viewer": "0.
|
|
49
|
-
"@fieldia/widgets": "0.
|
|
47
|
+
"@fieldia/core": "0.29.0",
|
|
48
|
+
"@fieldia/viewer": "0.29.0",
|
|
49
|
+
"@fieldia/widgets": "0.29.0",
|
|
50
50
|
"tslib": "^2.8.1"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Page } from '@fieldia/core';
|
|
2
|
+
import type { ElementFactory } from './chrome.mjs';
|
|
3
|
+
import type { Designer } from './designer.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Approvals on a record's screen (`approval`), on the screen's panel (panel-page.ts) beside its possible duplicates:
|
|
6
|
+
* whether its records wait for approval — who is asked, and in what order, is the app's data source's to say — whether
|
|
7
|
+
* a record is locked while it waits, and a tick for each field left open meanwhile, in the page's order. A form of
|
|
8
|
+
* responses, or a list, has no record to approve: no rows there.
|
|
9
|
+
*/
|
|
10
|
+
export declare function approvalSettings(el: ElementFactory, designer: Designer): {
|
|
11
|
+
rows: HTMLElement[];
|
|
12
|
+
update(page: Page): void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Page } from '@fieldia/core';
|
|
2
|
+
import type { ElementFactory } from './chrome';
|
|
3
|
+
import type { Designer } from './designer';
|
|
4
|
+
/**
|
|
5
|
+
* Approvals on a record's screen (`approval`), on the screen's panel (panel-page.ts) beside its possible duplicates:
|
|
6
|
+
* whether its records wait for approval — who is asked, and in what order, is the app's data source's to say — whether
|
|
7
|
+
* a record is locked while it waits, and a tick for each field left open meanwhile, in the page's order. A form of
|
|
8
|
+
* responses, or a list, has no record to approve: no rows there.
|
|
9
|
+
*/
|
|
10
|
+
export declare function approvalSettings(el: ElementFactory, designer: Designer): {
|
|
11
|
+
rows: HTMLElement[];
|
|
12
|
+
update(page: Page): void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.approvalSettings = approvalSettings;
|
|
4
|
+
const panel_controls_1 = require("./panel-controls");
|
|
5
|
+
/**
|
|
6
|
+
* Approvals on a record's screen (`approval`), on the screen's panel (panel-page.ts) beside its possible duplicates:
|
|
7
|
+
* whether its records wait for approval — who is asked, and in what order, is the app's data source's to say — whether
|
|
8
|
+
* a record is locked while it waits, and a tick for each field left open meanwhile, in the page's order. A form of
|
|
9
|
+
* responses, or a list, has no record to approve: no rows there.
|
|
10
|
+
*/
|
|
11
|
+
function approvalSettings(el, designer) {
|
|
12
|
+
const w = designer.words.panel;
|
|
13
|
+
const check = (label) => el('input', { type: 'checkbox', class: 'fd-check', 'aria-label': label });
|
|
14
|
+
const on = check(w.approvalOn);
|
|
15
|
+
on.addEventListener('change', () => designer.setApproval({ on: on.checked }));
|
|
16
|
+
const lock = check(w.approvalLockOn);
|
|
17
|
+
lock.addEventListener('change', () => designer.setApproval({ lock: lock.checked }));
|
|
18
|
+
const open = el('div', { class: 'fd-q-required-row', role: 'group', 'aria-label': w.approvalOpen });
|
|
19
|
+
const onRow = (0, panel_controls_1.setting)(el, 'rules', 'Approvals', on, { hint: w.approvalHint, words: w.approval });
|
|
20
|
+
const lockRow = (0, panel_controls_1.setting)(el, 'rules', 'Locked while it waits', lock, { hint: w.approvalLockHint, words: w.approvalLock });
|
|
21
|
+
const openRow = (0, panel_controls_1.setting)(el, 'rules', 'Open while it waits', open, { hint: w.approvalOpenHint, words: w.approvalOpen });
|
|
22
|
+
return {
|
|
23
|
+
rows: [onRow, lockRow, openRow],
|
|
24
|
+
update(page) {
|
|
25
|
+
onRow.hidden = page.data.kind !== 'record' || page.layout.type === 'list';
|
|
26
|
+
on.checked = !!page.approval;
|
|
27
|
+
lockRow.hidden = onRow.hidden || !page.approval;
|
|
28
|
+
lock.checked = page.approval?.lock !== false;
|
|
29
|
+
openRow.hidden = lockRow.hidden || page.approval?.lock === false;
|
|
30
|
+
// A tick for each field a person types in, in the page's order: one worked out from others is never typed in.
|
|
31
|
+
const fields = Object.entries(page.fields).filter(([, def]) => !def.compute && def.readonly !== true);
|
|
32
|
+
const key = JSON.stringify(fields.map(([name, def]) => [name, def.label]));
|
|
33
|
+
if (open.dataset['choices'] !== key) {
|
|
34
|
+
open.dataset['choices'] = key;
|
|
35
|
+
open.replaceChildren(...fields.map(([name, def]) => {
|
|
36
|
+
const tick = el('input', { type: 'checkbox', 'data-field': name });
|
|
37
|
+
tick.addEventListener('change', () => {
|
|
38
|
+
const ticked = new Set([...open.querySelectorAll('input:checked')].map((box) => box.dataset['field']));
|
|
39
|
+
designer.setApproval({ open: Object.keys(designer.getPage().fields).filter((field) => ticked.has(field)) });
|
|
40
|
+
});
|
|
41
|
+
return el('label', { class: 'fd-q-required' }, tick, el('span', {}, def.label));
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
for (const tick of open.querySelectorAll('input'))
|
|
45
|
+
tick.checked = !!page.approval?.open?.includes(tick.dataset['field']);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=approval-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-settings.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/approval-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { setting } from './panel-controls.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Approvals on a record's screen (`approval`), on the screen's panel (panel-page.ts) beside its possible duplicates:
|
|
4
|
+
* whether its records wait for approval — who is asked, and in what order, is the app's data source's to say — whether
|
|
5
|
+
* a record is locked while it waits, and a tick for each field left open meanwhile, in the page's order. A form of
|
|
6
|
+
* responses, or a list, has no record to approve: no rows there.
|
|
7
|
+
*/
|
|
8
|
+
export function approvalSettings(el, designer) {
|
|
9
|
+
const w = designer.words.panel;
|
|
10
|
+
const check = (label) => el('input', { type: 'checkbox', class: 'fd-check', 'aria-label': label });
|
|
11
|
+
const on = check(w.approvalOn);
|
|
12
|
+
on.addEventListener('change', () => designer.setApproval({ on: on.checked }));
|
|
13
|
+
const lock = check(w.approvalLockOn);
|
|
14
|
+
lock.addEventListener('change', () => designer.setApproval({ lock: lock.checked }));
|
|
15
|
+
const open = el('div', { class: 'fd-q-required-row', role: 'group', 'aria-label': w.approvalOpen });
|
|
16
|
+
const onRow = setting(el, 'rules', 'Approvals', on, { hint: w.approvalHint, words: w.approval });
|
|
17
|
+
const lockRow = setting(el, 'rules', 'Locked while it waits', lock, { hint: w.approvalLockHint, words: w.approvalLock });
|
|
18
|
+
const openRow = setting(el, 'rules', 'Open while it waits', open, { hint: w.approvalOpenHint, words: w.approvalOpen });
|
|
19
|
+
return {
|
|
20
|
+
rows: [onRow, lockRow, openRow],
|
|
21
|
+
update(page) {
|
|
22
|
+
onRow.hidden = page.data.kind !== 'record' || page.layout.type === 'list';
|
|
23
|
+
on.checked = !!page.approval;
|
|
24
|
+
lockRow.hidden = onRow.hidden || !page.approval;
|
|
25
|
+
lock.checked = page.approval?.lock !== false;
|
|
26
|
+
openRow.hidden = lockRow.hidden || page.approval?.lock === false;
|
|
27
|
+
// A tick for each field a person types in, in the page's order: one worked out from others is never typed in.
|
|
28
|
+
const fields = Object.entries(page.fields).filter(([, def]) => !def.compute && def.readonly !== true);
|
|
29
|
+
const key = JSON.stringify(fields.map(([name, def]) => [name, def.label]));
|
|
30
|
+
if (open.dataset['choices'] !== key) {
|
|
31
|
+
open.dataset['choices'] = key;
|
|
32
|
+
open.replaceChildren(...fields.map(([name, def]) => {
|
|
33
|
+
const tick = el('input', { type: 'checkbox', 'data-field': name });
|
|
34
|
+
tick.addEventListener('change', () => {
|
|
35
|
+
const ticked = new Set([...open.querySelectorAll('input:checked')].map((box) => box.dataset['field']));
|
|
36
|
+
designer.setApproval({ open: Object.keys(designer.getPage().fields).filter((field) => ticked.has(field)) });
|
|
37
|
+
});
|
|
38
|
+
return el('label', { class: 'fd-q-required' }, tick, el('span', {}, def.label));
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
for (const tick of open.querySelectorAll('input'))
|
|
42
|
+
tick.checked = !!page.approval?.open?.includes(tick.dataset['field']);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=approval-settings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-settings.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/approval-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Page } from '@fieldia/core';
|
|
2
|
+
import type { ElementFactory } from './chrome.mjs';
|
|
3
|
+
import type { Designer } from './designer.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* AI help's Fill from text (`suggest`) on the screen's panel (panel-page.ts), beside the rest of its rules: offered or
|
|
6
|
+
* not, its button's words, what it reads — words pasted or files, or a text field's own words — and the fields it may
|
|
7
|
+
* fill, a tick each (none ticked: every one shown that a person can set). A form's alone: a list fills nothing.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assistSettings(el: ElementFactory, designer: Designer): {
|
|
10
|
+
rows: HTMLElement[];
|
|
11
|
+
update(page: Page): void;
|
|
12
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Page } from '@fieldia/core';
|
|
2
|
+
import type { ElementFactory } from './chrome';
|
|
3
|
+
import type { Designer } from './designer';
|
|
4
|
+
/**
|
|
5
|
+
* AI help's Fill from text (`suggest`) on the screen's panel (panel-page.ts), beside the rest of its rules: offered or
|
|
6
|
+
* not, its button's words, what it reads — words pasted or files, or a text field's own words — and the fields it may
|
|
7
|
+
* fill, a tick each (none ticked: every one shown that a person can set). A form's alone: a list fills nothing.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assistSettings(el: ElementFactory, designer: Designer): {
|
|
10
|
+
rows: HTMLElement[];
|
|
11
|
+
update(page: Page): void;
|
|
12
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assistSettings = assistSettings;
|
|
4
|
+
const panel_controls_1 = require("./panel-controls");
|
|
5
|
+
/** The kinds Fill from text fills, and those whose words it reads. */
|
|
6
|
+
const FILLED = new Set(['char', 'text', 'html', 'integer', 'float', 'monetary', 'boolean', 'selection', 'date', 'datetime', 'many2one', 'many2many', 'one2many']);
|
|
7
|
+
const TEXTS = new Set(['char', 'text', 'html']);
|
|
8
|
+
/**
|
|
9
|
+
* AI help's Fill from text (`suggest`) on the screen's panel (panel-page.ts), beside the rest of its rules: offered or
|
|
10
|
+
* not, its button's words, what it reads — words pasted or files, or a text field's own words — and the fields it may
|
|
11
|
+
* fill, a tick each (none ticked: every one shown that a person can set). A form's alone: a list fills nothing.
|
|
12
|
+
*/
|
|
13
|
+
function assistSettings(el, designer) {
|
|
14
|
+
const w = designer.words.panel;
|
|
15
|
+
const focused = (node) => node.ownerDocument.activeElement === node;
|
|
16
|
+
const on = el('input', { type: 'checkbox', class: 'fd-check', 'aria-label': w.suggestOn });
|
|
17
|
+
on.addEventListener('change', () => designer.setSuggest(on.checked ? {} : null));
|
|
18
|
+
const label = el('input', { class: 'fd-input', 'aria-label': w.suggestLabel, placeholder: w.suggestLabelExample });
|
|
19
|
+
label.addEventListener('change', () => designer.setSuggest({ label: label.value.trim() || null }));
|
|
20
|
+
const from = el('select', { class: 'fd-input fd-select', 'aria-label': w.suggestFrom });
|
|
21
|
+
from.addEventListener('change', () => designer.setSuggest({ fromField: from.value || null }));
|
|
22
|
+
const fields = el('div', { class: 'fd-q-required-row', role: 'group', 'aria-label': w.suggestFields });
|
|
23
|
+
const onRow = (0, panel_controls_1.setting)(el, 'rules', 'Fill from text', on, { hint: w.suggestHint, words: w.suggest });
|
|
24
|
+
const labelRow = (0, panel_controls_1.setting)(el, 'rules', 'Its button’s words', label, { words: w.suggestLabel });
|
|
25
|
+
const fromRow = (0, panel_controls_1.setting)(el, 'rules', 'Fills from', from, { hint: w.suggestFromHint, words: w.suggestFrom });
|
|
26
|
+
const fieldsRow = (0, panel_controls_1.setting)(el, 'rules', 'Fields it may fill', fields, { hint: w.suggestFieldsHint, words: w.suggestFields });
|
|
27
|
+
return {
|
|
28
|
+
rows: [onRow, labelRow, fromRow, fieldsRow],
|
|
29
|
+
update(page) {
|
|
30
|
+
const suggest = page.suggest;
|
|
31
|
+
onRow.hidden = page.layout.type === 'list';
|
|
32
|
+
on.checked = !!suggest;
|
|
33
|
+
labelRow.hidden = fromRow.hidden = fieldsRow.hidden = onRow.hidden || !suggest;
|
|
34
|
+
if (!suggest)
|
|
35
|
+
return;
|
|
36
|
+
if (!focused(label))
|
|
37
|
+
label.value = suggest.label ?? '';
|
|
38
|
+
const texts = Object.entries(page.fields).filter(([, def]) => TEXTS.has(def.type));
|
|
39
|
+
const choices = [['', w.suggestPasted], ...texts.map(([name, def]) => [name, def.label])];
|
|
40
|
+
const key = JSON.stringify(choices);
|
|
41
|
+
if (from.dataset['choices'] !== key) {
|
|
42
|
+
from.dataset['choices'] = key;
|
|
43
|
+
from.replaceChildren(...choices.map(([value, words]) => el('option', { value }, words)));
|
|
44
|
+
}
|
|
45
|
+
from.value = suggest.fromField ?? '';
|
|
46
|
+
const fillable = Object.entries(page.fields).filter(([name, def]) => FILLED.has(def.type) && def.readonly !== true && def.compute === undefined && name !== suggest.fromField);
|
|
47
|
+
const fillKey = JSON.stringify(fillable.map(([name, def]) => [name, def.label]));
|
|
48
|
+
if (fields.dataset['choices'] !== fillKey) {
|
|
49
|
+
fields.dataset['choices'] = fillKey;
|
|
50
|
+
fields.replaceChildren(...fillable.map(([name, def]) => {
|
|
51
|
+
const tick = el('input', { type: 'checkbox', 'data-field': name });
|
|
52
|
+
tick.addEventListener('change', () => {
|
|
53
|
+
const ticked = new Set([...fields.querySelectorAll('input:checked')].map((box) => box.dataset['field']));
|
|
54
|
+
designer.setSuggest({ fields: Object.keys(designer.getPage().fields).filter((field) => ticked.has(field)) });
|
|
55
|
+
});
|
|
56
|
+
return el('label', { class: 'fd-q-required' }, tick, el('span', {}, def.label));
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
for (const tick of fields.querySelectorAll('input'))
|
|
60
|
+
tick.checked = !!suggest.fields?.includes(tick.dataset['field']);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=assist-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assist-settings.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/assist-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { setting } from './panel-controls.mjs';
|
|
2
|
+
/** The kinds Fill from text fills, and those whose words it reads. */
|
|
3
|
+
const FILLED = new Set(['char', 'text', 'html', 'integer', 'float', 'monetary', 'boolean', 'selection', 'date', 'datetime', 'many2one', 'many2many', 'one2many']);
|
|
4
|
+
const TEXTS = new Set(['char', 'text', 'html']);
|
|
5
|
+
/**
|
|
6
|
+
* AI help's Fill from text (`suggest`) on the screen's panel (panel-page.ts), beside the rest of its rules: offered or
|
|
7
|
+
* not, its button's words, what it reads — words pasted or files, or a text field's own words — and the fields it may
|
|
8
|
+
* fill, a tick each (none ticked: every one shown that a person can set). A form's alone: a list fills nothing.
|
|
9
|
+
*/
|
|
10
|
+
export function assistSettings(el, designer) {
|
|
11
|
+
const w = designer.words.panel;
|
|
12
|
+
const focused = (node) => node.ownerDocument.activeElement === node;
|
|
13
|
+
const on = el('input', { type: 'checkbox', class: 'fd-check', 'aria-label': w.suggestOn });
|
|
14
|
+
on.addEventListener('change', () => designer.setSuggest(on.checked ? {} : null));
|
|
15
|
+
const label = el('input', { class: 'fd-input', 'aria-label': w.suggestLabel, placeholder: w.suggestLabelExample });
|
|
16
|
+
label.addEventListener('change', () => designer.setSuggest({ label: label.value.trim() || null }));
|
|
17
|
+
const from = el('select', { class: 'fd-input fd-select', 'aria-label': w.suggestFrom });
|
|
18
|
+
from.addEventListener('change', () => designer.setSuggest({ fromField: from.value || null }));
|
|
19
|
+
const fields = el('div', { class: 'fd-q-required-row', role: 'group', 'aria-label': w.suggestFields });
|
|
20
|
+
const onRow = setting(el, 'rules', 'Fill from text', on, { hint: w.suggestHint, words: w.suggest });
|
|
21
|
+
const labelRow = setting(el, 'rules', 'Its button’s words', label, { words: w.suggestLabel });
|
|
22
|
+
const fromRow = setting(el, 'rules', 'Fills from', from, { hint: w.suggestFromHint, words: w.suggestFrom });
|
|
23
|
+
const fieldsRow = setting(el, 'rules', 'Fields it may fill', fields, { hint: w.suggestFieldsHint, words: w.suggestFields });
|
|
24
|
+
return {
|
|
25
|
+
rows: [onRow, labelRow, fromRow, fieldsRow],
|
|
26
|
+
update(page) {
|
|
27
|
+
const suggest = page.suggest;
|
|
28
|
+
onRow.hidden = page.layout.type === 'list';
|
|
29
|
+
on.checked = !!suggest;
|
|
30
|
+
labelRow.hidden = fromRow.hidden = fieldsRow.hidden = onRow.hidden || !suggest;
|
|
31
|
+
if (!suggest)
|
|
32
|
+
return;
|
|
33
|
+
if (!focused(label))
|
|
34
|
+
label.value = suggest.label ?? '';
|
|
35
|
+
const texts = Object.entries(page.fields).filter(([, def]) => TEXTS.has(def.type));
|
|
36
|
+
const choices = [['', w.suggestPasted], ...texts.map(([name, def]) => [name, def.label])];
|
|
37
|
+
const key = JSON.stringify(choices);
|
|
38
|
+
if (from.dataset['choices'] !== key) {
|
|
39
|
+
from.dataset['choices'] = key;
|
|
40
|
+
from.replaceChildren(...choices.map(([value, words]) => el('option', { value }, words)));
|
|
41
|
+
}
|
|
42
|
+
from.value = suggest.fromField ?? '';
|
|
43
|
+
const fillable = Object.entries(page.fields).filter(([name, def]) => FILLED.has(def.type) && def.readonly !== true && def.compute === undefined && name !== suggest.fromField);
|
|
44
|
+
const fillKey = JSON.stringify(fillable.map(([name, def]) => [name, def.label]));
|
|
45
|
+
if (fields.dataset['choices'] !== fillKey) {
|
|
46
|
+
fields.dataset['choices'] = fillKey;
|
|
47
|
+
fields.replaceChildren(...fillable.map(([name, def]) => {
|
|
48
|
+
const tick = el('input', { type: 'checkbox', 'data-field': name });
|
|
49
|
+
tick.addEventListener('change', () => {
|
|
50
|
+
const ticked = new Set([...fields.querySelectorAll('input:checked')].map((box) => box.dataset['field']));
|
|
51
|
+
designer.setSuggest({ fields: Object.keys(designer.getPage().fields).filter((field) => ticked.has(field)) });
|
|
52
|
+
});
|
|
53
|
+
return el('label', { class: 'fd-q-required' }, tick, el('span', {}, def.label));
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
for (const tick of fields.querySelectorAll('input'))
|
|
57
|
+
tick.checked = !!suggest.fields?.includes(tick.dataset['field']);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=assist-settings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assist-settings.mjs","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/assist-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bar kept at the foot of the screen (`position: sticky` with a `bottom`) never hides what a person works on, and
|
|
3
|
+
* keeping it clear never hides it under the bar at the top instead (WCAG 2.4.11, both ways). A control focused in the
|
|
4
|
+
* area the bar floats over — by Tab or Shift+Tab, by a press — is moved up from behind the bar once the engine's own
|
|
5
|
+
* scroll on focus is done (that scroll knows nothing of it), but never so far that its top goes under the room the
|
|
6
|
+
* top bar keeps (the scroller's `scroll-padding-top`, the designer bar's): where it cannot fit between the two, its
|
|
7
|
+
* top wins. The bar stays where it is; the area's end is the bar's own place in the flow, where it rests once the area
|
|
8
|
+
* is scrolled to its end. Where the bar is not at the foot (sticky no longer: a wide screen's rail beside its card),
|
|
9
|
+
* nothing is moved.
|
|
10
|
+
*
|
|
11
|
+
* No `scroll-margin-bottom` on what is focused: an element taller than the room between the bars would then be
|
|
12
|
+
* aligned by its end as the engine scrolls to it — walking up by Shift+Tab, its top under the top bar.
|
|
13
|
+
*/
|
|
14
|
+
export declare function keepClearOfBar(bar: HTMLElement, area: HTMLElement): () => void;
|
|
15
|
+
/**
|
|
16
|
+
* An element moved up from behind the bar at the foot (with a little air), as far as that takes — but its top never
|
|
17
|
+
* under the room its scroller keeps at its top (`scroll-padding-top`: the designer bar's, on the page). Where both
|
|
18
|
+
* cannot hold, the top wins. Nothing moves for an element clear of the bar already.
|
|
19
|
+
*/
|
|
20
|
+
export declare function clearOfBar(bar: HTMLElement, element: HTMLElement): void;
|
|
21
|
+
/** The room the bar takes now, as `keepClearOfBar` measured it: 0 where it is not at the foot. */
|
|
22
|
+
export declare const barRoom: (area: HTMLElement) => number;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bar kept at the foot of the screen (`position: sticky` with a `bottom`) never hides what a person works on, and
|
|
3
|
+
* keeping it clear never hides it under the bar at the top instead (WCAG 2.4.11, both ways). A control focused in the
|
|
4
|
+
* area the bar floats over — by Tab or Shift+Tab, by a press — is moved up from behind the bar once the engine's own
|
|
5
|
+
* scroll on focus is done (that scroll knows nothing of it), but never so far that its top goes under the room the
|
|
6
|
+
* top bar keeps (the scroller's `scroll-padding-top`, the designer bar's): where it cannot fit between the two, its
|
|
7
|
+
* top wins. The bar stays where it is; the area's end is the bar's own place in the flow, where it rests once the area
|
|
8
|
+
* is scrolled to its end. Where the bar is not at the foot (sticky no longer: a wide screen's rail beside its card),
|
|
9
|
+
* nothing is moved.
|
|
10
|
+
*
|
|
11
|
+
* No `scroll-margin-bottom` on what is focused: an element taller than the room between the bars would then be
|
|
12
|
+
* aligned by its end as the engine scrolls to it — walking up by Shift+Tab, its top under the top bar.
|
|
13
|
+
*/
|
|
14
|
+
export declare function keepClearOfBar(bar: HTMLElement, area: HTMLElement): () => void;
|
|
15
|
+
/**
|
|
16
|
+
* An element moved up from behind the bar at the foot (with a little air), as far as that takes — but its top never
|
|
17
|
+
* under the room its scroller keeps at its top (`scroll-padding-top`: the designer bar's, on the page). Where both
|
|
18
|
+
* cannot hold, the top wins. Nothing moves for an element clear of the bar already.
|
|
19
|
+
*/
|
|
20
|
+
export declare function clearOfBar(bar: HTMLElement, element: HTMLElement): void;
|
|
21
|
+
/** The room the bar takes now, as `keepClearOfBar` measured it: 0 where it is not at the foot. */
|
|
22
|
+
export declare const barRoom: (area: HTMLElement) => number;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.barRoom = void 0;
|
|
4
|
+
exports.keepClearOfBar = keepClearOfBar;
|
|
5
|
+
exports.clearOfBar = clearOfBar;
|
|
6
|
+
/** The air left between a control and the bar at the foot of the screen. */
|
|
7
|
+
const AIR = 8;
|
|
8
|
+
/**
|
|
9
|
+
* A bar kept at the foot of the screen (`position: sticky` with a `bottom`) never hides what a person works on, and
|
|
10
|
+
* keeping it clear never hides it under the bar at the top instead (WCAG 2.4.11, both ways). A control focused in the
|
|
11
|
+
* area the bar floats over — by Tab or Shift+Tab, by a press — is moved up from behind the bar once the engine's own
|
|
12
|
+
* scroll on focus is done (that scroll knows nothing of it), but never so far that its top goes under the room the
|
|
13
|
+
* top bar keeps (the scroller's `scroll-padding-top`, the designer bar's): where it cannot fit between the two, its
|
|
14
|
+
* top wins. The bar stays where it is; the area's end is the bar's own place in the flow, where it rests once the area
|
|
15
|
+
* is scrolled to its end. Where the bar is not at the foot (sticky no longer: a wide screen's rail beside its card),
|
|
16
|
+
* nothing is moved.
|
|
17
|
+
*
|
|
18
|
+
* No `scroll-margin-bottom` on what is focused: an element taller than the room between the bars would then be
|
|
19
|
+
* aligned by its end as the engine scrolls to it — walking up by Shift+Tab, its top under the top bar.
|
|
20
|
+
*/
|
|
21
|
+
function keepClearOfBar(bar, area) {
|
|
22
|
+
const view = bar.ownerDocument.defaultView;
|
|
23
|
+
/** Whether the bar has been in the page: once taken out of it (a new drawer in its place), the watch ends. */
|
|
24
|
+
let placed = false;
|
|
25
|
+
const measure = () => {
|
|
26
|
+
if (!bar.isConnected)
|
|
27
|
+
return placed ? stop() : undefined;
|
|
28
|
+
placed = true;
|
|
29
|
+
const style = view?.getComputedStyle(bar);
|
|
30
|
+
const atFoot = !!style && style.position === 'sticky' && style.bottom !== 'auto' && !bar.hidden;
|
|
31
|
+
const room = atFoot ? Math.ceil(bar.getBoundingClientRect().height + (parseFloat(style.bottom) || 0) + AIR) : 0;
|
|
32
|
+
area.style.setProperty('--fd-foot-room', `${room}px`);
|
|
33
|
+
};
|
|
34
|
+
const onFocus = (event) => {
|
|
35
|
+
const control = event.target;
|
|
36
|
+
if (!control?.getBoundingClientRect || !view)
|
|
37
|
+
return;
|
|
38
|
+
// After the engine's own scroll on focus, which comes after the focus event.
|
|
39
|
+
view.requestAnimationFrame(() => {
|
|
40
|
+
if ((0, exports.barRoom)(area) && view.document.activeElement === control)
|
|
41
|
+
clearOfBar(bar, control);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
area.addEventListener('focusin', onFocus);
|
|
45
|
+
const ResizeWatcher = view?.ResizeObserver;
|
|
46
|
+
const watcher = ResizeWatcher ? new ResizeWatcher(measure) : null;
|
|
47
|
+
// The bar's own size, and the area's width: a container query that puts the bar at the foot or takes it away.
|
|
48
|
+
watcher?.observe(bar);
|
|
49
|
+
watcher?.observe(area);
|
|
50
|
+
measure();
|
|
51
|
+
function stop() {
|
|
52
|
+
watcher?.disconnect();
|
|
53
|
+
area.removeEventListener('focusin', onFocus);
|
|
54
|
+
area.style.removeProperty('--fd-foot-room');
|
|
55
|
+
}
|
|
56
|
+
return stop;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The scroller that can move an element up by `by`: its nearest ancestor that scrolls up and down with that much room
|
|
60
|
+
* left — a row of tabs that scrolls sideways is no such scroller, though its `overflow-y` reads `auto` — else the page.
|
|
61
|
+
*/
|
|
62
|
+
function scrollerOf(element, by) {
|
|
63
|
+
const doc = element.ownerDocument;
|
|
64
|
+
const view = doc.defaultView;
|
|
65
|
+
for (let at = element.parentElement; at && at !== doc.body && at !== doc.documentElement; at = at.parentElement) {
|
|
66
|
+
const overflow = view?.getComputedStyle(at).overflowY ?? 'visible';
|
|
67
|
+
if ((overflow === 'auto' || overflow === 'scroll') && at.scrollHeight - at.clientHeight - at.scrollTop >= by)
|
|
68
|
+
return at;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* An element moved up from behind the bar at the foot (with a little air), as far as that takes — but its top never
|
|
74
|
+
* under the room its scroller keeps at its top (`scroll-padding-top`: the designer bar's, on the page). Where both
|
|
75
|
+
* cannot hold, the top wins. Nothing moves for an element clear of the bar already.
|
|
76
|
+
*/
|
|
77
|
+
function clearOfBar(bar, element) {
|
|
78
|
+
const box = element.getBoundingClientRect();
|
|
79
|
+
const limit = bar.getBoundingClientRect().top - AIR;
|
|
80
|
+
if (box.bottom <= limit)
|
|
81
|
+
return;
|
|
82
|
+
const doc = element.ownerDocument;
|
|
83
|
+
const view = doc.defaultView;
|
|
84
|
+
const want = box.bottom - limit;
|
|
85
|
+
const own = scrollerOf(element, want);
|
|
86
|
+
const scroller = own ?? (doc.scrollingElement ?? doc.documentElement);
|
|
87
|
+
const top = (own ? own.getBoundingClientRect().top : 0) + (parseFloat(view?.getComputedStyle(scroller).scrollPaddingTop ?? '') || 0);
|
|
88
|
+
const by = Math.min(want, box.top - top);
|
|
89
|
+
if (by <= 0)
|
|
90
|
+
return;
|
|
91
|
+
if (own)
|
|
92
|
+
own.scrollTop += by;
|
|
93
|
+
else
|
|
94
|
+
view?.scrollBy(0, by);
|
|
95
|
+
}
|
|
96
|
+
/** The room the bar takes now, as `keepClearOfBar` measured it: 0 where it is not at the foot. */
|
|
97
|
+
const barRoom = (area) => parseFloat(area.style.getPropertyValue('--fd-foot-room')) || 0;
|
|
98
|
+
exports.barRoom = barRoom;
|
|
99
|
+
//# sourceMappingURL=bottom-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bottom-bar.js","sourceRoot":"","sources":["../../../../../libs/designer/src/lib/bottom-bar.ts"],"names":[],"mappings":"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"}
|