@fieldia/widgets 0.11.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/package.json +2 -2
- package/src/index.d.mts +2 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +6 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +2 -0
- package/src/index.mjs.map +1 -1
- package/src/lib/badge.d.mts +8 -0
- package/src/lib/badge.d.ts +8 -0
- package/src/lib/badge.js +37 -0
- package/src/lib/badge.js.map +1 -0
- package/src/lib/badge.mjs +33 -0
- package/src/lib/badge.mjs.map +1 -0
- package/src/lib/calendar.d.mts +3 -1
- package/src/lib/calendar.d.ts +3 -1
- package/src/lib/calendar.js +17 -1
- package/src/lib/calendar.js.map +1 -1
- package/src/lib/calendar.mjs +17 -1
- package/src/lib/calendar.mjs.map +1 -1
- package/src/lib/cards.js +12 -4
- package/src/lib/cards.js.map +1 -1
- package/src/lib/cards.mjs +13 -5
- package/src/lib/cards.mjs.map +1 -1
- package/src/lib/choice-images.js +1 -1
- package/src/lib/choice-images.js.map +1 -1
- package/src/lib/choice-images.mjs +1 -1
- package/src/lib/choice-images.mjs.map +1 -1
- package/src/lib/choice-tags.js +2 -2
- package/src/lib/choice-tags.js.map +1 -1
- package/src/lib/choice-tags.mjs +2 -2
- package/src/lib/choice-tags.mjs.map +1 -1
- package/src/lib/colour.d.mts +11 -0
- package/src/lib/colour.d.ts +11 -0
- package/src/lib/colour.js +114 -0
- package/src/lib/colour.js.map +1 -0
- package/src/lib/colour.mjs +110 -0
- package/src/lib/colour.mjs.map +1 -0
- package/src/lib/copy.d.mts +8 -0
- package/src/lib/copy.d.ts +8 -0
- package/src/lib/copy.js +58 -0
- package/src/lib/copy.js.map +1 -0
- package/src/lib/copy.mjs +54 -0
- package/src/lib/copy.mjs.map +1 -0
- package/src/lib/date-range.d.mts +2 -0
- package/src/lib/date-range.d.ts +2 -0
- package/src/lib/date-range.js +220 -0
- package/src/lib/date-range.js.map +1 -0
- package/src/lib/date-range.mjs +216 -0
- package/src/lib/date-range.mjs.map +1 -0
- package/src/lib/display.d.mts +25 -1
- package/src/lib/display.d.ts +25 -1
- package/src/lib/display.js +42 -2
- package/src/lib/display.js.map +1 -1
- package/src/lib/display.mjs +39 -2
- package/src/lib/display.mjs.map +1 -1
- package/src/lib/distribution.d.mts +13 -0
- package/src/lib/distribution.d.ts +13 -0
- package/src/lib/distribution.js +159 -0
- package/src/lib/distribution.js.map +1 -0
- package/src/lib/distribution.mjs +152 -0
- package/src/lib/distribution.mjs.map +1 -0
- package/src/lib/duration.d.mts +18 -0
- package/src/lib/duration.d.ts +18 -0
- package/src/lib/duration.js +137 -0
- package/src/lib/duration.js.map +1 -0
- package/src/lib/duration.mjs +128 -0
- package/src/lib/duration.mjs.map +1 -0
- package/src/lib/embed.d.mts +3 -0
- package/src/lib/embed.d.ts +3 -0
- package/src/lib/embed.js +97 -0
- package/src/lib/embed.js.map +1 -0
- package/src/lib/embed.mjs +92 -0
- package/src/lib/embed.mjs.map +1 -0
- package/src/lib/extras.js +6 -0
- package/src/lib/extras.js.map +1 -1
- package/src/lib/extras.mjs +6 -0
- package/src/lib/extras.mjs.map +1 -1
- package/src/lib/files.d.mts +11 -0
- package/src/lib/files.d.ts +11 -0
- package/src/lib/files.js +19 -0
- package/src/lib/files.js.map +1 -1
- package/src/lib/files.mjs +18 -0
- package/src/lib/files.mjs.map +1 -1
- package/src/lib/kind-parts.d.mts +4 -3
- package/src/lib/kind-parts.d.ts +4 -3
- package/src/lib/kind-parts.js +5 -3
- package/src/lib/kind-parts.js.map +1 -1
- package/src/lib/kind-parts.mjs +5 -3
- package/src/lib/kind-parts.mjs.map +1 -1
- package/src/lib/labels.d.mts +37 -0
- package/src/lib/labels.d.ts +37 -0
- package/src/lib/labels.js +28 -0
- package/src/lib/labels.js.map +1 -1
- package/src/lib/labels.mjs +28 -0
- package/src/lib/labels.mjs.map +1 -1
- package/src/lib/lines.d.mts +12 -2
- package/src/lib/lines.d.ts +12 -2
- package/src/lib/lines.js +251 -15
- package/src/lib/lines.js.map +1 -1
- package/src/lib/lines.mjs +250 -16
- package/src/lib/lines.mjs.map +1 -1
- package/src/lib/links-table.d.mts +11 -0
- package/src/lib/links-table.d.ts +11 -0
- package/src/lib/links-table.js +116 -0
- package/src/lib/links-table.js.map +1 -0
- package/src/lib/links-table.mjs +112 -0
- package/src/lib/links-table.mjs.map +1 -0
- package/src/lib/locales/ar.js +28 -0
- package/src/lib/locales/ar.js.map +1 -1
- package/src/lib/locales/ar.mjs +28 -0
- package/src/lib/locales/ar.mjs.map +1 -1
- package/src/lib/locales/de.js +28 -0
- package/src/lib/locales/de.js.map +1 -1
- package/src/lib/locales/de.mjs +28 -0
- package/src/lib/locales/de.mjs.map +1 -1
- package/src/lib/locales/fr.js +28 -0
- package/src/lib/locales/fr.js.map +1 -1
- package/src/lib/locales/fr.mjs +28 -0
- package/src/lib/locales/fr.mjs.map +1 -1
- package/src/lib/payments.d.mts +2 -0
- package/src/lib/payments.d.ts +2 -0
- package/src/lib/payments.js +94 -0
- package/src/lib/payments.js.map +1 -0
- package/src/lib/payments.mjs +90 -0
- package/src/lib/payments.mjs.map +1 -0
- package/src/lib/popup.d.mts +11 -0
- package/src/lib/popup.d.ts +11 -0
- package/src/lib/popup.js +48 -0
- package/src/lib/popup.js.map +1 -0
- package/src/lib/popup.mjs +45 -0
- package/src/lib/popup.mjs.map +1 -0
- package/src/lib/priority.d.mts +10 -0
- package/src/lib/priority.d.ts +10 -0
- package/src/lib/priority.js +59 -0
- package/src/lib/priority.js.map +1 -0
- package/src/lib/priority.mjs +55 -0
- package/src/lib/priority.mjs.map +1 -0
- package/src/lib/progress.js +3 -0
- package/src/lib/progress.js.map +1 -1
- package/src/lib/progress.mjs +3 -0
- package/src/lib/progress.mjs.map +1 -1
- package/src/lib/properties.js +100 -9
- package/src/lib/properties.js.map +1 -1
- package/src/lib/properties.mjs +100 -9
- package/src/lib/properties.mjs.map +1 -1
- package/src/lib/read-text.d.mts +25 -0
- package/src/lib/read-text.d.ts +25 -0
- package/src/lib/read-text.js +102 -0
- package/src/lib/read-text.js.map +1 -0
- package/src/lib/read-text.mjs +98 -0
- package/src/lib/read-text.mjs.map +1 -0
- package/src/lib/relations.d.mts +12 -0
- package/src/lib/relations.d.ts +12 -0
- package/src/lib/relations.js +99 -8
- package/src/lib/relations.js.map +1 -1
- package/src/lib/relations.mjs +97 -8
- package/src/lib/relations.mjs.map +1 -1
- package/src/lib/slider.js +1 -1
- package/src/lib/slider.js.map +1 -1
- package/src/lib/slider.mjs +1 -1
- package/src/lib/slider.mjs.map +1 -1
- package/src/lib/state-dot.d.mts +2 -0
- package/src/lib/state-dot.d.ts +2 -0
- package/src/lib/state-dot.js +107 -0
- package/src/lib/state-dot.js.map +1 -0
- package/src/lib/state-dot.mjs +103 -0
- package/src/lib/state-dot.mjs.map +1 -0
- package/src/lib/statusbar.js +151 -14
- package/src/lib/statusbar.js.map +1 -1
- package/src/lib/statusbar.mjs +151 -14
- package/src/lib/statusbar.mjs.map +1 -1
- package/src/lib/styles-business.d.mts +8 -0
- package/src/lib/styles-business.d.ts +8 -0
- package/src/lib/styles-business.js +120 -0
- package/src/lib/styles-business.js.map +1 -0
- package/src/lib/styles-business.mjs +117 -0
- package/src/lib/styles-business.mjs.map +1 -0
- package/src/lib/styles-kinds.d.mts +1 -1
- package/src/lib/styles-kinds.d.ts +1 -1
- package/src/lib/styles-kinds.js +1 -1
- package/src/lib/styles-kinds.mjs +1 -1
- package/src/lib/styles-sheet.d.mts +6 -0
- package/src/lib/styles-sheet.d.ts +6 -0
- package/src/lib/styles-sheet.js +123 -0
- package/src/lib/styles-sheet.js.map +1 -0
- package/src/lib/styles-sheet.mjs +120 -0
- package/src/lib/styles-sheet.mjs.map +1 -0
- package/src/lib/styles.js +142 -10
- package/src/lib/styles.js.map +1 -1
- package/src/lib/styles.mjs +142 -10
- package/src/lib/styles.mjs.map +1 -1
- package/src/lib/tax-totals.d.mts +2 -0
- package/src/lib/tax-totals.d.ts +2 -0
- package/src/lib/tax-totals.js +92 -0
- package/src/lib/tax-totals.js.map +1 -0
- package/src/lib/tax-totals.mjs +88 -0
- package/src/lib/tax-totals.mjs.map +1 -0
- package/src/lib/timer.d.mts +4 -0
- package/src/lib/timer.d.ts +4 -0
- package/src/lib/timer.js +62 -0
- package/src/lib/timer.js.map +1 -0
- package/src/lib/timer.mjs +57 -0
- package/src/lib/timer.mjs.map +1 -0
- package/src/lib/widgets.d.mts +18 -3
- package/src/lib/widgets.d.ts +18 -3
- package/src/lib/widgets.js +63 -5
- package/src/lib/widgets.js.map +1 -1
- package/src/lib/widgets.mjs +63 -5
- package/src/lib/widgets.mjs.map +1 -1
- package/src/lib/yes-no.js +1 -1
- package/src/lib/yes-no.js.map +1 -1
- package/src/lib/yes-no.mjs +1 -1
- package/src/lib/yes-no.mjs.map +1 -1
package/src/lib/properties.js
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.propertiesWidget = void 0;
|
|
4
|
+
const kind_parts_1 = require("./kind-parts");
|
|
4
5
|
const widgets_1 = require("./widgets");
|
|
5
6
|
/**
|
|
6
7
|
* A properties field, one row per property, each edited with the widget for
|
|
7
8
|
* its type: text, numbers, yes/no, a choice, a date. The field's `definitions`
|
|
8
|
-
* say which properties there are;
|
|
9
|
-
*
|
|
9
|
+
* say which properties there are; with `definitionsFrom` the app gives them,
|
|
10
|
+
* those the linked record keeps (Flectra's definition_record), loaded again as
|
|
11
|
+
* the link changes; without either, each property is worked out from its
|
|
12
|
+
* value. The properties stay one value: an object by property name.
|
|
13
|
+
*
|
|
14
|
+
* Options: `columns` (1 or 2), the properties side by side, as Flectra's
|
|
15
|
+
* columns="2"; `add`, with definitions from a linked record, "Add a property"
|
|
16
|
+
* under them — its name and kind, kept on that record through the app.
|
|
10
17
|
*/
|
|
11
18
|
/** "lift_access" → "Lift access". */
|
|
12
19
|
const humanize = (name) => {
|
|
13
20
|
const words = name.replace(/_/g, ' ').trim();
|
|
14
21
|
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
15
22
|
};
|
|
23
|
+
/** A property's name from its label: "Locker number" → "locker_number". */
|
|
24
|
+
const nameFrom = (label) => label
|
|
25
|
+
.normalize('NFKD')
|
|
26
|
+
.replace(/[̀-ͯ]/g, '')
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
29
|
+
.replace(/^_+|_+$/g, '')
|
|
30
|
+
.replace(/^(\d)/, 'p_$1') || 'property';
|
|
16
31
|
/** A property's type, from what it holds. */
|
|
17
32
|
function guess(name, value) {
|
|
18
33
|
const label = humanize(name);
|
|
@@ -24,9 +39,14 @@ function guess(name, value) {
|
|
|
24
39
|
return { name, label, type: 'date' };
|
|
25
40
|
return { name, label, type: 'char' };
|
|
26
41
|
}
|
|
42
|
+
/** The kinds a property added in place may be, in the order their words name them. */
|
|
43
|
+
const KINDS = ['char', 'text', 'integer', 'float', 'boolean', 'date'];
|
|
27
44
|
const propertiesWidget = (context) => {
|
|
28
|
-
const { form, name, field, node, id, document } = context;
|
|
45
|
+
const { form, name, field, node, id, document, labels, locale } = context;
|
|
46
|
+
const make = (0, kind_parts_1.maker)(document);
|
|
47
|
+
const words = (0, kind_parts_1.wordsFor)(labels, locale);
|
|
29
48
|
const declared = field.type === 'properties' ? field.definitions : undefined;
|
|
49
|
+
const fromRecord = field.type === 'properties' && !!field.definitionsFrom;
|
|
30
50
|
const current = () => {
|
|
31
51
|
const value = form.getState().values[name];
|
|
32
52
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
@@ -38,9 +58,65 @@ const propertiesWidget = (context) => {
|
|
|
38
58
|
// Property values are plain JSON: text, numbers, yes/no, a choice, a date.
|
|
39
59
|
setValue: (property, value) => form.setValue(name, { ...current(), [property]: value }),
|
|
40
60
|
};
|
|
41
|
-
const
|
|
42
|
-
element
|
|
43
|
-
|
|
61
|
+
const list = make('div', { class: 'fd-properties-list' });
|
|
62
|
+
const element = make('div', { class: 'fd-properties', role: 'group' }, list);
|
|
63
|
+
const columns = node.options?.['columns'];
|
|
64
|
+
if (columns === 2)
|
|
65
|
+
element.dataset['columns'] = '2';
|
|
66
|
+
const status = make('div', { class: 'fd-help', role: 'status', hidden: '' });
|
|
67
|
+
element.append(status);
|
|
68
|
+
// Adding one in place: its name and its kind, then Add.
|
|
69
|
+
const adding = fromRecord && node.options?.['add'] === true;
|
|
70
|
+
const addButton = make('button', { type: 'button', class: 'fd-button fd-button-link fd-property-add', hidden: '' }, `+ ${words.addProperty}`);
|
|
71
|
+
const newName = make('input', { type: 'text', class: 'fd-input', 'aria-label': words.propertyName, placeholder: words.propertyName, autocomplete: 'off' });
|
|
72
|
+
const kindNames = words.propertyTypes.split('|');
|
|
73
|
+
const newKind = make('select', { class: 'fd-input fd-select', 'aria-label': words.propertyType }, ...KINDS.map((kind, i) => make('option', { value: kind }, kindNames[i] ?? kind)));
|
|
74
|
+
const confirm = make('button', { type: 'button', class: 'fd-button fd-button-primary' }, words.add);
|
|
75
|
+
const cancel = make('button', { type: 'button', class: 'fd-button' }, words.cancel);
|
|
76
|
+
const newRow = make('div', { class: 'fd-property-new', hidden: '' }, newName, newKind, confirm, cancel);
|
|
77
|
+
if (adding)
|
|
78
|
+
element.append(addButton, newRow);
|
|
79
|
+
let focusAfter = null;
|
|
80
|
+
const closeNew = () => {
|
|
81
|
+
newRow.hidden = true;
|
|
82
|
+
addButton.hidden = false;
|
|
83
|
+
};
|
|
84
|
+
addButton.addEventListener('click', () => {
|
|
85
|
+
newRow.hidden = false;
|
|
86
|
+
addButton.hidden = true;
|
|
87
|
+
newName.value = '';
|
|
88
|
+
newKind.value = 'char';
|
|
89
|
+
newName.focus();
|
|
90
|
+
});
|
|
91
|
+
cancel.addEventListener('click', () => {
|
|
92
|
+
closeNew();
|
|
93
|
+
addButton.focus();
|
|
94
|
+
});
|
|
95
|
+
const add = () => {
|
|
96
|
+
const label = newName.value.trim();
|
|
97
|
+
if (!label)
|
|
98
|
+
return newName.focus();
|
|
99
|
+
const taken = new Set(rows.map((row) => row.definition.name));
|
|
100
|
+
let made = nameFrom(label);
|
|
101
|
+
for (let n = 2; taken.has(made); n++)
|
|
102
|
+
made = `${nameFrom(label)}_${n}`;
|
|
103
|
+
focusAfter = made;
|
|
104
|
+
closeNew();
|
|
105
|
+
void form.addDefinition(name, { name: made, label, type: newKind.value });
|
|
106
|
+
};
|
|
107
|
+
confirm.addEventListener('click', add);
|
|
108
|
+
newRow.addEventListener('keydown', (event) => {
|
|
109
|
+
if (event.key === 'Enter' && event.target === newName) {
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
add();
|
|
112
|
+
}
|
|
113
|
+
else if (event.key === 'Escape') {
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
event.stopPropagation();
|
|
116
|
+
closeNew();
|
|
117
|
+
addButton.focus();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
44
120
|
let rows = [];
|
|
45
121
|
let drawn = '';
|
|
46
122
|
function draw(definitions) {
|
|
@@ -53,7 +129,7 @@ const propertiesWidget = (context) => {
|
|
|
53
129
|
const widget = (0, widgets_1.createWidget)({ ...context, form: properties, name: definition.name, field: propertyField, node: propertyNode, id: rowId });
|
|
54
130
|
return { definition, widget };
|
|
55
131
|
});
|
|
56
|
-
|
|
132
|
+
list.replaceChildren(...rows.map(({ definition, widget }) => {
|
|
57
133
|
const row = document.createElement('div');
|
|
58
134
|
row.className = 'fd-property';
|
|
59
135
|
row.dataset['type'] = definition.type;
|
|
@@ -64,13 +140,17 @@ const propertiesWidget = (context) => {
|
|
|
64
140
|
return row;
|
|
65
141
|
}));
|
|
66
142
|
}
|
|
143
|
+
// Definitions from the linked record: asked for once shown, then again as the link changes.
|
|
144
|
+
if (fromRecord && !form.getState().definitions[name])
|
|
145
|
+
form.loadDefinitions(name);
|
|
67
146
|
return {
|
|
68
147
|
element,
|
|
69
|
-
focus: () => rows[0]?.widget.focus(),
|
|
148
|
+
focus: () => (rows[0]?.widget ?? { focus: () => addButton.focus() }).focus(),
|
|
70
149
|
destroy: () => rows.forEach((row) => row.widget.destroy?.()),
|
|
71
150
|
update(state) {
|
|
72
151
|
const values = current();
|
|
73
|
-
const
|
|
152
|
+
const loaded = fromRecord ? form.getState().definitions[name] : undefined;
|
|
153
|
+
const definitions = fromRecord ? (loaded?.definitions ?? []) : (declared ?? Object.keys(values).map((key) => guess(key, values[key])));
|
|
74
154
|
const key = JSON.stringify(definitions);
|
|
75
155
|
if (key !== drawn) {
|
|
76
156
|
drawn = key;
|
|
@@ -79,6 +159,17 @@ const propertiesWidget = (context) => {
|
|
|
79
159
|
for (const { definition, widget } of rows) {
|
|
80
160
|
widget.update({ value: values[definition.name] ?? null, values, readonly: state.readonly, required: false, invalid: false });
|
|
81
161
|
}
|
|
162
|
+
status.textContent = loaded?.loading && !loaded.definitions ? words.loading : (loaded?.error ?? '');
|
|
163
|
+
status.hidden = !status.textContent;
|
|
164
|
+
if (adding) {
|
|
165
|
+
if (state.readonly)
|
|
166
|
+
closeNew();
|
|
167
|
+
addButton.hidden = state.readonly || !newRow.hidden;
|
|
168
|
+
}
|
|
169
|
+
if (focusAfter && rows.some((row) => row.definition.name === focusAfter)) {
|
|
170
|
+
rows.find((row) => row.definition.name === focusAfter)?.widget.focus();
|
|
171
|
+
focusAfter = null;
|
|
172
|
+
}
|
|
82
173
|
},
|
|
83
174
|
};
|
|
84
175
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":";;;AACA,uCAA0E;AAE1E
|
|
1
|
+
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":"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"}
|
package/src/lib/properties.mjs
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
|
+
import { maker, wordsFor } from './kind-parts.mjs';
|
|
1
2
|
import { createWidget } from './widgets.mjs';
|
|
2
3
|
/**
|
|
3
4
|
* A properties field, one row per property, each edited with the widget for
|
|
4
5
|
* its type: text, numbers, yes/no, a choice, a date. The field's `definitions`
|
|
5
|
-
* say which properties there are;
|
|
6
|
-
*
|
|
6
|
+
* say which properties there are; with `definitionsFrom` the app gives them,
|
|
7
|
+
* those the linked record keeps (Flectra's definition_record), loaded again as
|
|
8
|
+
* the link changes; without either, each property is worked out from its
|
|
9
|
+
* value. The properties stay one value: an object by property name.
|
|
10
|
+
*
|
|
11
|
+
* Options: `columns` (1 or 2), the properties side by side, as Flectra's
|
|
12
|
+
* columns="2"; `add`, with definitions from a linked record, "Add a property"
|
|
13
|
+
* under them — its name and kind, kept on that record through the app.
|
|
7
14
|
*/
|
|
8
15
|
/** "lift_access" → "Lift access". */
|
|
9
16
|
const humanize = (name) => {
|
|
10
17
|
const words = name.replace(/_/g, ' ').trim();
|
|
11
18
|
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
12
19
|
};
|
|
20
|
+
/** A property's name from its label: "Locker number" → "locker_number". */
|
|
21
|
+
const nameFrom = (label) => label
|
|
22
|
+
.normalize('NFKD')
|
|
23
|
+
.replace(/[̀-ͯ]/g, '')
|
|
24
|
+
.toLowerCase()
|
|
25
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
26
|
+
.replace(/^_+|_+$/g, '')
|
|
27
|
+
.replace(/^(\d)/, 'p_$1') || 'property';
|
|
13
28
|
/** A property's type, from what it holds. */
|
|
14
29
|
function guess(name, value) {
|
|
15
30
|
const label = humanize(name);
|
|
@@ -21,9 +36,14 @@ function guess(name, value) {
|
|
|
21
36
|
return { name, label, type: 'date' };
|
|
22
37
|
return { name, label, type: 'char' };
|
|
23
38
|
}
|
|
39
|
+
/** The kinds a property added in place may be, in the order their words name them. */
|
|
40
|
+
const KINDS = ['char', 'text', 'integer', 'float', 'boolean', 'date'];
|
|
24
41
|
export const propertiesWidget = (context) => {
|
|
25
|
-
const { form, name, field, node, id, document } = context;
|
|
42
|
+
const { form, name, field, node, id, document, labels, locale } = context;
|
|
43
|
+
const make = maker(document);
|
|
44
|
+
const words = wordsFor(labels, locale);
|
|
26
45
|
const declared = field.type === 'properties' ? field.definitions : undefined;
|
|
46
|
+
const fromRecord = field.type === 'properties' && !!field.definitionsFrom;
|
|
27
47
|
const current = () => {
|
|
28
48
|
const value = form.getState().values[name];
|
|
29
49
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
@@ -35,9 +55,65 @@ export const propertiesWidget = (context) => {
|
|
|
35
55
|
// Property values are plain JSON: text, numbers, yes/no, a choice, a date.
|
|
36
56
|
setValue: (property, value) => form.setValue(name, { ...current(), [property]: value }),
|
|
37
57
|
};
|
|
38
|
-
const
|
|
39
|
-
element
|
|
40
|
-
|
|
58
|
+
const list = make('div', { class: 'fd-properties-list' });
|
|
59
|
+
const element = make('div', { class: 'fd-properties', role: 'group' }, list);
|
|
60
|
+
const columns = node.options?.['columns'];
|
|
61
|
+
if (columns === 2)
|
|
62
|
+
element.dataset['columns'] = '2';
|
|
63
|
+
const status = make('div', { class: 'fd-help', role: 'status', hidden: '' });
|
|
64
|
+
element.append(status);
|
|
65
|
+
// Adding one in place: its name and its kind, then Add.
|
|
66
|
+
const adding = fromRecord && node.options?.['add'] === true;
|
|
67
|
+
const addButton = make('button', { type: 'button', class: 'fd-button fd-button-link fd-property-add', hidden: '' }, `+ ${words.addProperty}`);
|
|
68
|
+
const newName = make('input', { type: 'text', class: 'fd-input', 'aria-label': words.propertyName, placeholder: words.propertyName, autocomplete: 'off' });
|
|
69
|
+
const kindNames = words.propertyTypes.split('|');
|
|
70
|
+
const newKind = make('select', { class: 'fd-input fd-select', 'aria-label': words.propertyType }, ...KINDS.map((kind, i) => make('option', { value: kind }, kindNames[i] ?? kind)));
|
|
71
|
+
const confirm = make('button', { type: 'button', class: 'fd-button fd-button-primary' }, words.add);
|
|
72
|
+
const cancel = make('button', { type: 'button', class: 'fd-button' }, words.cancel);
|
|
73
|
+
const newRow = make('div', { class: 'fd-property-new', hidden: '' }, newName, newKind, confirm, cancel);
|
|
74
|
+
if (adding)
|
|
75
|
+
element.append(addButton, newRow);
|
|
76
|
+
let focusAfter = null;
|
|
77
|
+
const closeNew = () => {
|
|
78
|
+
newRow.hidden = true;
|
|
79
|
+
addButton.hidden = false;
|
|
80
|
+
};
|
|
81
|
+
addButton.addEventListener('click', () => {
|
|
82
|
+
newRow.hidden = false;
|
|
83
|
+
addButton.hidden = true;
|
|
84
|
+
newName.value = '';
|
|
85
|
+
newKind.value = 'char';
|
|
86
|
+
newName.focus();
|
|
87
|
+
});
|
|
88
|
+
cancel.addEventListener('click', () => {
|
|
89
|
+
closeNew();
|
|
90
|
+
addButton.focus();
|
|
91
|
+
});
|
|
92
|
+
const add = () => {
|
|
93
|
+
const label = newName.value.trim();
|
|
94
|
+
if (!label)
|
|
95
|
+
return newName.focus();
|
|
96
|
+
const taken = new Set(rows.map((row) => row.definition.name));
|
|
97
|
+
let made = nameFrom(label);
|
|
98
|
+
for (let n = 2; taken.has(made); n++)
|
|
99
|
+
made = `${nameFrom(label)}_${n}`;
|
|
100
|
+
focusAfter = made;
|
|
101
|
+
closeNew();
|
|
102
|
+
void form.addDefinition(name, { name: made, label, type: newKind.value });
|
|
103
|
+
};
|
|
104
|
+
confirm.addEventListener('click', add);
|
|
105
|
+
newRow.addEventListener('keydown', (event) => {
|
|
106
|
+
if (event.key === 'Enter' && event.target === newName) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
add();
|
|
109
|
+
}
|
|
110
|
+
else if (event.key === 'Escape') {
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
event.stopPropagation();
|
|
113
|
+
closeNew();
|
|
114
|
+
addButton.focus();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
41
117
|
let rows = [];
|
|
42
118
|
let drawn = '';
|
|
43
119
|
function draw(definitions) {
|
|
@@ -50,7 +126,7 @@ export const propertiesWidget = (context) => {
|
|
|
50
126
|
const widget = createWidget({ ...context, form: properties, name: definition.name, field: propertyField, node: propertyNode, id: rowId });
|
|
51
127
|
return { definition, widget };
|
|
52
128
|
});
|
|
53
|
-
|
|
129
|
+
list.replaceChildren(...rows.map(({ definition, widget }) => {
|
|
54
130
|
const row = document.createElement('div');
|
|
55
131
|
row.className = 'fd-property';
|
|
56
132
|
row.dataset['type'] = definition.type;
|
|
@@ -61,13 +137,17 @@ export const propertiesWidget = (context) => {
|
|
|
61
137
|
return row;
|
|
62
138
|
}));
|
|
63
139
|
}
|
|
140
|
+
// Definitions from the linked record: asked for once shown, then again as the link changes.
|
|
141
|
+
if (fromRecord && !form.getState().definitions[name])
|
|
142
|
+
form.loadDefinitions(name);
|
|
64
143
|
return {
|
|
65
144
|
element,
|
|
66
|
-
focus: () => rows[0]?.widget.focus(),
|
|
145
|
+
focus: () => (rows[0]?.widget ?? { focus: () => addButton.focus() }).focus(),
|
|
67
146
|
destroy: () => rows.forEach((row) => row.widget.destroy?.()),
|
|
68
147
|
update(state) {
|
|
69
148
|
const values = current();
|
|
70
|
-
const
|
|
149
|
+
const loaded = fromRecord ? form.getState().definitions[name] : undefined;
|
|
150
|
+
const definitions = fromRecord ? (loaded?.definitions ?? []) : (declared ?? Object.keys(values).map((key) => guess(key, values[key])));
|
|
71
151
|
const key = JSON.stringify(definitions);
|
|
72
152
|
if (key !== drawn) {
|
|
73
153
|
drawn = key;
|
|
@@ -76,6 +156,17 @@ export const propertiesWidget = (context) => {
|
|
|
76
156
|
for (const { definition, widget } of rows) {
|
|
77
157
|
widget.update({ value: values[definition.name] ?? null, values, readonly: state.readonly, required: false, invalid: false });
|
|
78
158
|
}
|
|
159
|
+
status.textContent = loaded?.loading && !loaded.definitions ? words.loading : (loaded?.error ?? '');
|
|
160
|
+
status.hidden = !status.textContent;
|
|
161
|
+
if (adding) {
|
|
162
|
+
if (state.readonly)
|
|
163
|
+
closeNew();
|
|
164
|
+
addButton.hidden = state.readonly || !newRow.hidden;
|
|
165
|
+
}
|
|
166
|
+
if (focusAfter && rows.some((row) => row.definition.name === focusAfter)) {
|
|
167
|
+
rows.find((row) => row.definition.name === focusAfter)?.widget.focus();
|
|
168
|
+
focusAfter = null;
|
|
169
|
+
}
|
|
79
170
|
},
|
|
80
171
|
};
|
|
81
172
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"properties.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAmC,MAAM,WAAW,CAAC;AAE1E
|
|
1
|
+
{"version":3,"file":"properties.mjs","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/properties.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Field, FieldNode, Locale, Value, Values } from '@fieldia/core';
|
|
2
|
+
import { type WidgetLabels } from './labels.mjs';
|
|
3
|
+
import type { WidgetDialogs } from './widgets.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* A read-only value drawn as its words, as Flectra draws one: a choice by its
|
|
6
|
+
* label without an arrow, an amount with its currency, a date as a person
|
|
7
|
+
* writes it, a link by its record's name (a link that opens it, where the
|
|
8
|
+
* app can show it), a mail, phone or web address as a link to it, and long
|
|
9
|
+
* words wrapped rather than cut at a box's edge. Empty, it is empty.
|
|
10
|
+
*/
|
|
11
|
+
/** Whether a field drawn this way is shown as words while it is read-only: kinds whose box holds a value, not a table, tags or a file. */
|
|
12
|
+
export declare function readsAsText(field: Field, node: FieldNode): boolean;
|
|
13
|
+
export interface ReadText {
|
|
14
|
+
element: HTMLElement;
|
|
15
|
+
update(value: Value | undefined, values: Readonly<Values>): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function readText(context: {
|
|
18
|
+
document: Document;
|
|
19
|
+
field: Field;
|
|
20
|
+
node: FieldNode;
|
|
21
|
+
id: string;
|
|
22
|
+
locale?: Locale;
|
|
23
|
+
labels?: WidgetLabels;
|
|
24
|
+
dialogs?: WidgetDialogs;
|
|
25
|
+
}): ReadText;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Field, FieldNode, Locale, Value, Values } from '@fieldia/core';
|
|
2
|
+
import { type WidgetLabels } from './labels';
|
|
3
|
+
import type { WidgetDialogs } from './widgets';
|
|
4
|
+
/**
|
|
5
|
+
* A read-only value drawn as its words, as Flectra draws one: a choice by its
|
|
6
|
+
* label without an arrow, an amount with its currency, a date as a person
|
|
7
|
+
* writes it, a link by its record's name (a link that opens it, where the
|
|
8
|
+
* app can show it), a mail, phone or web address as a link to it, and long
|
|
9
|
+
* words wrapped rather than cut at a box's edge. Empty, it is empty.
|
|
10
|
+
*/
|
|
11
|
+
/** Whether a field drawn this way is shown as words while it is read-only: kinds whose box holds a value, not a table, tags or a file. */
|
|
12
|
+
export declare function readsAsText(field: Field, node: FieldNode): boolean;
|
|
13
|
+
export interface ReadText {
|
|
14
|
+
element: HTMLElement;
|
|
15
|
+
update(value: Value | undefined, values: Readonly<Values>): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function readText(context: {
|
|
18
|
+
document: Document;
|
|
19
|
+
field: Field;
|
|
20
|
+
node: FieldNode;
|
|
21
|
+
id: string;
|
|
22
|
+
locale?: Locale;
|
|
23
|
+
labels?: WidgetLabels;
|
|
24
|
+
dialogs?: WidgetDialogs;
|
|
25
|
+
}): ReadText;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readsAsText = readsAsText;
|
|
4
|
+
exports.readText = readText;
|
|
5
|
+
const display_1 = require("./display");
|
|
6
|
+
const labels_1 = require("./labels");
|
|
7
|
+
const relations_1 = require("./relations");
|
|
8
|
+
/**
|
|
9
|
+
* A read-only value drawn as its words, as Flectra draws one: a choice by its
|
|
10
|
+
* label without an arrow, an amount with its currency, a date as a person
|
|
11
|
+
* writes it, a link by its record's name (a link that opens it, where the
|
|
12
|
+
* app can show it), a mail, phone or web address as a link to it, and long
|
|
13
|
+
* words wrapped rather than cut at a box's edge. Empty, it is empty.
|
|
14
|
+
*/
|
|
15
|
+
/** Whether a field drawn this way is shown as words while it is read-only: kinds whose box holds a value, not a table, tags or a file. */
|
|
16
|
+
function readsAsText(field, node) {
|
|
17
|
+
const widget = node.widget;
|
|
18
|
+
switch (field.type) {
|
|
19
|
+
case 'char':
|
|
20
|
+
return !widget || widget === 'email' || widget === 'phone' || widget === 'url';
|
|
21
|
+
case 'selection':
|
|
22
|
+
return !widget && !field.multiple && !field.optionsFrom;
|
|
23
|
+
case 'text':
|
|
24
|
+
case 'integer':
|
|
25
|
+
case 'float':
|
|
26
|
+
// Hours and per cents read as their widgets write them: 06:30, 35%.
|
|
27
|
+
return !widget || widget === 'duration' || widget === 'percentage';
|
|
28
|
+
case 'monetary':
|
|
29
|
+
case 'date':
|
|
30
|
+
case 'datetime':
|
|
31
|
+
case 'many2one':
|
|
32
|
+
case 'reference':
|
|
33
|
+
return !widget;
|
|
34
|
+
default:
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const ADDRESSES = {
|
|
39
|
+
email: [/^[^\s@]+@[^\s@]+$/, 'mailto:'],
|
|
40
|
+
phone: [/^\+?[\d\s().-]{3,}$/, 'tel:'],
|
|
41
|
+
url: [/^https?:\/\/\S+$/i, ''],
|
|
42
|
+
};
|
|
43
|
+
/** A number's unit around it, as its box shows it inside — "3.00 Days" — and nothing round an empty one. */
|
|
44
|
+
function withUnit(words, field, node, value) {
|
|
45
|
+
if ((field.type !== 'integer' && field.type !== 'float') || node.widget || value === null || value === undefined || words === '')
|
|
46
|
+
return words;
|
|
47
|
+
const unit = (key) => (typeof node.options?.[key] === 'string' ? node.options[key].trim() : '');
|
|
48
|
+
return [unit('prefix'), words, unit('suffix')].filter(Boolean).join(' ');
|
|
49
|
+
}
|
|
50
|
+
function readText(context) {
|
|
51
|
+
const { document: doc, field, node, locale = 'en', labels = labels_1.WIDGET_LABELS.en, dialogs } = context;
|
|
52
|
+
const element = doc.createElement('div');
|
|
53
|
+
element.className = 'fd-read-text';
|
|
54
|
+
element.id = `${context.id}-text`;
|
|
55
|
+
const relation = field.type === 'many2one' ? field.relation : null;
|
|
56
|
+
const opens = relation !== null && node.options?.['open'] !== false && !!dialogs?.canOpen(relation);
|
|
57
|
+
let drawn = '';
|
|
58
|
+
return {
|
|
59
|
+
element,
|
|
60
|
+
update(value, values) {
|
|
61
|
+
const words = withUnit((0, display_1.cellText)(field, value, values, locale, undefined, { widget: node.widget, options: node.options }), field, node, value);
|
|
62
|
+
const key = JSON.stringify([words, value ?? null]);
|
|
63
|
+
if (key === drawn)
|
|
64
|
+
return;
|
|
65
|
+
drawn = key;
|
|
66
|
+
const address = node.widget ? ADDRESSES[node.widget] : undefined;
|
|
67
|
+
const record = relation !== null && value && typeof value === 'object' && 'id' in value ? value : null;
|
|
68
|
+
let main;
|
|
69
|
+
if (address && typeof value === 'string' && address[0].test(value.trim())) {
|
|
70
|
+
const link = doc.createElement('a');
|
|
71
|
+
link.href = `${address[1]}${value.trim()}`;
|
|
72
|
+
if (node.widget === 'url')
|
|
73
|
+
Object.assign(link, { target: '_blank', rel: 'noopener noreferrer' });
|
|
74
|
+
link.textContent = words;
|
|
75
|
+
main = link;
|
|
76
|
+
}
|
|
77
|
+
else if (opens && record) {
|
|
78
|
+
// The linked record, opened where the app can show it, as Flectra's read-only link.
|
|
79
|
+
const link = doc.createElement('button');
|
|
80
|
+
link.type = 'button';
|
|
81
|
+
link.className = 'fd-read-link';
|
|
82
|
+
link.textContent = words;
|
|
83
|
+
link.setAttribute('aria-label', labels.openNamed.replace('{name}', record.label));
|
|
84
|
+
link.addEventListener('click', () => void dialogs?.openRecord(relation, { recordId: record.id, title: record.label }));
|
|
85
|
+
main = link;
|
|
86
|
+
}
|
|
87
|
+
else
|
|
88
|
+
main = doc.createTextNode(words);
|
|
89
|
+
// A link's picture before its name, and lines of it — an address — under it, when the page asks.
|
|
90
|
+
const picture = record && node.options?.['avatar'] === true ? [(0, relations_1.linkAvatar)(doc, record)] : [];
|
|
91
|
+
const lines = [];
|
|
92
|
+
if (record?.details?.trim() && node.options?.['details'] === true) {
|
|
93
|
+
const box = doc.createElement('div');
|
|
94
|
+
box.className = 'fd-link-details';
|
|
95
|
+
(0, relations_1.detailLines)(box, record.details.trim());
|
|
96
|
+
lines.push(box);
|
|
97
|
+
}
|
|
98
|
+
element.replaceChildren(...picture, main, ...lines);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=read-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-text.js","sourceRoot":"","sources":["../../../../../libs/widgets/src/lib/read-text.ts"],"names":[],"mappings":"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"}
|