@cssints/headless 0.14.0 → 0.15.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/README.md +50 -0
- package/dist/index.d.mts +99 -0
- package/dist/index.mjs +171 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -220,6 +220,56 @@ const remove = async () => {
|
|
|
220
220
|
- **Labels are the host's.** The defaults, `"Confirm"` and `"Cancel"`, stay English. An app that translates passes `confirmLabel` and `cancelLabel` (and the `title`) with each request, `confirm({ title: t("unsaved"), confirmLabel: t("discard"), cancelLabel: t("keep") })`; a label left out, or `undefined`, falls back to the English default. Nothing in the options needed to change for this: `ConfirmRequest` already carried both labels.
|
|
221
221
|
- `aria-labelledby` is the title and `aria-describedby` **always** the description (an alertdialog needs one), so render `descriptionProps` always: it is `hidden` when the request has no description. `triggerProps` are dialog-modal's trigger attributes without the handlers; the click that calls `confirm()` is the host's. `request()` keeps the last request after it settles, so a closing animation does not flash empty.
|
|
222
222
|
|
|
223
|
+
## Toast and status
|
|
224
|
+
|
|
225
|
+
Two live regions for the two sizes of feedback: `createStatus` is one `role=status` message whose text the host replaces ("Link copied", "Saved"); `createToast` is a queue of toasts, each with its own live region, a timeout, a ceiling and a countdown that pauses. Neither touches the DOM: like every primitive here they return state and attribute objects. **There is no APG pattern for either** (APG's Alert, `createAlert`, is imperative and assertive), so there is no Quint spec and `test/toast.browser.test.tsx` is the oracle. The behaviour is copied from Base UI's Toast and React Aria's Toast (a landmark, F6 into it, at least 5 s, timers paused on hover or focus, the announced text handed in rather than read from the DOM).
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
const toast = createToast();
|
|
229
|
+
const status = createStatus();
|
|
230
|
+
|
|
231
|
+
const copy = async () => {
|
|
232
|
+
await navigator.clipboard.writeText(url);
|
|
233
|
+
status.show("Link copied");
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const upload = async () => {
|
|
237
|
+
try {
|
|
238
|
+
await send(file);
|
|
239
|
+
toast.show({ title: "Uploaded", description: file.name, tone: "success" });
|
|
240
|
+
} catch {
|
|
241
|
+
toast.show({
|
|
242
|
+
title: "Upload failed",
|
|
243
|
+
description: "Try again from the file row",
|
|
244
|
+
tone: "error",
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
<p {...status.statusProps}>{status.message()}</p>;
|
|
250
|
+
|
|
251
|
+
<div {...toast.regionProps} tabindex={-1}>
|
|
252
|
+
<For each={toast.toasts()}>
|
|
253
|
+
{(item) => (
|
|
254
|
+
<div {...toast.toastProps(item.id)}>
|
|
255
|
+
<p>{item.title}</p>
|
|
256
|
+
<p>{item.description}</p>
|
|
257
|
+
<button type="button" onClick={() => toast.dismiss(item.id)}>
|
|
258
|
+
Dismiss
|
|
259
|
+
</button>
|
|
260
|
+
</div>
|
|
261
|
+
)}
|
|
262
|
+
</For>
|
|
263
|
+
</div>;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
- **A status replaces, it does not stack.** `show(text)` writes the one region and `clear()` empties it; a second message before the first is read replaces it. A status is never for errors: an error is `createAlert` (`role=alert`, assertive), and a titled message with a timeout is a toast.
|
|
267
|
+
- **Toast roles.** `toastProps(id).role` is `"alert"` for `tone: "error"` and `"status"` otherwise, so an error interrupts and the rest wait. The container is `role="region"` with `aria-label` ("Notifications" unless `labels.region`), and each toast is `aria-atomic`, so its title and description are announced as one — the toast's own text is the announcement, a close button's label included, so keep a toast to its title and description. The role sits on the toast rather than on one container per tone: the container is the `region` landmark, so it cannot also be the live region, and a role per toast needs no second region from the host.
|
|
268
|
+
- **Timers.** `timeout` defaults to 5000 ms, the five seconds Base UI and React Aria call the minimum for reading a message; shorter values are for tests. One timer per toast, cleared by `dismiss`/`dismissAll` and all of them on dispose.
|
|
269
|
+
- **Pause.** Hovering a toast pauses its countdown and leaving resumes it with the time it had left (the deadline is kept, not restarted); focus always pauses, because a reader who tabbed into the toast must not lose it. `pauseOnHover: false` leaves focus as the only pause.
|
|
270
|
+
- **The ceiling.** `max` (default 3) keeps the newest: a `show` past it drops the oldest. `onDismiss(id)` fires for every toast that leaves, whichever way — a timeout, a dismiss, `dismissAll` or the ceiling.
|
|
271
|
+
- **F6.** Base UI and React Aria enter the toast region with F6 and return with F6: the region is the target, so give it `tabindex="-1"` and focus it from the host's F6 handler, remembering the element to restore. The primitive binds no keys: global hotkeys are a separate piece (bean cssints-h0d5).
|
|
272
|
+
|
|
223
273
|
## Popover
|
|
224
274
|
|
|
225
275
|
`createPopover` is the non-modal overlay: an anchored surface a trigger opens, dismissed by a click on the trigger, an outside `pointerdown` or Escape, with focus moving into it and back to the trigger. **There is no APG pattern for a popover** (APG has Dialog, which is modal), so there is no Quint spec and `test/popover.browser.test.tsx` is the oracle. It is copied from Base UI's Popover (the trigger click toggle, Enter / Space / ArrowDown, light dismiss on an outside `pointerdown` that does not steal focus) and React Aria's `usePopover` (focus in on open, back on close, `role="dialog"` without `aria-modal`, a placement that flips at the viewport edge).
|
package/dist/index.d.mts
CHANGED
|
@@ -2712,6 +2712,37 @@ export interface Spinbutton {
|
|
|
2712
2712
|
* APG text.
|
|
2713
2713
|
*/
|
|
2714
2714
|
export declare const createSpinbutton: (options?: SpinbuttonOptions) => Spinbutton;
|
|
2715
|
+
export interface StatusOptions {
|
|
2716
|
+
/** Rendered on `statusProps`; generated when absent. */
|
|
2717
|
+
readonly id?: string | undefined;
|
|
2718
|
+
}
|
|
2719
|
+
/** Spread onto the `role=status` live region. Render it once, always. */
|
|
2720
|
+
export interface StatusProps {
|
|
2721
|
+
readonly id: string;
|
|
2722
|
+
readonly role: "status";
|
|
2723
|
+
readonly "aria-live": "polite";
|
|
2724
|
+
readonly "aria-atomic": "true";
|
|
2725
|
+
}
|
|
2726
|
+
export interface Status {
|
|
2727
|
+
/** The text currently shown, or `undefined` before the first `show`. */
|
|
2728
|
+
readonly message: Accessor<string | undefined>;
|
|
2729
|
+
/** Writes the message, replacing the previous one; nothing is queued. */
|
|
2730
|
+
readonly show: (text: string) => void;
|
|
2731
|
+
readonly clear: () => void;
|
|
2732
|
+
readonly statusProps: StatusProps;
|
|
2733
|
+
}
|
|
2734
|
+
/**
|
|
2735
|
+
* APG Alert's polite sibling: one `role=status` live region whose text the host
|
|
2736
|
+
* replaces ("Link copied", "Saved"). It is not a queue: a second message shows
|
|
2737
|
+
* in place of the first, so a burst reads as the last state, not as N alerts.
|
|
2738
|
+
* The region is rendered once and stays mounted, which is what makes a change
|
|
2739
|
+
* of its text announced.
|
|
2740
|
+
*
|
|
2741
|
+
* A status is never for errors: an error that needs attention now is
|
|
2742
|
+
* `createAlert` (`role=alert`, assertive), and a message with a title, a
|
|
2743
|
+
* description and a timeout is `createToast`.
|
|
2744
|
+
*/
|
|
2745
|
+
export declare const createStatus: (options?: StatusOptions) => Status;
|
|
2715
2746
|
export interface SwitchOptions {
|
|
2716
2747
|
/** Controlled: the host owns the state and this is the only thing that changes it. */
|
|
2717
2748
|
readonly value?: boolean | undefined;
|
|
@@ -3037,6 +3068,74 @@ export interface Timeline {
|
|
|
3037
3068
|
* reactive.
|
|
3038
3069
|
*/
|
|
3039
3070
|
export declare const createTimeline: (options?: TimelineOptions) => Timeline;
|
|
3071
|
+
/** A toast's urgency; `error` is the only tone that announces assertively. */
|
|
3072
|
+
export type ToastTone = "info" | "success" | "error";
|
|
3073
|
+
export interface ToastOptions {
|
|
3074
|
+
/** Auto-dismiss delay in ms, default 5000. A number; `0` dismisses on the next tick. */
|
|
3075
|
+
readonly timeout?: number | undefined;
|
|
3076
|
+
/** Visible toasts kept, default 3; a new one past the ceiling drops the oldest. */
|
|
3077
|
+
readonly max?: number | undefined;
|
|
3078
|
+
/** Pauses the countdown while a pointer is over a toast, default true. Focus always pauses. */
|
|
3079
|
+
readonly pauseOnHover?: boolean | undefined;
|
|
3080
|
+
/** The region's accessible name; `region` defaults to `"Notifications"`. */
|
|
3081
|
+
readonly labels?: {
|
|
3082
|
+
readonly region?: string | undefined;
|
|
3083
|
+
} | undefined;
|
|
3084
|
+
/** Called with the id whenever a toast leaves, for whatever reason. */
|
|
3085
|
+
readonly onDismiss?: ((id: string) => void) | undefined;
|
|
3086
|
+
}
|
|
3087
|
+
/** What `show` takes; `tone` defaults to `"info"`. */
|
|
3088
|
+
export interface ToastInput {
|
|
3089
|
+
readonly title: string;
|
|
3090
|
+
readonly description?: string | undefined;
|
|
3091
|
+
readonly tone?: ToastTone | undefined;
|
|
3092
|
+
}
|
|
3093
|
+
/** A toast in the queue, oldest first in `toasts()`. */
|
|
3094
|
+
export interface ToastItem {
|
|
3095
|
+
readonly id: string;
|
|
3096
|
+
readonly title: string;
|
|
3097
|
+
readonly description: string | undefined;
|
|
3098
|
+
readonly tone: ToastTone;
|
|
3099
|
+
}
|
|
3100
|
+
/** Spread onto the container that holds every toast and the F6 target. */
|
|
3101
|
+
export interface ToastRegionProps {
|
|
3102
|
+
readonly role: "region";
|
|
3103
|
+
readonly "aria-label": string;
|
|
3104
|
+
}
|
|
3105
|
+
/**
|
|
3106
|
+
* Spread onto one toast. `role` is `alert` for the `error` tone and `status`
|
|
3107
|
+
* otherwise; both pause the countdown while hovered or focused.
|
|
3108
|
+
*/
|
|
3109
|
+
export interface ToastItemProps {
|
|
3110
|
+
readonly role: "alert" | "status";
|
|
3111
|
+
readonly "aria-atomic": "true";
|
|
3112
|
+
readonly onMouseEnter: () => void;
|
|
3113
|
+
readonly onMouseLeave: () => void;
|
|
3114
|
+
readonly onFocusIn: () => void;
|
|
3115
|
+
readonly onFocusOut: () => void;
|
|
3116
|
+
}
|
|
3117
|
+
export interface Toast {
|
|
3118
|
+
/** Oldest first. */
|
|
3119
|
+
readonly toasts: Accessor<readonly ToastItem[]>;
|
|
3120
|
+
/** Queues a toast and returns its id. */
|
|
3121
|
+
readonly show: (input: ToastInput) => string;
|
|
3122
|
+
readonly dismiss: (id: string) => void;
|
|
3123
|
+
readonly dismissAll: () => void;
|
|
3124
|
+
readonly regionProps: ToastRegionProps;
|
|
3125
|
+
readonly toastProps: (id: string) => ToastItemProps;
|
|
3126
|
+
}
|
|
3127
|
+
/**
|
|
3128
|
+
* A toast queue: one timeout per toast, a ceiling that drops the oldest, and a
|
|
3129
|
+
* countdown that pauses on hover and focus and resumes from where it stopped.
|
|
3130
|
+
* A toast announces itself through its own live region (`role=status`, or
|
|
3131
|
+
* `role=alert` for `error`), so the host renders one element per toast inside
|
|
3132
|
+
* `regionProps`. No DOM access here: the host renders, the primitive decides.
|
|
3133
|
+
*
|
|
3134
|
+
* The timeout is a floor of practice, not of code: the default is 5000 ms
|
|
3135
|
+
* because both Base UI and React Aria agree on at least five seconds to read a
|
|
3136
|
+
* message; shorter values exist for tests and are the host's judgement.
|
|
3137
|
+
*/
|
|
3138
|
+
export declare const createToast: (options?: ToastOptions) => Toast;
|
|
3040
3139
|
/**
|
|
3041
3140
|
* APG Toolbar on Solid 2: state plus attribute objects, no elements, no
|
|
3042
3141
|
* styling. A faithful transcription of `specs/apg/toolbar.qnt`.
|
package/dist/index.mjs
CHANGED
|
@@ -4982,7 +4982,7 @@ const createRadioGroup = (options) => {
|
|
|
4982
4982
|
};
|
|
4983
4983
|
// src/resizable-panels.ts
|
|
4984
4984
|
const DEFAULT_MIN = 10;
|
|
4985
|
-
const DEFAULT_MAX = 80;
|
|
4985
|
+
const DEFAULT_MAX$1 = 80;
|
|
4986
4986
|
const DEFAULT_STEP = 10;
|
|
4987
4987
|
const FULL = 100;
|
|
4988
4988
|
const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
|
|
@@ -5052,7 +5052,7 @@ const createResizablePanels = (options) => {
|
|
|
5052
5052
|
const minOf = (index) => panes()[index]?.min ?? DEFAULT_MIN;
|
|
5053
5053
|
/** The smallest committed size (a collapsible pane may sit at collapsedSize). */
|
|
5054
5054
|
const lowOf = (index) => panes()[index]?.collapsible === true ? collapsedSize(index) : minOf(index);
|
|
5055
|
-
const highOf = (index) => panes()[index]?.max ?? DEFAULT_MAX;
|
|
5055
|
+
const highOf = (index) => panes()[index]?.max ?? DEFAULT_MAX$1;
|
|
5056
5056
|
/** Clamp every pane, then push the residual into the panes in order. */
|
|
5057
5057
|
const fit = (raw) => {
|
|
5058
5058
|
const next = panes().map((_, index) => clamp(round2(raw[index] ?? FULL / Math.max(count(), 1)), lowOf(index), highOf(index)));
|
|
@@ -5702,6 +5702,37 @@ const createSpinbutton = (options = {}) => {
|
|
|
5702
5702
|
}
|
|
5703
5703
|
};
|
|
5704
5704
|
};
|
|
5705
|
+
// src/status.ts
|
|
5706
|
+
/**
|
|
5707
|
+
* APG Alert's polite sibling: one `role=status` live region whose text the host
|
|
5708
|
+
* replaces ("Link copied", "Saved"). It is not a queue: a second message shows
|
|
5709
|
+
* in place of the first, so a burst reads as the last state, not as N alerts.
|
|
5710
|
+
* The region is rendered once and stays mounted, which is what makes a change
|
|
5711
|
+
* of its text announced.
|
|
5712
|
+
*
|
|
5713
|
+
* A status is never for errors: an error that needs attention now is
|
|
5714
|
+
* `createAlert` (`role=alert`, assertive), and a message with a title, a
|
|
5715
|
+
* description and a timeout is `createToast`.
|
|
5716
|
+
*/
|
|
5717
|
+
const createStatus = (options = {}) => {
|
|
5718
|
+
const id = options.id ?? createUniqueId();
|
|
5719
|
+
const [message, setMessage] = createSignal();
|
|
5720
|
+
return {
|
|
5721
|
+
message,
|
|
5722
|
+
show: (text) => {
|
|
5723
|
+
setMessage(text);
|
|
5724
|
+
},
|
|
5725
|
+
clear: () => {
|
|
5726
|
+
setMessage(void 0);
|
|
5727
|
+
},
|
|
5728
|
+
statusProps: {
|
|
5729
|
+
id,
|
|
5730
|
+
role: "status",
|
|
5731
|
+
"aria-live": "polite",
|
|
5732
|
+
"aria-atomic": "true"
|
|
5733
|
+
}
|
|
5734
|
+
};
|
|
5735
|
+
};
|
|
5705
5736
|
// src/switch.ts
|
|
5706
5737
|
/**
|
|
5707
5738
|
* APG Switch (https://www.w3.org/WAI/ARIA/apg/patterns/switch/): a binary on/off
|
|
@@ -6248,6 +6279,143 @@ const createTimeline = (options = {}) => {
|
|
|
6248
6279
|
}
|
|
6249
6280
|
};
|
|
6250
6281
|
};
|
|
6282
|
+
// src/toast.ts
|
|
6283
|
+
const DEFAULT_TIMEOUT_MS = 5e3;
|
|
6284
|
+
const DEFAULT_MAX = 3;
|
|
6285
|
+
const DEFAULT_REGION_LABEL = "Notifications";
|
|
6286
|
+
/**
|
|
6287
|
+
* A toast queue: one timeout per toast, a ceiling that drops the oldest, and a
|
|
6288
|
+
* countdown that pauses on hover and focus and resumes from where it stopped.
|
|
6289
|
+
* A toast announces itself through its own live region (`role=status`, or
|
|
6290
|
+
* `role=alert` for `error`), so the host renders one element per toast inside
|
|
6291
|
+
* `regionProps`. No DOM access here: the host renders, the primitive decides.
|
|
6292
|
+
*
|
|
6293
|
+
* The timeout is a floor of practice, not of code: the default is 5000 ms
|
|
6294
|
+
* because both Base UI and React Aria agree on at least five seconds to read a
|
|
6295
|
+
* message; shorter values exist for tests and are the host's judgement.
|
|
6296
|
+
*/
|
|
6297
|
+
const createToast = (options = {}) => {
|
|
6298
|
+
const [version, setVersion] = createSignal(0);
|
|
6299
|
+
let items = [];
|
|
6300
|
+
const timers = /* @__PURE__ */ new Map();
|
|
6301
|
+
const toasts = () => {
|
|
6302
|
+
version();
|
|
6303
|
+
return items;
|
|
6304
|
+
};
|
|
6305
|
+
const commit = (next) => {
|
|
6306
|
+
items = [...next];
|
|
6307
|
+
setVersion((count) => count + 1);
|
|
6308
|
+
};
|
|
6309
|
+
const clear = (id) => {
|
|
6310
|
+
const countdown = timers.get(id);
|
|
6311
|
+
if (countdown === void 0) return;
|
|
6312
|
+
if (countdown.handle !== void 0) clearTimeout(countdown.handle);
|
|
6313
|
+
timers.delete(id);
|
|
6314
|
+
};
|
|
6315
|
+
const dismiss = (id) => {
|
|
6316
|
+
if (!items.some((item) => item.id === id)) return;
|
|
6317
|
+
clear(id);
|
|
6318
|
+
commit(items.filter((item) => item.id !== id));
|
|
6319
|
+
options.onDismiss?.(id);
|
|
6320
|
+
};
|
|
6321
|
+
const dismissAll = () => {
|
|
6322
|
+
const ids = items.map((item) => item.id);
|
|
6323
|
+
if (ids.length === 0) return;
|
|
6324
|
+
for (const id of ids) clear(id);
|
|
6325
|
+
commit([]);
|
|
6326
|
+
for (const id of ids) options.onDismiss?.(id);
|
|
6327
|
+
};
|
|
6328
|
+
const arm = (id, countdown) => {
|
|
6329
|
+
countdown.handle = setTimeout(() => dismiss(id), countdown.remaining);
|
|
6330
|
+
};
|
|
6331
|
+
const pause = (id) => {
|
|
6332
|
+
const countdown = timers.get(id);
|
|
6333
|
+
if (countdown === void 0 || countdown.handle === void 0) return;
|
|
6334
|
+
clearTimeout(countdown.handle);
|
|
6335
|
+
countdown.handle = void 0;
|
|
6336
|
+
countdown.remaining = Math.max(0, countdown.deadline - Date.now());
|
|
6337
|
+
};
|
|
6338
|
+
const paused = (countdown) => countdown.focused || countdown.hovered && (options.pauseOnHover ?? true);
|
|
6339
|
+
const resume = (id) => {
|
|
6340
|
+
const countdown = timers.get(id);
|
|
6341
|
+
if (countdown === void 0 || countdown.handle !== void 0 || paused(countdown)) return;
|
|
6342
|
+
countdown.deadline = Date.now() + countdown.remaining;
|
|
6343
|
+
arm(id, countdown);
|
|
6344
|
+
};
|
|
6345
|
+
const sync = (id, countdown) => {
|
|
6346
|
+
if (paused(countdown)) pause(id);
|
|
6347
|
+
else resume(id);
|
|
6348
|
+
};
|
|
6349
|
+
const show = (input) => {
|
|
6350
|
+
const item = {
|
|
6351
|
+
id: createUniqueId(),
|
|
6352
|
+
title: input.title,
|
|
6353
|
+
description: input.description,
|
|
6354
|
+
tone: input.tone ?? "info"
|
|
6355
|
+
};
|
|
6356
|
+
const limit = Math.max(1, options.max ?? DEFAULT_MAX);
|
|
6357
|
+
const next = [...items, item];
|
|
6358
|
+
const dropped = [];
|
|
6359
|
+
while (next.length > limit) {
|
|
6360
|
+
const oldest = next.shift();
|
|
6361
|
+
if (oldest !== void 0) dropped.push(oldest.id);
|
|
6362
|
+
}
|
|
6363
|
+
commit(next);
|
|
6364
|
+
for (const id of dropped) {
|
|
6365
|
+
clear(id);
|
|
6366
|
+
options.onDismiss?.(id);
|
|
6367
|
+
}
|
|
6368
|
+
const duration = Math.max(0, options.timeout ?? DEFAULT_TIMEOUT_MS);
|
|
6369
|
+
const countdown = {
|
|
6370
|
+
handle: void 0,
|
|
6371
|
+
deadline: Date.now() + duration,
|
|
6372
|
+
remaining: duration,
|
|
6373
|
+
hovered: false,
|
|
6374
|
+
focused: false
|
|
6375
|
+
};
|
|
6376
|
+
timers.set(item.id, countdown);
|
|
6377
|
+
arm(item.id, countdown);
|
|
6378
|
+
return item.id;
|
|
6379
|
+
};
|
|
6380
|
+
const hover = (id, next) => {
|
|
6381
|
+
const countdown = timers.get(id);
|
|
6382
|
+
if (countdown === void 0) return;
|
|
6383
|
+
countdown.hovered = next;
|
|
6384
|
+
sync(id, countdown);
|
|
6385
|
+
};
|
|
6386
|
+
const focus = (id, next) => {
|
|
6387
|
+
const countdown = timers.get(id);
|
|
6388
|
+
if (countdown === void 0) return;
|
|
6389
|
+
countdown.focused = next;
|
|
6390
|
+
sync(id, countdown);
|
|
6391
|
+
};
|
|
6392
|
+
if (getOwner() !== null) onCleanup(() => {
|
|
6393
|
+
for (const countdown of timers.values()) if (countdown.handle !== void 0) clearTimeout(countdown.handle);
|
|
6394
|
+
timers.clear();
|
|
6395
|
+
});
|
|
6396
|
+
return {
|
|
6397
|
+
toasts,
|
|
6398
|
+
show,
|
|
6399
|
+
dismiss,
|
|
6400
|
+
dismissAll,
|
|
6401
|
+
regionProps: {
|
|
6402
|
+
role: "region",
|
|
6403
|
+
get "aria-label"() {
|
|
6404
|
+
return options.labels?.region ?? DEFAULT_REGION_LABEL;
|
|
6405
|
+
}
|
|
6406
|
+
},
|
|
6407
|
+
toastProps: (id) => ({
|
|
6408
|
+
get role() {
|
|
6409
|
+
return items.find((item) => item.id === id)?.tone === "error" ? "alert" : "status";
|
|
6410
|
+
},
|
|
6411
|
+
"aria-atomic": "true",
|
|
6412
|
+
onMouseEnter: () => hover(id, true),
|
|
6413
|
+
onMouseLeave: () => hover(id, false),
|
|
6414
|
+
onFocusIn: () => focus(id, true),
|
|
6415
|
+
onFocusOut: () => focus(id, false)
|
|
6416
|
+
})
|
|
6417
|
+
};
|
|
6418
|
+
};
|
|
6251
6419
|
// src/toolbar.ts
|
|
6252
6420
|
const AXIS = (o) => o === "horizontal" ? "inline" : "block";
|
|
6253
6421
|
const delta = (axis, key) => {
|
|
@@ -7841,4 +8009,4 @@ const createRearrangeableListbox = (options) => {
|
|
|
7841
8009
|
})
|
|
7842
8010
|
};
|
|
7843
8011
|
};
|
|
7844
|
-
export { ConfirmPendingError, DEFAULT_PREFS, DRAG_PX, GRID, NO_POS, SNAP_PX, TONE, TREEVIEW_NODES, TWEEN_TICKS, WORLD_BOUND, YES_POS, ZMAX, ZMIN, ZONE, cellPart, createAccordion, createAlert, createAlertDialog, createBreadcrumb, createButton, createCanvas, createCarousel, createCheckbox, createCheckboxGroup, createCombobox, createConfirm, createDialogModal, createDisclosure, createFeed, createField, createGrid, createLink, createListbox, createMenu, createMenubar, createMeter, createPagination, createPlayer, createPopover, createRadioGroup, createRearrangeableListbox, createResizablePanels, createSlider, createSliderMultiThumb, createSpinbutton, createSwitch, createTabs, createTextArea, createTextInput, createTimeline, createToolbar, createTooltipGroup, createTreegrid, createTreeview, createWindowSplitter, gridCandidates, headerPart, packSelection, packSort, rowPart, treegridCellPart, treegridFocusTargetPart, treegridRowPart, withPrefs };
|
|
8012
|
+
export { ConfirmPendingError, DEFAULT_PREFS, DRAG_PX, GRID, NO_POS, SNAP_PX, TONE, TREEVIEW_NODES, TWEEN_TICKS, WORLD_BOUND, YES_POS, ZMAX, ZMIN, ZONE, cellPart, createAccordion, createAlert, createAlertDialog, createBreadcrumb, createButton, createCanvas, createCarousel, createCheckbox, createCheckboxGroup, createCombobox, createConfirm, createDialogModal, createDisclosure, createFeed, createField, createGrid, createLink, createListbox, createMenu, createMenubar, createMeter, createPagination, createPlayer, createPopover, createRadioGroup, createRearrangeableListbox, createResizablePanels, createSlider, createSliderMultiThumb, createSpinbutton, createStatus, createSwitch, createTabs, createTextArea, createTextInput, createTimeline, createToast, createToolbar, createTooltipGroup, createTreegrid, createTreeview, createWindowSplitter, gridCandidates, headerPart, packSelection, packSort, rowPart, treegridCellPart, treegridFocusTargetPart, treegridRowPart, withPrefs };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cssints/headless",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Headless APG widgets on Solid 2: state plus attribute objects, no elements, no styling, each conformance-checked against its Quint spec",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|