@optionfactory/fml 9.0.0-rc16 → 9.0.0-rc19
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/dist/custom-elements.json +17 -3
- package/dist/fml.css +9 -9
- package/dist/fml.css.map +1 -1
- package/dist/fml.iife.js +132 -37
- package/dist/fml.iife.js.map +1 -1
- package/dist/fml.iife.min.js +1 -1
- package/dist/fml.iife.min.js.map +1 -1
- package/dist/ful.css +9 -9
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +41 -12
- package/dist/ful.iife.js +132 -37
- 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 +132 -37
- package/dist/ful.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +1 -1
- package/dist/web-types.json +12 -4
- package/package.json +1 -1
package/dist/ful.iife.js
CHANGED
|
@@ -1578,6 +1578,8 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1578
1578
|
|
|
1579
1579
|
const INPUT_MODES = { numeric: 'numeric', decimal: 'decimal' };
|
|
1580
1580
|
|
|
1581
|
+
const SEGMENTED = new Set(['date', 'time', 'datetime-local', 'month', 'week']);
|
|
1582
|
+
|
|
1581
1583
|
const signed = (v, digits) => (v.startsWith('-') ? '-' : '') + digits(v);
|
|
1582
1584
|
|
|
1583
1585
|
const NUMERIC_DIGITS = {
|
|
@@ -1639,14 +1641,18 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1639
1641
|
* `autocomplete` attribute of the nearest enclosing `<form>`, which the
|
|
1640
1642
|
* platform does not pass on because the control carries `form=""`.
|
|
1641
1643
|
* - `uppercase`, `trim` and `v-type` shape the value as it is read; see `value`.
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1644
|
+
* - The control's native `change` is stopped and the field dispatches its own
|
|
1645
|
+
* once the user commits a new value, as a text input does. A date, time,
|
|
1646
|
+
* datetime-local, month or week control fires its native `change` while its
|
|
1647
|
+
* segments are typed, as soon as they make a valid value; for those the field
|
|
1648
|
+
* reports when the control is left or Enter is pressed, at once for a value
|
|
1649
|
+
* picked from the browser's picker, and never a half-typed value.
|
|
1644
1650
|
*
|
|
1645
1651
|
* A subclass template may render more than one control, as the compare filters
|
|
1646
1652
|
* render the two bounds of a range: the first is `_input`, the one the field is
|
|
1647
|
-
* named by
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
1653
|
+
* named by, and every one of them gets the inputmode, `autocomplete`, the
|
|
1654
|
+
* `input-` passthrough, the keystroke filter, the placeholder and the `change`
|
|
1655
|
+
* reporting. The passthrough leaves `input-id` to the first alone, so no
|
|
1650
1656
|
* two controls share an id.
|
|
1651
1657
|
*/
|
|
1652
1658
|
class Input extends Field {
|
|
@@ -1713,10 +1719,6 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1713
1719
|
for (const control of this.#controls) {
|
|
1714
1720
|
this.#configure(control, mode, autocomplete, strip);
|
|
1715
1721
|
}
|
|
1716
|
-
this._input.addEventListener('change', (evt) => {
|
|
1717
|
-
evt.stopPropagation();
|
|
1718
|
-
this._notifyChange();
|
|
1719
|
-
});
|
|
1720
1722
|
return {
|
|
1721
1723
|
fragment,
|
|
1722
1724
|
control: this._input,
|
|
@@ -1740,6 +1742,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1740
1742
|
if (control !== this._input) {
|
|
1741
1743
|
index_mjs.Attributes.set(control, 'id', id || null);
|
|
1742
1744
|
}
|
|
1745
|
+
this.#reportChanges(control);
|
|
1743
1746
|
control.addEventListener('input', () => {
|
|
1744
1747
|
if (!strip) {
|
|
1745
1748
|
return;
|
|
@@ -1758,13 +1761,53 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1758
1761
|
control.setSelectionRange(caret, caret);
|
|
1759
1762
|
});
|
|
1760
1763
|
}
|
|
1764
|
+
/** @param {HTMLInputElement|HTMLTextAreaElement} control */
|
|
1765
|
+
#reportChanges(control) {
|
|
1766
|
+
if (!SEGMENTED.has(control.type)) {
|
|
1767
|
+
control.addEventListener('change', (evt) => {
|
|
1768
|
+
evt.stopPropagation();
|
|
1769
|
+
this._notifyChange();
|
|
1770
|
+
});
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
/** @type {string|null} */
|
|
1774
|
+
let committed = null;
|
|
1775
|
+
let typed = false;
|
|
1776
|
+
const commit = () => {
|
|
1777
|
+
typed = false;
|
|
1778
|
+
const now = JSON.stringify(this.value);
|
|
1779
|
+
if (now === committed) {
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
committed = now;
|
|
1783
|
+
this._notifyChange();
|
|
1784
|
+
};
|
|
1785
|
+
control.addEventListener('focus', () => {
|
|
1786
|
+
committed = JSON.stringify(this.value);
|
|
1787
|
+
});
|
|
1788
|
+
control.addEventListener('keydown', (/** @type any */ evt) => {
|
|
1789
|
+
if (evt.key === 'Enter' && !evt.isComposing) {
|
|
1790
|
+
commit();
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
typed = true;
|
|
1794
|
+
});
|
|
1795
|
+
control.addEventListener('blur', commit);
|
|
1796
|
+
control.addEventListener('change', (evt) => {
|
|
1797
|
+
evt.stopPropagation();
|
|
1798
|
+
if (!typed) {
|
|
1799
|
+
commit();
|
|
1800
|
+
}
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1761
1803
|
/**
|
|
1762
1804
|
* The control's text, shaped in this order: upper cased under `uppercase`,
|
|
1763
1805
|
* trimmed under `trim`, `null` when that leaves it empty, every `,` read as
|
|
1764
1806
|
* `.` for `type="decimal"`, and decoded to a number under
|
|
1765
1807
|
* `v-type="number"`, where text that does not decode is answered as it is.
|
|
1766
1808
|
* Writing `null`, `undefined` or `''` empties the control; anything else is
|
|
1767
|
-
* written as its string
|
|
1809
|
+
* written as its string, replacing whatever was being typed, as a native
|
|
1810
|
+
* control's value does. Answers a `string`, a `number` or `null`; typed
|
|
1768
1811
|
* `any` because subclasses answer other values.
|
|
1769
1812
|
* @type {any}
|
|
1770
1813
|
*/
|
|
@@ -1785,7 +1828,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1785
1828
|
return normalized;
|
|
1786
1829
|
}
|
|
1787
1830
|
set value(value) {
|
|
1788
|
-
this._input.value = value === '' || value === undefined
|
|
1831
|
+
this._input.value = value === '' || value === undefined || value === null ? '' : `${value}`;
|
|
1789
1832
|
}
|
|
1790
1833
|
/**
|
|
1791
1834
|
* The control's placeholder, `null` when there is none. The control always
|
|
@@ -2054,7 +2097,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
2054
2097
|
}
|
|
2055
2098
|
/** @param {string|null|undefined} v an ISO instant; a falsy value empties the input */
|
|
2056
2099
|
set value(v) {
|
|
2057
|
-
|
|
2100
|
+
super.value = v ? Instant.isoToLocal(v) : '';
|
|
2058
2101
|
}
|
|
2059
2102
|
/**
|
|
2060
2103
|
* The lower bound as a UTC ISO instant.
|
|
@@ -2087,7 +2130,6 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
2087
2130
|
}
|
|
2088
2131
|
/** @param {string|null} v */
|
|
2089
2132
|
set step(v) {
|
|
2090
|
-
|
|
2091
2133
|
this._input.step = v ?? '';
|
|
2092
2134
|
}
|
|
2093
2135
|
}
|
|
@@ -3964,6 +4006,15 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
3964
4006
|
#query() {
|
|
3965
4007
|
return this.#editing ? this.#input.value : '';
|
|
3966
4008
|
}
|
|
4009
|
+
/**
|
|
4010
|
+
* The text typed to search the vocabulary: what the dropdown was last
|
|
4011
|
+
* asked to match. `''` while the field is not being searched, its control
|
|
4012
|
+
* then showing the selection's label rather than a query.
|
|
4013
|
+
* @returns {string}
|
|
4014
|
+
*/
|
|
4015
|
+
get query() {
|
|
4016
|
+
return this.#query();
|
|
4017
|
+
}
|
|
3967
4018
|
#display() {
|
|
3968
4019
|
const entry = this.#values.values().next().value;
|
|
3969
4020
|
this.#input.value = this.#multiple ? '' : (entry?.label ?? '');
|
|
@@ -5640,10 +5691,6 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
5640
5691
|
},
|
|
5641
5692
|
});
|
|
5642
5693
|
this.operators = this.declared('operators');
|
|
5643
|
-
this._value2.addEventListener('change', (evt) => {
|
|
5644
|
-
evt.stopPropagation();
|
|
5645
|
-
this._notifyChange();
|
|
5646
|
-
});
|
|
5647
5694
|
if (this._operator.value === null) {
|
|
5648
5695
|
this._showDefaultOperator();
|
|
5649
5696
|
}
|
|
@@ -6121,9 +6168,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6121
6168
|
*/
|
|
6122
6169
|
get criterion() {
|
|
6123
6170
|
const token = this._value.value;
|
|
6124
|
-
return asCriterion(labelTextOf(this), this._operator.value, [
|
|
6125
|
-
token === '' ? '' : booleanValueLabel(token),
|
|
6126
|
-
]);
|
|
6171
|
+
return asCriterion(labelTextOf(this), this._operator.value, [token === '' ? '' : booleanValueLabel(token)]);
|
|
6127
6172
|
}
|
|
6128
6173
|
/**
|
|
6129
6174
|
* The field's own disabled claim. Setting it disables the value button and
|
|
@@ -6412,6 +6457,18 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6412
6457
|
get section() {
|
|
6413
6458
|
return this.#section;
|
|
6414
6459
|
}
|
|
6460
|
+
/**
|
|
6461
|
+
* Dispatches the dismissal on the host and calls `close` unless a listener
|
|
6462
|
+
* prevented it. A dismissal that is not cancelable announces a close the
|
|
6463
|
+
* platform makes whatever the page does, so `close` is not called for it.
|
|
6464
|
+
* @param {CustomEvent} asked
|
|
6465
|
+
* @param {() => void} close
|
|
6466
|
+
*/
|
|
6467
|
+
dismiss(asked, close) {
|
|
6468
|
+
if (this.#host.dispatchEvent(asked) && asked.cancelable) {
|
|
6469
|
+
close();
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6415
6472
|
/**
|
|
6416
6473
|
* Calls `dismiss` when a press and its release both land on the backdrop,
|
|
6417
6474
|
* so a selection dragged out of the panel and released outside does not.
|
|
@@ -6550,6 +6607,18 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6550
6607
|
* and a press and release both on the backdrop close the dialog, each as a
|
|
6551
6608
|
* dismissal, as Escape does.
|
|
6552
6609
|
*
|
|
6610
|
+
* Before any of those three gestures closes it, the element dispatches a
|
|
6611
|
+
* cancelable, non-bubbling `dialog:dismiss` with `detail: { reason }`, the
|
|
6612
|
+
* reason being `button`, `backdrop` or `escape`; a listener calling
|
|
6613
|
+
* `preventDefault()` keeps it open, to guard unsaved edits. A `data-result`
|
|
6614
|
+
* button, `close-on-submit` and `close()` answer rather than dismiss, and
|
|
6615
|
+
* dispatch none.
|
|
6616
|
+
*
|
|
6617
|
+
* The platform lets a page refuse Escape once per user interaction: a second
|
|
6618
|
+
* Escape with no click or keystroke in between closes the dialog whatever the
|
|
6619
|
+
* page does, `requires-answer` included. That close is still announced by a
|
|
6620
|
+
* `dialog:dismiss`, which is then not cancelable.
|
|
6621
|
+
*
|
|
6553
6622
|
* `requires-answer` withholds the close button and refuses Escape and the
|
|
6554
6623
|
* backdrop, so the dialog is closed only by a button carrying `data-result`
|
|
6555
6624
|
* or from code through `close()`.
|
|
@@ -6622,21 +6691,32 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6622
6691
|
this.#dialog.close(result);
|
|
6623
6692
|
}
|
|
6624
6693
|
});
|
|
6694
|
+
const dismiss = (/** @type {'button'|'backdrop'|'escape'} */ reason, platformCloses = false) =>
|
|
6695
|
+
this.#sections.dismiss(
|
|
6696
|
+
new CustomEvent('dialog:dismiss', { cancelable: !platformCloses, detail: { reason } }),
|
|
6697
|
+
() => this.#dialog.close(''),
|
|
6698
|
+
);
|
|
6625
6699
|
if (!requiresAnswer) {
|
|
6626
|
-
this.#sections.onBackdrop(() =>
|
|
6700
|
+
this.#sections.onBackdrop(() => dismiss('backdrop'));
|
|
6627
6701
|
}
|
|
6628
|
-
fragment
|
|
6629
|
-
.querySelector('[data-ref=close]')
|
|
6630
|
-
?.addEventListener('click', () => this.#dialog.close(''));
|
|
6702
|
+
fragment.querySelector('[data-ref=close]')?.addEventListener('click', () => dismiss('button'));
|
|
6631
6703
|
if (closeOnSubmit) {
|
|
6632
6704
|
this.#sections.onSubmitted((response) => {
|
|
6633
6705
|
this.#answer = { dismissed: false, result: null, response };
|
|
6634
6706
|
this.#dialog.close('submitted');
|
|
6635
6707
|
});
|
|
6636
6708
|
}
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6709
|
+
this.#dialog.addEventListener('cancel', (/** @type any */ e) => {
|
|
6710
|
+
if (!e.cancelable) {
|
|
6711
|
+
this.#dialog.returnValue = '';
|
|
6712
|
+
dismiss('escape', true);
|
|
6713
|
+
return;
|
|
6714
|
+
}
|
|
6715
|
+
e.preventDefault();
|
|
6716
|
+
if (!requiresAnswer) {
|
|
6717
|
+
dismiss('escape');
|
|
6718
|
+
}
|
|
6719
|
+
});
|
|
6640
6720
|
this.replaceChildren(fragment);
|
|
6641
6721
|
wireTargets();
|
|
6642
6722
|
}
|
|
@@ -6837,7 +6917,14 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6837
6917
|
* default, when absent) or `start`, following the writing direction.
|
|
6838
6918
|
*
|
|
6839
6919
|
* The close button, Escape, and a press and release both on the backdrop all
|
|
6840
|
-
* go through `close()
|
|
6920
|
+
* go through `close()`, once a cancelable, non-bubbling `drawer:dismiss` with
|
|
6921
|
+
* `detail: { reason }` (`button`, `backdrop` or `escape`) has been dispatched
|
|
6922
|
+
* on the element and no listener prevented it: `preventDefault()` keeps the
|
|
6923
|
+
* drawer open, to guard unsaved edits. `close()` and `close-on-submit`
|
|
6924
|
+
* dispatch none. The platform lets a page refuse Escape once per user
|
|
6925
|
+
* interaction: a second Escape with no click or keystroke in between closes
|
|
6926
|
+
* the drawer at once, without the slide, and its `drawer:dismiss` is then not
|
|
6927
|
+
* cancelable. Every close dispatches a non-bubbling `close` event on
|
|
6841
6928
|
* the element with `detail: { dismissed, response }`: `{ dismissed: false,
|
|
6842
6929
|
* response }` when a form closed it under `close-on-submit`, and
|
|
6843
6930
|
* `{ dismissed: true, response: null }` for any other close.
|
|
@@ -6893,13 +6980,23 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
6893
6980
|
if (placement) {
|
|
6894
6981
|
this.#dialog.setAttribute('placement', placement);
|
|
6895
6982
|
}
|
|
6983
|
+
const dismiss = (/** @type {'button'|'backdrop'|'escape'} */ reason, platformCloses = false) =>
|
|
6984
|
+
this.#sections.dismiss(
|
|
6985
|
+
new CustomEvent('drawer:dismiss', { cancelable: !platformCloses, detail: { reason } }),
|
|
6986
|
+
() => this.close(),
|
|
6987
|
+
);
|
|
6896
6988
|
/** @type {HTMLElement} */ (fragment.querySelector('[data-ref=close]')).addEventListener('click', () =>
|
|
6897
|
-
|
|
6989
|
+
dismiss('button'),
|
|
6898
6990
|
);
|
|
6899
|
-
this.#sections.onBackdrop(() =>
|
|
6991
|
+
this.#sections.onBackdrop(() => dismiss('backdrop'));
|
|
6900
6992
|
this.#dialog.addEventListener('cancel', (e) => {
|
|
6993
|
+
if (!e.cancelable) {
|
|
6994
|
+
this.#stopSlidingOut();
|
|
6995
|
+
dismiss('escape', true);
|
|
6996
|
+
return;
|
|
6997
|
+
}
|
|
6901
6998
|
e.preventDefault();
|
|
6902
|
-
|
|
6999
|
+
dismiss('escape');
|
|
6903
7000
|
});
|
|
6904
7001
|
this.#dialog.addEventListener('close', () => {
|
|
6905
7002
|
this.dispatchEvent(
|
|
@@ -7582,11 +7679,9 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
7582
7679
|
}
|
|
7583
7680
|
/**
|
|
7584
7681
|
* Moves to the section carrying `data-step="<ref>"`. A move makes that step
|
|
7585
|
-
* and section current, moves the focus to the section, dispatches
|
|
7586
|
-
* on the host (not bubbling) with detail `{ index, step }`,
|
|
7587
|
-
* section requests for it.
|
|
7588
|
-
* bubbles through the host under the same name, so a listener tells the
|
|
7589
|
-
* two apart by `e.target`.
|
|
7682
|
+
* and section current, moves the focus to the section, dispatches
|
|
7683
|
+
* `wizard:change` on the host (not bubbling) with detail `{ index, step }`,
|
|
7684
|
+
* then fires the section requests for it.
|
|
7590
7685
|
* @param {string} ref the section's `data-step`
|
|
7591
7686
|
* @returns {Promise<any[] | undefined> | undefined} a promise resolving to
|
|
7592
7687
|
* the answers once they are delivered, or to undefined when nobody
|
|
@@ -7643,7 +7738,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
7643
7738
|
this.#apply(clamped);
|
|
7644
7739
|
this.#sections[this.#index].focus();
|
|
7645
7740
|
if (this.rendered) {
|
|
7646
|
-
this.dispatchEvent(new CustomEvent('change', { detail: { index: this.#index, step: this.step } }));
|
|
7741
|
+
this.dispatchEvent(new CustomEvent('wizard:change', { detail: { index: this.#index, step: this.step } }));
|
|
7647
7742
|
}
|
|
7648
7743
|
return this.#enter(clamped);
|
|
7649
7744
|
}
|