@optionfactory/ful 6.0.3 → 6.0.5
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 +6 -109
- package/dist/ful.css +1 -1
- package/dist/ful.css.map +1 -1
- package/dist/ful.iife.js +52 -25
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +53 -26
- package/dist/ful.mjs.map +1 -1
- package/package.json +7 -7
package/dist/ful.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ParsedElement, Attributes, registry, Fragments, Nodes, Rendering } from '@optionfactory/ftl';
|
|
1
|
+
import { ParsedElement, Attributes, registry, Fragments, Templates, Nodes, Rendering } from '@optionfactory/ftl';
|
|
2
2
|
|
|
3
3
|
class Base64 {
|
|
4
4
|
static encode(arrayBuffer, dialect) {
|
|
@@ -1356,7 +1356,7 @@ class Form extends ParsedElement {
|
|
|
1356
1356
|
form.addEventListener('submit', async (e) => {
|
|
1357
1357
|
e.preventDefault();
|
|
1358
1358
|
e.stopPropagation();
|
|
1359
|
-
await this.submit(e.submitter);
|
|
1359
|
+
await this.submit(e.submitter ?? undefined);
|
|
1360
1360
|
});
|
|
1361
1361
|
if (this.hasAttribute("clear-invalid-on-change")) {
|
|
1362
1362
|
this.addEventListener('change', (/** @type any */evt) => {
|
|
@@ -1377,19 +1377,20 @@ class Form extends ParsedElement {
|
|
|
1377
1377
|
const values = Bindings.extractFrom(this.form, submitter);
|
|
1378
1378
|
let request = await loader.prepare(values, this);
|
|
1379
1379
|
try {
|
|
1380
|
-
const se = new CustomEvent('submit', { bubbles: true, cancelable: true, detail: { values, request } });
|
|
1380
|
+
const se = new CustomEvent('submit', { bubbles: true, cancelable: true, detail: { submitter, values, request } });
|
|
1381
1381
|
if (!this.dispatchEvent(se)) {
|
|
1382
1382
|
return;
|
|
1383
1383
|
}
|
|
1384
|
-
|
|
1384
|
+
this.errors = [];
|
|
1385
|
+
const sre = new CustomEvent('submit:requested', { bubbles: true, cancelable: false, detail: { submitter, values: se.detail.values, request: se.detail.request} });
|
|
1385
1386
|
let response = await AsyncEvents.fireAsync(this, sre);
|
|
1386
1387
|
request = sre.detail.request;
|
|
1387
1388
|
|
|
1388
1389
|
response = await loader.submit(request, this, response);
|
|
1389
1390
|
const mapped = await loader.transform(response, this);
|
|
1390
|
-
this.dispatchEvent(new CustomEvent('submit:success', { bubbles: true, cancelable: false, detail: { values, request, response: mapped } }));
|
|
1391
|
+
this.dispatchEvent(new CustomEvent('submit:success', { bubbles: true, cancelable: false, detail: { submitter, values, request, response: mapped } }));
|
|
1391
1392
|
} catch (e) {
|
|
1392
|
-
this.dispatchEvent(new CustomEvent('submit:failure', { bubbles: true, cancelable: false, detail: { values, request, exception: e } }));
|
|
1393
|
+
this.dispatchEvent(new CustomEvent('submit:failure', { bubbles: true, cancelable: false, detail: { submitter, values, request, exception: e } }));
|
|
1393
1394
|
if (e instanceof Failure) {
|
|
1394
1395
|
this.errors = e.problems;
|
|
1395
1396
|
}
|
|
@@ -1470,7 +1471,35 @@ class Input extends ParsedElement {
|
|
|
1470
1471
|
this.required = observed.required;
|
|
1471
1472
|
this.value = observed.value;
|
|
1472
1473
|
}
|
|
1473
|
-
|
|
1474
|
+
this._input.addEventListener('keydown', (evt) => {
|
|
1475
|
+
if (evt.key !== 'Enter' || this._type() === 'textarea') {
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
const form = this.internals.form;
|
|
1479
|
+
if(!form){
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
const candidates = /** @type [HTMLButtonElement|HTMLInputElement] */ (Array.from(form.querySelectorAll(
|
|
1483
|
+
'button:not(:disabled), input:not(:disabled)'
|
|
1484
|
+
)));
|
|
1485
|
+
const submitter = candidates.find(el => el.type === 'submit');
|
|
1486
|
+
form.requestSubmit(submitter);
|
|
1487
|
+
});
|
|
1488
|
+
this._input.addEventListener('input', (evt) => {
|
|
1489
|
+
const re = this.getAttribute('mask');
|
|
1490
|
+
if (!re) {
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
const before = evt.target.value;
|
|
1494
|
+
const after = before.replace(new RegExp(re, 'g'), '');
|
|
1495
|
+
if (before === after) {
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
const start = evt.target.selectionStart;
|
|
1499
|
+
const offset = before.length - after.length;
|
|
1500
|
+
evt.target.value = after;
|
|
1501
|
+
evt.target.setSelectionRange(start - offset, start - offset);
|
|
1502
|
+
});
|
|
1474
1503
|
this._input.addEventListener('change', (evt) => {
|
|
1475
1504
|
evt.stopPropagation();
|
|
1476
1505
|
this.dispatchEvent(new CustomEvent('change', {
|
|
@@ -1518,7 +1547,7 @@ class Input extends ParsedElement {
|
|
|
1518
1547
|
this.reflect(() => {
|
|
1519
1548
|
Attributes.toggle(this, 'required', d);
|
|
1520
1549
|
});
|
|
1521
|
-
}
|
|
1550
|
+
}
|
|
1522
1551
|
focus(options) {
|
|
1523
1552
|
this._input.focus(options);
|
|
1524
1553
|
}
|
|
@@ -2108,11 +2137,20 @@ class Dropdown extends ParsedElement {
|
|
|
2108
2137
|
<ful-spinner class="centered" hidden></ful-spinner>
|
|
2109
2138
|
<menu tabindex="-1" hidden></menu>
|
|
2110
2139
|
`;
|
|
2140
|
+
static templates = {
|
|
2141
|
+
options: `
|
|
2142
|
+
<li data-tpl-each="self" data-tpl-selected="index == 0" data-tpl-value="index">
|
|
2143
|
+
{{ label }}
|
|
2144
|
+
</li>
|
|
2145
|
+
`
|
|
2146
|
+
};
|
|
2111
2147
|
#spinner;
|
|
2112
2148
|
#menu;
|
|
2149
|
+
#optionstemplate;
|
|
2113
2150
|
#options = new Map();
|
|
2114
2151
|
render({ slots }) {
|
|
2115
2152
|
const fragment = this.template().render();
|
|
2153
|
+
this.#optionstemplate = Fragments.isBlank(slots.default) ? this.template('options') : Templates.fromFragment(slots.default);
|
|
2116
2154
|
this.#spinner = fragment.querySelector("ful-spinner");
|
|
2117
2155
|
this.#menu = fragment.querySelector("menu");
|
|
2118
2156
|
this.#menu.addEventListener('click', evt => {
|
|
@@ -2134,21 +2172,8 @@ class Dropdown extends ParsedElement {
|
|
|
2134
2172
|
throw new Error("null data");
|
|
2135
2173
|
}
|
|
2136
2174
|
this.#options = new Map(values.map((v, i) => [String(i), v]));
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
el.classList.add('text-center', 'py-2', 'bi', 'bi-database-slash');
|
|
2140
|
-
this.#menu.replaceChildren(el);
|
|
2141
|
-
return;
|
|
2142
|
-
}
|
|
2143
|
-
this.#menu.replaceChildren(...values.map(([k, v, m], i) => {
|
|
2144
|
-
const el = document.createElement('li');
|
|
2145
|
-
if (i === 0) {
|
|
2146
|
-
el.setAttribute("selected", '');
|
|
2147
|
-
}
|
|
2148
|
-
el.setAttribute("value", i);
|
|
2149
|
-
el.innerText = v;
|
|
2150
|
-
return el;
|
|
2151
|
-
}));
|
|
2175
|
+
const data = values.map(([key, label, metadata], index) => ({ index, key, label, metadata}));
|
|
2176
|
+
this.#optionstemplate.withOverlay(data).renderTo(this.#menu);
|
|
2152
2177
|
}
|
|
2153
2178
|
#change(target) {
|
|
2154
2179
|
const index = target.getAttribute('value');
|
|
@@ -2209,7 +2234,7 @@ class Select extends ParsedElement {
|
|
|
2209
2234
|
<badges></badges>
|
|
2210
2235
|
<input type="text" form="">
|
|
2211
2236
|
</div>
|
|
2212
|
-
<ful-dropdown hidden popover="manual"
|
|
2237
|
+
<ful-dropdown hidden popover="manual">{{{{ slots.dropdown }}}}</ful-dropdown>
|
|
2213
2238
|
</div>
|
|
2214
2239
|
{{{{ slots.after }}}}
|
|
2215
2240
|
<span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
|
|
@@ -2323,16 +2348,17 @@ class Select extends ParsedElement {
|
|
|
2323
2348
|
this.#input.value = '';
|
|
2324
2349
|
});
|
|
2325
2350
|
this.#input.addEventListener('keydown', e => {
|
|
2326
|
-
e.stopPropagation();
|
|
2327
2351
|
if (this.disabled || this.readonly) {
|
|
2328
2352
|
return;
|
|
2329
2353
|
}
|
|
2330
2354
|
switch (e.code) {
|
|
2331
2355
|
case 'ArrowUp': {
|
|
2356
|
+
e.preventDefault();
|
|
2332
2357
|
this.#ddmenu.moveOrShow(false, () => self.#loader.load(self.#input.value));
|
|
2333
2358
|
break;
|
|
2334
2359
|
}
|
|
2335
2360
|
case 'ArrowDown': {
|
|
2361
|
+
e.preventDefault();
|
|
2336
2362
|
this.#ddmenu.moveOrShow(true, () => self.#loader.load(self.#input.value));
|
|
2337
2363
|
break;
|
|
2338
2364
|
}
|
|
@@ -2341,12 +2367,13 @@ class Select extends ParsedElement {
|
|
|
2341
2367
|
break;
|
|
2342
2368
|
}
|
|
2343
2369
|
case 'Enter': {
|
|
2370
|
+
e.preventDefault();
|
|
2344
2371
|
this.#ddmenu.acceptSelection();
|
|
2345
2372
|
this.#input.value = '';
|
|
2346
2373
|
break;
|
|
2347
2374
|
}
|
|
2348
2375
|
case 'Backspace': {
|
|
2349
|
-
//remove last if caret
|
|
2376
|
+
//remove last if caret at position 0
|
|
2350
2377
|
if (this.#values.size && this.#input.selectionStart === 0 && this.#input.selectionEnd === 0) {
|
|
2351
2378
|
this.#values.delete(Array.from(this.#values.keys()).pop());
|
|
2352
2379
|
this.#changed();
|