@typed/ui 1.0.0-beta.5 → 1.0.0-beta.7
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/dist/Alert.d.ts +35 -41
- package/dist/Alert.d.ts.map +1 -1
- package/dist/Alert.js +23 -20
- package/dist/Button.d.ts +34 -78
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +16 -12
- package/dist/Carousel.d.ts +35 -236
- package/dist/Carousel.d.ts.map +1 -1
- package/dist/Carousel.js +13 -136
- package/dist/Checkbox.d.ts +55 -90
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +44 -38
- package/dist/Collection.d.ts +15 -15
- package/dist/Collection.js +7 -7
- package/dist/Combobox.d.ts +38 -187
- package/dist/Combobox.d.ts.map +1 -1
- package/dist/Combobox.js +9 -80
- package/dist/Component.d.ts +30 -24
- package/dist/Component.d.ts.map +1 -1
- package/dist/Component.js +23 -12
- package/dist/Composite.d.ts +50 -50
- package/dist/Composite.js +20 -20
- package/dist/Dialog.d.ts +34 -34
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +16 -14
- package/dist/Disclosure.d.ts +15 -15
- package/dist/Disclosure.js +6 -6
- package/dist/Dom/Events.d.ts +4 -4
- package/dist/Dom/Events.js +4 -4
- package/dist/Dom/Props.d.ts +9 -9
- package/dist/Dom/Props.js +4 -4
- package/dist/Dom/Refs.d.ts +2 -2
- package/dist/Dom/Refs.js +1 -1
- package/dist/Dom/Render.d.ts +2 -2
- package/dist/Dom/Render.js +2 -2
- package/dist/Dom/Types.d.ts +33 -33
- package/dist/Dom/index.d.ts +5 -5
- package/dist/Dom/index.d.ts.map +1 -1
- package/dist/Dom/index.js +4 -4
- package/dist/Dom.d.ts +1 -1
- package/dist/Dom.js +1 -1
- package/dist/Focusable.d.ts +5 -5
- package/dist/Focusable.js +1 -1
- package/dist/Form.d.ts +565 -533
- package/dist/Form.d.ts.map +1 -1
- package/dist/Form.js +350 -195
- package/dist/Grid.d.ts +39 -220
- package/dist/Grid.d.ts.map +1 -1
- package/dist/Grid.js +12 -107
- package/dist/Group.d.ts +50 -69
- package/dist/Group.d.ts.map +1 -1
- package/dist/Group.js +33 -25
- package/dist/Heading.d.ts +41 -40
- package/dist/Heading.d.ts.map +1 -1
- package/dist/Heading.js +26 -16
- package/dist/Hovercard.d.ts +18 -18
- package/dist/Hovercard.js +6 -6
- package/dist/HttpRouter.d.ts +3 -3
- package/dist/HttpRouter.js +5 -5
- package/dist/Link.d.ts +17 -21
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +11 -0
- package/dist/Listbox.d.ts +31 -163
- package/dist/Listbox.d.ts.map +1 -1
- package/dist/Listbox.js +9 -80
- package/dist/Menu.d.ts +67 -376
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +17 -179
- package/dist/Menubar.d.ts +24 -142
- package/dist/Menubar.d.ts.map +1 -1
- package/dist/Menubar.js +8 -66
- package/dist/Meter.d.ts +72 -132
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +35 -42
- package/dist/NativeDetails.d.ts +1 -1
- package/dist/NativeDetails.js +1 -1
- package/dist/NativeDialog.d.ts +7 -5
- package/dist/NativeDialog.d.ts.map +1 -1
- package/dist/NativeDialog.js +42 -4
- package/dist/NativePopover.d.ts +6 -4
- package/dist/NativePopover.d.ts.map +1 -1
- package/dist/NativePopover.js +43 -5
- package/dist/Popover.d.ts +18 -19
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +7 -8
- package/dist/RadioGroup.d.ts +86 -188
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +55 -105
- package/dist/Role.d.ts +4 -4
- package/dist/Role.js +1 -1
- package/dist/Select.d.ts +109 -220
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +67 -117
- package/dist/Separator.d.ts +30 -26
- package/dist/Separator.d.ts.map +1 -1
- package/dist/Separator.js +16 -10
- package/dist/Slider.d.ts +64 -111
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +47 -42
- package/dist/SpinButton.d.ts +64 -111
- package/dist/SpinButton.d.ts.map +1 -1
- package/dist/SpinButton.js +47 -42
- package/dist/Storybook.d.ts +2 -2
- package/dist/Storybook.js +1 -1
- package/dist/Switch.d.ts +52 -91
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +30 -36
- package/dist/Tabs.d.ts +44 -224
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +10 -94
- package/dist/Toolbar.d.ts +24 -142
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar.js +8 -66
- package/dist/Tooltip.d.ts +20 -20
- package/dist/Tooltip.js +6 -6
- package/dist/Tree.d.ts +43 -229
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +12 -113
- package/dist/TreeGrid.d.ts +45 -264
- package/dist/TreeGrid.d.ts.map +1 -1
- package/dist/TreeGrid.js +13 -125
- package/dist/VisuallyHidden.d.ts +41 -27
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +27 -10
- package/dist/WindowSplitter.d.ts +68 -108
- package/dist/WindowSplitter.d.ts.map +1 -1
- package/dist/WindowSplitter.js +106 -23
- package/package.json +9 -8
package/dist/WindowSplitter.d.ts
CHANGED
|
@@ -1,172 +1,130 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Scope from "effect/Scope";
|
|
2
3
|
import * as Schema from "effect/Schema";
|
|
3
|
-
import { RefSubject } from "@typed/fx";
|
|
4
|
+
import { Fx, RefSubject } from "@typed/fx";
|
|
4
5
|
import { EventHandler, type Renderable } from "@typed/template";
|
|
5
6
|
import * as Dom from "./Dom.js";
|
|
7
|
+
import type { ComposedRef } from "./Dom/Refs.js";
|
|
6
8
|
import type { HostResult } from "./Dom/Types.js";
|
|
7
9
|
/** Visual orientation of the separator between panes.
|
|
8
10
|
* @remarks
|
|
9
|
-
* ## Why
|
|
10
11
|
* A vertical separator adjusts with Left/Right; a horizontal separator adjusts
|
|
11
12
|
* with Up/Down, matching the axis perpendicular to the dividing line.
|
|
12
|
-
* ## Ownership and lifetime
|
|
13
|
-
* This pure type acquires no resources.
|
|
14
13
|
* @since 1.0.0
|
|
15
|
-
* @category
|
|
14
|
+
* @category Resize axis
|
|
16
15
|
*/
|
|
17
16
|
export type Orientation = "horizontal" | "vertical";
|
|
18
17
|
/** Current value and keyboard policy for a window splitter.
|
|
19
18
|
* @remarks
|
|
20
|
-
* ## Why
|
|
21
19
|
* All range and collapse information remains renderer-independent and directly
|
|
22
20
|
* testable.
|
|
23
|
-
* ## Ownership and lifetime
|
|
24
21
|
* Plain state retains no resources; its hydrated RefSubject is Scope-owned.
|
|
25
22
|
* @since 1.0.0
|
|
26
|
-
* @category state
|
|
23
|
+
* @category Pane sizing state
|
|
27
24
|
*/
|
|
28
25
|
export interface State {
|
|
29
26
|
/** Current pane size value.
|
|
30
27
|
* @remarks
|
|
31
|
-
* ## Why
|
|
32
28
|
* It drives `aria-valuenow` and keyboard adjustments.
|
|
33
|
-
* ## Ownership and lifetime
|
|
34
|
-
* Plain numeric data acquires no resources.
|
|
35
29
|
* @since 1.0.0
|
|
36
|
-
* @category
|
|
30
|
+
* @category Current value
|
|
37
31
|
*/
|
|
38
32
|
readonly value: number;
|
|
39
33
|
/** Restore value used by `toggleCollapsed`.
|
|
40
34
|
* @remarks
|
|
41
|
-
* ## Why
|
|
42
35
|
* It starts at the initial clamped value. `toggleCollapsed` overwrites it only
|
|
43
36
|
* when collapsing from a non-minimum value, then reads it when restoring.
|
|
44
37
|
* Ordinary `setValue` and `adjust` calls do not update it.
|
|
45
|
-
* ## Ownership and lifetime
|
|
46
|
-
* Plain numeric data acquires no resources.
|
|
47
38
|
* @since 1.0.0
|
|
48
|
-
* @category
|
|
39
|
+
* @category Collapse and restore
|
|
49
40
|
*/
|
|
50
41
|
readonly previousValue: number;
|
|
51
42
|
/** Inclusive minimum pane value.
|
|
52
43
|
* @remarks
|
|
53
|
-
* ## Why
|
|
54
44
|
* Updates clamp to this bound and Home jumps to it.
|
|
55
|
-
* ## Ownership and lifetime
|
|
56
|
-
* Plain numeric data acquires no resources.
|
|
57
45
|
* @since 1.0.0
|
|
58
|
-
* @category constraints
|
|
46
|
+
* @category Range constraints
|
|
59
47
|
*/
|
|
60
48
|
readonly min: number;
|
|
61
49
|
/** Inclusive maximum pane value.
|
|
62
50
|
* @remarks
|
|
63
|
-
* ## Why
|
|
64
51
|
* Updates clamp to this bound and End jumps to it.
|
|
65
|
-
* ## Ownership and lifetime
|
|
66
|
-
* Plain numeric data acquires no resources.
|
|
67
52
|
* @since 1.0.0
|
|
68
|
-
* @category constraints
|
|
53
|
+
* @category Range constraints
|
|
69
54
|
*/
|
|
70
55
|
readonly max: number;
|
|
71
56
|
/** Keyboard adjustment increment.
|
|
72
57
|
* @remarks
|
|
73
|
-
* ## Why
|
|
74
58
|
* Arrow keys require a deterministic application-defined change size. The
|
|
75
59
|
* state constructor does not enforce positivity; callers must provide a
|
|
76
60
|
* positive value for conventional keyboard direction.
|
|
77
|
-
* ## Ownership and lifetime
|
|
78
|
-
* Plain numeric data acquires no resources.
|
|
79
61
|
* @since 1.0.0
|
|
80
|
-
* @category
|
|
62
|
+
* @category Keyboard adjustment
|
|
81
63
|
*/
|
|
82
64
|
readonly step: number;
|
|
83
65
|
/** Separator orientation and keyboard axis.
|
|
84
66
|
* @remarks
|
|
85
|
-
* ## Why
|
|
86
67
|
* The value drives both `aria-orientation` and valid arrow keys.
|
|
87
|
-
* ## Ownership and lifetime
|
|
88
|
-
* Plain data acquires no resources.
|
|
89
68
|
* @since 1.0.0
|
|
90
|
-
* @category
|
|
69
|
+
* @category Keyboard navigation
|
|
91
70
|
*/
|
|
92
71
|
readonly orientation: Orientation;
|
|
93
72
|
}
|
|
94
73
|
/** Initial splitter range and keyboard configuration.
|
|
95
74
|
* @remarks
|
|
96
|
-
* ## Why
|
|
97
75
|
* Defaults give the widget a complete deterministic state before rendering.
|
|
98
76
|
* Callers remain responsible for `min <= max` and `step > 0`.
|
|
99
|
-
* ## Ownership and lifetime
|
|
100
|
-
* Configuration is inert.
|
|
101
77
|
* @since 1.0.0
|
|
102
|
-
* @category state
|
|
78
|
+
* @category Pane sizing state
|
|
103
79
|
*/
|
|
104
80
|
export interface InitialState {
|
|
105
81
|
/** Initial pane size, clamped to min/max.
|
|
106
82
|
* @remarks
|
|
107
|
-
* ## Why
|
|
108
83
|
* Invalid out-of-range starts become a valid accessible value.
|
|
109
|
-
* ## Ownership and lifetime
|
|
110
|
-
* Plain data is copied into state.
|
|
111
84
|
* @since 1.0.0
|
|
112
|
-
* @category
|
|
85
|
+
* @category Current value
|
|
113
86
|
*/
|
|
114
87
|
readonly value: number;
|
|
115
88
|
/** Minimum value, defaulting to zero.
|
|
116
89
|
* @remarks
|
|
117
|
-
* ## Why
|
|
118
90
|
* It defines the collapsed boundary and Home result. Callers must ensure it is
|
|
119
91
|
* less than or equal to `max`; neither the schema nor constructor compares them.
|
|
120
|
-
* ## Ownership and lifetime
|
|
121
|
-
* Plain data is copied into state.
|
|
122
92
|
* @since 1.0.0
|
|
123
|
-
* @category constraints
|
|
93
|
+
* @category Range constraints
|
|
124
94
|
*/
|
|
125
95
|
readonly min?: number;
|
|
126
96
|
/** Maximum value, defaulting to one hundred.
|
|
127
97
|
* @remarks
|
|
128
|
-
* ## Why
|
|
129
98
|
* It defines the upper keyboard and ARIA bound. Callers must ensure it is
|
|
130
99
|
* greater than or equal to `min`; neither the schema nor constructor compares them.
|
|
131
|
-
* ## Ownership and lifetime
|
|
132
|
-
* Plain data is copied into state.
|
|
133
100
|
* @since 1.0.0
|
|
134
|
-
* @category constraints
|
|
101
|
+
* @category Range constraints
|
|
135
102
|
*/
|
|
136
103
|
readonly max?: number;
|
|
137
104
|
/** Arrow-key increment, defaulting to ten.
|
|
138
105
|
* @remarks
|
|
139
|
-
* ## Why
|
|
140
106
|
* The widget needs an explicit adjustment granularity. Callers must provide a
|
|
141
107
|
* positive value; `Schema.Finite` rejects infinities and NaN but accepts zero
|
|
142
108
|
* and negative numbers.
|
|
143
|
-
* ## Ownership and lifetime
|
|
144
|
-
* Plain data is copied into state.
|
|
145
109
|
* @since 1.0.0
|
|
146
|
-
* @category
|
|
110
|
+
* @category Keyboard adjustment
|
|
147
111
|
*/
|
|
148
112
|
readonly step?: number;
|
|
149
113
|
/** Separator orientation, defaulting to vertical.
|
|
150
114
|
* @remarks
|
|
151
|
-
* ## Why
|
|
152
115
|
* Orientation determines ARIA output and arrow-key mapping.
|
|
153
|
-
* ## Ownership and lifetime
|
|
154
|
-
* Plain data is copied into state.
|
|
155
116
|
* @since 1.0.0
|
|
156
|
-
* @category
|
|
117
|
+
* @category Keyboard navigation
|
|
157
118
|
*/
|
|
158
119
|
readonly orientation?: Orientation;
|
|
159
120
|
}
|
|
160
121
|
/** Schema for the structural splitter hydration state.
|
|
161
122
|
* @remarks
|
|
162
|
-
* ## Why
|
|
163
123
|
* It validates finite numeric fields and the orientation union. It does not
|
|
164
124
|
* enforce `min <= max`, a positive `step`, or any relationship among fields;
|
|
165
125
|
* callers must satisfy those semantic preconditions.
|
|
166
|
-
* ## Ownership and lifetime
|
|
167
|
-
* The immutable schema acquires no resources.
|
|
168
126
|
* @since 1.0.0
|
|
169
|
-
* @category
|
|
127
|
+
* @category Pane sizing state
|
|
170
128
|
*/
|
|
171
129
|
export declare const StateSchema: Schema.Struct<{
|
|
172
130
|
readonly value: Schema.Finite;
|
|
@@ -178,11 +136,9 @@ export declare const StateSchema: Schema.Struct<{
|
|
|
178
136
|
}>;
|
|
179
137
|
/** Creates hydrated splitter state and clamps the initial value.
|
|
180
138
|
* @remarks
|
|
181
|
-
* ## Why
|
|
182
139
|
* Pane sizing behavior can be composed and tested without mounting a separator.
|
|
183
140
|
* Callers must supply `min <= max` and `step > 0`; the constructor defaults
|
|
184
141
|
* omitted bounds/step but does not validate those relationships.
|
|
185
|
-
* ## Ownership and lifetime
|
|
186
142
|
* The calling Effect Scope owns the returned RefSubject.
|
|
187
143
|
* @example
|
|
188
144
|
* ```ts
|
|
@@ -194,7 +150,7 @@ export declare const StateSchema: Schema.Struct<{
|
|
|
194
150
|
* })
|
|
195
151
|
* ```
|
|
196
152
|
* @since 1.0.0
|
|
197
|
-
* @category
|
|
153
|
+
* @category Pane sizing state
|
|
198
154
|
*/
|
|
199
155
|
export declare function makeState(initial: InitialState): Effect.Effect<RefSubject.HydratedRefSubject<{
|
|
200
156
|
readonly value: number;
|
|
@@ -203,14 +159,12 @@ export declare function makeState(initial: InitialState): Effect.Effect<RefSubje
|
|
|
203
159
|
readonly max: number;
|
|
204
160
|
readonly step: number;
|
|
205
161
|
readonly orientation: "horizontal" | "vertical";
|
|
206
|
-
}, Schema.SchemaError, never, never>, never,
|
|
162
|
+
}, Schema.SchemaError, never, never>, never, Scope.Scope>;
|
|
207
163
|
/** Sets and clamps the current splitter value.
|
|
208
164
|
* @remarks
|
|
209
|
-
* ## Why
|
|
210
165
|
* All callers share one transition bounded by the state's `min` and `max`.
|
|
211
166
|
* Correct range ordering remains a caller precondition. This operation does not
|
|
212
167
|
* change `previousValue`.
|
|
213
|
-
* ## Ownership and lifetime
|
|
214
168
|
* The Effect uses the existing RefSubject lifetime and acquires no resource.
|
|
215
169
|
* @example
|
|
216
170
|
* ```ts
|
|
@@ -223,16 +177,14 @@ export declare function makeState(initial: InitialState): Effect.Effect<RefSubje
|
|
|
223
177
|
* })
|
|
224
178
|
* ```
|
|
225
179
|
* @since 1.0.0
|
|
226
|
-
* @category
|
|
180
|
+
* @category Bounded resizing
|
|
227
181
|
*/
|
|
228
182
|
export declare function setValue<E, R>(state: RefSubject.RefSubject<State, E, R>, value: number): Effect.Effect<State, E, R>;
|
|
229
183
|
/** Adds a delta and clamps the resulting splitter value.
|
|
230
184
|
* @remarks
|
|
231
|
-
* ## Why
|
|
232
185
|
* Arrow-key behavior can be tested independently of DOM events. Correct range
|
|
233
186
|
* ordering remains a caller precondition, and this operation does not change
|
|
234
187
|
* `previousValue`.
|
|
235
|
-
* ## Ownership and lifetime
|
|
236
188
|
* The Effect uses the existing RefSubject lifetime and acquires no resource.
|
|
237
189
|
* @example
|
|
238
190
|
* ```ts
|
|
@@ -245,16 +197,14 @@ export declare function setValue<E, R>(state: RefSubject.RefSubject<State, E, R>
|
|
|
245
197
|
* })
|
|
246
198
|
* ```
|
|
247
199
|
* @since 1.0.0
|
|
248
|
-
* @category
|
|
200
|
+
* @category Bounded resizing
|
|
249
201
|
*/
|
|
250
202
|
export declare function adjust<E, R>(state: RefSubject.RefSubject<State, E, R>, delta: number): Effect.Effect<State, E, R>;
|
|
251
203
|
/** Collapses to min or restores the recorded collapse value.
|
|
252
204
|
* @remarks
|
|
253
|
-
* ## Why
|
|
254
205
|
* When the current value is not `min`, the operation records that exact value in
|
|
255
206
|
* `previousValue` and collapses. At `min`, it restores the stored value after
|
|
256
207
|
* clamping it to the current range. Other updates do not maintain a history.
|
|
257
|
-
* ## Ownership and lifetime
|
|
258
208
|
* The Effect updates existing state atomically and acquires no resource.
|
|
259
209
|
* @example
|
|
260
210
|
* ```ts
|
|
@@ -267,94 +217,104 @@ export declare function adjust<E, R>(state: RefSubject.RefSubject<State, E, R>,
|
|
|
267
217
|
* })
|
|
268
218
|
* ```
|
|
269
219
|
* @since 1.0.0
|
|
270
|
-
* @category
|
|
220
|
+
* @category Collapse and restore
|
|
271
221
|
*/
|
|
272
222
|
export declare function toggleCollapsed<E, R>(state: RefSubject.RefSubject<State, E, R>): Effect.Effect<State, E, R>;
|
|
273
223
|
/** Options for the focusable ARIA window splitter.
|
|
274
224
|
* @remarks
|
|
275
|
-
* ## Why
|
|
276
225
|
* The model connects renderer-independent sizing to its controlled pane and
|
|
277
226
|
* accessible range metadata. Its state must already satisfy `min <= max` and a
|
|
278
227
|
* positive `step`; the component does not repair invalid state.
|
|
279
|
-
* ## Ownership and lifetime
|
|
280
228
|
* Options are inert; rendering owns subscriptions/listeners by Scope.
|
|
281
229
|
* @since 1.0.0
|
|
282
|
-
* @category
|
|
230
|
+
* @category Resize separator
|
|
283
231
|
*/
|
|
284
232
|
export interface WindowSplitterOptions extends Dom.HostOptions<HTMLDivElement> {
|
|
285
233
|
/** Hydrated sizing state.
|
|
286
234
|
* @remarks
|
|
287
|
-
* ## Why
|
|
288
235
|
* One source drives keyboard updates and every ARIA range attribute.
|
|
289
|
-
* ## Ownership and lifetime
|
|
290
236
|
* The splitter borrows state; its original Scope owns it.
|
|
291
237
|
* @since 1.0.0
|
|
292
|
-
* @category
|
|
238
|
+
* @category State connection
|
|
293
239
|
*/
|
|
294
240
|
readonly state: RefSubject.HydratedRefSubject<State, Schema.SchemaError>;
|
|
295
241
|
/** Id of the pane controlled by the splitter.
|
|
296
242
|
* @remarks
|
|
297
|
-
* ## Why
|
|
298
243
|
* `aria-controls` makes the resizing relationship explicit.
|
|
299
|
-
* ## Ownership and lifetime
|
|
300
244
|
* Dynamic values follow the component Scope.
|
|
301
245
|
* @since 1.0.0
|
|
302
|
-
* @category relationships
|
|
246
|
+
* @category Identity and relationships
|
|
303
247
|
*/
|
|
304
248
|
readonly primaryPaneId: Renderable.Any<string | null | undefined>;
|
|
305
249
|
/** Accessible name when no external label is supplied.
|
|
306
250
|
* @remarks
|
|
307
|
-
* ## Why
|
|
308
251
|
* A focusable separator needs a discoverable purpose.
|
|
309
|
-
* ## Ownership and lifetime
|
|
310
252
|
* Dynamic values follow the component Scope.
|
|
311
253
|
* @since 1.0.0
|
|
312
|
-
* @category
|
|
254
|
+
* @category Accessible naming
|
|
313
255
|
*/
|
|
314
256
|
readonly label?: Renderable.Any<string | null | undefined>;
|
|
315
257
|
/** Human-readable value text supplementing the number.
|
|
316
258
|
* @remarks
|
|
317
|
-
* ## Why
|
|
318
259
|
* Pane sizes such as percentages or labels may be clearer than raw values.
|
|
319
|
-
* ## Ownership and lifetime
|
|
320
260
|
* Dynamic values follow the component Scope.
|
|
321
261
|
* @since 1.0.0
|
|
322
|
-
* @category
|
|
262
|
+
* @category Accessible value text
|
|
323
263
|
*/
|
|
324
264
|
readonly valueText?: Renderable.Any<string | null | undefined>;
|
|
325
|
-
/**
|
|
265
|
+
/** State-value units represented by one CSS pixel of pointer movement.
|
|
266
|
+
* @remarks
|
|
267
|
+
* By default, the usable parent width (vertical separator) or height
|
|
268
|
+
* (horizontal separator), minus the separator thickness, represents 100
|
|
269
|
+
* units. This matches percentage pane sizes. Set `1` for CSS-pixel values.
|
|
270
|
+
* Positive axis-aligned CSS scaling is accounted for; pointer coordinates
|
|
271
|
+
* are converted from viewport pixels to the parent's CSS-pixel scale.
|
|
272
|
+
* Supply a positive finite number when using another unit system.
|
|
273
|
+
* Keyboard step and min/max remain independent of pointer resolution.
|
|
274
|
+
* @since 1.0.0
|
|
275
|
+
* @category Pointer resizing
|
|
276
|
+
*/
|
|
277
|
+
readonly valuePerPixel?: number;
|
|
278
|
+
/** Whether keyboard and pointer adjustments are disabled.
|
|
326
279
|
* @remarks
|
|
327
|
-
* ## Why
|
|
328
280
|
* ARIA disabled state and handler behavior must agree.
|
|
329
|
-
* ## Ownership and lifetime
|
|
330
281
|
* Dynamic values follow the component Scope.
|
|
331
282
|
* @since 1.0.0
|
|
332
|
-
* @category
|
|
283
|
+
* @category Availability
|
|
333
284
|
*/
|
|
334
285
|
readonly disabled?: Renderable.Any<boolean | null | undefined>;
|
|
335
286
|
}
|
|
336
|
-
|
|
287
|
+
type WindowSplitterInternalProps<Options extends WindowSplitterOptions> = {
|
|
337
288
|
readonly role: "separator";
|
|
289
|
+
readonly style: Fx.Fx<string | Partial<CSSStyleDeclaration>, Renderable.Error<Options>, Renderable.Services<Options>>;
|
|
338
290
|
readonly tabindex: 0;
|
|
339
|
-
readonly "aria-orientation": RefSubject.Computed<Orientation, Schema.SchemaError
|
|
340
|
-
readonly "aria-valuenow": RefSubject.Computed<number, Schema.SchemaError
|
|
341
|
-
readonly "aria-valuemin": RefSubject.Computed<number, Schema.SchemaError
|
|
342
|
-
readonly "aria-valuemax": RefSubject.Computed<number, Schema.SchemaError
|
|
343
|
-
readonly "aria-controls":
|
|
344
|
-
readonly "aria-label":
|
|
345
|
-
readonly "aria-valuetext":
|
|
346
|
-
readonly "aria-disabled":
|
|
347
|
-
readonly onkeydown: EventHandler.EventHandler<KeyboardEvent, Schema.SchemaError
|
|
348
|
-
readonly
|
|
291
|
+
readonly "aria-orientation": RefSubject.Computed<Orientation, Schema.SchemaError>;
|
|
292
|
+
readonly "aria-valuenow": RefSubject.Computed<number, Schema.SchemaError>;
|
|
293
|
+
readonly "aria-valuemin": RefSubject.Computed<number, Schema.SchemaError>;
|
|
294
|
+
readonly "aria-valuemax": RefSubject.Computed<number, Schema.SchemaError>;
|
|
295
|
+
readonly "aria-controls": Dom.NonNullish<Dom.Property<Options, "primaryPaneId">> | undefined;
|
|
296
|
+
readonly "aria-label": Dom.NonNullish<Dom.Property<Options, "label">> | undefined;
|
|
297
|
+
readonly "aria-valuetext": Dom.NonNullish<Dom.Property<Options, "valueText">> | undefined;
|
|
298
|
+
readonly "aria-disabled": Dom.NonNullish<Dom.Property<Options, "disabled">> | false;
|
|
299
|
+
readonly onkeydown: EventHandler.EventHandler<KeyboardEvent, Schema.SchemaError>;
|
|
300
|
+
readonly onpointerdown: EventHandler.EventHandler<PointerEvent>;
|
|
301
|
+
readonly onpointermove: EventHandler.EventHandler<PointerEvent, Schema.SchemaError>;
|
|
302
|
+
readonly onpointerup: EventHandler.EventHandler<PointerEvent>;
|
|
303
|
+
readonly onpointercancel: EventHandler.EventHandler<PointerEvent>;
|
|
304
|
+
readonly onlostpointercapture: EventHandler.EventHandler<PointerEvent>;
|
|
305
|
+
readonly ref: ComposedRef<RefSubject.HydratedRefSubject<State, Schema.SchemaError>, (element: HTMLDivElement) => Effect.Effect<void, never, Scope.Scope>> | undefined;
|
|
349
306
|
};
|
|
350
|
-
type WindowSplitterInternalProps<Options extends WindowSplitterOptions> = ReturnType<ReturnType<typeof internalProps<Options>>>;
|
|
351
307
|
/** Renders a focusable ARIA separator for resizing a pane.
|
|
352
308
|
* @remarks
|
|
353
|
-
* ## Why
|
|
354
309
|
* The component exposes native DOM focus/events and the ARIA window-splitter
|
|
355
310
|
* range contract: arrows adjust by step, Home/End reach bounds, and Enter
|
|
356
|
-
* collapses/restores.
|
|
357
|
-
*
|
|
311
|
+
* collapses/restores. Pointer dragging adjusts the same clamped state, using
|
|
312
|
+
* percentage-of-parent movement by default or the supplied `valuePerPixel`.
|
|
313
|
+
* Native pointer capture keeps movement attached outside the separator;
|
|
314
|
+
* release, cancellation, lost capture, and Scope teardown end the drag.
|
|
315
|
+
* The host composes caller styles with `touch-action: none` so touch gestures
|
|
316
|
+
* remain resize interactions. The caller binds state to actual pane layout. Disabled state
|
|
317
|
+
* leaves keyboard and pointer activation inert.
|
|
358
318
|
* Running the returned Fx owns real key listeners, reactive ARIA attributes,
|
|
359
319
|
* and the hydration ref in its Effect Scope. A custom host must preserve role,
|
|
360
320
|
* tab index, range/relationship attributes, handler, and one hydration owner.
|
|
@@ -369,7 +329,7 @@ type WindowSplitterInternalProps<Options extends WindowSplitterOptions> = Return
|
|
|
369
329
|
* })
|
|
370
330
|
* ```
|
|
371
331
|
* @since 1.0.0
|
|
372
|
-
* @category
|
|
332
|
+
* @category Resize separator
|
|
373
333
|
*/
|
|
374
334
|
export declare function WindowSplitter<const Options extends WindowSplitterOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, WindowSplitterInternalProps<Options>>, "", Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
375
335
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WindowSplitter.d.ts","sourceRoot":"","sources":["../src/WindowSplitter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"WindowSplitter.d.ts","sourceRoot":"","sources":["../src/WindowSplitter.ts"],"names":[],"mappings":"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"}
|
package/dist/WindowSplitter.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Scope from "effect/Scope";
|
|
2
3
|
import * as Schema from "effect/Schema";
|
|
3
|
-
import { RefSubject } from "@typed/fx";
|
|
4
|
-
import { EventHandler, html } from "@typed/template";
|
|
4
|
+
import { Fx, RefSubject } from "@typed/fx";
|
|
5
|
+
import { EventHandler, html, liftRenderableToFx } from "@typed/template";
|
|
5
6
|
import * as Dom from "./Dom.js";
|
|
6
7
|
/** Schema for the structural splitter hydration state.
|
|
7
8
|
* @remarks
|
|
8
|
-
* ## Why
|
|
9
9
|
* It validates finite numeric fields and the orientation union. It does not
|
|
10
10
|
* enforce `min <= max`, a positive `step`, or any relationship among fields;
|
|
11
11
|
* callers must satisfy those semantic preconditions.
|
|
12
|
-
* ## Ownership and lifetime
|
|
13
|
-
* The immutable schema acquires no resources.
|
|
14
12
|
* @since 1.0.0
|
|
15
|
-
* @category
|
|
13
|
+
* @category Pane sizing state
|
|
16
14
|
*/
|
|
17
15
|
export const StateSchema = Schema.Struct({
|
|
18
16
|
value: Schema.Finite,
|
|
@@ -24,11 +22,9 @@ export const StateSchema = Schema.Struct({
|
|
|
24
22
|
});
|
|
25
23
|
/** Creates hydrated splitter state and clamps the initial value.
|
|
26
24
|
* @remarks
|
|
27
|
-
* ## Why
|
|
28
25
|
* Pane sizing behavior can be composed and tested without mounting a separator.
|
|
29
26
|
* Callers must supply `min <= max` and `step > 0`; the constructor defaults
|
|
30
27
|
* omitted bounds/step but does not validate those relationships.
|
|
31
|
-
* ## Ownership and lifetime
|
|
32
28
|
* The calling Effect Scope owns the returned RefSubject.
|
|
33
29
|
* @example
|
|
34
30
|
* ```ts
|
|
@@ -40,7 +36,7 @@ export const StateSchema = Schema.Struct({
|
|
|
40
36
|
* })
|
|
41
37
|
* ```
|
|
42
38
|
* @since 1.0.0
|
|
43
|
-
* @category
|
|
39
|
+
* @category Pane sizing state
|
|
44
40
|
*/
|
|
45
41
|
export function makeState(initial) {
|
|
46
42
|
const min = initial.min ?? 0;
|
|
@@ -57,11 +53,9 @@ export function makeState(initial) {
|
|
|
57
53
|
}
|
|
58
54
|
/** Sets and clamps the current splitter value.
|
|
59
55
|
* @remarks
|
|
60
|
-
* ## Why
|
|
61
56
|
* All callers share one transition bounded by the state's `min` and `max`.
|
|
62
57
|
* Correct range ordering remains a caller precondition. This operation does not
|
|
63
58
|
* change `previousValue`.
|
|
64
|
-
* ## Ownership and lifetime
|
|
65
59
|
* The Effect uses the existing RefSubject lifetime and acquires no resource.
|
|
66
60
|
* @example
|
|
67
61
|
* ```ts
|
|
@@ -74,7 +68,7 @@ export function makeState(initial) {
|
|
|
74
68
|
* })
|
|
75
69
|
* ```
|
|
76
70
|
* @since 1.0.0
|
|
77
|
-
* @category
|
|
71
|
+
* @category Bounded resizing
|
|
78
72
|
*/
|
|
79
73
|
export function setValue(state, value) {
|
|
80
74
|
return RefSubject.update(state, (current) => ({
|
|
@@ -84,11 +78,9 @@ export function setValue(state, value) {
|
|
|
84
78
|
}
|
|
85
79
|
/** Adds a delta and clamps the resulting splitter value.
|
|
86
80
|
* @remarks
|
|
87
|
-
* ## Why
|
|
88
81
|
* Arrow-key behavior can be tested independently of DOM events. Correct range
|
|
89
82
|
* ordering remains a caller precondition, and this operation does not change
|
|
90
83
|
* `previousValue`.
|
|
91
|
-
* ## Ownership and lifetime
|
|
92
84
|
* The Effect uses the existing RefSubject lifetime and acquires no resource.
|
|
93
85
|
* @example
|
|
94
86
|
* ```ts
|
|
@@ -101,7 +93,7 @@ export function setValue(state, value) {
|
|
|
101
93
|
* })
|
|
102
94
|
* ```
|
|
103
95
|
* @since 1.0.0
|
|
104
|
-
* @category
|
|
96
|
+
* @category Bounded resizing
|
|
105
97
|
*/
|
|
106
98
|
export function adjust(state, delta) {
|
|
107
99
|
return RefSubject.update(state, (current) => ({
|
|
@@ -111,11 +103,9 @@ export function adjust(state, delta) {
|
|
|
111
103
|
}
|
|
112
104
|
/** Collapses to min or restores the recorded collapse value.
|
|
113
105
|
* @remarks
|
|
114
|
-
* ## Why
|
|
115
106
|
* When the current value is not `min`, the operation records that exact value in
|
|
116
107
|
* `previousValue` and collapses. At `min`, it restores the stored value after
|
|
117
108
|
* clamping it to the current range. Other updates do not maintain a history.
|
|
118
|
-
* ## Ownership and lifetime
|
|
119
109
|
* The Effect updates existing state atomically and acquires no resource.
|
|
120
110
|
* @example
|
|
121
111
|
* ```ts
|
|
@@ -128,7 +118,7 @@ export function adjust(state, delta) {
|
|
|
128
118
|
* })
|
|
129
119
|
* ```
|
|
130
120
|
* @since 1.0.0
|
|
131
|
-
* @category
|
|
121
|
+
* @category Collapse and restore
|
|
132
122
|
*/
|
|
133
123
|
export function toggleCollapsed(state) {
|
|
134
124
|
return RefSubject.update(state, (current) => current.value === current.min
|
|
@@ -136,6 +126,89 @@ export function toggleCollapsed(state) {
|
|
|
136
126
|
: { ...current, previousValue: current.value, value: current.min });
|
|
137
127
|
}
|
|
138
128
|
function internalProps(options) {
|
|
129
|
+
const drags = new WeakMap();
|
|
130
|
+
const release = (element) => {
|
|
131
|
+
const drag = drags.get(element);
|
|
132
|
+
drags.delete(element);
|
|
133
|
+
if (drag !== undefined && element.hasPointerCapture(drag.pointerId)) {
|
|
134
|
+
element.releasePointerCapture(drag.pointerId);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const pointerRef = Effect.fn(function* (element) {
|
|
138
|
+
yield* Scope.addFinalizer(yield* Effect.scope, Effect.sync(() => {
|
|
139
|
+
release(element);
|
|
140
|
+
}));
|
|
141
|
+
});
|
|
142
|
+
const pointerStyle = liftRenderableToFx(options.props?.style).pipe(Fx.map((style) => {
|
|
143
|
+
if (typeof style === "string")
|
|
144
|
+
return `${style};touch-action:none;`;
|
|
145
|
+
if (typeof style?.cssText === "string")
|
|
146
|
+
return `${style.cssText};touch-action:none;`;
|
|
147
|
+
return { ...style, touchAction: "none" };
|
|
148
|
+
}));
|
|
149
|
+
const onpointerdown = EventHandler.make((event) => Effect.sync(() => {
|
|
150
|
+
const element = Dom.currentTarget(event);
|
|
151
|
+
if (event.button !== 0 || !event.isPrimary || element.getAttribute("aria-disabled") === "true")
|
|
152
|
+
return;
|
|
153
|
+
if (drags.has(element))
|
|
154
|
+
return;
|
|
155
|
+
// The visible ARIA snapshot starts the native gesture without yielding to
|
|
156
|
+
// state acquisition before preventDefault and pointer capture.
|
|
157
|
+
const valueAttribute = element.getAttribute("aria-valuenow");
|
|
158
|
+
const value = Number(valueAttribute);
|
|
159
|
+
const orientation = element.getAttribute("aria-orientation");
|
|
160
|
+
if (valueAttribute === null || !Number.isFinite(value))
|
|
161
|
+
return;
|
|
162
|
+
const parent = element.parentElement;
|
|
163
|
+
if (parent === null)
|
|
164
|
+
return;
|
|
165
|
+
const vertical = orientation === "vertical";
|
|
166
|
+
const parentRect = parent.getBoundingClientRect();
|
|
167
|
+
const separatorRect = element.getBoundingClientRect();
|
|
168
|
+
// Pointer coordinates and DOMRects use viewport pixels. Convert the
|
|
169
|
+
// parent's client extent to that same unit, excluding its border/scrollbar.
|
|
170
|
+
const axisScale = vertical
|
|
171
|
+
? parentRect.width / parent.offsetWidth
|
|
172
|
+
: parentRect.height / parent.offsetHeight;
|
|
173
|
+
if (!Number.isFinite(axisScale) || axisScale <= 0)
|
|
174
|
+
return;
|
|
175
|
+
const extent = vertical
|
|
176
|
+
? parent.clientWidth * axisScale - separatorRect.width
|
|
177
|
+
: parent.clientHeight * axisScale - separatorRect.height;
|
|
178
|
+
const scale = options.valuePerPixel === undefined
|
|
179
|
+
? 100 / extent
|
|
180
|
+
: options.valuePerPixel / axisScale;
|
|
181
|
+
if (!Number.isFinite(scale) || scale <= 0)
|
|
182
|
+
return;
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
element.focus();
|
|
185
|
+
element.setPointerCapture(event.pointerId);
|
|
186
|
+
drags.set(element, {
|
|
187
|
+
pointerId: event.pointerId,
|
|
188
|
+
coordinate: vertical ? event.clientX : event.clientY,
|
|
189
|
+
value,
|
|
190
|
+
orientation: vertical ? "vertical" : "horizontal",
|
|
191
|
+
scale,
|
|
192
|
+
});
|
|
193
|
+
}));
|
|
194
|
+
const onpointermove = EventHandler.make(Effect.fn(function* (event) {
|
|
195
|
+
const element = Dom.currentTarget(event);
|
|
196
|
+
const drag = drags.get(element);
|
|
197
|
+
if (drag === undefined || drag.pointerId !== event.pointerId)
|
|
198
|
+
return;
|
|
199
|
+
if (element.getAttribute("aria-disabled") === "true" || (event.buttons & 1) === 0) {
|
|
200
|
+
release(element);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
event.preventDefault();
|
|
204
|
+
const coordinate = drag.orientation === "vertical" ? event.clientX : event.clientY;
|
|
205
|
+
yield* setValue(options.state, drag.value + (coordinate - drag.coordinate) * drag.scale);
|
|
206
|
+
}));
|
|
207
|
+
const endDrag = EventHandler.make((event) => Effect.sync(() => {
|
|
208
|
+
const element = Dom.currentTarget(event);
|
|
209
|
+
if (drags.get(element)?.pointerId === event.pointerId)
|
|
210
|
+
release(element);
|
|
211
|
+
}));
|
|
139
212
|
const onkeydown = EventHandler.make(Effect.fn(function* (event) {
|
|
140
213
|
const current = yield* options.state;
|
|
141
214
|
if (Dom.currentTarget(event).getAttribute("aria-disabled") === "true") {
|
|
@@ -162,6 +235,7 @@ function internalProps(options) {
|
|
|
162
235
|
}));
|
|
163
236
|
return ({ property }) => ({
|
|
164
237
|
role: "separator",
|
|
238
|
+
style: pointerStyle,
|
|
165
239
|
tabindex: 0,
|
|
166
240
|
"aria-orientation": RefSubject.map(options.state, (state) => state.orientation),
|
|
167
241
|
"aria-valuenow": RefSubject.map(options.state, (state) => state.value),
|
|
@@ -172,16 +246,25 @@ function internalProps(options) {
|
|
|
172
246
|
"aria-valuetext": property("valueText", undefined),
|
|
173
247
|
"aria-disabled": property("disabled", false),
|
|
174
248
|
onkeydown,
|
|
175
|
-
|
|
249
|
+
onpointerdown,
|
|
250
|
+
onpointermove,
|
|
251
|
+
onpointerup: endDrag,
|
|
252
|
+
onpointercancel: endDrag,
|
|
253
|
+
onlostpointercapture: endDrag,
|
|
254
|
+
ref: Dom.composeRefs(options.state, pointerRef),
|
|
176
255
|
});
|
|
177
256
|
}
|
|
178
257
|
/** Renders a focusable ARIA separator for resizing a pane.
|
|
179
258
|
* @remarks
|
|
180
|
-
* ## Why
|
|
181
259
|
* The component exposes native DOM focus/events and the ARIA window-splitter
|
|
182
260
|
* range contract: arrows adjust by step, Home/End reach bounds, and Enter
|
|
183
|
-
* collapses/restores.
|
|
184
|
-
*
|
|
261
|
+
* collapses/restores. Pointer dragging adjusts the same clamped state, using
|
|
262
|
+
* percentage-of-parent movement by default or the supplied `valuePerPixel`.
|
|
263
|
+
* Native pointer capture keeps movement attached outside the separator;
|
|
264
|
+
* release, cancellation, lost capture, and Scope teardown end the drag.
|
|
265
|
+
* The host composes caller styles with `touch-action: none` so touch gestures
|
|
266
|
+
* remain resize interactions. The caller binds state to actual pane layout. Disabled state
|
|
267
|
+
* leaves keyboard and pointer activation inert.
|
|
185
268
|
* Running the returned Fx owns real key listeners, reactive ARIA attributes,
|
|
186
269
|
* and the hydration ref in its Effect Scope. A custom host must preserve role,
|
|
187
270
|
* tab index, range/relationship attributes, handler, and one hydration owner.
|
|
@@ -196,7 +279,7 @@ function internalProps(options) {
|
|
|
196
279
|
* })
|
|
197
280
|
* ```
|
|
198
281
|
* @since 1.0.0
|
|
199
|
-
* @category
|
|
282
|
+
* @category Resize separator
|
|
200
283
|
*/
|
|
201
284
|
export function WindowSplitter(options, host) {
|
|
202
285
|
return Dom.renderHost()(options, host, internalProps(options), "", (props) => {
|