@optionfactory/fml 8.0.2 → 8.0.3
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 +11 -11
- package/dist/fml.css +1 -1
- package/dist/fml.css.map +1 -1
- package/dist/fml.d.mts +36 -13
- package/dist/fml.iife.js +104 -61
- 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/fml.min.mjs +1 -1
- package/dist/fml.min.mjs.map +1 -1
- package/dist/fml.mjs +104 -61
- package/dist/fml.mjs.map +1 -1
- package/dist/ftl.d.mts +24 -1
- package/dist/ftl.iife.js +27 -26
- package/dist/ftl.iife.js.map +1 -1
- package/dist/ftl.iife.min.js +1 -1
- package/dist/ftl.iife.min.js.map +1 -1
- package/dist/ftl.min.mjs +1 -1
- package/dist/ftl.min.mjs.map +1 -1
- package/dist/ftl.mjs +27 -26
- package/dist/ftl.mjs.map +1 -1
- package/dist/ful.d.mts +12 -12
- package/dist/ful.iife.js +77 -35
- 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 +77 -35
- package/dist/ful.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +11 -11
- package/dist/web-types.json +12 -12
- package/package.json +1 -1
package/dist/fml.iife.js
CHANGED
|
@@ -4697,27 +4697,30 @@ var fml = (function (exports) {
|
|
|
4697
4697
|
}
|
|
4698
4698
|
this[attr] = this.unmarshal(attr, newValue);
|
|
4699
4699
|
}
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4700
|
+
/**
|
|
4701
|
+
* The disabled protocol follows the semantics of a native form control:
|
|
4702
|
+
*
|
|
4703
|
+
* - the `disabled` attribute on the host is the field's own claim, and nothing
|
|
4704
|
+
* but its author ever writes or removes it, in markup or through the property.
|
|
4705
|
+
* The framework never claims on the form's behalf, so there is nothing to
|
|
4706
|
+
* unclaim and nothing to lose: a field declared disabled inside a disabled
|
|
4707
|
+
* `<fieldset>` stays disabled when the fieldset comes back, exactly like a
|
|
4708
|
+
* native input keeps its attribute.
|
|
4709
|
+
* - the effective state is the claim OR a disabled fieldset ancestry, which the
|
|
4710
|
+
* platform maintains on its own: `:disabled` matches both, a disabled field is
|
|
4711
|
+
* left out of the submitted values, and the inner native controls are reached
|
|
4712
|
+
* by the ancestry as descendants of the fieldset.
|
|
4713
|
+
* - the `disabled` property reflects the claim only, like a native input's: a
|
|
4714
|
+
* field disabled by its ancestry reads `false` while `matches(':disabled')`
|
|
4715
|
+
* tells the effective state. Un-claiming inside a disabled fieldset cannot
|
|
4716
|
+
* enable the field.
|
|
4717
|
+
* - the inner controls mirror the claim and nothing else: the ancestry state is
|
|
4718
|
+
* never written anywhere, so it can never go stale, and the browser composes
|
|
4719
|
+
* the two on its own when it disables and re-enables a fieldset's descendants.
|
|
4720
|
+
*
|
|
4721
|
+
* Because of this, formDisabledCallback carries nothing the framework needs to
|
|
4722
|
+
* apply, and the protocol does not define it.
|
|
4723
|
+
*/
|
|
4721
4724
|
async upgrade() {
|
|
4722
4725
|
if (this.#parsed) {
|
|
4723
4726
|
return;
|
|
@@ -4730,11 +4733,9 @@ var fml = (function (exports) {
|
|
|
4730
4733
|
this.unmarshal(attribute, this.getAttribute(attribute)),
|
|
4731
4734
|
]),
|
|
4732
4735
|
);
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
this.#unclaimFormDisabled();
|
|
4737
|
-
}
|
|
4736
|
+
//the declared claim is what render receives: the ancestry state is not
|
|
4737
|
+
//passed around, it is already where it needs to be
|
|
4738
|
+
await this.render({ slots, observed, disabled: this.hasAttribute('disabled') });
|
|
4738
4739
|
}
|
|
4739
4740
|
render(c) {}
|
|
4740
4741
|
reflect(fn) {
|
|
@@ -6331,15 +6332,17 @@ var fml = (function (exports) {
|
|
|
6331
6332
|
});
|
|
6332
6333
|
}
|
|
6333
6334
|
get disabled() {
|
|
6334
|
-
|
|
6335
|
+
//the claim only, like a native input: the effective state, claim or disabled
|
|
6336
|
+
//ancestry, is what :disabled matches
|
|
6337
|
+
return this.hasAttribute('disabled');
|
|
6335
6338
|
}
|
|
6336
6339
|
set disabled(d) {
|
|
6337
|
-
|
|
6338
|
-
//also on the host: a form associated element only matches :disabled through its
|
|
6339
|
-
//own attribute, and that is what keeps it out of the submitted values. no reflect
|
|
6340
|
-
//is needed, disabled is deliberately not observed: the platform delivers it
|
|
6341
|
-
//through formDisabledCallback, which also covers a disabled ancestor fieldset
|
|
6340
|
+
//the claim belongs to the author alone, nothing else ever writes it
|
|
6342
6341
|
Attributes.toggle(this, 'disabled', d);
|
|
6342
|
+
//the inner control carries the claim as a native input would: a disabled
|
|
6343
|
+
//fieldset ancestry is left to the browser, which reaches the inner control
|
|
6344
|
+
//as a descendant of the fieldset and re-enables it on its own
|
|
6345
|
+
Attributes.toggle(this._input, 'disabled', d);
|
|
6343
6346
|
}
|
|
6344
6347
|
get required() {
|
|
6345
6348
|
return this._input.getAttribute('aria-required') === 'true';
|
|
@@ -7259,7 +7262,9 @@ var fml = (function (exports) {
|
|
|
7259
7262
|
if (e.target.matches('input')) {
|
|
7260
7263
|
return;
|
|
7261
7264
|
}
|
|
7262
|
-
|
|
7265
|
+
//badges and other chrome are not form controls, the guard must ask the
|
|
7266
|
+
//effective state
|
|
7267
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7263
7268
|
return;
|
|
7264
7269
|
}
|
|
7265
7270
|
if (this.#ddmenu.shown) {
|
|
@@ -7275,7 +7280,7 @@ var fml = (function (exports) {
|
|
|
7275
7280
|
if (!e.target.closest('button')) {
|
|
7276
7281
|
return;
|
|
7277
7282
|
}
|
|
7278
|
-
if (this.disabled || this.readonly) {
|
|
7283
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7279
7284
|
return;
|
|
7280
7285
|
}
|
|
7281
7286
|
const idx = [...this.#items.children].indexOf(e.target.closest('ful-item'));
|
|
@@ -7288,7 +7293,7 @@ var fml = (function (exports) {
|
|
|
7288
7293
|
});
|
|
7289
7294
|
this.#badges.addEventListener('click', (e) => {
|
|
7290
7295
|
e.stopPropagation();
|
|
7291
|
-
if (this.disabled || this.readonly) {
|
|
7296
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7292
7297
|
return;
|
|
7293
7298
|
}
|
|
7294
7299
|
const idx = [...this.#badges.children].indexOf(e.target);
|
|
@@ -7313,7 +7318,7 @@ var fml = (function (exports) {
|
|
|
7313
7318
|
this.#input.value = '';
|
|
7314
7319
|
});
|
|
7315
7320
|
this.#input.addEventListener('keydown', (e) => {
|
|
7316
|
-
if (this.disabled || this.readonly) {
|
|
7321
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7317
7322
|
return;
|
|
7318
7323
|
}
|
|
7319
7324
|
switch (e.code) {
|
|
@@ -7366,7 +7371,7 @@ var fml = (function (exports) {
|
|
|
7366
7371
|
});
|
|
7367
7372
|
this.#input.addEventListener('input', (e) => {
|
|
7368
7373
|
e.stopPropagation();
|
|
7369
|
-
if (this.disabled || this.readonly) {
|
|
7374
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7370
7375
|
return;
|
|
7371
7376
|
}
|
|
7372
7377
|
dload();
|
|
@@ -7376,7 +7381,7 @@ var fml = (function (exports) {
|
|
|
7376
7381
|
if (!this.#multiple) {
|
|
7377
7382
|
this.#values.clear();
|
|
7378
7383
|
}
|
|
7379
|
-
this.#values.set(e.detail.data[0], e.detail.data.slice(1));
|
|
7384
|
+
this.#values.set(this.#coerceKey(e.detail.data[0]), e.detail.data.slice(1));
|
|
7380
7385
|
this.#changed();
|
|
7381
7386
|
this.#syncBadges();
|
|
7382
7387
|
this.#input.focus();
|
|
@@ -7427,10 +7432,36 @@ var fml = (function (exports) {
|
|
|
7427
7432
|
this.#items.replaceChildren();
|
|
7428
7433
|
this.template('items').withOverlay({ entries: this.#values.entries() }).renderTo(this.#items);
|
|
7429
7434
|
}
|
|
7435
|
+
/**
|
|
7436
|
+
* Coerces a key to the type declared by `k-type`. Keys reach the element from
|
|
7437
|
+
* both worlds: the `value` attribute is text, a loader returns whatever its
|
|
7438
|
+
* endpoint carries. One canonical type keeps the internal Map, which compares
|
|
7439
|
+
* keys strictly, consistent. A key that does not decode is left as it is.
|
|
7440
|
+
*/
|
|
7441
|
+
#coerceKey(k) {
|
|
7442
|
+
switch (this.getAttribute('k-type')) {
|
|
7443
|
+
case 'number': {
|
|
7444
|
+
const n = k === '' ? Number.NaN : Number(k);
|
|
7445
|
+
return Number.isNaN(n) ? k : n;
|
|
7446
|
+
}
|
|
7447
|
+
case 'boolean': {
|
|
7448
|
+
if (k === true || k === 'true') {
|
|
7449
|
+
return true;
|
|
7450
|
+
}
|
|
7451
|
+
if (k === false || k === 'false') {
|
|
7452
|
+
return false;
|
|
7453
|
+
}
|
|
7454
|
+
return k;
|
|
7455
|
+
}
|
|
7456
|
+
default:
|
|
7457
|
+
return String(k);
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
|
|
7430
7461
|
set value(vs) {
|
|
7431
7462
|
//the csvm mapper yields [] for a missing multiple value, an empty string is
|
|
7432
7463
|
//left alone: it is a usable key for an <option value="">
|
|
7433
|
-
const keys = vs == null ? [] : Array.isArray(vs) ? vs : [vs];
|
|
7464
|
+
const keys = (vs == null ? [] : Array.isArray(vs) ? vs : [vs]).map((k) => this.#coerceKey(k));
|
|
7434
7465
|
//the keys are known synchronously and are all `value` reads, so they are applied
|
|
7435
7466
|
//now: only the labels need the loader, until then a key stands in for its own
|
|
7436
7467
|
this.#values = new Map(keys.map((k) => [k, [k]]));
|
|
@@ -7453,7 +7484,8 @@ var fml = (function (exports) {
|
|
|
7453
7484
|
}
|
|
7454
7485
|
//label the keys that are still selected: a removal made while the lookup was in
|
|
7455
7486
|
//flight must not be undone by it, and a key the loader does not know is dropped
|
|
7456
|
-
|
|
7487
|
+
//the loader keys are coerced too, so they line up with the assigned ones
|
|
7488
|
+
const resolved = new Map(entries.map((e) => [this.#coerceKey(e[0]), e.slice(1)]));
|
|
7457
7489
|
for (const key of keys) {
|
|
7458
7490
|
if (!this.#values.has(key)) {
|
|
7459
7491
|
continue;
|
|
@@ -7479,15 +7511,17 @@ var fml = (function (exports) {
|
|
|
7479
7511
|
return [...this.#values.entries()][0] ?? null;
|
|
7480
7512
|
}
|
|
7481
7513
|
get disabled() {
|
|
7482
|
-
|
|
7514
|
+
//the claim only, like a native input: the effective state, claim or disabled
|
|
7515
|
+
//ancestry, is what :disabled matches
|
|
7516
|
+
return this.hasAttribute('disabled');
|
|
7483
7517
|
}
|
|
7484
7518
|
set disabled(d) {
|
|
7485
|
-
|
|
7486
|
-
//also on the host: a form associated element only matches :disabled through its
|
|
7487
|
-
//own attribute, and that is what keeps it out of the submitted values. no reflect
|
|
7488
|
-
//is needed, disabled is deliberately not observed: the platform delivers it
|
|
7489
|
-
//through formDisabledCallback, which also covers a disabled ancestor fieldset
|
|
7519
|
+
//the claim belongs to the author alone, nothing else ever writes it
|
|
7490
7520
|
Attributes.toggle(this, 'disabled', d);
|
|
7521
|
+
//the inner control carries the claim as a native input would: a disabled
|
|
7522
|
+
//fieldset ancestry is left to the browser, which reaches the inner control
|
|
7523
|
+
//as a descendant of the fieldset and re-enables it on its own
|
|
7524
|
+
Attributes.toggle(this.#input, 'disabled', d);
|
|
7491
7525
|
}
|
|
7492
7526
|
get readonly() {
|
|
7493
7527
|
return this.#input.readOnly;
|
|
@@ -7635,15 +7669,17 @@ var fml = (function (exports) {
|
|
|
7635
7669
|
});
|
|
7636
7670
|
}
|
|
7637
7671
|
get disabled() {
|
|
7638
|
-
|
|
7672
|
+
//the claim only, like a native input: the effective state, claim or disabled
|
|
7673
|
+
//ancestry, is what :disabled matches
|
|
7674
|
+
return this.hasAttribute('disabled');
|
|
7639
7675
|
}
|
|
7640
7676
|
set disabled(d) {
|
|
7641
|
-
|
|
7642
|
-
//also on the host: a form associated element only matches :disabled through its
|
|
7643
|
-
//own attribute, and that is what keeps it out of the submitted values. no reflect
|
|
7644
|
-
//is needed, disabled is deliberately not observed: the platform delivers it
|
|
7645
|
-
//through formDisabledCallback, which also covers a disabled ancestor fieldset
|
|
7677
|
+
//the claim belongs to the author alone, nothing else ever writes it
|
|
7646
7678
|
Attributes.toggle(this, 'disabled', d);
|
|
7679
|
+
//the group disables through its own fieldset, which carries the claim like
|
|
7680
|
+
//a native input would: a disabled outer ancestry is left to the browser,
|
|
7681
|
+
//which reaches the radios as descendants and re-enables them on its own
|
|
7682
|
+
this.#fieldset.disabled = d;
|
|
7647
7683
|
}
|
|
7648
7684
|
get required() {
|
|
7649
7685
|
return this.#fieldset.getAttribute('aria-required') === 'true';
|
|
@@ -7718,7 +7754,8 @@ var fml = (function (exports) {
|
|
|
7718
7754
|
const label = fragment.querySelector('label');
|
|
7719
7755
|
label.addEventListener('click', () => {
|
|
7720
7756
|
this.focus();
|
|
7721
|
-
|
|
7757
|
+
//a label is not a form control, the guard must ask the effective state
|
|
7758
|
+
if (this.matches(':disabled') || this.readonly) {
|
|
7722
7759
|
return;
|
|
7723
7760
|
}
|
|
7724
7761
|
this.value = !this.value;
|
|
@@ -7753,15 +7790,17 @@ var fml = (function (exports) {
|
|
|
7753
7790
|
});
|
|
7754
7791
|
}
|
|
7755
7792
|
get disabled() {
|
|
7756
|
-
|
|
7793
|
+
//the claim only, like a native input: the effective state, claim or disabled
|
|
7794
|
+
//ancestry, is what :disabled matches
|
|
7795
|
+
return this.hasAttribute('disabled');
|
|
7757
7796
|
}
|
|
7758
7797
|
set disabled(d) {
|
|
7759
|
-
|
|
7760
|
-
//also on the host: a form associated element only matches :disabled through its
|
|
7761
|
-
//own attribute, and that is what keeps it out of the submitted values. no reflect
|
|
7762
|
-
//is needed, disabled is deliberately not observed: the platform delivers it
|
|
7763
|
-
//through formDisabledCallback, which also covers a disabled ancestor fieldset
|
|
7798
|
+
//the claim belongs to the author alone, nothing else ever writes it
|
|
7764
7799
|
Attributes.toggle(this, 'disabled', d);
|
|
7800
|
+
//the inner control carries the claim as a native input would: a disabled
|
|
7801
|
+
//fieldset ancestry is left to the browser, which reaches the inner control
|
|
7802
|
+
//as a descendant of the fieldset and re-enables it on its own
|
|
7803
|
+
Attributes.toggle(this.#input, 'disabled', d);
|
|
7765
7804
|
}
|
|
7766
7805
|
get required() {
|
|
7767
7806
|
return this.#input.getAttribute('aria-required') === 'true';
|
|
@@ -8399,8 +8438,10 @@ var fml = (function (exports) {
|
|
|
8399
8438
|
return super.disabled;
|
|
8400
8439
|
}
|
|
8401
8440
|
set disabled(d) {
|
|
8402
|
-
|
|
8441
|
+
//the claim and the first operand are the base's, the second operand mirrors
|
|
8442
|
+
//the claim like the first one does
|
|
8403
8443
|
super.disabled = d;
|
|
8444
|
+
Attributes.toggle(this.#value2, 'disabled', d);
|
|
8404
8445
|
}
|
|
8405
8446
|
}
|
|
8406
8447
|
|
|
@@ -8515,8 +8556,10 @@ var fml = (function (exports) {
|
|
|
8515
8556
|
return super.disabled;
|
|
8516
8557
|
}
|
|
8517
8558
|
set disabled(d) {
|
|
8518
|
-
|
|
8559
|
+
//the claim and the first operand are the base's, the second operand mirrors
|
|
8560
|
+
//the claim like the first one does
|
|
8519
8561
|
super.disabled = d;
|
|
8562
|
+
Attributes.toggle(this.#value2, 'disabled', d);
|
|
8520
8563
|
}
|
|
8521
8564
|
}
|
|
8522
8565
|
|