foldkit 0.101.0 → 0.102.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 -1
- package/dist/canvas/view.d.ts +1 -1
- package/dist/canvas/view.d.ts.map +1 -1
- package/dist/canvas/view.js +5 -5
- package/dist/command/index.d.ts +71 -0
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +34 -1
- package/dist/command/public.d.ts +1 -1
- package/dist/command/public.d.ts.map +1 -1
- package/dist/command/public.js +1 -1
- package/dist/devTools/overlay.d.ts.map +1 -1
- package/dist/devTools/overlay.js +137 -110
- package/dist/dom/dom.d.ts +8 -11
- package/dist/dom/dom.d.ts.map +1 -1
- package/dist/dom/dom.js +8 -11
- package/dist/dom/elementMovement.d.ts +1 -3
- package/dist/dom/elementMovement.d.ts.map +1 -1
- package/dist/dom/elementMovement.js +1 -3
- package/dist/dom/inert.d.ts +2 -4
- package/dist/dom/inert.d.ts.map +1 -1
- package/dist/dom/inert.js +2 -4
- package/dist/dom/scrollLock.d.ts +2 -2
- package/dist/dom/scrollLock.js +2 -2
- package/dist/dom/waitForAnimation.d.ts +1 -1
- package/dist/dom/waitForAnimation.js +1 -1
- package/dist/html/boundary.d.ts +98 -0
- package/dist/html/boundary.d.ts.map +1 -0
- package/dist/html/boundary.js +176 -0
- package/dist/html/childAttribute.d.ts +44 -0
- package/dist/html/childAttribute.d.ts.map +1 -0
- package/dist/html/childAttribute.js +34 -0
- package/dist/html/index.d.ts +70 -23
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +639 -575
- package/dist/html/lazy.d.ts +12 -7
- package/dist/html/lazy.d.ts.map +1 -1
- package/dist/html/lazy.js +30 -11
- package/dist/html/public.d.ts +2 -2
- package/dist/html/public.d.ts.map +1 -1
- package/dist/html/public.js +1 -1
- package/dist/html/runtimeSingleton.d.ts +72 -0
- package/dist/html/runtimeSingleton.d.ts.map +1 -0
- package/dist/html/runtimeSingleton.js +112 -0
- package/dist/html/submodel.d.ts +98 -0
- package/dist/html/submodel.d.ts.map +1 -0
- package/dist/html/submodel.js +190 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/render/render.d.ts +1 -1
- package/dist/render/render.js +1 -1
- package/dist/runtime/messagePriority.d.ts +5 -1
- package/dist/runtime/messagePriority.d.ts.map +1 -1
- package/dist/runtime/messagePriority.js +25 -4
- package/dist/runtime/runtime.d.ts +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +115 -61
- package/dist/submodel/public.d.ts +4 -0
- package/dist/submodel/public.d.ts.map +1 -0
- package/dist/submodel/public.js +1 -0
- package/dist/submodel/submodel.d.ts +32 -0
- package/dist/submodel/submodel.d.ts.map +1 -0
- package/dist/submodel/submodel.js +1 -0
- package/dist/test/apps/disabledButton.d.ts +4 -5
- package/dist/test/apps/disabledButton.d.ts.map +1 -1
- package/dist/test/apps/disabledButton.js +16 -16
- package/dist/test/scene.d.ts +8 -8
- package/dist/test/scene.d.ts.map +1 -1
- package/dist/test/scene.js +25 -13
- package/dist/test/story.d.ts +15 -8
- package/dist/test/story.d.ts.map +1 -1
- package/dist/test/story.js +21 -9
- package/dist/ui/animation/index.d.ts +30 -14
- package/dist/ui/animation/index.d.ts.map +1 -1
- package/dist/ui/animation/index.js +9 -19
- package/dist/ui/animation/public.d.ts +2 -2
- package/dist/ui/animation/public.d.ts.map +1 -1
- package/dist/ui/animation/public.js +1 -1
- package/dist/ui/calendar/index.d.ts +199 -84
- package/dist/ui/calendar/index.d.ts.map +1 -1
- package/dist/ui/calendar/index.js +129 -140
- package/dist/ui/calendar/public.d.ts +2 -2
- package/dist/ui/calendar/public.d.ts.map +1 -1
- package/dist/ui/calendar/public.js +1 -1
- package/dist/ui/checkbox/index.d.ts +93 -21
- package/dist/ui/checkbox/index.d.ts.map +1 -1
- package/dist/ui/checkbox/index.js +62 -33
- package/dist/ui/checkbox/public.d.ts +2 -2
- package/dist/ui/checkbox/public.d.ts.map +1 -1
- package/dist/ui/checkbox/public.js +1 -1
- package/dist/ui/combobox/multi.d.ts +35 -91
- package/dist/ui/combobox/multi.d.ts.map +1 -1
- package/dist/ui/combobox/multi.js +34 -17
- package/dist/ui/combobox/multiPublic.d.ts +2 -2
- package/dist/ui/combobox/multiPublic.d.ts.map +1 -1
- package/dist/ui/combobox/multiPublic.js +1 -1
- package/dist/ui/combobox/public.d.ts +3 -3
- package/dist/ui/combobox/public.d.ts.map +1 -1
- package/dist/ui/combobox/public.js +2 -2
- package/dist/ui/combobox/shared.d.ts +56 -31
- package/dist/ui/combobox/shared.d.ts.map +1 -1
- package/dist/ui/combobox/shared.js +333 -322
- package/dist/ui/combobox/single.d.ts +46 -93
- package/dist/ui/combobox/single.d.ts.map +1 -1
- package/dist/ui/combobox/single.js +44 -17
- package/dist/ui/datePicker/index.d.ts +256 -48
- package/dist/ui/datePicker/index.d.ts.map +1 -1
- package/dist/ui/datePicker/index.js +149 -104
- package/dist/ui/datePicker/public.d.ts +2 -2
- package/dist/ui/datePicker/public.d.ts.map +1 -1
- package/dist/ui/datePicker/public.js +1 -1
- package/dist/ui/dialog/index.d.ts +95 -39
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +71 -62
- package/dist/ui/dialog/public.d.ts +2 -2
- package/dist/ui/dialog/public.d.ts.map +1 -1
- package/dist/ui/dialog/public.js +1 -1
- package/dist/ui/disclosure/index.d.ts +71 -31
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +57 -62
- package/dist/ui/disclosure/public.d.ts +2 -2
- package/dist/ui/disclosure/public.d.ts.map +1 -1
- package/dist/ui/disclosure/public.js +1 -1
- package/dist/ui/dragAndDrop/index.d.ts +6 -6
- package/dist/ui/dragAndDrop/index.d.ts.map +1 -1
- package/dist/ui/dragAndDrop/index.js +7 -7
- package/dist/ui/dragAndDrop/public.d.ts +1 -1
- package/dist/ui/dragAndDrop/public.d.ts.map +1 -1
- package/dist/ui/dragAndDrop/public.js +1 -1
- package/dist/ui/fileDrop/index.d.ts +42 -46
- package/dist/ui/fileDrop/index.d.ts.map +1 -1
- package/dist/ui/fileDrop/index.js +30 -46
- package/dist/ui/fileDrop/public.d.ts +2 -2
- package/dist/ui/fileDrop/public.d.ts.map +1 -1
- package/dist/ui/fileDrop/public.js +1 -1
- package/dist/ui/listbox/multi.d.ts +39 -84
- package/dist/ui/listbox/multi.d.ts.map +1 -1
- package/dist/ui/listbox/multi.js +38 -20
- package/dist/ui/listbox/multiPublic.d.ts +2 -2
- package/dist/ui/listbox/multiPublic.d.ts.map +1 -1
- package/dist/ui/listbox/multiPublic.js +1 -1
- package/dist/ui/listbox/public.d.ts +3 -3
- package/dist/ui/listbox/public.d.ts.map +1 -1
- package/dist/ui/listbox/public.js +2 -2
- package/dist/ui/listbox/shared.d.ts +71 -30
- package/dist/ui/listbox/shared.d.ts.map +1 -1
- package/dist/ui/listbox/shared.js +319 -296
- package/dist/ui/listbox/single.d.ts +57 -85
- package/dist/ui/listbox/single.d.ts.map +1 -1
- package/dist/ui/listbox/single.js +48 -24
- package/dist/ui/menu/index.d.ts +80 -36
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +117 -86
- package/dist/ui/menu/public.d.ts +2 -2
- package/dist/ui/menu/public.d.ts.map +1 -1
- package/dist/ui/menu/public.js +1 -1
- package/dist/ui/popover/index.d.ts +117 -44
- package/dist/ui/popover/index.d.ts.map +1 -1
- package/dist/ui/popover/index.js +88 -101
- package/dist/ui/popover/public.d.ts +2 -2
- package/dist/ui/popover/public.d.ts.map +1 -1
- package/dist/ui/popover/public.js +1 -1
- package/dist/ui/radioGroup/index.d.ts +122 -45
- package/dist/ui/radioGroup/index.d.ts.map +1 -1
- package/dist/ui/radioGroup/index.js +111 -72
- package/dist/ui/radioGroup/public.d.ts +2 -2
- package/dist/ui/radioGroup/public.d.ts.map +1 -1
- package/dist/ui/radioGroup/public.js +1 -1
- package/dist/ui/slider/index.d.ts +72 -34
- package/dist/ui/slider/index.d.ts.map +1 -1
- package/dist/ui/slider/index.js +40 -49
- package/dist/ui/slider/public.d.ts +2 -2
- package/dist/ui/slider/public.d.ts.map +1 -1
- package/dist/ui/slider/public.js +1 -1
- package/dist/ui/switch/index.d.ts +74 -21
- package/dist/ui/switch/index.d.ts.map +1 -1
- package/dist/ui/switch/index.js +62 -33
- package/dist/ui/switch/public.d.ts +2 -2
- package/dist/ui/switch/public.d.ts.map +1 -1
- package/dist/ui/switch/public.js +1 -1
- package/dist/ui/tabs/index.d.ts +107 -45
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +99 -81
- package/dist/ui/tabs/public.d.ts +2 -2
- package/dist/ui/tabs/public.d.ts.map +1 -1
- package/dist/ui/tabs/public.js +1 -1
- package/dist/ui/toast/index.d.ts +93 -109
- package/dist/ui/toast/index.d.ts.map +1 -1
- package/dist/ui/toast/index.js +16 -29
- package/dist/ui/toast/schema.d.ts +15 -4
- package/dist/ui/toast/schema.d.ts.map +1 -1
- package/dist/ui/toast/schema.js +11 -4
- package/dist/ui/toast/update.d.ts +36 -18
- package/dist/ui/toast/update.d.ts.map +1 -1
- package/dist/ui/toast/update.js +33 -14
- package/dist/ui/tooltip/index.d.ts +94 -42
- package/dist/ui/tooltip/index.d.ts.map +1 -1
- package/dist/ui/tooltip/index.js +64 -73
- package/dist/ui/tooltip/public.d.ts +2 -2
- package/dist/ui/tooltip/public.d.ts.map +1 -1
- package/dist/ui/tooltip/public.js +1 -1
- package/dist/ui/virtualList/index.d.ts +18 -41
- package/dist/ui/virtualList/index.d.ts.map +1 -1
- package/dist/ui/virtualList/index.js +17 -37
- package/dist/ui/virtualList/public.d.ts +2 -2
- package/dist/ui/virtualList/public.d.ts.map +1 -1
- package/dist/ui/virtualList/public.js +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Effect, Schema as S } from 'effect';
|
|
1
|
+
import { Effect, Option, Schema as S } from 'effect';
|
|
2
2
|
import * as Command from '../../command/index.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type ChildAttribute, type Html, type SubmodelView } from '../../html/index.js';
|
|
4
|
+
import type { Reflect } from '../../submodel/submodel.js';
|
|
4
5
|
/** Controls the radio group layout direction and which arrow keys navigate between options. */
|
|
5
6
|
export declare const Orientation: S.Literals<readonly ["Horizontal", "Vertical"]>;
|
|
6
7
|
export type Orientation = typeof Orientation.Type;
|
|
@@ -26,6 +27,33 @@ export declare const Message: S.Union<[
|
|
|
26
27
|
export type SelectedOption = typeof SelectedOption.Type;
|
|
27
28
|
export type CompletedFocusOption = typeof CompletedFocusOption.Type;
|
|
28
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("../../schema/index.js").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("../../schema/index.js").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 `Ui.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>;
|
|
29
57
|
/** Configuration for creating a radio group model with `init`. */
|
|
30
58
|
export type InitConfig = Readonly<{
|
|
31
59
|
id: string;
|
|
@@ -41,52 +69,101 @@ export declare const FocusOption: Command.CommandDefinitionWithArgs<"FocusOption
|
|
|
41
69
|
}, Effect.Effect<{
|
|
42
70
|
readonly _tag: "CompletedFocusOption";
|
|
43
71
|
}, never, never>>;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
/** Per-option render info passed to the consumer's `toView`. The consumer
|
|
95
|
+
* spreads `option`, `label`, and `description` onto whichever elements
|
|
96
|
+
* carry that role in their layout. Generic over `Value extends string`:
|
|
97
|
+
* when `Ui.RadioGroup.create<MyUnion>()` is declared, `option.value` is
|
|
98
|
+
* typed `MyUnion` so the consumer can switch on it without casting. */
|
|
99
|
+
export type OptionInfo<Value extends string = string> = Readonly<{
|
|
100
|
+
value: Value;
|
|
101
|
+
index: number;
|
|
102
|
+
isSelected: boolean;
|
|
103
|
+
isActive: boolean;
|
|
104
|
+
isDisabled: boolean;
|
|
105
|
+
option: ReadonlyArray<ChildAttribute>;
|
|
106
|
+
label: ReadonlyArray<ChildAttribute>;
|
|
107
|
+
description: ReadonlyArray<ChildAttribute>;
|
|
54
108
|
}>;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
109
|
+
/** Render-time payload published to the consumer's `toView`.
|
|
110
|
+
*
|
|
111
|
+
* - `group`: ARIA + role attributes for the wrapping radiogroup element.
|
|
112
|
+
* - `options`: one entry per option in `viewInputs.options`, in the same
|
|
113
|
+
* order. Includes the value, derived state, and the attribute bundles
|
|
114
|
+
* for the option element, its label, and its description.
|
|
115
|
+
* - `selectedValue`: the currently-selected value, if any. Convenient
|
|
116
|
+
* for the consumer when rendering selected-state visuals next to the
|
|
117
|
+
* option attributes.
|
|
118
|
+
* - `hiddenInput`: when `viewInputs.name` was supplied, attributes for a
|
|
119
|
+
* hidden form input carrying the selected value. The consumer
|
|
120
|
+
* renders the `<input>` themselves. Empty array when `name` is
|
|
121
|
+
* undefined. */
|
|
122
|
+
export type RenderInfo<Value extends string = string> = Readonly<{
|
|
123
|
+
group: ReadonlyArray<ChildAttribute>;
|
|
124
|
+
options: ReadonlyArray<OptionInfo<Value>>;
|
|
125
|
+
selectedValue: Option.Option<Value>;
|
|
126
|
+
hiddenInput: ReadonlyArray<ChildAttribute>;
|
|
60
127
|
}>;
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/** Configuration for rendering a radio group with `view`. */
|
|
69
|
-
export type ViewConfig<ParentMessage, RadioOption extends string> = Readonly<{
|
|
70
|
-
model: Model;
|
|
71
|
-
toParentMessage: (message: NarrowedSelectedOption<RadioOption> | CompletedFocusOption) => ParentMessage;
|
|
72
|
-
onSelected?: (value: RadioOption, index: number) => ParentMessage;
|
|
73
|
-
options: ReadonlyArray<RadioOption>;
|
|
74
|
-
optionToConfig: (option: RadioOption, context: Readonly<{
|
|
75
|
-
isSelected: boolean;
|
|
76
|
-
isActive: boolean;
|
|
77
|
-
isDisabled: boolean;
|
|
78
|
-
}>) => OptionConfig<ParentMessage, RadioOption>;
|
|
79
|
-
isOptionDisabled?: (option: RadioOption, index: number) => boolean;
|
|
80
|
-
orientation?: Orientation;
|
|
128
|
+
/** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field.
|
|
129
|
+
* Generic over `Value extends string` so consumers using
|
|
130
|
+
* `Ui.RadioGroup.create<MyUnion>()` receive `option.value: MyUnion` in
|
|
131
|
+
* `toView` and `(value: MyUnion, index) => boolean` in
|
|
132
|
+
* `isOptionDisabled`, without casting. */
|
|
133
|
+
export type ViewInputs<Value extends string = string> = Readonly<{
|
|
134
|
+
options: ReadonlyArray<Value>;
|
|
81
135
|
ariaLabel: string;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
name?: string;
|
|
136
|
+
toView: (render: RenderInfo<Value>) => Html;
|
|
137
|
+
isOptionDisabled?: (value: Value, index: number) => boolean;
|
|
85
138
|
isDisabled?: boolean;
|
|
139
|
+
name?: string;
|
|
140
|
+
orientation?: Orientation;
|
|
141
|
+
}>;
|
|
142
|
+
/** Pairs the radio group's `view` and `update` (and `select`) behind a
|
|
143
|
+
* single Value-typed entry point. Declaring the radio group once at
|
|
144
|
+
* module scope ensures the OutMessage's `value` field carries the
|
|
145
|
+
* consumer's union type without an `as` cast at the call site:
|
|
146
|
+
*
|
|
147
|
+
* ```ts
|
|
148
|
+
* const ToolRadioGroup = Ui.RadioGroup.create<Tool>()
|
|
149
|
+
*
|
|
150
|
+
* // In view:
|
|
151
|
+
* h.submodel({ view: ToolRadioGroup.view, ... })
|
|
152
|
+
*
|
|
153
|
+
* // In update:
|
|
154
|
+
* const [next, commands, maybeOutMessage] = ToolRadioGroup.update(model, message)
|
|
155
|
+
* // maybeOutMessage: Option<RadioGroup.OutMessage<Tool>>
|
|
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>>;
|
|
86
167
|
}>;
|
|
87
|
-
|
|
88
|
-
export declare const view: <ParentMessage, RadioOption extends string>(config: ViewConfig<ParentMessage, RadioOption>) => Html;
|
|
89
|
-
/** Creates a memoized radio group view. Static config is captured in a closure;
|
|
90
|
-
* only `model` and `toParentMessage` are compared per render via `createLazy`. */
|
|
91
|
-
export declare const lazy: <ParentMessage, RadioOption extends string>(staticConfig: Omit<ViewConfig<ParentMessage, RadioOption>, "model" | "toParentMessage" | "onSelected">) => ((model: Model, toParentMessage: ViewConfig<ParentMessage, RadioOption>["toParentMessage"]) => Html);
|
|
168
|
+
export {};
|
|
92
169
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/radioGroup/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/radioGroup/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Array, Effect, Match as M, Option, Predicate, Schema as S, String, pipe, } from 'effect';
|
|
1
|
+
import { Array, Effect, Function, Match as M, Option, Predicate, Schema as S, String, pipe, } from 'effect';
|
|
2
2
|
import * as Command from '../../command/index.js';
|
|
3
3
|
import * as Dom from '../../dom/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { childAttributes, defineView, html, } from '../../html/index.js';
|
|
5
5
|
import { m } from '../../message/index.js';
|
|
6
6
|
import { evo } from '../../struct/index.js';
|
|
7
7
|
import { keyToIndex } from '../keyboard.js';
|
|
@@ -24,6 +24,17 @@ export const SelectedOption = m('SelectedOption', {
|
|
|
24
24
|
export const CompletedFocusOption = m('CompletedFocusOption');
|
|
25
25
|
/** Union of all messages the radio group component can produce. */
|
|
26
26
|
export const Message = S.Union([SelectedOption, CompletedFocusOption]);
|
|
27
|
+
// OUT MESSAGE
|
|
28
|
+
/** Sent to the parent when an option is committed. Carries the selected
|
|
29
|
+
* value and its index. Generic over `Value extends string`: the runtime
|
|
30
|
+
* schema stores `value: string`, but the type-level OutMessage exposes
|
|
31
|
+
* `value: Value` so consumers who supply `options: ReadonlyArray<MyUnion>`
|
|
32
|
+
* receive `value: MyUnion` from the factory's `update` without casting at
|
|
33
|
+
* the call site. The cast is fenced inside this module's `update` return,
|
|
34
|
+
* sound because the value was selected from the options array the
|
|
35
|
+
* consumer supplied. */
|
|
36
|
+
export const Selected = m('Selected', { value: S.String, index: S.Number });
|
|
37
|
+
export const OutMessage = S.Union([Selected]);
|
|
27
38
|
/** Creates an initial radio group model from a config. Defaults to no selection and vertical orientation. */
|
|
28
39
|
export const init = (config) => ({
|
|
29
40
|
id: config.id,
|
|
@@ -34,29 +45,44 @@ export const init = (config) => ({
|
|
|
34
45
|
const optionId = (id, index) => `${id}-option-${index}`;
|
|
35
46
|
/** Moves focus to the radio option at the given index. */
|
|
36
47
|
export const FocusOption = Command.define('FocusOption', { id: S.String, index: S.Number }, CompletedFocusOption)(({ id, index }) => Dom.focus(`#${optionId(id, index)}`).pipe(Effect.ignore, Effect.as(CompletedFocusOption())));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
const withInternalUpdateReturn = M.withReturnType();
|
|
49
|
+
/** Processes a radio group message and returns the next model, commands, and
|
|
50
|
+
* optional OutMessage. Generic over `Value extends string`: pass the consumer's
|
|
51
|
+
* union type at the call site to receive `Selected({ value: MyUnion })` without
|
|
52
|
+
* casting. Defaults to `string`. */
|
|
53
|
+
export const update = (model, message) => {
|
|
54
|
+
const result = M.value(message).pipe(withInternalUpdateReturn, M.tagsExhaustive({
|
|
55
|
+
SelectedOption: ({ value, index }) => [
|
|
56
|
+
evo(model, { selectedValue: () => Option.some(value) }),
|
|
57
|
+
[FocusOption({ id: model.id, index })],
|
|
58
|
+
Option.some(Selected({ value, index })),
|
|
59
|
+
],
|
|
60
|
+
CompletedFocusOption: () => [model, [], Option.none()],
|
|
61
|
+
}));
|
|
62
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
/** Programmatically selects a value in the radio group, updating the model
|
|
66
|
+
* and returning focus commands plus a `Selected` OutMessage. */
|
|
47
67
|
export const select = (model, value, options) => pipe(options, Array.findFirstIndex(option => option === value), Option.match({
|
|
48
|
-
onNone: () => [model, []],
|
|
68
|
+
onNone: () => [model, [], Option.none()],
|
|
49
69
|
onSome: index => update(model, SelectedOption({ value, index })),
|
|
50
70
|
}));
|
|
71
|
+
/** Reflects an externally-sourced selection onto the model without
|
|
72
|
+
* emitting an OutMessage or running the focus command. Use this to mirror
|
|
73
|
+
* external truth (a URL parameter, restored storage, a server push) onto
|
|
74
|
+
* the radio group's selection. Contrast with `select`, which represents a
|
|
75
|
+
* user or programmatic *choice*: it focuses the option and emits
|
|
76
|
+
* `Selected`. Takes no `options` (unlike `select`) because it sets the
|
|
77
|
+
* value directly rather than deriving a focus index. Returns the model
|
|
78
|
+
* directly because it produces no commands and no OutMessage. */
|
|
79
|
+
export const reflectSelectedValue = Function.dual(2, (model, maybeValue) => evo(model, { selectedValue: () => maybeValue }));
|
|
51
80
|
const labelId = (id, index) => `${id}-option-${index}-label`;
|
|
52
81
|
const descriptionId = (id, index) => `${id}-option-${index}-description`;
|
|
53
|
-
|
|
54
|
-
export const view = (config) => {
|
|
82
|
+
const internalView = defineView((model, viewInputs) => {
|
|
55
83
|
const h = html();
|
|
56
|
-
const {
|
|
57
|
-
const
|
|
58
|
-
? onSelected(value, index)
|
|
59
|
-
: toParentMessage({ _tag: 'SelectedOption', value, index });
|
|
84
|
+
const { id, selectedValue } = model;
|
|
85
|
+
const { options, ariaLabel, toView, isOptionDisabled: isOptionDisabledFn, isDisabled: isGroupDisabled = false, name, orientation = model.orientation, } = viewInputs;
|
|
60
86
|
const isDisabled = (index) => {
|
|
61
87
|
if (isGroupDisabled) {
|
|
62
88
|
return true;
|
|
@@ -66,11 +92,7 @@ export const view = (config) => {
|
|
|
66
92
|
}
|
|
67
93
|
return pipe(options, Array.get(index), Option.exists(option => isOptionDisabledFn(option, index)));
|
|
68
94
|
};
|
|
69
|
-
const selectedIndex = Option.flatMap(selectedValue, value => Array.findFirstIndex(options, option =>
|
|
70
|
-
isSelected: false,
|
|
71
|
-
isActive: false,
|
|
72
|
-
isDisabled: false,
|
|
73
|
-
}).value === value));
|
|
95
|
+
const selectedIndex = Option.flatMap(selectedValue, value => Array.findFirstIndex(options, option => option === value));
|
|
74
96
|
const focusedIndex = pipe(selectedIndex, Option.getOrElse(() => pipe(options.length, Array.makeBy(index => index), Array.findFirst(Predicate.not(isDisabled)), Option.getOrElse(() => 0))));
|
|
75
97
|
const { nextKey, previousKey } = M.value(orientation).pipe(M.when('Horizontal', () => ({
|
|
76
98
|
nextKey: 'ArrowRight',
|
|
@@ -79,28 +101,22 @@ export const view = (config) => {
|
|
|
79
101
|
nextKey: 'ArrowDown',
|
|
80
102
|
previousKey: 'ArrowUp',
|
|
81
103
|
})), M.exhaustive);
|
|
82
|
-
const optionValues = Array.map(options, (option, index) => optionToConfig(option, {
|
|
83
|
-
isSelected: Option.exists(selectedIndex, selectedIdx => selectedIdx === index),
|
|
84
|
-
isActive: index === focusedIndex,
|
|
85
|
-
isDisabled: isDisabled(index),
|
|
86
|
-
}).value);
|
|
87
104
|
const resolveKeyIndex = keyToIndex(nextKey, previousKey, options.length, focusedIndex, isDisabled);
|
|
88
105
|
const handleKeyDown = (currentIndex) => (key) => M.value(key).pipe(M.whenOr(nextKey, previousKey, 'Home', 'End', 'PageUp', 'PageDown', () => {
|
|
89
106
|
const nextIndex = resolveKeyIndex(key);
|
|
90
|
-
return pipe(
|
|
91
|
-
}), M.when(' ', () => pipe(
|
|
92
|
-
const
|
|
107
|
+
return pipe(options, Array.get(nextIndex), Option.map(value => SelectedOption({ value, index: nextIndex })));
|
|
108
|
+
}), M.when(' ', () => pipe(options, Array.get(currentIndex), Option.map(value => SelectedOption({ value, index: currentIndex })))), M.orElse(() => Option.none()));
|
|
109
|
+
const optionInfos = Array.map(options, (value, index) => {
|
|
93
110
|
const isSelected = Option.exists(selectedIndex, selectedIdx => selectedIdx === index);
|
|
94
111
|
const isFocusable = index === focusedIndex;
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
const disabledAttributes = isOptionDisabled
|
|
112
|
+
const isOptionDisabledNow = isDisabled(index);
|
|
113
|
+
const checkedAttributes = isSelected
|
|
114
|
+
? [h.DataAttribute('checked', '')]
|
|
115
|
+
: [];
|
|
116
|
+
const activeAttributes = isFocusable
|
|
117
|
+
? [h.DataAttribute('active', '')]
|
|
118
|
+
: [];
|
|
119
|
+
const disabledAttributes = isOptionDisabledNow
|
|
104
120
|
? [h.AriaDisabled(true), h.DataAttribute('disabled', '')]
|
|
105
121
|
: [];
|
|
106
122
|
const optionAttributes = [
|
|
@@ -113,45 +129,68 @@ export const view = (config) => {
|
|
|
113
129
|
...checkedAttributes,
|
|
114
130
|
...activeAttributes,
|
|
115
131
|
...disabledAttributes,
|
|
116
|
-
...(
|
|
132
|
+
...(isOptionDisabledNow
|
|
117
133
|
? []
|
|
118
134
|
: [
|
|
119
|
-
h.OnClick(
|
|
135
|
+
h.OnClick(SelectedOption({ value, index })),
|
|
120
136
|
h.OnKeyDownPreventDefault(handleKeyDown(index)),
|
|
121
137
|
]),
|
|
122
138
|
];
|
|
123
|
-
const labelAttributes = [
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
const labelAttributes = [h.Id(labelId(id, index))];
|
|
140
|
+
const descriptionAttributes = [h.Id(descriptionId(id, index))];
|
|
141
|
+
return {
|
|
142
|
+
value,
|
|
143
|
+
index,
|
|
144
|
+
isSelected,
|
|
145
|
+
isActive: isFocusable,
|
|
146
|
+
isDisabled: isOptionDisabledNow,
|
|
147
|
+
option: childAttributes(optionAttributes),
|
|
148
|
+
label: childAttributes(labelAttributes),
|
|
149
|
+
description: childAttributes(descriptionAttributes),
|
|
150
|
+
};
|
|
134
151
|
});
|
|
135
|
-
const hiddenInputs = pipe(name, Option.fromNullishOr, Option.flatMap(inputName => pipe(selectedValue, Option.map(value => h.input([h.Type('hidden'), h.Name(inputName), h.Value(value)])))), Option.match({
|
|
136
|
-
onNone: () => [],
|
|
137
|
-
onSome: hiddenInput => [hiddenInput],
|
|
138
|
-
}));
|
|
139
152
|
const groupAttributes = [
|
|
140
153
|
h.Role('radiogroup'),
|
|
141
154
|
h.AriaOrientation(String.toLowerCase(orientation)),
|
|
142
155
|
h.AriaLabel(ariaLabel),
|
|
143
|
-
...(className ? [h.Class(className)] : []),
|
|
144
|
-
...attributes,
|
|
145
156
|
];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
})
|
|
157
|
-
};
|
|
157
|
+
const hiddenInputAttributes = pipe(Option.fromNullishOr(name), Option.flatMap(inputName => Option.map(selectedValue, value => [
|
|
158
|
+
h.Type('hidden'),
|
|
159
|
+
h.Name(inputName),
|
|
160
|
+
h.Value(value),
|
|
161
|
+
])), Option.getOrElse(() => []));
|
|
162
|
+
return toView({
|
|
163
|
+
group: childAttributes(groupAttributes),
|
|
164
|
+
options: optionInfos,
|
|
165
|
+
selectedValue,
|
|
166
|
+
hiddenInput: childAttributes(hiddenInputAttributes),
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
/** Pairs the radio group's `view` and `update` (and `select`) behind a
|
|
170
|
+
* single Value-typed entry point. Declaring the radio group once at
|
|
171
|
+
* module scope ensures the OutMessage's `value` field carries the
|
|
172
|
+
* consumer's union type without an `as` cast at the call site:
|
|
173
|
+
*
|
|
174
|
+
* ```ts
|
|
175
|
+
* const ToolRadioGroup = Ui.RadioGroup.create<Tool>()
|
|
176
|
+
*
|
|
177
|
+
* // In view:
|
|
178
|
+
* h.submodel({ view: ToolRadioGroup.view, ... })
|
|
179
|
+
*
|
|
180
|
+
* // In update:
|
|
181
|
+
* const [next, commands, maybeOutMessage] = ToolRadioGroup.update(model, message)
|
|
182
|
+
* // maybeOutMessage: Option<RadioGroup.OutMessage<Tool>>
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* The view's `ViewInputs.options` stays typed `ReadonlyArray<string>`;
|
|
186
|
+
* consumers can pass a `ReadonlyArray<MyUnion>` (assignable) and the
|
|
187
|
+
* fenced cast inside `update` types the OutMessage's `value` as
|
|
188
|
+
* `MyUnion`. */
|
|
189
|
+
export const create = () => ({
|
|
190
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
191
|
+
view: internalView,
|
|
192
|
+
update: (model, message) => update(model, message),
|
|
193
|
+
select: (model, value, options) => select(model, value, options),
|
|
194
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
195
|
+
reflectSelectedValue: reflectSelectedValue,
|
|
196
|
+
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { init,
|
|
2
|
-
export type {
|
|
1
|
+
export { init, create, Model, Message, OutMessage, Selected, SelectedOption, CompletedFocusOption, FocusOption, } from './index.js';
|
|
2
|
+
export type { Orientation, InitConfig, ViewInputs, RenderInfo, OptionInfo, } from './index.js';
|
|
3
3
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/radioGroup/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/radioGroup/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,KAAK,EACL,OAAO,EACP,UAAU,EACV,QAAQ,EACR,cAAc,EACd,oBAAoB,EACpB,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { init,
|
|
1
|
+
export { init, create, Model, Message, OutMessage, Selected, SelectedOption, CompletedFocusOption, FocusOption, } from './index.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Option, Schema as S, Stream } from 'effect';
|
|
2
2
|
import type { Command } from '../../command/index.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type ChildAttribute, type Html } from '../../html/index.js';
|
|
4
|
+
import type { Reflect } from '../../submodel/submodel.js';
|
|
4
5
|
/** Schema for the slider component's state. Tracks the current value, the
|
|
5
6
|
* range (min/max/step), and the active drag phase. */
|
|
6
7
|
export declare const Model: S.Struct<{
|
|
@@ -51,15 +52,16 @@ export type MovedDragPointer = typeof MovedDragPointer.Type;
|
|
|
51
52
|
export type ReleasedDragPointer = typeof ReleasedDragPointer.Type;
|
|
52
53
|
export type CancelledDrag = typeof CancelledDrag.Type;
|
|
53
54
|
export type PressedKeyboardNavigation = typeof PressedKeyboardNavigation.Type;
|
|
54
|
-
/** Emitted when the slider value changes. The parent
|
|
55
|
-
*
|
|
55
|
+
/** Emitted when the slider value changes. The parent can handle this to
|
|
56
|
+
* update its own state or dispatch its own Commands, for example to run
|
|
57
|
+
* validation or trigger a downstream Command. */
|
|
56
58
|
export declare const ChangedValue: import("../../schema/index.js").CallableTaggedStruct<"ChangedValue", {
|
|
57
59
|
value: S.Number;
|
|
58
60
|
}>;
|
|
59
61
|
/** Union of all out-messages the slider component can emit to its parent. */
|
|
60
|
-
export declare const OutMessage: import("../../schema/index.js").CallableTaggedStruct<"ChangedValue", {
|
|
62
|
+
export declare const OutMessage: S.Union<readonly [import("../../schema/index.js").CallableTaggedStruct<"ChangedValue", {
|
|
61
63
|
value: S.Number;
|
|
62
|
-
}>;
|
|
64
|
+
}>]>;
|
|
63
65
|
export type OutMessage = typeof OutMessage.Type;
|
|
64
66
|
/** Configuration for creating a slider model with `init`. */
|
|
65
67
|
export type InitConfig = Readonly<{
|
|
@@ -83,20 +85,20 @@ type UpdateReturn = readonly [
|
|
|
83
85
|
/** Processes a slider message and returns the next model, commands, and an
|
|
84
86
|
* optional out-message for the parent. */
|
|
85
87
|
export declare const update: (model: Model, message: Message) => UpdateReturn;
|
|
86
|
-
/**
|
|
87
|
-
* new range. Use this when min/max derive from
|
|
88
|
-
* bounded buffer whose first/last index shifts over
|
|
89
|
-
* this runs even while the user is Dragging: a
|
|
90
|
-
* cannot leave the value out of bounds. */
|
|
91
|
-
export declare const
|
|
88
|
+
/** Reflects an externally-driven range onto the slider. Snaps and clamps the
|
|
89
|
+
* current value into the new range. Use this when min/max derive from
|
|
90
|
+
* external state (e.g. a bounded buffer whose first/last index shifts over
|
|
91
|
+
* time). Unlike `reflectValue`, this runs even while the user is Dragging: a
|
|
92
|
+
* structural range change cannot leave the value out of bounds. */
|
|
93
|
+
export declare const reflectRange: Reflect<Model, Readonly<{
|
|
92
94
|
min: number;
|
|
93
95
|
max: number;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
*
|
|
97
|
-
* Does not emit `ChangedValue`; use when the value is being driven by
|
|
96
|
+
}>>;
|
|
97
|
+
/** Reflects an externally-driven value onto the slider, snapped and clamped
|
|
98
|
+
* into range; a no-op while the user is dragging, since drag state owns the
|
|
99
|
+
* value. Does not emit `ChangedValue`; use when the value is being driven by
|
|
98
100
|
* external state rather than user input. */
|
|
99
|
-
export declare const
|
|
101
|
+
export declare const reflectValue: Reflect<Model, number>;
|
|
100
102
|
/** Builds slider drag subscriptions, looking up the track
|
|
101
103
|
* element through the supplied root resolver. Use this when the slider is
|
|
102
104
|
* rendered inside a Shadow DOM. The root is read lazily so consumers can
|
|
@@ -297,20 +299,20 @@ export declare const subscriptions: {
|
|
|
297
299
|
};
|
|
298
300
|
};
|
|
299
301
|
/** Attribute groups the slider component provides to the consumer's `toView`
|
|
300
|
-
* callback.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
302
|
+
* callback. Each bundle carries the boundary's captured dispatch, so the
|
|
303
|
+
* consumer can spread it directly into element attributes without manual
|
|
304
|
+
* Message wrapping. */
|
|
305
|
+
export type SliderAttributes = Readonly<{
|
|
306
|
+
root: ReadonlyArray<ChildAttribute>;
|
|
307
|
+
track: ReadonlyArray<ChildAttribute>;
|
|
308
|
+
filledTrack: ReadonlyArray<ChildAttribute>;
|
|
309
|
+
thumb: ReadonlyArray<ChildAttribute>;
|
|
310
|
+
label: ReadonlyArray<ChildAttribute>;
|
|
311
|
+
hiddenInput: ReadonlyArray<ChildAttribute>;
|
|
308
312
|
}>;
|
|
309
|
-
/**
|
|
310
|
-
export type
|
|
311
|
-
|
|
312
|
-
toParentMessage: (message: PressedThumb | PressedPointer | MovedDragPointer | ReleasedDragPointer | CancelledDrag | PressedKeyboardNavigation) => ParentMessage;
|
|
313
|
-
toView: (attributes: SliderAttributes<ParentMessage>) => Html;
|
|
313
|
+
/** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
|
|
314
|
+
export type ViewInputs = Readonly<{
|
|
315
|
+
toView: (attributes: SliderAttributes) => Html;
|
|
314
316
|
ariaLabel?: string;
|
|
315
317
|
ariaLabelledBy?: string;
|
|
316
318
|
formatValue?: (value: number) => string;
|
|
@@ -324,12 +326,48 @@ export type ViewConfig<ParentMessage> = Readonly<{
|
|
|
324
326
|
}>;
|
|
325
327
|
/** Renders an accessible slider by building ARIA attribute groups and
|
|
326
328
|
* delegating layout to the consumer's `toView` callback. Follows the
|
|
327
|
-
* WAI-ARIA slider pattern
|
|
329
|
+
* WAI-ARIA slider pattern: role="slider" on the thumb, aria-valuemin /
|
|
328
330
|
* aria-valuemax / aria-valuenow, keyboard navigation by step / page / home /
|
|
329
331
|
* end. Pointer drag is handled by the component's drag subscriptions. */
|
|
330
|
-
export declare const view:
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
332
|
+
export declare const view: import("../../html/submodel.js").SubmodelView<{
|
|
333
|
+
readonly id: string;
|
|
334
|
+
readonly value: number;
|
|
335
|
+
readonly min: number;
|
|
336
|
+
readonly max: number;
|
|
337
|
+
readonly step: number;
|
|
338
|
+
readonly dragState: {
|
|
339
|
+
readonly _tag: "Idle";
|
|
340
|
+
} | {
|
|
341
|
+
readonly _tag: "Dragging";
|
|
342
|
+
readonly originValue: number;
|
|
343
|
+
};
|
|
344
|
+
}, {
|
|
345
|
+
readonly _tag: "PressedThumb";
|
|
346
|
+
} | {
|
|
347
|
+
readonly _tag: "PressedPointer";
|
|
348
|
+
readonly value: number;
|
|
349
|
+
} | {
|
|
350
|
+
readonly _tag: "MovedDragPointer";
|
|
351
|
+
readonly value: number;
|
|
352
|
+
} | {
|
|
353
|
+
readonly _tag: "ReleasedDragPointer";
|
|
354
|
+
} | {
|
|
355
|
+
readonly _tag: "CancelledDrag";
|
|
356
|
+
} | {
|
|
357
|
+
readonly _tag: "PressedKeyboardNavigation";
|
|
358
|
+
readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
|
|
359
|
+
}, Readonly<{
|
|
360
|
+
toView: (attributes: SliderAttributes) => Html;
|
|
361
|
+
ariaLabel?: string;
|
|
362
|
+
ariaLabelledBy?: string;
|
|
363
|
+
formatValue?: (value: number) => string;
|
|
364
|
+
isDisabled?: boolean;
|
|
365
|
+
name?: string;
|
|
366
|
+
/** Resolves the root that holds the slider track when looking it up by its
|
|
367
|
+
* `data-slider-track-id` attribute. Defaults to `document`. Provide a
|
|
368
|
+
* ShadowRoot when rendering the slider inside a shadow tree so pointer
|
|
369
|
+
* events on the track can map clientX into a value. */
|
|
370
|
+
getTrackRoot?: () => Document | ShadowRoot;
|
|
371
|
+
}>>;
|
|
334
372
|
export {};
|
|
335
373
|
//# sourceMappingURL=index.d.ts.map
|