@foldkit/ui 0.126.0 → 0.128.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 +2 -2
- package/dist/calendar/index.d.ts +17 -23
- package/dist/calendar/index.d.ts.map +1 -1
- package/dist/calendar/index.js +16 -25
- package/dist/calendar/public.d.ts +1 -1
- package/dist/calendar/public.d.ts.map +1 -1
- package/dist/calendar/public.js +1 -1
- package/dist/checkbox/index.d.ts +47 -104
- package/dist/checkbox/index.d.ts.map +1 -1
- package/dist/checkbox/index.js +48 -87
- package/dist/checkbox/public.d.ts +2 -2
- package/dist/checkbox/public.d.ts.map +1 -1
- package/dist/checkbox/public.js +1 -1
- package/dist/combobox/multi.d.ts +19 -30
- package/dist/combobox/multi.d.ts.map +1 -1
- package/dist/combobox/multi.js +32 -53
- package/dist/combobox/public.d.ts +2 -2
- package/dist/combobox/public.d.ts.map +1 -1
- package/dist/combobox/public.js +1 -1
- package/dist/combobox/shared.d.ts +59 -35
- package/dist/combobox/shared.d.ts.map +1 -1
- package/dist/combobox/shared.js +58 -45
- package/dist/combobox/single.d.ts +36 -48
- package/dist/combobox/single.d.ts.map +1 -1
- package/dist/combobox/single.js +49 -76
- package/dist/datePicker/index.d.ts +33 -41
- package/dist/datePicker/index.d.ts.map +1 -1
- package/dist/datePicker/index.js +31 -40
- package/dist/datePicker/public.d.ts +1 -1
- package/dist/datePicker/public.d.ts.map +1 -1
- package/dist/datePicker/public.js +1 -1
- package/dist/dialog/index.d.ts +17 -1
- package/dist/dialog/index.d.ts.map +1 -1
- package/dist/dialog/index.js +12 -5
- package/dist/disclosure/index.d.ts +49 -113
- package/dist/disclosure/index.d.ts.map +1 -1
- package/dist/disclosure/index.js +35 -92
- package/dist/disclosure/public.d.ts +2 -2
- package/dist/disclosure/public.d.ts.map +1 -1
- package/dist/disclosure/public.js +1 -1
- package/dist/listbox/multi.d.ts +7 -21
- package/dist/listbox/multi.d.ts.map +1 -1
- package/dist/listbox/multi.js +12 -36
- package/dist/listbox/public.d.ts +1 -1
- package/dist/listbox/public.d.ts.map +1 -1
- package/dist/listbox/shared.d.ts +28 -20
- package/dist/listbox/shared.d.ts.map +1 -1
- package/dist/listbox/shared.js +6 -7
- package/dist/listbox/single.d.ts +17 -27
- package/dist/listbox/single.d.ts.map +1 -1
- package/dist/listbox/single.js +18 -30
- package/dist/radioGroup/index.d.ts +57 -142
- package/dist/radioGroup/index.d.ts.map +1 -1
- package/dist/radioGroup/index.js +44 -119
- package/dist/radioGroup/public.d.ts +2 -2
- package/dist/radioGroup/public.d.ts.map +1 -1
- package/dist/radioGroup/public.js +1 -1
- package/dist/slider/index.d.ts +51 -27
- package/dist/slider/index.d.ts.map +1 -1
- package/dist/slider/index.js +66 -66
- package/dist/slider/public.d.ts +1 -1
- package/dist/slider/public.d.ts.map +1 -1
- package/dist/slider/public.js +1 -1
- package/dist/switch/index.d.ts +45 -92
- package/dist/switch/index.d.ts.map +1 -1
- package/dist/switch/index.js +36 -81
- package/dist/switch/public.d.ts +2 -2
- package/dist/switch/public.d.ts.map +1 -1
- package/dist/switch/public.js +1 -1
- package/dist/tabs/index.d.ts +33 -33
- package/dist/tabs/index.d.ts.map +1 -1
- package/dist/tabs/index.js +36 -49
- package/dist/toast/index.d.ts +1 -0
- package/dist/toast/index.d.ts.map +1 -1
- package/dist/toast/index.js +1 -0
- package/dist/toast/public.d.ts +2 -0
- package/dist/toast/public.d.ts.map +1 -1
- package/dist/toast/public.js +1 -0
- package/dist/toast/test.d.ts +41 -0
- package/dist/toast/test.d.ts.map +1 -0
- package/dist/toast/test.js +36 -0
- package/package.json +2 -2
package/dist/listbox/shared.d.ts
CHANGED
|
@@ -156,20 +156,17 @@ export type IgnoredMouseClick = typeof IgnoredMouseClick.Type;
|
|
|
156
156
|
export type SuppressedSpaceScroll = typeof SuppressedSpaceScroll.Type;
|
|
157
157
|
export type PressedPointerOnButton = typeof PressedPointerOnButton.Type;
|
|
158
158
|
export type Message = typeof Message.Type;
|
|
159
|
-
/** Sent when
|
|
159
|
+
/** Sent when the user activates an item (single-select commit or multi-select toggle). Carries the neutral fact that the item was activated; the parent owns the selection and decides what it means (single-select sets it, multi-select toggles membership). Generic over `Value extends string`: the runtime schema stores `value: string`, but the type-level OutMessage exposes `value: Value` so consumers who supply `items: ReadonlyArray<MyUnion>` receive `value: MyUnion` from `update<MyUnion>` without casting. The cast is fenced inside this module's `update` return, sound because the value was extracted from the items array the consumer supplied. */
|
|
160
160
|
export declare const Selected: import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
161
161
|
value: S.String;
|
|
162
|
-
wasAdded: S.Boolean;
|
|
163
162
|
}>;
|
|
164
163
|
export type Selected<Value extends string = string> = Readonly<{
|
|
165
164
|
readonly _tag: 'Selected';
|
|
166
165
|
readonly value: Value;
|
|
167
|
-
readonly wasAdded: boolean;
|
|
168
166
|
}>;
|
|
169
|
-
/** Union of out-messages the listbox component can produce.
|
|
167
|
+
/** Union of out-messages the listbox component can produce. The parent folds `Selected` into the selection it owns: single-select stores the value, multi-select toggles the value's membership. */
|
|
170
168
|
export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
171
169
|
value: S.String;
|
|
172
|
-
wasAdded: S.Boolean;
|
|
173
170
|
}>]>;
|
|
174
171
|
/** Generic over `Value extends string` so consumers who create the listbox
|
|
175
172
|
* via `Listbox.create<MyUnion>()` receive `value: MyUnion` in the
|
|
@@ -338,7 +335,6 @@ export declare const makeUpdate: <Model extends BaseModel>(handleSelectedItem: (
|
|
|
338
335
|
}>[], Option.Option<Readonly<{
|
|
339
336
|
readonly _tag: "Selected";
|
|
340
337
|
readonly value: string;
|
|
341
|
-
readonly wasAdded: boolean;
|
|
342
338
|
}>>];
|
|
343
339
|
/** The anchor-positioning Mount this Listbox renders on its items panel.
|
|
344
340
|
* The panel is always anchored to the button via Floating UI and portaled
|
|
@@ -376,10 +372,10 @@ export type GroupHeading = Readonly<{
|
|
|
376
372
|
}>;
|
|
377
373
|
/** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field.
|
|
378
374
|
*
|
|
379
|
-
* The Listbox emits a `Selected({ value
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
type BaseViewInputsCommon<Item> = Readonly<{
|
|
375
|
+
* The Listbox emits a `Selected({ value })` OutMessage on commit.
|
|
376
|
+
* Consumers pattern-match this in their `GotListboxMessage` handler:
|
|
377
|
+
* single-select stores the value, multi-select toggles its membership. */
|
|
378
|
+
export type BaseViewInputsCommon<Item> = Readonly<{
|
|
383
379
|
items: ReadonlyArray<Item>;
|
|
384
380
|
itemToConfig: (item: Item, context: Readonly<{
|
|
385
381
|
isActive: boolean;
|
|
@@ -414,19 +410,31 @@ type BaseViewInputsCommon<Item> = Readonly<{
|
|
|
414
410
|
ariaLabel?: string;
|
|
415
411
|
ariaLabelledBy?: string;
|
|
416
412
|
}>;
|
|
417
|
-
/**
|
|
418
|
-
* is optional when `Item` is itself a string (the default
|
|
419
|
-
* item unchanged) and required when items are objects, so the
|
|
420
|
-
* payload type can't drift from what the consumer actually
|
|
421
|
-
|
|
413
|
+
/** The `itemToValue` extractor piece of a Listbox's view inputs. The
|
|
414
|
+
* extractor is optional when `Item` is itself a string (the default
|
|
415
|
+
* returns the item unchanged) and required when items are objects, so the
|
|
416
|
+
* OutMessage payload type can't drift from what the consumer actually
|
|
417
|
+
* emits. */
|
|
418
|
+
export type ItemToValueInput<Item, Value extends string = string> = [
|
|
419
|
+
Item
|
|
420
|
+
] extends [string] ? Readonly<{
|
|
422
421
|
itemToValue?: (item: Item) => Value;
|
|
423
422
|
}> : Readonly<{
|
|
424
423
|
itemToValue: (item: Item) => Value;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
424
|
+
}>;
|
|
425
|
+
/** Per-render view inputs for the shared array-based Listbox view. The
|
|
426
|
+
* multi-select variant exposes this shape directly; the single-select
|
|
427
|
+
* variant swaps `selectedValues` for `maybeSelectedValue` at its public
|
|
428
|
+
* seam and adapts to this shape internally. */
|
|
429
|
+
export type BaseViewInputs<Item, Value extends string = string> = BaseViewInputsCommon<Item> & Readonly<{
|
|
430
|
+
/** The selection the parent owns, passed in fresh on every render.
|
|
431
|
+
* Drives `aria-selected` and `data-selected` on items, which item the
|
|
432
|
+
* Listbox highlights when it opens onto a selection, and the hidden
|
|
433
|
+
* form inputs submitted under `name`. */
|
|
434
|
+
selectedValues: ReadonlyArray<Value>;
|
|
435
|
+
}> & ItemToValueInput<Item, Value>;
|
|
436
|
+
type ViewBehavior = Readonly<{
|
|
429
437
|
ariaMultiSelectable: boolean;
|
|
430
438
|
}>;
|
|
431
|
-
export declare const makeView: <Model extends BaseModel>(behavior: ViewBehavior
|
|
439
|
+
export declare const makeView: <Model extends BaseModel>(behavior: ViewBehavior) => <Item, Value extends string = string>() => SubmodelView<Model, Message, BaseViewInputs<Item, Value>>;
|
|
432
440
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/listbox/shared.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/listbox/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/listbox/shared.js
CHANGED
|
@@ -149,12 +149,11 @@ export const Message = S.Union([
|
|
|
149
149
|
PressedPointerOnButton,
|
|
150
150
|
]);
|
|
151
151
|
// OUT MESSAGE
|
|
152
|
-
/** Sent when
|
|
152
|
+
/** Sent when the user activates an item (single-select commit or multi-select toggle). Carries the neutral fact that the item was activated; the parent owns the selection and decides what it means (single-select sets it, multi-select toggles membership). Generic over `Value extends string`: the runtime schema stores `value: string`, but the type-level OutMessage exposes `value: Value` so consumers who supply `items: ReadonlyArray<MyUnion>` receive `value: MyUnion` from `update<MyUnion>` without casting. The cast is fenced inside this module's `update` return, sound because the value was extracted from the items array the consumer supplied. */
|
|
153
153
|
export const Selected = m('Selected', {
|
|
154
154
|
value: S.String,
|
|
155
|
-
wasAdded: S.Boolean,
|
|
156
155
|
});
|
|
157
|
-
/** Union of out-messages the listbox component can produce.
|
|
156
|
+
/** Union of out-messages the listbox component can produce. The parent folds `Selected` into the selection it owns: single-select stores the value, multi-select toggles the value's membership. */
|
|
158
157
|
export const OutMessage = S.Union([Selected]);
|
|
159
158
|
// CONSTANTS
|
|
160
159
|
export const SEARCH_DEBOUNCE_MILLISECONDS = 350;
|
|
@@ -404,8 +403,9 @@ export const makeView = (behavior) => {
|
|
|
404
403
|
const impl = defineView((model, viewInputs) => {
|
|
405
404
|
const h = html();
|
|
406
405
|
const { id, isOpen, orientation, animation: { transitionState }, maybeActiveItemIndex, searchQuery, maybeLastButtonPointerType, } = model;
|
|
407
|
-
const { items, itemToConfig, isItemDisabled, isButtonDisabled, buttonContent, buttonClassName, buttonAttributes = [], itemsClassName, itemsAttributes = [], itemsScrollClassName, itemsScrollAttributes = [], backdropClassName, backdropAttributes = [], className, attributes = [], itemGroupKey, groupToHeading, groupClassName, groupAttributes = [], separatorClassName, separatorAttributes = [], anchor = {}, name, form, isDisabled, isInvalid, ariaLabel, ariaLabelledBy, } = viewInputs;
|
|
406
|
+
const { items, itemToConfig, isItemDisabled, isButtonDisabled, buttonContent, buttonClassName, buttonAttributes = [], itemsClassName, itemsAttributes = [], itemsScrollClassName, itemsScrollAttributes = [], backdropClassName, backdropAttributes = [], className, attributes = [], itemGroupKey, groupToHeading, groupClassName, groupAttributes = [], separatorClassName, separatorAttributes = [], anchor = {}, name, form, isDisabled, isInvalid, ariaLabel, ariaLabelledBy, selectedValues, } = viewInputs;
|
|
408
407
|
const itemToValue = viewInputs.itemToValue ?? ((item) => String(item));
|
|
408
|
+
const isValueSelected = (itemValue) => Array.contains(selectedValues, itemValue);
|
|
409
409
|
const itemToSearchText = viewInputs.itemToSearchText ?? ((item) => itemToValue(item));
|
|
410
410
|
const isLeaving = transitionState === 'LeaveStart' || transitionState === 'LeaveAnimating';
|
|
411
411
|
const isVisible = isOpen || isLeaving;
|
|
@@ -440,7 +440,7 @@ export const makeView = (behavior) => {
|
|
|
440
440
|
const isNavigationKey = (key) => Array.contains(navigationKeys, key);
|
|
441
441
|
const firstEnabledIndex = findFirstEnabledIndex(items.length, 0, isItemDisabledByIndex)(0, 1);
|
|
442
442
|
const lastEnabledIndex = findFirstEnabledIndex(items.length, 0, isItemDisabledByIndex)(items.length - 1, -1);
|
|
443
|
-
const selectedItemIndex =
|
|
443
|
+
const selectedItemIndex = pipe(selectedValues, Array.head, Option.flatMap(selectedValue => Array.findFirstIndex(items, item => itemToValue(item) === selectedValue)));
|
|
444
444
|
const handleButtonKeyDown = (key) => {
|
|
445
445
|
if (isOpen) {
|
|
446
446
|
return handleItemsKeyDown(key);
|
|
@@ -552,7 +552,7 @@ export const makeView = (behavior) => {
|
|
|
552
552
|
const listboxItems = Array.map(items, (item, index) => {
|
|
553
553
|
const isActiveItem = Option.exists(maybeActiveItemIndex, activeIndex => activeIndex === index);
|
|
554
554
|
const isDisabledItem = isItemDisabledByIndex(index);
|
|
555
|
-
const isSelectedItem =
|
|
555
|
+
const isSelectedItem = isValueSelected(itemToValue(item));
|
|
556
556
|
const itemConfig = itemToConfig(item, {
|
|
557
557
|
isActive: isActiveItem,
|
|
558
558
|
isDisabled: isDisabledItem,
|
|
@@ -655,7 +655,6 @@ export const makeView = (behavior) => {
|
|
|
655
655
|
h.keyed('div')(`${id}-items-container`, itemsContainerAttributes, scrollableItems),
|
|
656
656
|
];
|
|
657
657
|
const formAttribute = form ? [h.Attribute('form', form)] : [];
|
|
658
|
-
const selectedValues = pipe(items, Array.filter(item => behavior.isItemSelected(model, itemToValue(item))), Array.map(itemToValue));
|
|
659
658
|
const hiddenInputs = name
|
|
660
659
|
? Array.match(selectedValues, {
|
|
661
660
|
onEmpty: () => [
|
package/dist/listbox/single.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Option, Schema as S } from 'effect';
|
|
2
2
|
import type * as Command from 'foldkit/command';
|
|
3
|
-
import
|
|
4
|
-
import { type BaseInitConfig, type
|
|
5
|
-
/** Schema for the listbox
|
|
3
|
+
import { type View as SubmodelView } from 'foldkit/submodel';
|
|
4
|
+
import { type BaseInitConfig, type BaseViewInputsCommon, type ItemToValueInput, type Message, type OutMessage } from './shared.js';
|
|
5
|
+
/** Schema for the single-select listbox's private interaction state (open/closed status, active item, activation trigger, typeahead search). The selection is owned by the parent and passed in via `ViewInputs.maybeSelectedValue`. */
|
|
6
6
|
export declare const Model: S.Struct<{
|
|
7
|
-
readonly maybeSelectedItem: S.Option<S.String>;
|
|
8
7
|
readonly id: S.String;
|
|
9
8
|
readonly isOpen: S.Boolean;
|
|
10
9
|
readonly isAnimated: S.Boolean;
|
|
@@ -26,15 +25,12 @@ export declare const Model: S.Struct<{
|
|
|
26
25
|
readonly maybeLastButtonPointerType: S.Option<S.String>;
|
|
27
26
|
}>;
|
|
28
27
|
export type Model = typeof Model.Type;
|
|
29
|
-
/** Configuration for creating a single-select listbox model with `init`. `isAnimated` enables CSS transition coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`).
|
|
30
|
-
export type InitConfig = BaseInitConfig
|
|
31
|
-
|
|
32
|
-
}>;
|
|
33
|
-
/** Creates an initial single-select listbox model from a config. Defaults to closed with no active item and no selection. */
|
|
28
|
+
/** Configuration for creating a single-select listbox model with `init`. `isAnimated` enables CSS transition coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). */
|
|
29
|
+
export type InitConfig = BaseInitConfig;
|
|
30
|
+
/** Creates an initial single-select listbox model from a config. Defaults to closed with no active item. */
|
|
34
31
|
export declare const init: (config: InitConfig) => Model;
|
|
35
|
-
/** Processes a listbox message and returns the next model, commands, and optional OutMessage. Closes the listbox on selection (single-select behavior); emits a `Selected({ value
|
|
32
|
+
/** Processes a listbox message and returns the next model, commands, and optional OutMessage. Closes the listbox on selection (single-select behavior); emits a `Selected({ value })` OutMessage the parent stores as the selection. */
|
|
36
33
|
export declare const update: (model: S.Struct.ReadonlySide<{
|
|
37
|
-
readonly maybeSelectedItem: S.Option<S.String>;
|
|
38
34
|
readonly id: S.String;
|
|
39
35
|
readonly isOpen: S.Boolean;
|
|
40
36
|
readonly isAnimated: S.Boolean;
|
|
@@ -55,7 +51,6 @@ export declare const update: (model: S.Struct.ReadonlySide<{
|
|
|
55
51
|
}>>;
|
|
56
52
|
readonly maybeLastButtonPointerType: S.Option<S.String>;
|
|
57
53
|
}, "Type">, message: Message) => readonly [S.Struct.ReadonlySide<{
|
|
58
|
-
readonly maybeSelectedItem: S.Option<S.String>;
|
|
59
54
|
readonly id: S.String;
|
|
60
55
|
readonly isOpen: S.Boolean;
|
|
61
56
|
readonly isAnimated: S.Boolean;
|
|
@@ -144,7 +139,6 @@ export declare const update: (model: S.Struct.ReadonlySide<{
|
|
|
144
139
|
}>[], Option.Option<Readonly<{
|
|
145
140
|
readonly _tag: "Selected";
|
|
146
141
|
readonly value: string;
|
|
147
|
-
readonly wasAdded: boolean;
|
|
148
142
|
}>>];
|
|
149
143
|
type UpdateReturn = ReturnType<typeof update>;
|
|
150
144
|
/** Programmatically opens the listbox, updating the model and returning
|
|
@@ -153,20 +147,17 @@ export declare const open: (model: Model) => UpdateReturn;
|
|
|
153
147
|
/** Programmatically closes the listbox, updating the model and returning
|
|
154
148
|
* focus and modal commands. Use this in domain-event handlers to close the listbox. */
|
|
155
149
|
export declare const close: (model: Model) => UpdateReturn;
|
|
156
|
-
/** Programmatically selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value
|
|
150
|
+
/** Programmatically selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value })` OutMessage. */
|
|
157
151
|
export declare const selectItem: (model: Model, item: string) => UpdateReturn;
|
|
158
|
-
/** Reflects an externally-sourced selection onto the model without
|
|
159
|
-
* emitting an OutMessage or running the user-selection side effects (no
|
|
160
|
-
* close, no focus). Use this to mirror external truth (a URL parameter,
|
|
161
|
-
* restored storage, a server push) onto the listbox's selection.
|
|
162
|
-
* Contrast with `selectItem`, which represents a user or programmatic
|
|
163
|
-
* *choice*: it closes the listbox, restores focus, and emits `Selected`.
|
|
164
|
-
* `reflect` returns the model directly because it produces no commands and
|
|
165
|
-
* no OutMessage, so a parent reflecting external state cannot
|
|
166
|
-
* accidentally echo it back out. */
|
|
167
|
-
export declare const reflectSelectedItem: Reflect<Model, Option.Option<string>>;
|
|
168
152
|
/** Per-render view inputs passed to the view via `h.submodel`'s `viewInputs` field. */
|
|
169
|
-
export type ViewInputs<Item, Value extends string = string> =
|
|
153
|
+
export type ViewInputs<Item, Value extends string = string> = BaseViewInputsCommon<Item> & Readonly<{
|
|
154
|
+
/** The selection the parent owns, passed in fresh on every render.
|
|
155
|
+
* `Option` because a single-select listbox may have no selection yet.
|
|
156
|
+
* Drives `aria-selected` and `data-selected` on items, which item the
|
|
157
|
+
* Listbox highlights when it opens onto a selection, and the hidden
|
|
158
|
+
* form input submitted under `name`. */
|
|
159
|
+
maybeSelectedValue: Option.Option<Value>;
|
|
160
|
+
}> & ItemToValueInput<Item, Value>;
|
|
170
161
|
/** Pairs the single-select listbox's `view` and `update` (and programmatic
|
|
171
162
|
* helpers) behind a single Item-typed entry point. Declaring the listbox
|
|
172
163
|
* once at module scope ensures the view's `Item` type and the update's
|
|
@@ -188,12 +179,11 @@ export type ViewInputs<Item, Value extends string = string> = BaseViewInputs<Ite
|
|
|
188
179
|
* extracted value is a plain string. `Value` defaults to `Item` when
|
|
189
180
|
* `Item extends string`, else defaults to `string`. */
|
|
190
181
|
export declare const create: <Item = string, Value extends string = Item extends string ? Item : string>() => Readonly<{
|
|
191
|
-
view: SubmodelView<Model, Message,
|
|
182
|
+
view: SubmodelView<Model, Message, ViewInputs<Item, Value>>;
|
|
192
183
|
update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
193
184
|
selectItem: (model: Model, item: Value) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
194
185
|
open: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
195
186
|
close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
196
|
-
reflectSelectedItem: Reflect<Model, Option.Option<Value>>;
|
|
197
187
|
}>;
|
|
198
188
|
export {};
|
|
199
189
|
//# sourceMappingURL=single.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/listbox/single.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/listbox/single.ts"],"names":[],"mappings":"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"}
|
package/dist/listbox/single.js
CHANGED
|
@@ -1,43 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Option, Schema as S } from 'effect';
|
|
2
|
+
import { defineView } from 'foldkit/submodel';
|
|
3
3
|
import { BaseModel, Closed, Opened, SelectedItem, Selected as SharedSelected, baseInit, makeUpdate, makeView, } from './shared.js';
|
|
4
4
|
// MODEL
|
|
5
|
-
/** Schema for the listbox
|
|
5
|
+
/** Schema for the single-select listbox's private interaction state (open/closed status, active item, activation trigger, typeahead search). The selection is owned by the parent and passed in via `ViewInputs.maybeSelectedValue`. */
|
|
6
6
|
export const Model = S.Struct({
|
|
7
7
|
...BaseModel.fields,
|
|
8
|
-
maybeSelectedItem: S.Option(S.String),
|
|
9
|
-
});
|
|
10
|
-
/** Creates an initial single-select listbox model from a config. Defaults to closed with no active item and no selection. */
|
|
11
|
-
export const init = (config) => ({
|
|
12
|
-
...baseInit(config),
|
|
13
|
-
maybeSelectedItem: Option.fromNullishOr(config.selectedItem),
|
|
14
8
|
});
|
|
9
|
+
/** Creates an initial single-select listbox model from a config. Defaults to closed with no active item. */
|
|
10
|
+
export const init = (config) => baseInit(config);
|
|
15
11
|
// UPDATE
|
|
16
|
-
/** Processes a listbox message and returns the next model, commands, and optional OutMessage. Closes the listbox on selection (single-select behavior); emits a `Selected({ value
|
|
17
|
-
export const update = makeUpdate((model, item, context) => context.closeWithFocus(
|
|
12
|
+
/** Processes a listbox message and returns the next model, commands, and optional OutMessage. Closes the listbox on selection (single-select behavior); emits a `Selected({ value })` OutMessage the parent stores as the selection. */
|
|
13
|
+
export const update = makeUpdate((model, item, context) => context.closeWithFocus(model, Option.some(SharedSelected({ value: item }))));
|
|
18
14
|
/** Programmatically opens the listbox, updating the model and returning
|
|
19
15
|
* focus and modal commands. Use this in domain-event handlers to open the listbox. */
|
|
20
16
|
export const open = (model) => update(model, Opened({ maybeActiveItemIndex: Option.none() }));
|
|
21
17
|
/** Programmatically closes the listbox, updating the model and returning
|
|
22
18
|
* focus and modal commands. Use this in domain-event handlers to close the listbox. */
|
|
23
19
|
export const close = (model) => update(model, Closed());
|
|
24
|
-
/** Programmatically selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value
|
|
20
|
+
/** Programmatically selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value })` OutMessage. */
|
|
25
21
|
export const selectItem = (model, item) => update(model, SelectedItem({ item }));
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* `reflect` returns the model directly because it produces no commands and
|
|
33
|
-
* no OutMessage, so a parent reflecting external state cannot
|
|
34
|
-
* accidentally echo it back out. */
|
|
35
|
-
export const reflectSelectedItem = Function.dual(2, (model, maybeItem) => evo(model, { maybeSelectedItem: () => maybeItem }));
|
|
36
|
-
const internalView = makeView({
|
|
37
|
-
isItemSelected: (model, itemValue) => Option.exists(model.maybeSelectedItem, selectedItem => selectedItem === itemValue),
|
|
38
|
-
selectedItemIndex: (model, items, itemToValue) => Option.flatMap(model.maybeSelectedItem, selectedItem => Array.findFirstIndex(items, item => itemToValue(item) === selectedItem)),
|
|
39
|
-
ariaMultiSelectable: false,
|
|
40
|
-
});
|
|
22
|
+
const internalView = makeView({ ariaMultiSelectable: false });
|
|
23
|
+
const arrayBasedView = internalView();
|
|
24
|
+
const singleViewImpl = defineView((model, { maybeSelectedValue, ...baseInputs }) => arrayBasedView(model, {
|
|
25
|
+
...baseInputs,
|
|
26
|
+
selectedValues: Option.toArray(maybeSelectedValue),
|
|
27
|
+
}));
|
|
41
28
|
/** Pairs the single-select listbox's `view` and `update` (and programmatic
|
|
42
29
|
* helpers) behind a single Item-typed entry point. Declaring the listbox
|
|
43
30
|
* once at module scope ensures the view's `Item` type and the update's
|
|
@@ -61,13 +48,14 @@ const internalView = makeView({
|
|
|
61
48
|
export const create = () => {
|
|
62
49
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
63
50
|
const typedUpdate = update;
|
|
51
|
+
const view =
|
|
52
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
53
|
+
singleViewImpl;
|
|
64
54
|
return {
|
|
65
|
-
view
|
|
55
|
+
view,
|
|
66
56
|
update: typedUpdate,
|
|
67
57
|
selectItem: (model, item) => typedUpdate(model, SelectedItem({ item })),
|
|
68
58
|
open: model => typedUpdate(model, Opened({ maybeActiveItemIndex: Option.none() })),
|
|
69
59
|
close: model => typedUpdate(model, Closed()),
|
|
70
|
-
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
71
|
-
reflectSelectedItem: reflectSelectedItem,
|
|
72
60
|
};
|
|
73
61
|
};
|
|
@@ -1,169 +1,84 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { type ChildAttribute, type Html } from 'foldkit/html';
|
|
4
|
-
import { type Reflect, type View as SubmodelView } from 'foldkit/submodel';
|
|
1
|
+
import { Option, Schema as S } from 'effect';
|
|
2
|
+
import { type Attribute, type Html } from 'foldkit/html';
|
|
5
3
|
/** Controls the radio group layout direction and which arrow keys navigate between options. */
|
|
6
4
|
export declare const Orientation: S.Literals<readonly ["Horizontal", "Vertical"]>;
|
|
7
5
|
export type Orientation = typeof Orientation.Type;
|
|
8
|
-
/** Schema for the radio group component's state, tracking the selected value and orientation. */
|
|
9
|
-
export declare const Model: S.Struct<{
|
|
10
|
-
readonly id: S.String;
|
|
11
|
-
readonly selectedValue: S.Option<S.String>;
|
|
12
|
-
readonly orientation: S.Literals<readonly ["Horizontal", "Vertical"]>;
|
|
13
|
-
}>;
|
|
14
|
-
export type Model = typeof Model.Type;
|
|
15
|
-
/** Sent when a radio option is selected via click or keyboard navigation. */
|
|
16
|
-
export declare const SelectedOption: import("foldkit/schema").CallableTaggedStruct<"SelectedOption", {
|
|
17
|
-
value: S.String;
|
|
18
|
-
index: S.Number;
|
|
19
|
-
}>;
|
|
20
|
-
/** Sent when the focus-option command completes. */
|
|
21
|
-
export declare const CompletedFocusOption: import("foldkit/schema").CallableTaggedStruct<"CompletedFocusOption", {}>;
|
|
22
|
-
/** Union of all messages the radio group component can produce. */
|
|
23
|
-
export declare const Message: S.Union<[
|
|
24
|
-
typeof SelectedOption,
|
|
25
|
-
typeof CompletedFocusOption
|
|
26
|
-
]>;
|
|
27
|
-
export type SelectedOption = typeof SelectedOption.Type;
|
|
28
|
-
export type CompletedFocusOption = typeof CompletedFocusOption.Type;
|
|
29
|
-
export type Message = typeof Message.Type;
|
|
30
|
-
/** Sent to the parent when an option is committed. Carries the selected
|
|
31
|
-
* value and its index. Generic over `Value extends string`: the runtime
|
|
32
|
-
* schema stores `value: string`, but the type-level OutMessage exposes
|
|
33
|
-
* `value: Value` so consumers who supply `options: ReadonlyArray<MyUnion>`
|
|
34
|
-
* receive `value: MyUnion` from the factory's `update` without casting at
|
|
35
|
-
* the call site. The cast is fenced inside this module's `update` return,
|
|
36
|
-
* sound because the value was selected from the options array the
|
|
37
|
-
* consumer supplied. */
|
|
38
|
-
export declare const Selected: import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
39
|
-
value: S.String;
|
|
40
|
-
index: S.Number;
|
|
41
|
-
}>;
|
|
42
|
-
export type Selected<Value extends string = string> = Readonly<{
|
|
43
|
-
readonly _tag: 'Selected';
|
|
44
|
-
readonly value: Value;
|
|
45
|
-
readonly index: number;
|
|
46
|
-
}>;
|
|
47
|
-
export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
48
|
-
value: S.String;
|
|
49
|
-
index: S.Number;
|
|
50
|
-
}>]>;
|
|
51
|
-
/** Generic over `Value extends string` so consumers who create the radio
|
|
52
|
-
* group via `RadioGroup.create<MyUnion>()` receive `value: MyUnion` in
|
|
53
|
-
* the `Selected` OutMessage from the factory's `update`, instead of
|
|
54
|
-
* `value: string`. Defaults to `string` for consumers that don't need the
|
|
55
|
-
* lift. */
|
|
56
|
-
export type OutMessage<Value extends string = string> = Selected<Value>;
|
|
57
|
-
/** Configuration for creating a radio group model with `init`. */
|
|
58
|
-
export type InitConfig = Readonly<{
|
|
59
|
-
id: string;
|
|
60
|
-
selectedValue?: string;
|
|
61
|
-
orientation?: Orientation;
|
|
62
|
-
}>;
|
|
63
|
-
/** Creates an initial radio group model from a config. Defaults to no selection and vertical orientation. */
|
|
64
|
-
export declare const init: (config: InitConfig) => Model;
|
|
65
|
-
/** Moves focus to the radio option at the given index. */
|
|
66
|
-
export declare const FocusOption: Command.CommandDefinitionWithArgs<"FocusOption", {
|
|
67
|
-
id: S.String;
|
|
68
|
-
index: S.Number;
|
|
69
|
-
}, Effect.Effect<{
|
|
70
|
-
readonly _tag: "CompletedFocusOption";
|
|
71
|
-
}, never, never>>;
|
|
72
|
-
type UpdateReturn<Value extends string = string> = readonly [
|
|
73
|
-
Model,
|
|
74
|
-
ReadonlyArray<Command.Command<Message>>,
|
|
75
|
-
Option.Option<OutMessage<Value>>
|
|
76
|
-
];
|
|
77
|
-
/** Processes a radio group message and returns the next model, commands, and
|
|
78
|
-
* optional OutMessage. Generic over `Value extends string`: pass the consumer's
|
|
79
|
-
* union type at the call site to receive `Selected({ value: MyUnion })` without
|
|
80
|
-
* casting. Defaults to `string`. */
|
|
81
|
-
export declare const update: <Value extends string = string>(model: Model, message: Message) => UpdateReturn<Value>;
|
|
82
|
-
/** Programmatically selects a value in the radio group, updating the model
|
|
83
|
-
* and returning focus commands plus a `Selected` OutMessage. */
|
|
84
|
-
export declare const select: <Value extends string = string>(model: Model, value: Value, options: ReadonlyArray<Value>) => UpdateReturn<Value>;
|
|
85
|
-
/** Reflects an externally-sourced selection onto the model without
|
|
86
|
-
* emitting an OutMessage or running the focus command. Use this to mirror
|
|
87
|
-
* external truth (a URL parameter, restored storage, a server push) onto
|
|
88
|
-
* the radio group's selection. Contrast with `select`, which represents a
|
|
89
|
-
* user or programmatic *choice*: it focuses the option and emits
|
|
90
|
-
* `Selected`. Takes no `options` (unlike `select`) because it sets the
|
|
91
|
-
* value directly rather than deriving a focus index. Returns the model
|
|
92
|
-
* directly because it produces no commands and no OutMessage. */
|
|
93
|
-
export declare const reflectSelectedValue: Reflect<Model, Option.Option<string>>;
|
|
94
6
|
/** Per-option render info passed to the consumer's `toView`. The consumer
|
|
95
|
-
* spreads `option`, `label`, and `description` onto whichever elements
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
export type OptionInfo<Value extends string
|
|
7
|
+
* spreads `option`, `label`, and `description` onto whichever elements carry
|
|
8
|
+
* that role in their layout. Generic over `Value extends string` so
|
|
9
|
+
* `option.value` carries the consumer's union type, and over `ParentMessage`
|
|
10
|
+
* so the attribute bundles dispatch the parent's own Message. */
|
|
11
|
+
export type OptionInfo<Value extends string, ParentMessage> = Readonly<{
|
|
100
12
|
value: Value;
|
|
101
13
|
index: number;
|
|
102
14
|
isSelected: boolean;
|
|
103
15
|
isActive: boolean;
|
|
104
16
|
isDisabled: boolean;
|
|
105
|
-
option: ReadonlyArray<
|
|
106
|
-
label: ReadonlyArray<
|
|
107
|
-
description: ReadonlyArray<
|
|
17
|
+
option: ReadonlyArray<Attribute<ParentMessage>>;
|
|
18
|
+
label: ReadonlyArray<Attribute<ParentMessage>>;
|
|
19
|
+
description: ReadonlyArray<Attribute<ParentMessage>>;
|
|
108
20
|
}>;
|
|
109
21
|
/** Render-time payload published to the consumer's `toView`.
|
|
110
22
|
*
|
|
111
23
|
* - `group`: ARIA + role attributes for the wrapping radiogroup element.
|
|
112
|
-
* - `options`: one entry per option in `
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* - `selectedValue`: the currently-selected value, if any. Convenient
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* - `hiddenInput`: when `
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
options: ReadonlyArray<OptionInfo<Value>>;
|
|
24
|
+
* - `options`: one entry per option in `options`, in the same order. Includes
|
|
25
|
+
* the value, derived state, and the attribute bundles for the option
|
|
26
|
+
* element, its label, and its description.
|
|
27
|
+
* - `selectedValue`: the currently-selected value, if any. Convenient for the
|
|
28
|
+
* consumer when rendering selected-state visuals next to the option
|
|
29
|
+
* attributes.
|
|
30
|
+
* - `hiddenInput`: when `name` was supplied, attributes for a hidden form
|
|
31
|
+
* input carrying the selected value. The consumer renders the `<input>`
|
|
32
|
+
* themselves. Empty array when `name` is undefined. */
|
|
33
|
+
export type RenderInfo<Value extends string, ParentMessage> = Readonly<{
|
|
34
|
+
group: ReadonlyArray<Attribute<ParentMessage>>;
|
|
35
|
+
options: ReadonlyArray<OptionInfo<Value, ParentMessage>>;
|
|
125
36
|
selectedValue: Option.Option<Value>;
|
|
126
|
-
hiddenInput: ReadonlyArray<
|
|
37
|
+
hiddenInput: ReadonlyArray<Attribute<ParentMessage>>;
|
|
127
38
|
}>;
|
|
128
|
-
/** Per-render view
|
|
129
|
-
* Generic over `Value extends string`
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* `
|
|
133
|
-
|
|
39
|
+
/** Per-render view configuration for the stateless controlled {@link view}.
|
|
40
|
+
* Generic over `Value extends string` (the option union) and `ParentMessage`
|
|
41
|
+
* (the message `onSelect` dispatches).
|
|
42
|
+
*
|
|
43
|
+
* - `selectedValue`: the current selection, read straight from the parent
|
|
44
|
+
* Model. The roving tabindex and checked state derive from it.
|
|
45
|
+
* - `onSelect`: dispatched with the chosen value when an option is clicked or
|
|
46
|
+
* navigated to. Handle it in the parent's `update` by storing the value.
|
|
47
|
+
* The radio group manages focus itself, so the handler needs to do nothing
|
|
48
|
+
* else.
|
|
49
|
+
* - `toView`: receives the {@link RenderInfo} and lays out the group. */
|
|
50
|
+
export type ViewConfig<Value extends string, ParentMessage> = Readonly<{
|
|
51
|
+
id: string;
|
|
52
|
+
selectedValue: Option.Option<Value>;
|
|
134
53
|
options: ReadonlyArray<Value>;
|
|
54
|
+
onSelect: (value: Value) => ParentMessage;
|
|
135
55
|
ariaLabel: string;
|
|
136
|
-
toView: (render: RenderInfo<Value>) => Html;
|
|
56
|
+
toView: (render: RenderInfo<Value, ParentMessage>) => Html;
|
|
57
|
+
orientation?: Orientation;
|
|
137
58
|
isOptionDisabled?: (value: Value, index: number) => boolean;
|
|
138
59
|
isDisabled?: boolean;
|
|
139
60
|
name?: string;
|
|
140
|
-
orientation?: Orientation;
|
|
141
61
|
}>;
|
|
142
|
-
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
62
|
+
/** Renders an accessible radio group as a stateless controlled component. The
|
|
63
|
+
* parent owns the selection (`selectedValue`) and receives the parent's own
|
|
64
|
+
* Message via `onSelect` when an option is chosen. Moving focus onto the
|
|
65
|
+
* newly-active option is the radio group's own concern: it happens inside the
|
|
66
|
+
* component's click and keydown handlers, so the parent's `update` only stores
|
|
67
|
+
* the value.
|
|
146
68
|
*
|
|
147
69
|
* ```ts
|
|
148
|
-
* const ToolRadioGroup = RadioGroup.create<Tool>()
|
|
149
|
-
*
|
|
150
70
|
* // In view:
|
|
151
|
-
*
|
|
71
|
+
* RadioGroup.view<Tool, Message>({
|
|
72
|
+
* id: TOOL_RADIO_GROUP_ID,
|
|
73
|
+
* selectedValue: Option.some(model.tool),
|
|
74
|
+
* options: TOOLS,
|
|
75
|
+
* ariaLabel: 'Tool',
|
|
76
|
+
* onSelect: tool => SelectedTool({ tool }),
|
|
77
|
+
* toView: ({ group, options }) => ...,
|
|
78
|
+
* })
|
|
152
79
|
*
|
|
153
80
|
* // In update:
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
|
|
157
|
-
*
|
|
158
|
-
* The view's `ViewInputs.options` stays typed `ReadonlyArray<string>`;
|
|
159
|
-
* consumers can pass a `ReadonlyArray<MyUnion>` (assignable) and the
|
|
160
|
-
* fenced cast inside `update` types the OutMessage's `value` as
|
|
161
|
-
* `MyUnion`. */
|
|
162
|
-
export declare const create: <Value extends string = string>() => Readonly<{
|
|
163
|
-
view: SubmodelView<Model, Message, ViewInputs<Value>>;
|
|
164
|
-
update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
165
|
-
select: (model: Model, value: Value, options: ReadonlyArray<Value>) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
166
|
-
reflectSelectedValue: Reflect<Model, Option.Option<Value>>;
|
|
167
|
-
}>;
|
|
168
|
-
export {};
|
|
81
|
+
* SelectedTool: ({ tool }) => [evo(model, { tool: () => tool }), []],
|
|
82
|
+
* ``` */
|
|
83
|
+
export declare const view: <Value extends string, ParentMessage>(config: ViewConfig<Value, ParentMessage>) => Html;
|
|
169
84
|
//# sourceMappingURL=index.d.ts.map
|