@fusion.dev/helix-headless 0.47.1 → 0.48.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 +143 -33
- package/dist/color-picker/root/color-picker-root.d.ts +78 -3
- package/dist/color-picker/root/color-picker-root.js +47 -4
- package/dist/rating/root/rating-root.d.ts +65 -7
- package/dist/rating/root/rating-root.js +35 -8
- package/dist/time-picker/root/time-picker-root.d.ts +13 -0
- package/dist/time-picker/root/time-picker-root.js +2 -0
- package/package.json +5 -5
- package/types/jsx.d.ts +377 -22
- package/types/vue.d.ts +99 -4
|
@@ -89,18 +89,28 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
89
89
|
this.handleLeave = () => {
|
|
90
90
|
this.previewing = undefined;
|
|
91
91
|
};
|
|
92
|
+
this.warned = false;
|
|
93
|
+
}
|
|
94
|
+
get floor() {
|
|
95
|
+
if (!Number.isFinite(this.min)) {
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
return Math.min(Math.max(this.min, 0), Math.max(this.max, 0));
|
|
92
99
|
}
|
|
93
100
|
get score() {
|
|
94
101
|
const parsed = Number.parseFloat(this.value);
|
|
95
102
|
if (!Number.isFinite(parsed)) {
|
|
96
|
-
return
|
|
103
|
+
return this.floor;
|
|
97
104
|
}
|
|
98
|
-
return Math.min(Math.max(parsed,
|
|
105
|
+
return Math.min(Math.max(parsed, this.floor), this.max);
|
|
99
106
|
}
|
|
100
|
-
get
|
|
107
|
+
get positions() {
|
|
101
108
|
const count = Math.max(1, Math.round(this.max / this.step));
|
|
102
109
|
return Array.from({ length: count }, (_, index) => Number(((index + 1) * this.step).toFixed(2)));
|
|
103
110
|
}
|
|
111
|
+
get steps() {
|
|
112
|
+
return this.positions.filter((score) => score >= this.floor);
|
|
113
|
+
}
|
|
104
114
|
get options() {
|
|
105
115
|
const found = [...(this.renderRoot?.querySelectorAll('[part="option"]') ?? [])];
|
|
106
116
|
return found.map((element) => ({
|
|
@@ -157,6 +167,12 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
157
167
|
updated(changed) {
|
|
158
168
|
super.updated?.(changed);
|
|
159
169
|
this.sync();
|
|
170
|
+
if (this.floor !== this.min && !this.warned) {
|
|
171
|
+
this.warned = true;
|
|
172
|
+
console.warn(`<${this.localName}> has min="${this.min}", which is not a score between 0 and its max of ` +
|
|
173
|
+
`${this.max}, so the lowest score it offers is ${this.floor}. Put min inside the marks, ` +
|
|
174
|
+
'or move max.');
|
|
175
|
+
}
|
|
160
176
|
}
|
|
161
177
|
willUpdate(changed) {
|
|
162
178
|
super.willUpdate(changed);
|
|
@@ -177,12 +193,16 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
177
193
|
const first = this.steps[0];
|
|
178
194
|
const mark = (layer, index) => html `<span part="mark">${this.markFor(layer, index)}</span>`;
|
|
179
195
|
const marksIn = (layer) => Array.from({ length: count }, (_, index) => mark(layer, index));
|
|
180
|
-
return html
|
|
196
|
+
return html `${this.renderGroupLabel()}
|
|
197
|
+
<div part="field">
|
|
198
|
+
<div
|
|
181
199
|
part="marks"
|
|
182
200
|
role=${this.readOnly ? 'img' : 'radiogroup'}
|
|
183
201
|
aria-label=${this.readOnly ? said : this.label || nothing}
|
|
202
|
+
aria-describedby=${this.describedBy ?? nothing}
|
|
203
|
+
aria-required=${this.required && !this.readOnly ? 'true' : nothing}
|
|
184
204
|
data-slotted=${this.markSource ? '' : nothing}
|
|
185
|
-
style=${`--rating-full: ${Math.floor(showing)}; --rating-part: ${showing - Math.floor(showing)}; --rating-steps: ${this.
|
|
205
|
+
style=${`--rating-full: ${Math.floor(showing)}; --rating-part: ${showing - Math.floor(showing)}; --rating-steps: ${this.positions.length}`}
|
|
186
206
|
@pointercancel=${this.handleDragCancel}
|
|
187
207
|
@pointerdown=${this.handleDragStart}
|
|
188
208
|
@pointermove=${this.handleDragMove}
|
|
@@ -207,7 +227,10 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
207
227
|
>
|
|
208
228
|
${this.readOnly
|
|
209
229
|
? nothing
|
|
210
|
-
:
|
|
230
|
+
:
|
|
231
|
+
this.positions.map((score, index) => score < this.floor
|
|
232
|
+
? nothing
|
|
233
|
+
: html `<button
|
|
211
234
|
part="option"
|
|
212
235
|
role="radio"
|
|
213
236
|
type="button"
|
|
@@ -216,7 +239,9 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
216
239
|
data-score=${String(score)}
|
|
217
240
|
style=${`--rating-step: ${index + 1}`}
|
|
218
241
|
?disabled=${this.isDisabled}
|
|
219
|
-
tabindex=${this.score === score || (this.score ===
|
|
242
|
+
tabindex=${this.score === score || (this.score === this.floor && score === first)
|
|
243
|
+
? '0'
|
|
244
|
+
: '-1'}
|
|
220
245
|
@click=${this.handleOptionClick}
|
|
221
246
|
@pointerenter=${this.handleOptionEnter}
|
|
222
247
|
></button>`)}
|
|
@@ -227,7 +252,9 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
227
252
|
aria-hidden="true"
|
|
228
253
|
>${showing}</span
|
|
229
254
|
>`
|
|
230
|
-
: nothing}
|
|
255
|
+
: nothing}
|
|
256
|
+
</div>
|
|
257
|
+
${this.renderHint()}${this.renderFeedback()}`;
|
|
231
258
|
}
|
|
232
259
|
get valueAsNumber() {
|
|
233
260
|
return asNumber(this.value);
|
|
@@ -43,6 +43,19 @@ declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fu
|
|
|
43
43
|
* string, which is the whole reason the shape is that one. What each row *says*
|
|
44
44
|
* is the reader's own convention, from `Intl`.
|
|
45
45
|
*
|
|
46
|
+
* **The chosen row is marked in the markup, not worked out on upgrade.** The
|
|
47
|
+
* listbox is handed the answer as `.value`, and lit-ssr serializes no property
|
|
48
|
+
* binding, so a served `value="09:30"` shipped ninety-six rows with nothing on
|
|
49
|
+
* any of them saying which one it was: the mark arrived when the listbox
|
|
50
|
+
* upgraded and ran `place`. So each option is given `selected` as well, which
|
|
51
|
+
* is an attribute binding and does serve, and which the listbox then agrees
|
|
52
|
+
* with rather than fights, `place` writing the same answer from the same value.
|
|
53
|
+
* `selected` is the declaration a consumer writes on `Option` anywhere else in
|
|
54
|
+
* the library, and Date Picker expresses its own choice as markup for the same
|
|
55
|
+
* reason: a picker whose answer is invisible until a script runs is a picker
|
|
56
|
+
* whose answer is not served at all. Both readings do it, the list and the
|
|
57
|
+
* wheels, a wheel being a listbox like the list is.
|
|
58
|
+
*
|
|
46
59
|
* @since 0.1.0
|
|
47
60
|
* @status experimental
|
|
48
61
|
* @category forms
|
|
@@ -248,6 +248,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
248
248
|
label: option-label, text: option-text"
|
|
249
249
|
value=${one}
|
|
250
250
|
?disabled=${barred(one)}
|
|
251
|
+
?selected=${one === value}
|
|
251
252
|
>${written(one)}</${this.tag('option')}
|
|
252
253
|
>`)}
|
|
253
254
|
</${this.tag('listbox')}>`;
|
|
@@ -291,6 +292,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
291
292
|
label: option-label, text: option-text"
|
|
292
293
|
value=${at}
|
|
293
294
|
?disabled=${this.barred(at)}
|
|
295
|
+
?selected=${this.held.includes(at)}
|
|
294
296
|
data-between=${between ? '' : nothing}
|
|
295
297
|
>${writeTime(at, this.locale)}</${this.tag('option')}
|
|
296
298
|
>`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-headless",
|
|
3
3
|
"description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.48.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
},
|
|
47
47
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@fusion.dev/helix-core": "0.
|
|
50
|
-
"@fusion.dev/helix-icons": "0.
|
|
49
|
+
"@fusion.dev/helix-core": "0.48.0",
|
|
50
|
+
"@fusion.dev/helix-icons": "0.48.0",
|
|
51
51
|
"uqr": "^0.1.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
55
|
-
"@fusion.dev/helix-cem": "0.
|
|
56
|
-
"@fusion.dev/helix-testing": "0.
|
|
55
|
+
"@fusion.dev/helix-cem": "0.48.0",
|
|
56
|
+
"@fusion.dev/helix-testing": "0.48.0",
|
|
57
57
|
"@fusion.dev/scripts": "0.0.0-dev",
|
|
58
58
|
"@happy-dom/global-registrator": "^20.0.0",
|
|
59
59
|
"@lit-labs/ssr": "^4.1.0",
|