@fusion.dev/helix-core 0.157.0 → 0.159.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/custom-elements.json +59 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mixins/mixin-dismissible/mixin-dismissible.js +1 -1
- package/dist/utils/audit-name/audit-name.d.ts +5 -1
- package/dist/utils/audit-name/audit-name.js +4 -1
- package/dist/utils/autofill-select/autofill-select.js +2 -1
- package/dist/utils/chosen-values/chosen-values.d.ts +17 -0
- package/dist/utils/chosen-values/chosen-values.js +19 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/custom-elements.json
CHANGED
|
@@ -14857,6 +14857,14 @@
|
|
|
14857
14857
|
"module": "./utils/chord/key-names.js"
|
|
14858
14858
|
}
|
|
14859
14859
|
},
|
|
14860
|
+
{
|
|
14861
|
+
"kind": "js",
|
|
14862
|
+
"name": "chosenValues",
|
|
14863
|
+
"declaration": {
|
|
14864
|
+
"name": "chosenValues",
|
|
14865
|
+
"module": "./utils/chosen-values/chosen-values.js"
|
|
14866
|
+
}
|
|
14867
|
+
},
|
|
14860
14868
|
{
|
|
14861
14869
|
"kind": "js",
|
|
14862
14870
|
"name": "clamp",
|
|
@@ -19459,7 +19467,7 @@
|
|
|
19459
19467
|
"text": "HTMLElement | undefined"
|
|
19460
19468
|
}
|
|
19461
19469
|
},
|
|
19462
|
-
"description": "The tab stop after this element on the page, or the one before it at the\nend, for
|
|
19470
|
+
"description": "The tab stop after this element on the page, or the one before it at the\nend, for an element whose removal would drop focus to the body because\nno neighbor of its kind has a control to take it.\n\n**A lone Callout or Announcement had nowhere to hand focus**, so a\nkeyboard reader who dismissed one started again from the top of the\npage. React Aria's Toast hands focus on the same way. Read before the\nevent, in the order Tab reaches the stops, while this element's own are\nstill among them."
|
|
19463
19471
|
},
|
|
19464
19472
|
{
|
|
19465
19473
|
"kind": "method",
|
|
@@ -23632,7 +23640,7 @@
|
|
|
23632
23640
|
{
|
|
23633
23641
|
"name": "control",
|
|
23634
23642
|
"type": {
|
|
23635
|
-
"text": "() => HTMLElement | null"
|
|
23643
|
+
"text": "() => HTMLElement | null | undefined"
|
|
23636
23644
|
}
|
|
23637
23645
|
},
|
|
23638
23646
|
{
|
|
@@ -23656,7 +23664,7 @@
|
|
|
23656
23664
|
}
|
|
23657
23665
|
}
|
|
23658
23666
|
],
|
|
23659
|
-
"description": "Warns once, through the runtime channel, when a control has no accessible\nname: none on the host, and none on the control inside it.\n\n**Read a task after the control first renders**, so a label that arrives in\nthe same pass counts: slotted, written by a framework beside the control, or\nforwarded from a `<label for>`. One timer serves every control that asked in\nthat task, and an element is read once in its life, so a name taken away\nlater is not reported.\n\n**In a development build only.** Every field and Button calls it, so in\nproduction it would cost each of them about 450 bytes gzip for a sentence\nmeant for the person writing the page. Core imports it as `#audit-name`,\nwhich `package.json` resolves here under the `development` condition (Vite\nand webpack in development, `bun --conditions development`,\n`node --conditions=development`) and to `audit-name-off.ts`, which does\nnothing, everywhere else. Like every runtime warning it reports through the\none channel, and a project that wants the console quiet tells\n`@fusion.dev/helix-diagnostics` with `core.warnings: false`.\n\n`also` answers for a name the component gave through its internals, which no\nattribute shows. `fix` is the sentence that says how to name it. `shown` is\nthe part where the control shows its value or its placeholder, whose words\nare no name."
|
|
23667
|
+
"description": "Warns once, through the runtime channel, when a control has no accessible\nname: none on the host, and none on the control inside it.\n\n**Read a task after the control first renders**, so a label that arrives in\nthe same pass counts: slotted, written by a framework beside the control, or\nforwarded from a `<label for>`. One timer serves every control that asked in\nthat task, and an element is read once in its life, so a name taken away\nlater is not reported.\n\n**In a development build only.** Every field and Button calls it, so in\nproduction it would cost each of them about 450 bytes gzip for a sentence\nmeant for the person writing the page. Core imports it as `#audit-name`,\nwhich `package.json` resolves here under the `development` condition (Vite\nand webpack in development, `bun --conditions development`,\n`node --conditions=development`) and to `audit-name-off.ts`, which does\nnothing, everywhere else. Like every runtime warning it reports through the\none channel, and a project that wants the console quiet tells\n`@fusion.dev/helix-diagnostics` with `core.warnings: false`.\n\n`control` returns the control inside the host, `null` where the host is the\ncontrol, or `undefined` where the control is not drawn at the moment of the\nread: the host is then read again the next time it asks.\n\n`also` answers for a name the component gave through its internals, which no\nattribute shows. `fix` is the sentence that says how to name it. `shown` is\nthe part where the control shows its value or its placeholder, whose words\nare no name."
|
|
23660
23668
|
}
|
|
23661
23669
|
],
|
|
23662
23670
|
"exports": [
|
|
@@ -24675,6 +24683,52 @@
|
|
|
24675
24683
|
}
|
|
24676
24684
|
]
|
|
24677
24685
|
},
|
|
24686
|
+
{
|
|
24687
|
+
"kind": "javascript-module",
|
|
24688
|
+
"path": "src/utils/chosen-values/chosen-values.ts",
|
|
24689
|
+
"declarations": [
|
|
24690
|
+
{
|
|
24691
|
+
"kind": "function",
|
|
24692
|
+
"name": "chosenValues",
|
|
24693
|
+
"return": {
|
|
24694
|
+
"type": {
|
|
24695
|
+
"text": "string[]"
|
|
24696
|
+
}
|
|
24697
|
+
},
|
|
24698
|
+
"parameters": [
|
|
24699
|
+
{
|
|
24700
|
+
"name": "value",
|
|
24701
|
+
"type": {
|
|
24702
|
+
"text": "string"
|
|
24703
|
+
}
|
|
24704
|
+
},
|
|
24705
|
+
{
|
|
24706
|
+
"name": "known",
|
|
24707
|
+
"type": {
|
|
24708
|
+
"text": "ReadonlySet<string>"
|
|
24709
|
+
}
|
|
24710
|
+
},
|
|
24711
|
+
{
|
|
24712
|
+
"name": "multiple",
|
|
24713
|
+
"type": {
|
|
24714
|
+
"text": "boolean"
|
|
24715
|
+
}
|
|
24716
|
+
}
|
|
24717
|
+
],
|
|
24718
|
+
"description": "The values a chooser's `value` holds, read against the values of its\noptions.\n\n**One chosen value is the whole string.** A single select whose option is\n`x,y` holds `x,y`, and splitting it found no option of either half, so the\ntrigger showed the placeholder while the form sent `x,y`.\n\n**Several are joined with commas, and an option's own comma is kept.** The\nstring is split on its commas, and fragments next to each other are read as\none value where they join into the value of an option, the longest first.\nA fragment that matches no option is kept as it is, so a value set ahead of\noptions that load later is not lost. Where an option's value is also two\nother options' values joined, such as `x`, `y` and `x,y`, the longer one is\nread."
|
|
24719
|
+
}
|
|
24720
|
+
],
|
|
24721
|
+
"exports": [
|
|
24722
|
+
{
|
|
24723
|
+
"kind": "js",
|
|
24724
|
+
"name": "chosenValues",
|
|
24725
|
+
"declaration": {
|
|
24726
|
+
"name": "chosenValues",
|
|
24727
|
+
"module": "src/utils/chosen-values/chosen-values.ts"
|
|
24728
|
+
}
|
|
24729
|
+
}
|
|
24730
|
+
]
|
|
24731
|
+
},
|
|
24678
24732
|
{
|
|
24679
24733
|
"kind": "javascript-module",
|
|
24680
24734
|
"path": "src/utils/clamp/clamp.ts",
|
|
@@ -32420,7 +32474,7 @@
|
|
|
32420
32474
|
"type": {
|
|
32421
32475
|
"text": "string"
|
|
32422
32476
|
},
|
|
32423
|
-
"default": "'0.
|
|
32477
|
+
"default": "'0.159.0'",
|
|
32424
32478
|
"description": "The version of the package this file ships in.\n\n**Written by `fusion/scripts/version.mjs`** wherever it writes the package's\n`package.json`, and stamped back into the repository beside it after a\nrelease, so the two never disagree; a spec beside this holds them to it.\nNothing else in the running code knows which release it is."
|
|
32425
32479
|
}
|
|
32426
32480
|
],
|
|
@@ -32980,6 +33034,6 @@
|
|
|
32980
33034
|
],
|
|
32981
33035
|
"helix": {
|
|
32982
33036
|
"package": "@fusion.dev/helix-core",
|
|
32983
|
-
"version": "0.
|
|
33037
|
+
"version": "0.159.0"
|
|
32984
33038
|
}
|
|
32985
33039
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export { capturePointer } from './utils/capture-pointer/capture-pointer.js';
|
|
|
61
61
|
export { centerInView } from './utils/center-in-view/center-in-view.js';
|
|
62
62
|
export { ariaChord, type ChordPress, chordParts, matchesChord, printableChord, selectsAll, } from './utils/chord/chord.js';
|
|
63
63
|
export { type KeyNames, keyNames } from './utils/chord/key-names.js';
|
|
64
|
+
export { chosenValues } from './utils/chosen-values/chosen-values.js';
|
|
64
65
|
export { clamp } from './utils/clamp/clamp.js';
|
|
65
66
|
export { clockLocale, dayPeriod, type HourCycle, isTwelveHour, nearestTime, offeredTimes, type TimeFault, type TimeRules, timeBarred, timeFault, wheelParts, wholeHour, } from './utils/clock/clock.js';
|
|
66
67
|
export { closestInstance } from './utils/closest-instance/closest-instance.js';
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,7 @@ export { capturePointer } from './utils/capture-pointer/capture-pointer.js';
|
|
|
61
61
|
export { centerInView } from './utils/center-in-view/center-in-view.js';
|
|
62
62
|
export { ariaChord, chordParts, matchesChord, printableChord, selectsAll, } from './utils/chord/chord.js';
|
|
63
63
|
export { keyNames } from './utils/chord/key-names.js';
|
|
64
|
+
export { chosenValues } from './utils/chosen-values/chosen-values.js';
|
|
64
65
|
export { clamp } from './utils/clamp/clamp.js';
|
|
65
66
|
export { clockLocale, dayPeriod, isTwelveHour, nearestTime, offeredTimes, timeBarred, timeFault, wheelParts, wholeHour, } from './utils/clock/clock.js';
|
|
66
67
|
export { closestInstance } from './utils/closest-instance/closest-instance.js';
|
|
@@ -32,7 +32,7 @@ export const MixinDismissible = (Base) => {
|
|
|
32
32
|
dismiss() {
|
|
33
33
|
const inside = deepContains(this, deepActiveElement());
|
|
34
34
|
const neighbors = inside ? this.neighbors() : [];
|
|
35
|
-
const beside = inside
|
|
35
|
+
const beside = inside ? this.stopBeside() : undefined;
|
|
36
36
|
const event = this.dismissEvent();
|
|
37
37
|
this.dispatchEvent(event);
|
|
38
38
|
if ((neighbors.length > 0 || beside) && !event.defaultPrevented) {
|
|
@@ -38,9 +38,13 @@ export declare const hasName: (element: HTMLElement, shown?: Element | null) =>
|
|
|
38
38
|
* one channel, and a project that wants the console quiet tells
|
|
39
39
|
* `@fusion.dev/helix-diagnostics` with `core.warnings: false`.
|
|
40
40
|
*
|
|
41
|
+
* `control` returns the control inside the host, `null` where the host is the
|
|
42
|
+
* control, or `undefined` where the control is not drawn at the moment of the
|
|
43
|
+
* read: the host is then read again the next time it asks.
|
|
44
|
+
*
|
|
41
45
|
* `also` answers for a name the component gave through its internals, which no
|
|
42
46
|
* attribute shows. `fix` is the sentence that says how to name it. `shown` is
|
|
43
47
|
* the part where the control shows its value or its placeholder, whose words
|
|
44
48
|
* are no name.
|
|
45
49
|
*/
|
|
46
|
-
export declare const auditName: (host: HTMLElement, control: () => HTMLElement | null, fix: string, also?: () => boolean, shown?: () => Element | null) => void;
|
|
50
|
+
export declare const auditName: (host: HTMLElement, control: () => HTMLElement | null | undefined, fix: string, also?: () => boolean, shown?: () => Element | null) => void;
|
|
@@ -69,8 +69,11 @@ export const auditName = (host, control, fix, also, shown) => {
|
|
|
69
69
|
if (!host.isConnected) {
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
|
-
audited.add(host);
|
|
73
72
|
const inner = control();
|
|
73
|
+
if (inner === undefined) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
audited.add(host);
|
|
74
77
|
const value = shown?.();
|
|
75
78
|
if (also?.() || hasName(host) || (inner !== null && hasName(inner, value))) {
|
|
76
79
|
return;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { html, nothing } from 'lit';
|
|
2
|
+
import { chosenValues } from '../chosen-values/chosen-values.js';
|
|
2
3
|
const HIDDEN = 'position:fixed;top:0;left:0;width:1px;height:1px;opacity:0;pointer-events:none';
|
|
3
4
|
export const drawAutofill = ({ autocomplete, disabled, multiple, onFill, options, value, }) => {
|
|
4
5
|
if (autocomplete === '') {
|
|
5
6
|
return nothing;
|
|
6
7
|
}
|
|
7
|
-
const chosen = value.
|
|
8
|
+
const chosen = chosenValues(value, new Set(options.map((option) => option.value)), multiple);
|
|
8
9
|
const fill = (event) => onFill([...event.currentTarget.selectedOptions]
|
|
9
10
|
.map((option) => option.value)
|
|
10
11
|
.filter(Boolean)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The values a chooser's `value` holds, read against the values of its
|
|
3
|
+
* options.
|
|
4
|
+
*
|
|
5
|
+
* **One chosen value is the whole string.** A single select whose option is
|
|
6
|
+
* `x,y` holds `x,y`, and splitting it found no option of either half, so the
|
|
7
|
+
* trigger showed the placeholder while the form sent `x,y`.
|
|
8
|
+
*
|
|
9
|
+
* **Several are joined with commas, and an option's own comma is kept.** The
|
|
10
|
+
* string is split on its commas, and fragments next to each other are read as
|
|
11
|
+
* one value where they join into the value of an option, the longest first.
|
|
12
|
+
* A fragment that matches no option is kept as it is, so a value set ahead of
|
|
13
|
+
* options that load later is not lost. Where an option's value is also two
|
|
14
|
+
* other options' values joined, such as `x`, `y` and `x,y`, the longer one is
|
|
15
|
+
* read.
|
|
16
|
+
*/
|
|
17
|
+
export declare const chosenValues: (value: string, known: ReadonlySet<string>, multiple: boolean) => string[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const chosenValues = (value, known, multiple) => {
|
|
2
|
+
if (value === '') {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
if (!multiple || known.has(value)) {
|
|
6
|
+
return [value];
|
|
7
|
+
}
|
|
8
|
+
const fragments = value.split(',');
|
|
9
|
+
const values = [];
|
|
10
|
+
for (let from = 0; from < fragments.length;) {
|
|
11
|
+
let to = fragments.length;
|
|
12
|
+
while (to > from + 1 && !known.has(fragments.slice(from, to).join(','))) {
|
|
13
|
+
to -= 1;
|
|
14
|
+
}
|
|
15
|
+
values.push(fragments.slice(from, to).join(','));
|
|
16
|
+
from = to;
|
|
17
|
+
}
|
|
18
|
+
return values;
|
|
19
|
+
};
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.159.0';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-core",
|
|
3
3
|
"description": "Helix element primitives: base classes, mixins, decorators, utilities.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.159.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@floating-ui/dom": "^1.8.0",
|
|
59
|
-
"@fusion.dev/helix-icons": "0.
|
|
59
|
+
"@fusion.dev/helix-icons": "0.159.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@fusion.dev/helix-cem": "0.
|
|
63
|
-
"@fusion.dev/helix-testing": "0.
|
|
62
|
+
"@fusion.dev/helix-cem": "0.159.0",
|
|
63
|
+
"@fusion.dev/helix-testing": "0.159.0",
|
|
64
64
|
"@lit-labs/ssr": "^4.1.0",
|
|
65
65
|
"lit": "^3.2.1"
|
|
66
66
|
},
|