@typed/ui 1.0.0-beta.1 → 1.0.0-beta.11
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/LICENSE +21 -0
- package/README.md +54 -10
- package/dist/Alert.d.ts +72 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Alert.js +40 -0
- package/dist/Button.d.ts +100 -0
- package/dist/Button.d.ts.map +1 -0
- package/dist/Button.js +42 -0
- package/dist/Carousel.d.ts +346 -0
- package/dist/Carousel.d.ts.map +1 -0
- package/dist/Carousel.js +264 -0
- package/dist/Checkbox.d.ts +168 -0
- package/dist/Checkbox.d.ts.map +1 -0
- package/dist/Checkbox.js +146 -0
- package/dist/Collection.d.ts +254 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Collection.js +218 -0
- package/dist/Combobox.d.ts +367 -0
- package/dist/Combobox.d.ts.map +1 -0
- package/dist/Combobox.js +300 -0
- package/dist/Composite.d.ts +823 -0
- package/dist/Composite.d.ts.map +1 -0
- package/dist/Composite.js +615 -0
- package/dist/Dialog.d.ts +544 -0
- package/dist/Dialog.d.ts.map +1 -0
- package/dist/Dialog.js +357 -0
- package/dist/Disclosure.d.ts +219 -0
- package/dist/Disclosure.d.ts.map +1 -0
- package/dist/Disclosure.js +128 -0
- package/dist/Dom/Events.d.ts +122 -0
- package/dist/Dom/Events.d.ts.map +1 -0
- package/dist/Dom/Events.js +192 -0
- package/dist/Dom/Props.d.ts +161 -0
- package/dist/Dom/Props.d.ts.map +1 -0
- package/dist/Dom/Props.js +110 -0
- package/dist/Dom/Refs.d.ts +58 -0
- package/dist/Dom/Refs.d.ts.map +1 -0
- package/dist/Dom/Refs.js +61 -0
- package/dist/Dom/Render.d.ts +59 -0
- package/dist/Dom/Render.d.ts.map +1 -0
- package/dist/Dom/Render.js +71 -0
- package/dist/Dom/Types.d.ts +570 -0
- package/dist/Dom/Types.d.ts.map +1 -0
- package/dist/Dom/Types.js +1 -0
- package/dist/Dom/index.d.ts +20 -0
- package/dist/Dom/index.d.ts.map +1 -0
- package/dist/Dom/index.js +8 -0
- package/dist/Dom.d.ts +14 -0
- package/dist/Dom.d.ts.map +1 -0
- package/dist/Dom.js +13 -0
- package/dist/Focusable.d.ts +85 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Focusable.js +35 -0
- package/dist/Form.d.ts +1727 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/Form.js +1142 -0
- package/dist/Grid.d.ts +388 -0
- package/dist/Grid.d.ts.map +1 -0
- package/dist/Grid.js +284 -0
- package/dist/Group.d.ts +128 -0
- package/dist/Group.d.ts.map +1 -0
- package/dist/Group.js +71 -0
- package/dist/Heading.d.ts +87 -0
- package/dist/Heading.d.ts.map +1 -0
- package/dist/Heading.js +58 -0
- package/dist/Hovercard.d.ts +297 -0
- package/dist/Hovercard.d.ts.map +1 -0
- package/dist/Hovercard.js +188 -0
- package/dist/HttpRouter.d.ts +129 -6
- package/dist/HttpRouter.d.ts.map +1 -1
- package/dist/HttpRouter.js +198 -55
- package/dist/Link.d.ts +63 -28
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +84 -37
- package/dist/Listbox.d.ts +305 -0
- package/dist/Listbox.d.ts.map +1 -0
- package/dist/Listbox.js +245 -0
- package/dist/Menu.d.ts +663 -0
- package/dist/Menu.d.ts.map +1 -0
- package/dist/Menu.js +569 -0
- package/dist/Menubar.d.ts +249 -0
- package/dist/Menubar.d.ts.map +1 -0
- package/dist/Menubar.js +207 -0
- package/dist/Meter.d.ts +157 -0
- package/dist/Meter.d.ts.map +1 -0
- package/dist/Meter.js +87 -0
- package/dist/NativeDetails.d.ts +41 -0
- package/dist/NativeDetails.d.ts.map +1 -0
- package/dist/NativeDetails.js +40 -0
- package/dist/NativeDialog.d.ts +66 -0
- package/dist/NativeDialog.d.ts.map +1 -0
- package/dist/NativeDialog.js +88 -0
- package/dist/NativePopover.d.ts +43 -0
- package/dist/NativePopover.d.ts.map +1 -0
- package/dist/NativePopover.js +84 -0
- package/dist/Popover.d.ts +240 -0
- package/dist/Popover.d.ts.map +1 -0
- package/dist/Popover.js +140 -0
- package/dist/RadioGroup.d.ts +330 -0
- package/dist/RadioGroup.d.ts.map +1 -0
- package/dist/RadioGroup.js +241 -0
- package/dist/Role.d.ts +64 -0
- package/dist/Role.d.ts.map +1 -0
- package/dist/Role.js +27 -0
- package/dist/Select.d.ts +418 -0
- package/dist/Select.d.ts.map +1 -0
- package/dist/Select.js +357 -0
- package/dist/Separator.d.ts +58 -0
- package/dist/Separator.d.ts.map +1 -0
- package/dist/Separator.js +32 -0
- package/dist/Slider.d.ts +141 -0
- package/dist/Slider.d.ts.map +1 -0
- package/dist/Slider.js +101 -0
- package/dist/SpinButton.d.ts +141 -0
- package/dist/SpinButton.d.ts.map +1 -0
- package/dist/SpinButton.js +101 -0
- package/dist/Storybook.d.ts +76 -0
- package/dist/Storybook.d.ts.map +1 -0
- package/dist/Storybook.js +102 -0
- package/dist/Switch.d.ts +148 -0
- package/dist/Switch.d.ts.map +1 -0
- package/dist/Switch.js +110 -0
- package/dist/Tab.d.ts +26 -0
- package/dist/Tab.d.ts.map +1 -0
- package/dist/Tab.js +25 -0
- package/dist/Tabs.d.ts +411 -0
- package/dist/Tabs.d.ts.map +1 -0
- package/dist/Tabs.js +262 -0
- package/dist/Toolbar.d.ts +248 -0
- package/dist/Toolbar.d.ts.map +1 -0
- package/dist/Toolbar.js +187 -0
- package/dist/Tooltip.d.ts +296 -0
- package/dist/Tooltip.d.ts.map +1 -0
- package/dist/Tooltip.js +172 -0
- package/dist/Tree.d.ts +405 -0
- package/dist/Tree.d.ts.map +1 -0
- package/dist/Tree.js +333 -0
- package/dist/TreeGrid.d.ts +426 -0
- package/dist/TreeGrid.d.ts.map +1 -0
- package/dist/TreeGrid.js +308 -0
- package/dist/VisuallyHidden.d.ts +68 -0
- package/dist/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden.js +44 -0
- package/dist/WindowSplitter.d.ts +336 -0
- package/dist/WindowSplitter.d.ts.map +1 -0
- package/dist/WindowSplitter.js +305 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -0
- package/package.json +48 -20
- package/src/HttpRouter.test.ts +0 -294
- package/src/HttpRouter.ts +0 -168
- package/src/Link.test.ts +0 -84
- package/src/Link.ts +0 -107
- package/src/index.ts +0 -2
package/dist/Form.d.ts
ADDED
|
@@ -0,0 +1,1727 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-bound native controls, decoded values, field errors, and submit lifetime.
|
|
3
|
+
* Start with make for application forms; explicit-state controls support library boundaries.
|
|
4
|
+
* Browser FormData conversion and structured input codecs are separate APIs.
|
|
5
|
+
*
|
|
6
|
+
* Read the [Form guide](/explore/ui-form) for a complete example.
|
|
7
|
+
*
|
|
8
|
+
* [Platform reference](https://html.spec.whatwg.org/multipage/forms.html#the-form-element).
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
* @category Overview
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
import * as Effect from "effect/Effect";
|
|
14
|
+
import * as Context from "effect/Context";
|
|
15
|
+
import * as Schema from "effect/Schema";
|
|
16
|
+
import { RefSubject } from "@typed/fx";
|
|
17
|
+
import * as Scope from "effect/Scope";
|
|
18
|
+
import type { Fx } from "@typed/fx/Fx";
|
|
19
|
+
import { EventHandler, type Renderable, type RenderEvent, type RenderTemplate } from "@typed/template";
|
|
20
|
+
import * as Dom from "./Dom.js";
|
|
21
|
+
import type { HostResult } from "./Dom/Types.js";
|
|
22
|
+
/**
|
|
23
|
+
* Metadata updated after a successful field mutation.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* dirty compares the new field value with defaultValues using !==, so object and array
|
|
27
|
+
* comparisons are by identity. touched becomes true for both user and programmatic updates; it
|
|
28
|
+
* is not specifically a blur flag.
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
* @category State models
|
|
31
|
+
*/
|
|
32
|
+
export interface FieldMeta {
|
|
33
|
+
/**
|
|
34
|
+
* Whether the updated value differs from its default under !== comparison.
|
|
35
|
+
*/
|
|
36
|
+
readonly dirty: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether user or programmatic field mutation has occurred.
|
|
39
|
+
*/
|
|
40
|
+
readonly touched: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Serializable renderer-independent state of a form.
|
|
44
|
+
*
|
|
45
|
+
* @remarks
|
|
46
|
+
* Values, defaults, validation messages, interaction metadata, and submission
|
|
47
|
+
* state can be inspected and tested without rendering a component.
|
|
48
|
+
*
|
|
49
|
+
* A `FormState` RefSubject owns this value. Renderers subscribe to it; they do
|
|
50
|
+
* not contain or become the source of truth.
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
* @category State models
|
|
53
|
+
*/
|
|
54
|
+
export interface State<Values extends object = object> {
|
|
55
|
+
/**
|
|
56
|
+
* Current decoded field values.
|
|
57
|
+
*/
|
|
58
|
+
readonly values: Values;
|
|
59
|
+
/**
|
|
60
|
+
* Exact baseline reference used by reset and retained independently from current values.
|
|
61
|
+
*/
|
|
62
|
+
readonly defaultValues: Values;
|
|
63
|
+
/**
|
|
64
|
+
* Current validation messages keyed by field name.
|
|
65
|
+
*/
|
|
66
|
+
readonly errors: Partial<Record<keyof Values & string, string>>;
|
|
67
|
+
/**
|
|
68
|
+
* Dirty/touched metadata keyed by field name.
|
|
69
|
+
*/
|
|
70
|
+
readonly meta: Partial<Record<keyof Values & string, FieldMeta>>;
|
|
71
|
+
/**
|
|
72
|
+
* Whether validation or the returned submit Effect is running.
|
|
73
|
+
*/
|
|
74
|
+
readonly submitting: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Input used to construct a hydrated form state.
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* Defaults make the common case concise while allowing SSR callers to provide
|
|
81
|
+
* deterministic identity and server-known validation state.
|
|
82
|
+
*
|
|
83
|
+
* `values` and an explicit `defaultValues` are retained by reference, including
|
|
84
|
+
* their nested objects. When `defaultValues` is omitted, both state fields
|
|
85
|
+
* initially reference the exact `values` object. Subsequent helpers replace the
|
|
86
|
+
* top-level `values` record but do not deep-clone nested values.
|
|
87
|
+
* @since 1.0.0
|
|
88
|
+
* @category State models
|
|
89
|
+
*/
|
|
90
|
+
export interface InitialState<Values extends object> {
|
|
91
|
+
/**
|
|
92
|
+
* Stable relationship/hydration id; provide it for deterministic SSR.
|
|
93
|
+
*/
|
|
94
|
+
readonly id?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Initial decoded values.
|
|
97
|
+
*/
|
|
98
|
+
readonly values: Values;
|
|
99
|
+
/**
|
|
100
|
+
* Exact reset-baseline reference; defaults to the same object as `values`.
|
|
101
|
+
*/
|
|
102
|
+
readonly defaultValues?: Values;
|
|
103
|
+
/**
|
|
104
|
+
* Optional initial validation messages.
|
|
105
|
+
*/
|
|
106
|
+
readonly errors?: Partial<Record<keyof Values & string, string>>;
|
|
107
|
+
/**
|
|
108
|
+
* Optional initial field metadata.
|
|
109
|
+
*/
|
|
110
|
+
readonly meta?: Partial<Record<keyof Values & string, FieldMeta>>;
|
|
111
|
+
/**
|
|
112
|
+
* Whether validation or the returned submit Effect is running.
|
|
113
|
+
*/
|
|
114
|
+
readonly submitting?: boolean;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Hydrated RefSubject carrying form state plus runtime schema metadata.
|
|
118
|
+
*
|
|
119
|
+
* @remarks
|
|
120
|
+
* State is serializable across SSR while codecs and field validators stay as
|
|
121
|
+
* runtime capabilities. This keeps validation type-safe without trying to
|
|
122
|
+
* serialize executable schemas.
|
|
123
|
+
*
|
|
124
|
+
* The surrounding Effect Scope owns the hydrated RefSubject and its subscribers.
|
|
125
|
+
* On the server, serializable state is emitted for hydration; on the client it
|
|
126
|
+
* must be restored before mounted controls begin producing updates.
|
|
127
|
+
* @since 1.0.0
|
|
128
|
+
* @category State models
|
|
129
|
+
*/
|
|
130
|
+
export type FormState<Values extends object> = RefSubject.HydratedRefSubject<State<Values>, Schema.SchemaError> & {
|
|
131
|
+
/**
|
|
132
|
+
* Runtime identity used to scope field/error relationships. Pass an id for deterministic SSR.
|
|
133
|
+
*/
|
|
134
|
+
readonly id: string;
|
|
135
|
+
/**
|
|
136
|
+
* Runtime-only validation codec; it is deliberately absent from hydration state.
|
|
137
|
+
*/
|
|
138
|
+
readonly codec: Schema.Codec<Values, unknown>;
|
|
139
|
+
/**
|
|
140
|
+
* Runtime field codecs used for field-level validation.
|
|
141
|
+
*/
|
|
142
|
+
readonly fields: Readonly<Record<keyof Values & string, Schema.Codec<any, any>>>;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Context service exposed to schema-bound descendant controls.
|
|
146
|
+
*
|
|
147
|
+
* @remarks
|
|
148
|
+
* A bound form can share its state through Effect context without a component tree.
|
|
149
|
+
*
|
|
150
|
+
* The root form provides the service only for its rendered Fx lifetime; it does
|
|
151
|
+
* not own the underlying state beyond that state's Scope.
|
|
152
|
+
* @since 1.0.0
|
|
153
|
+
* @category Form context
|
|
154
|
+
*/
|
|
155
|
+
export interface FormService<Values extends object> {
|
|
156
|
+
/**
|
|
157
|
+
* Form state visible to bound descendants.
|
|
158
|
+
*/
|
|
159
|
+
readonly state: FormState<Values>;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Effect context service used by schema-bound form controls.
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* Bound controls avoid threading `state` through every call while their
|
|
166
|
+
* service requirement remains visible in the Fx type.
|
|
167
|
+
*
|
|
168
|
+
* `Form` provides the service for its child render lifetime; use outside that
|
|
169
|
+
* boundary fails with the ordinary Effect missing-service defect.
|
|
170
|
+
* @since 1.0.0
|
|
171
|
+
* @category Form context
|
|
172
|
+
*/
|
|
173
|
+
export declare const CurrentForm: Context.Service<FormService<any>, FormService<any>>;
|
|
174
|
+
declare const FieldMetaSchema: Schema.Struct<{
|
|
175
|
+
readonly dirty: Schema.Boolean;
|
|
176
|
+
readonly touched: Schema.Boolean;
|
|
177
|
+
}>;
|
|
178
|
+
/**
|
|
179
|
+
* Schema field map accepted by the schema-bound form factory.
|
|
180
|
+
*
|
|
181
|
+
* @remarks
|
|
182
|
+
* A Struct's individual codecs drive field-name inference and field-level decoding.
|
|
183
|
+
*
|
|
184
|
+
* Codecs are runtime values retained by the created form API; they are not hydrated.
|
|
185
|
+
* @since 1.0.0
|
|
186
|
+
* @category State models
|
|
187
|
+
*/
|
|
188
|
+
export type FormFields = Readonly<Record<string, Schema.Codec<any, any>>>;
|
|
189
|
+
type OptionalFields<Fields extends FormFields, Value extends Schema.Constraint> = {
|
|
190
|
+
readonly [Key in keyof Fields]: Schema.optionalKey<Value>;
|
|
191
|
+
};
|
|
192
|
+
type InitialStateFor<Fields extends FormFields> = {
|
|
193
|
+
readonly id?: string;
|
|
194
|
+
readonly values: Schema.Struct.Type<Fields>;
|
|
195
|
+
readonly defaultValues?: Schema.Struct.Type<Fields>;
|
|
196
|
+
readonly errors?: Schema.Struct.Type<OptionalFields<Fields, typeof Schema.String>>;
|
|
197
|
+
readonly meta?: Schema.Struct.Type<OptionalFields<Fields, typeof FieldMetaSchema>>;
|
|
198
|
+
readonly submitting?: boolean;
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Builds the serializable schema for a form's hydrated state.
|
|
202
|
+
*
|
|
203
|
+
* @remarks
|
|
204
|
+
* The hydration payload needs validation independent from runtime-only field codecs.
|
|
205
|
+
*
|
|
206
|
+
* Pure schema construction; the returned Schema acquires no Scope or subscription.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* import { StateSchema } from "@typed/ui/Form"
|
|
211
|
+
* import { Schema } from "effect"
|
|
212
|
+
*
|
|
213
|
+
* const codec = Schema.Struct({ email: Schema.String })
|
|
214
|
+
* const stateCodec = StateSchema(codec)
|
|
215
|
+
* ```
|
|
216
|
+
* @since 1.0.0
|
|
217
|
+
* @category Hydration schemas
|
|
218
|
+
*/
|
|
219
|
+
export declare function StateSchema<const Fields extends FormFields>(codec: Schema.Struct<Fields>): Schema.Struct<{
|
|
220
|
+
readonly values: Schema.Struct<Fields>;
|
|
221
|
+
readonly defaultValues: Schema.Struct<Fields>;
|
|
222
|
+
readonly errors: Schema.Struct<OptionalFields<Fields, Schema.String>>;
|
|
223
|
+
readonly meta: Schema.Struct<OptionalFields<Fields, Schema.Struct<{
|
|
224
|
+
readonly dirty: Schema.Boolean;
|
|
225
|
+
readonly touched: Schema.Boolean;
|
|
226
|
+
}>>>;
|
|
227
|
+
readonly submitting: Schema.Boolean;
|
|
228
|
+
}>;
|
|
229
|
+
/**
|
|
230
|
+
* Creates a Scope-owned hydrated form RefSubject from a Struct codec.
|
|
231
|
+
*
|
|
232
|
+
* @remarks
|
|
233
|
+
* One constructor establishes values, defaults, validation state, field codecs,
|
|
234
|
+
* and hydration identity consistently.
|
|
235
|
+
*
|
|
236
|
+
* Requires `Scope.Scope`. Provide an explicit `id` during SSR; the counter-based
|
|
237
|
+
* fallback is process/order dependent. Only state data hydrates—`codec` and
|
|
238
|
+
* `fields` are reattached from the live Struct on each runtime.
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```ts
|
|
242
|
+
* import { makeState } from "@typed/ui/Form"
|
|
243
|
+
* import { Effect, Schema } from "effect"
|
|
244
|
+
*
|
|
245
|
+
* const codec = Schema.Struct({ email: Schema.String })
|
|
246
|
+
* const program = Effect.gen(function* () {
|
|
247
|
+
* const state = yield* makeState(codec, { id: "signup", values: { email: "" } })
|
|
248
|
+
* return state
|
|
249
|
+
* })
|
|
250
|
+
* ```
|
|
251
|
+
* @since 1.0.0
|
|
252
|
+
* @category State construction
|
|
253
|
+
*/
|
|
254
|
+
export declare function makeState<const Fields extends FormFields>(codec: Schema.Struct<Fields>, initial: InitialStateFor<Fields>): Effect.Effect<RefSubject.HydratedRefSubject<{
|
|
255
|
+
readonly values: Schema.Struct.View<Fields, "Type", Schema.Struct.TypeOptionalKeys<Fields>, Schema.Struct.TypeMutableKeys<Fields>>;
|
|
256
|
+
readonly defaultValues: Schema.Struct.View<Fields, "Type", Schema.Struct.TypeOptionalKeys<Fields>, Schema.Struct.TypeMutableKeys<Fields>>;
|
|
257
|
+
readonly errors: Schema.Struct.View<OptionalFields<Fields, Schema.String>, "Type", Schema.Struct.TypeOptionalKeys<OptionalFields<Fields, Schema.String>>, Schema.Struct.TypeMutableKeys<OptionalFields<Fields, Schema.String>>>;
|
|
258
|
+
readonly meta: Schema.Struct.View<OptionalFields<Fields, Schema.Struct<{
|
|
259
|
+
readonly dirty: Schema.Boolean;
|
|
260
|
+
readonly touched: Schema.Boolean;
|
|
261
|
+
}>>, "Type", Schema.Struct.TypeOptionalKeys<OptionalFields<Fields, Schema.Struct<{
|
|
262
|
+
readonly dirty: Schema.Boolean;
|
|
263
|
+
readonly touched: Schema.Boolean;
|
|
264
|
+
}>>>, Schema.Struct.TypeMutableKeys<OptionalFields<Fields, Schema.Struct<{
|
|
265
|
+
readonly dirty: Schema.Boolean;
|
|
266
|
+
readonly touched: Schema.Boolean;
|
|
267
|
+
}>>>>;
|
|
268
|
+
readonly submitting: boolean;
|
|
269
|
+
}, Schema.SchemaError, never, Schema.Struct.DecodingServices<{
|
|
270
|
+
readonly values: Schema.Struct<Fields>;
|
|
271
|
+
readonly defaultValues: Schema.Struct<Fields>;
|
|
272
|
+
readonly errors: Schema.Struct<OptionalFields<Fields, Schema.String>>;
|
|
273
|
+
readonly meta: Schema.Struct<OptionalFields<Fields, Schema.Struct<{
|
|
274
|
+
readonly dirty: Schema.Boolean;
|
|
275
|
+
readonly touched: Schema.Boolean;
|
|
276
|
+
}>>>;
|
|
277
|
+
readonly submitting: Schema.Boolean;
|
|
278
|
+
}> | Schema.Struct.EncodingServices<{
|
|
279
|
+
readonly values: Schema.Struct<Fields>;
|
|
280
|
+
readonly defaultValues: Schema.Struct<Fields>;
|
|
281
|
+
readonly errors: Schema.Struct<OptionalFields<Fields, Schema.String>>;
|
|
282
|
+
readonly meta: Schema.Struct<OptionalFields<Fields, Schema.Struct<{
|
|
283
|
+
readonly dirty: Schema.Boolean;
|
|
284
|
+
readonly touched: Schema.Boolean;
|
|
285
|
+
}>>>;
|
|
286
|
+
readonly submitting: Schema.Boolean;
|
|
287
|
+
}>> & {
|
|
288
|
+
codec: Schema.Struct<Fields>;
|
|
289
|
+
fields: Fields;
|
|
290
|
+
id: string;
|
|
291
|
+
}, never, Scope.Scope>;
|
|
292
|
+
/**
|
|
293
|
+
* Field names whose decoded value is assignable to `Value`.
|
|
294
|
+
*
|
|
295
|
+
* @remarks
|
|
296
|
+
* Control options reject incompatible fields at compile time.
|
|
297
|
+
* @since 1.0.0
|
|
298
|
+
* @category Field types
|
|
299
|
+
*/
|
|
300
|
+
export type FieldNameFor<Values extends object, Value> = {
|
|
301
|
+
[Key in keyof Values & string]: Values[Key] extends Value ? Key : never;
|
|
302
|
+
}[keyof Values & string];
|
|
303
|
+
/**
|
|
304
|
+
* Struct field names matching both decoded and encoded control value types.
|
|
305
|
+
*
|
|
306
|
+
* @remarks
|
|
307
|
+
* Schema-bound controls require an encoded form compatible with the native element.
|
|
308
|
+
* @since 1.0.0
|
|
309
|
+
* @category Field types
|
|
310
|
+
*/
|
|
311
|
+
export type SchemaFieldNameFor<Fields extends FormFields, Value, Encoded> = {
|
|
312
|
+
[Key in keyof Fields & string]: Fields[Key]["Type"] extends Value ? Fields[Key]["Encoded"] extends Encoded ? Key : never : never;
|
|
313
|
+
}[keyof Fields & string];
|
|
314
|
+
/**
|
|
315
|
+
* State-explicit native input binding with a compatible field name and optional string codec.
|
|
316
|
+
*
|
|
317
|
+
* @remarks
|
|
318
|
+
* Successful native input decoding updates values and metadata; failure records an error while
|
|
319
|
+
* retaining the last decoded value. Rendering encodes the retained value into .value, so
|
|
320
|
+
* arbitrary invalid draft text is not guaranteed to remain visible. Native constraints and codec
|
|
321
|
+
* validation are separate boundaries.
|
|
322
|
+
* @since 1.0.0
|
|
323
|
+
* @category Component options
|
|
324
|
+
*/
|
|
325
|
+
export interface InputOptions<Values extends object, Value> extends Dom.HostOptions<HTMLInputElement> {
|
|
326
|
+
/**
|
|
327
|
+
* Renderer-independent form state to read and update.
|
|
328
|
+
*/
|
|
329
|
+
readonly state: FormState<Values>;
|
|
330
|
+
/**
|
|
331
|
+
* Type-compatible field name.
|
|
332
|
+
*/
|
|
333
|
+
readonly name: FieldNameFor<Values, Value>;
|
|
334
|
+
/**
|
|
335
|
+
* Optional string codec overriding the input type's default codec.
|
|
336
|
+
*/
|
|
337
|
+
readonly codec?: Schema.Codec<Value, string>;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* String-valued native input options.
|
|
341
|
+
* @remarks
|
|
342
|
+
* Names are restricted to fields a text-like control can represent without an incompatible cast.
|
|
343
|
+
* The control Scope owns DOM work; the referenced state and optional codec are borrowed.
|
|
344
|
+
* @since 1.0.0
|
|
345
|
+
* @category Component options
|
|
346
|
+
*/
|
|
347
|
+
export type TextInputOptions<Values extends object> = InputOptions<Values, string>;
|
|
348
|
+
/**
|
|
349
|
+
* Finite-number native input options.
|
|
350
|
+
* @remarks
|
|
351
|
+
* Names are restricted to numeric fields compatible with number/range decoding.
|
|
352
|
+
* The control Scope owns DOM work; the referenced state and optional codec are borrowed.
|
|
353
|
+
* @since 1.0.0
|
|
354
|
+
* @category Component options
|
|
355
|
+
*/
|
|
356
|
+
export type NumberInputOptions<Values extends object> = InputOptions<Values, number>;
|
|
357
|
+
/**
|
|
358
|
+
* Date-valued native input options.
|
|
359
|
+
* @remarks
|
|
360
|
+
* Names are restricted to Date fields compatible with native date-string decoding.
|
|
361
|
+
* The control Scope owns DOM work; the referenced state and optional codec are borrowed.
|
|
362
|
+
* @since 1.0.0
|
|
363
|
+
* @category Component options
|
|
364
|
+
*/
|
|
365
|
+
export type DateInputOptions<Values extends object> = InputOptions<Values, Date>;
|
|
366
|
+
declare function inputProps<Values extends object, Value>(options: InputOptions<Values, Value>, type: string, codec: Schema.Codec<Value, string>): (() => {
|
|
367
|
+
readonly type: string;
|
|
368
|
+
readonly name: FieldNameFor<Values, Value>;
|
|
369
|
+
readonly "aria-describedby": RefSubject.Computed<string | undefined, Schema.SchemaError, never>;
|
|
370
|
+
readonly "aria-invalid": RefSubject.Computed<true | undefined, Schema.SchemaError, never>;
|
|
371
|
+
readonly ".value": RefSubject.Computed<string, Schema.SchemaError, never>;
|
|
372
|
+
readonly oninput: EventHandler.EventHandler<Event, Schema.SchemaError, never>;
|
|
373
|
+
}) | (() => {
|
|
374
|
+
readonly type: string;
|
|
375
|
+
readonly name: FieldNameFor<Values, Value>;
|
|
376
|
+
readonly "aria-describedby": RefSubject.Computed<string | undefined, Schema.SchemaError, never>;
|
|
377
|
+
readonly "aria-invalid": RefSubject.Computed<true | undefined, Schema.SchemaError, never>;
|
|
378
|
+
readonly ".value": Effect.Effect<string, Schema.SchemaError, never>;
|
|
379
|
+
readonly ref: (element: HTMLInputElement) => Effect.Effect<void, Schema.SchemaError, Scope.Scope>;
|
|
380
|
+
readonly onbeforeinput: EventHandler.EventHandler<InputEvent, Schema.SchemaError, never>;
|
|
381
|
+
readonly oninput: EventHandler.EventHandler<InputEvent, Schema.SchemaError, never>;
|
|
382
|
+
readonly oncompositionstart: EventHandler.EventHandler<Event, never, never>;
|
|
383
|
+
readonly oncompositionend: EventHandler.EventHandler<CompositionEvent, Schema.SchemaError, never>;
|
|
384
|
+
});
|
|
385
|
+
type InputProps<Values extends object, Value> = ReturnType<ReturnType<typeof inputProps<Values, Value>>>;
|
|
386
|
+
type RenderableComponentOptions<Options> = Pick<Options, Extract<keyof Options, "props" | "ref" | "content" | Dom.EventHandlerProperty>>;
|
|
387
|
+
/**
|
|
388
|
+
* Options for a schema-bound native input.
|
|
389
|
+
*
|
|
390
|
+
* @remarks
|
|
391
|
+
* The factory's Struct infers compatible field names, so callers need not pass state or a codec.
|
|
392
|
+
*
|
|
393
|
+
* State is borrowed from `CurrentForm`; the control's Scope owns its DOM subscription.
|
|
394
|
+
* @since 1.0.0
|
|
395
|
+
* @category Component options
|
|
396
|
+
*/
|
|
397
|
+
export interface SchemaBoundInputOptions<Fields extends FormFields, Value> extends Dom.HostOptions<HTMLInputElement> {
|
|
398
|
+
/**
|
|
399
|
+
* Struct field whose decoded type matches `Value` and whose encoded type is string.
|
|
400
|
+
*/
|
|
401
|
+
readonly name: SchemaFieldNameFor<Fields, Value, string>;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Options for a schema-bound masked text input.
|
|
405
|
+
*
|
|
406
|
+
* @remarks
|
|
407
|
+
* Any field with a string encoding can use the Struct field codec as its mask codec.
|
|
408
|
+
*
|
|
409
|
+
* State is borrowed from `CurrentForm`; the control Scope owns DOM work.
|
|
410
|
+
* @since 1.0.0
|
|
411
|
+
* @category Component options
|
|
412
|
+
*/
|
|
413
|
+
export interface SchemaBoundMaskedInputOptions<Fields extends FormFields> extends Dom.HostOptions<HTMLInputElement> {
|
|
414
|
+
/**
|
|
415
|
+
* Struct field whose codec accepts the input's string representation.
|
|
416
|
+
*/
|
|
417
|
+
readonly name: SchemaFieldNameFor<Fields, unknown, string>;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Options for a schema-bound boolean checkbox.
|
|
421
|
+
*
|
|
422
|
+
* @remarks
|
|
423
|
+
* Field-name inference limits the native checked binding to boolean fields.
|
|
424
|
+
*
|
|
425
|
+
* State is borrowed from `CurrentForm`; the control Scope owns DOM work.
|
|
426
|
+
* @since 1.0.0
|
|
427
|
+
* @category Component options
|
|
428
|
+
*/
|
|
429
|
+
export interface SchemaBoundCheckboxOptions<Values extends object> extends Dom.HostOptions<HTMLInputElement> {
|
|
430
|
+
/**
|
|
431
|
+
* Boolean field controlled by the checkbox.
|
|
432
|
+
*/
|
|
433
|
+
readonly name: BooleanFieldName<Values>;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Options for a schema-bound native select.
|
|
437
|
+
*
|
|
438
|
+
* @remarks
|
|
439
|
+
* Native option markup remains caller-authored while selection binds to a string field.
|
|
440
|
+
*
|
|
441
|
+
* State is borrowed from `CurrentForm`; rendered content is owned by the control Scope.
|
|
442
|
+
* @since 1.0.0
|
|
443
|
+
* @category Component options
|
|
444
|
+
*/
|
|
445
|
+
export interface SchemaBoundSelectOptions<Values extends object> extends Dom.HostOptions<HTMLSelectElement> {
|
|
446
|
+
/**
|
|
447
|
+
* String field controlled by the select.
|
|
448
|
+
*/
|
|
449
|
+
readonly name: FieldNameFor<Values, string>;
|
|
450
|
+
/**
|
|
451
|
+
* Native option/optgroup renderable content.
|
|
452
|
+
*/
|
|
453
|
+
readonly content: Renderable.Any;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Options for a schema-bound field-error region.
|
|
457
|
+
*
|
|
458
|
+
* @remarks
|
|
459
|
+
* Error text and ARIA relationships derive from the same form identity and field name.
|
|
460
|
+
*
|
|
461
|
+
* State is borrowed from `CurrentForm`; the error host Scope owns its subscription.
|
|
462
|
+
* @since 1.0.0
|
|
463
|
+
* @category Component options
|
|
464
|
+
*/
|
|
465
|
+
export interface SchemaBoundErrorOptions<Values extends object> extends Dom.HostOptions<HTMLDivElement> {
|
|
466
|
+
/**
|
|
467
|
+
* Field whose current validation message is rendered.
|
|
468
|
+
*/
|
|
469
|
+
readonly name: keyof Values & string;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Options for a schema-bound reset button.
|
|
473
|
+
*
|
|
474
|
+
* @remarks
|
|
475
|
+
* The button can use native semantics without receiving state explicitly.
|
|
476
|
+
*
|
|
477
|
+
* State is borrowed from `CurrentForm`; button content is Scope-owned renderable work.
|
|
478
|
+
* @since 1.0.0
|
|
479
|
+
* @category Component options
|
|
480
|
+
*/
|
|
481
|
+
export interface SchemaBoundResetOptions extends Dom.HostOptions<HTMLButtonElement> {
|
|
482
|
+
/**
|
|
483
|
+
* Reset button label/content.
|
|
484
|
+
*/
|
|
485
|
+
readonly content: Renderable.Any;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Options for a schema-bound array append button.
|
|
489
|
+
*
|
|
490
|
+
* @remarks
|
|
491
|
+
* Array field and element types are inferred from the form schema.
|
|
492
|
+
*
|
|
493
|
+
* State is borrowed from `CurrentForm`; the click Effect and content share the host Scope.
|
|
494
|
+
* @since 1.0.0
|
|
495
|
+
* @category Component options
|
|
496
|
+
*/
|
|
497
|
+
export interface SchemaBoundPushOptions<Values extends object, Name extends ArrayFieldName<Values>> extends Dom.HostOptions<HTMLButtonElement> {
|
|
498
|
+
/**
|
|
499
|
+
* Array-valued field to append to.
|
|
500
|
+
*/
|
|
501
|
+
readonly name: Name;
|
|
502
|
+
/**
|
|
503
|
+
* Type-compatible item appended on activation.
|
|
504
|
+
*/
|
|
505
|
+
readonly value: ArrayFieldValue<Values, Name>;
|
|
506
|
+
/**
|
|
507
|
+
* Button label/content.
|
|
508
|
+
*/
|
|
509
|
+
readonly content: Renderable.Any;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Options for a schema-bound array removal button.
|
|
513
|
+
*
|
|
514
|
+
* @remarks
|
|
515
|
+
* The field is constrained to arrays and the index remains an explicit local operation.
|
|
516
|
+
*
|
|
517
|
+
* State is borrowed from `CurrentForm`; the click Effect and content share the host Scope.
|
|
518
|
+
* @since 1.0.0
|
|
519
|
+
* @category Component options
|
|
520
|
+
*/
|
|
521
|
+
export interface SchemaBoundRemoveOptions<Values extends object, Name extends ArrayFieldName<Values>> extends Dom.HostOptions<HTMLButtonElement> {
|
|
522
|
+
/**
|
|
523
|
+
* Array-valued field to remove from.
|
|
524
|
+
*/
|
|
525
|
+
readonly name: Name;
|
|
526
|
+
/**
|
|
527
|
+
* Zero-based item index removed on activation.
|
|
528
|
+
*/
|
|
529
|
+
readonly index: number;
|
|
530
|
+
/**
|
|
531
|
+
* Button label/content.
|
|
532
|
+
*/
|
|
533
|
+
readonly content: Renderable.Any;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Public component contract shared by state-explicit native input factories.
|
|
537
|
+
*
|
|
538
|
+
* @remarks
|
|
539
|
+
* Text-like, numeric, range, and date controls differ in their default codec while preserving one
|
|
540
|
+
* field-inference, host-override, error, and service contract. Naming that contract keeps emitted
|
|
541
|
+
* declarations readable without hiding any generic channel behind a private compiler alias.
|
|
542
|
+
*
|
|
543
|
+
* Calling an input component starts no work. The returned Fx requires the Scope and RenderTemplate
|
|
544
|
+
* that own DOM rendering; the supplied FormState remains independently owned and may outlive it.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* import { InputComponent, makeState, TextInput } from "@typed/ui/Form"
|
|
549
|
+
* import { html } from "@typed/template"
|
|
550
|
+
* import { Effect, Schema } from "effect"
|
|
551
|
+
*
|
|
552
|
+
* const Text: InputComponent<string> = TextInput
|
|
553
|
+
* const rendered = Effect.gen(function* () {
|
|
554
|
+
* const state = yield* makeState(Schema.Struct({ name: Schema.String }), {
|
|
555
|
+
* values: { name: "" }
|
|
556
|
+
* })
|
|
557
|
+
* return Text({ state, name: "name" }, (props) => html`<input ...${props} />`)
|
|
558
|
+
* })
|
|
559
|
+
* ```
|
|
560
|
+
* @since 1.0.0
|
|
561
|
+
* @category Native controls
|
|
562
|
+
*/
|
|
563
|
+
export type InputComponent<Value> = <const Values extends object, const Options extends InputOptions<Values, Value>, const Host extends HostResult = never>(options: Options & Pick<InputOptions<Values, Value>, "state" | "name">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, InputProps<Values, Value>>, "", Host>) => Fx<RenderEvent, Schema.SchemaError | Renderable.Error<RenderableComponentOptions<Options> | Host>, Renderable.Services<RenderableComponentOptions<Options> | Host> | Scope.Scope | RenderTemplate>;
|
|
564
|
+
/**
|
|
565
|
+
* Binds a native `input[type=text]` to a string field.
|
|
566
|
+
*
|
|
567
|
+
* @remarks
|
|
568
|
+
* The control uses the browser's real input event and a Schema codec while
|
|
569
|
+
* keeping state independently testable.
|
|
570
|
+
*
|
|
571
|
+
* The control Scope owns DOM listeners/subscriptions; the supplied `FormState`
|
|
572
|
+
* may outlive the rendered input. A custom host must apply all merged props.
|
|
573
|
+
*
|
|
574
|
+
* @example
|
|
575
|
+
* ```ts
|
|
576
|
+
* import { TextInput, makeState } from "@typed/ui/Form"
|
|
577
|
+
* import { Effect, Schema } from "effect"
|
|
578
|
+
*
|
|
579
|
+
* const codec = Schema.Struct({ name: Schema.String })
|
|
580
|
+
* const input = Effect.gen(function* () {
|
|
581
|
+
* const state = yield* makeState(codec, { values: { name: "" } })
|
|
582
|
+
* return TextInput({ state, name: "name" })
|
|
583
|
+
* })
|
|
584
|
+
* ```
|
|
585
|
+
* @since 1.0.0
|
|
586
|
+
* @category Native controls
|
|
587
|
+
*/
|
|
588
|
+
export declare const TextInput: InputComponent<string>;
|
|
589
|
+
/**
|
|
590
|
+
* Binds a native search input to a string field.
|
|
591
|
+
* @remarks
|
|
592
|
+
* Preserves the platform's search-input semantics while sharing Typed validation.
|
|
593
|
+
* @since 1.0.0
|
|
594
|
+
* @category Native controls
|
|
595
|
+
*/
|
|
596
|
+
export declare const SearchInput: InputComponent<string>;
|
|
597
|
+
/**
|
|
598
|
+
* Binds a native email input to a string field.
|
|
599
|
+
* @remarks
|
|
600
|
+
* Keeps browser email affordances and constraints available alongside Schema validation.
|
|
601
|
+
* @since 1.0.0
|
|
602
|
+
* @category Native controls
|
|
603
|
+
*/
|
|
604
|
+
export declare const EmailInput: InputComponent<string>;
|
|
605
|
+
/**
|
|
606
|
+
* Binds a native URL input to a string field.
|
|
607
|
+
* @remarks
|
|
608
|
+
* Keeps browser URL affordances while the schema remains the decoded state contract.
|
|
609
|
+
* @since 1.0.0
|
|
610
|
+
* @category Native controls
|
|
611
|
+
*/
|
|
612
|
+
export declare const UrlInput: InputComponent<string>;
|
|
613
|
+
/**
|
|
614
|
+
* Binds a native telephone input to a string field.
|
|
615
|
+
* @remarks
|
|
616
|
+
* Preserves platform telephone keyboards and autocomplete behavior.
|
|
617
|
+
* @since 1.0.0
|
|
618
|
+
* @category Native controls
|
|
619
|
+
*/
|
|
620
|
+
export declare const TelInput: InputComponent<string>;
|
|
621
|
+
/**
|
|
622
|
+
* Binds a native password input to a string field.
|
|
623
|
+
* @remarks
|
|
624
|
+
* Uses browser password handling instead of recreating sensitive-input behavior.
|
|
625
|
+
* @since 1.0.0
|
|
626
|
+
* @category Native controls
|
|
627
|
+
*/
|
|
628
|
+
export declare const PasswordInput: InputComponent<string>;
|
|
629
|
+
/**
|
|
630
|
+
* Binds a native hidden input to a string field.
|
|
631
|
+
* @remarks
|
|
632
|
+
* Allows standards-based form serialization for non-visible values.
|
|
633
|
+
* @since 1.0.0
|
|
634
|
+
* @category Native controls
|
|
635
|
+
*/
|
|
636
|
+
export declare const HiddenInput: InputComponent<string>;
|
|
637
|
+
/**
|
|
638
|
+
* Binds a native color input to a string field.
|
|
639
|
+
* @remarks
|
|
640
|
+
* Retains the browser's color picker while state receives its string value.
|
|
641
|
+
* @since 1.0.0
|
|
642
|
+
* @category Native controls
|
|
643
|
+
*/
|
|
644
|
+
export declare const ColorInput: InputComponent<string>;
|
|
645
|
+
/**
|
|
646
|
+
* Binds a native time input to a string field.
|
|
647
|
+
* @remarks
|
|
648
|
+
* Preserves browser locale and time-entry behavior without inventing a picker.
|
|
649
|
+
* @since 1.0.0
|
|
650
|
+
* @category Native controls
|
|
651
|
+
*/
|
|
652
|
+
export declare const TimeInput: InputComponent<string>;
|
|
653
|
+
/**
|
|
654
|
+
* Binds a native local date-time input to a string field.
|
|
655
|
+
* @remarks
|
|
656
|
+
* Keeps the platform's local date-time UI and its standard encoded value.
|
|
657
|
+
* @since 1.0.0
|
|
658
|
+
* @category Native controls
|
|
659
|
+
*/
|
|
660
|
+
export declare const DateTimeLocalInput: InputComponent<string>;
|
|
661
|
+
/**
|
|
662
|
+
* Binds a native month input to a string field.
|
|
663
|
+
* @remarks
|
|
664
|
+
* Preserves the browser month picker and standardized string encoding.
|
|
665
|
+
* @since 1.0.0
|
|
666
|
+
* @category Native controls
|
|
667
|
+
*/
|
|
668
|
+
export declare const MonthInput: InputComponent<string>;
|
|
669
|
+
/**
|
|
670
|
+
* Binds a native week input to a string field.
|
|
671
|
+
* @remarks
|
|
672
|
+
* Preserves platform week-entry behavior and standardized string encoding.
|
|
673
|
+
* @since 1.0.0
|
|
674
|
+
* @category Native controls
|
|
675
|
+
*/
|
|
676
|
+
export declare const WeekInput: InputComponent<string>;
|
|
677
|
+
/**
|
|
678
|
+
* Binds a native number input to a finite number field.
|
|
679
|
+
* @remarks
|
|
680
|
+
* `FiniteFromString` makes the browser's string value an explicit typed decode.
|
|
681
|
+
* @since 1.0.0
|
|
682
|
+
* @category Native controls
|
|
683
|
+
*/
|
|
684
|
+
export declare const NumberInput: InputComponent<number>;
|
|
685
|
+
/**
|
|
686
|
+
* Binds a native range input to a finite number field.
|
|
687
|
+
* @remarks
|
|
688
|
+
* Retains native slider interaction while exposing a decoded numeric value.
|
|
689
|
+
* @since 1.0.0
|
|
690
|
+
* @category Native controls
|
|
691
|
+
*/
|
|
692
|
+
export declare const RangeInput: InputComponent<number>;
|
|
693
|
+
/**
|
|
694
|
+
* Binds a native date input to a `Date` field.
|
|
695
|
+
* @remarks
|
|
696
|
+
* `DateFromString` makes the native encoded value's conversion explicit and fallible.
|
|
697
|
+
* @since 1.0.0
|
|
698
|
+
* @category Native controls
|
|
699
|
+
*/
|
|
700
|
+
export declare const DateInput: InputComponent<Date>;
|
|
701
|
+
/**
|
|
702
|
+
* Native value emitted by `FormData`.
|
|
703
|
+
* @remarks
|
|
704
|
+
* Browser serialization produces strings and Files; the union states that boundary exactly.
|
|
705
|
+
* Files remain browser-owned objects referenced by the converted record.
|
|
706
|
+
* @since 1.0.0
|
|
707
|
+
* @category Browser form data
|
|
708
|
+
*/
|
|
709
|
+
export type FormDataValue = string | File;
|
|
710
|
+
/**
|
|
711
|
+
* Object representation of native FormData, preserving repeated names as arrays.
|
|
712
|
+
* @remarks
|
|
713
|
+
* A plain record is directly consumable by Effect Schema without losing repeats.
|
|
714
|
+
* Conversion allocates arrays/record entries but retains original File objects.
|
|
715
|
+
* @since 1.0.0
|
|
716
|
+
* @category Browser form data
|
|
717
|
+
*/
|
|
718
|
+
export type FormDataRecord = Readonly<Record<string, FormDataValue | ReadonlyArray<FormDataValue>>>;
|
|
719
|
+
/**
|
|
720
|
+
* Converts native form data to a record, preserving repeated names as arrays.
|
|
721
|
+
* @example
|
|
722
|
+
* ```ts
|
|
723
|
+
* import { formDataToRecord } from "@typed/ui/Form"
|
|
724
|
+
*
|
|
725
|
+
* const data = new FormData()
|
|
726
|
+
* data.append("tag", "one")
|
|
727
|
+
* data.append("tag", "two")
|
|
728
|
+
* const record = formDataToRecord(data)
|
|
729
|
+
* ```
|
|
730
|
+
* @since 1.0.0
|
|
731
|
+
* @category Browser form data
|
|
732
|
+
*/
|
|
733
|
+
export declare function formDataToRecord(data: FormData): FormDataRecord;
|
|
734
|
+
/**
|
|
735
|
+
* Decodes native FormData through an Effect Schema codec.
|
|
736
|
+
* @remarks
|
|
737
|
+
* Browser serialization, repeated values, Files, and typed validation meet at
|
|
738
|
+
* one explicit fallible boundary.
|
|
739
|
+
* The returned Effect is lazy and owns no browser resource; it references File
|
|
740
|
+
* objects present in the supplied FormData.
|
|
741
|
+
* @example
|
|
742
|
+
* ```ts
|
|
743
|
+
* import { decodeFormData } from "@typed/ui/Form"
|
|
744
|
+
* import { Schema } from "effect"
|
|
745
|
+
*
|
|
746
|
+
* const decode = decodeFormData(Schema.Struct({ name: Schema.String }), new FormData())
|
|
747
|
+
* ```
|
|
748
|
+
* @since 1.0.0
|
|
749
|
+
* @category Browser form data
|
|
750
|
+
*/
|
|
751
|
+
export declare function decodeFormData<Values extends object, Codec extends Schema.Codec<Values, unknown>>(codec: Codec, data: FormData): Effect.Effect<Codec["Type"], Schema.SchemaError, Codec["DecodingServices"]>;
|
|
752
|
+
/**
|
|
753
|
+
* Checks retained decoded values against the form codec Type.
|
|
754
|
+
*
|
|
755
|
+
* @remarks
|
|
756
|
+
* Success replaces values and clears errors. Failure copies the aggregate schema message across
|
|
757
|
+
* fields and re-fails with SchemaError; this is not per-field issue-path mapping. A prior input
|
|
758
|
+
* decode error does not independently block success when the retained decoded value still
|
|
759
|
+
* validates.
|
|
760
|
+
* @since 1.0.0
|
|
761
|
+
* @category Validation
|
|
762
|
+
*/
|
|
763
|
+
export declare function validate<Values extends object>(state: FormState<Values>): Effect.Effect<Values, Schema.SchemaError, never>;
|
|
764
|
+
/**
|
|
765
|
+
* Named decoded segment in a bidirectional text mask.
|
|
766
|
+
* @remarks
|
|
767
|
+
* The codec preserves the slot's domain type. Supply a fixed length and charset
|
|
768
|
+
* when the input should insert unambiguous surrounding literals while editing.
|
|
769
|
+
* Use string codecs for identifiers such as phone segments that may start with zero.
|
|
770
|
+
* @since 1.0.0
|
|
771
|
+
* @category Input codecs
|
|
772
|
+
*/
|
|
773
|
+
export interface MaskSlot<Name extends string = string, Value = unknown> {
|
|
774
|
+
/**
|
|
775
|
+
* Discriminant used to distinguish slots from literal mask parts.
|
|
776
|
+
*/
|
|
777
|
+
readonly _tag: "MaskSlot";
|
|
778
|
+
/**
|
|
779
|
+
* Property name written into the decoded mask object.
|
|
780
|
+
*/
|
|
781
|
+
readonly name: Name;
|
|
782
|
+
/**
|
|
783
|
+
* Bidirectional conversion between this slot's string segment and decoded value.
|
|
784
|
+
*/
|
|
785
|
+
readonly codec: Schema.Codec<Value, string>;
|
|
786
|
+
/**
|
|
787
|
+
* Exact encoded character count, when fixed-width.
|
|
788
|
+
*/
|
|
789
|
+
readonly length?: number;
|
|
790
|
+
/**
|
|
791
|
+
* Per-character acceptance test applied before Schema decoding.
|
|
792
|
+
*/
|
|
793
|
+
readonly charset?: RegExp | ((character: string) => boolean);
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Literal or decoded segment of a mask.
|
|
797
|
+
* @remarks
|
|
798
|
+
* The tuple order completely specifies parsing and formatting.
|
|
799
|
+
* Immutable description data with no runtime ownership.
|
|
800
|
+
* @since 1.0.0
|
|
801
|
+
* @category Input codecs
|
|
802
|
+
*/
|
|
803
|
+
export type MaskPart = string | MaskSlot;
|
|
804
|
+
/**
|
|
805
|
+
*/
|
|
806
|
+
export type MaskValue<Parts extends ReadonlyArray<MaskPart>> = {
|
|
807
|
+
readonly [Part in Parts[number] as Part extends MaskSlot<infer Name> ? Name : never]: Part extends MaskSlot<string, infer Value> ? Value : never;
|
|
808
|
+
};
|
|
809
|
+
/**
|
|
810
|
+
* Creates a named, Schema-decoded mask slot.
|
|
811
|
+
* @remarks
|
|
812
|
+
* Length and character constraints are expressed beside the codec that owns conversion.
|
|
813
|
+
* Pure constructor; the returned descriptor retains the codec but acquires no Scope.
|
|
814
|
+
* @example
|
|
815
|
+
* ```ts
|
|
816
|
+
* import { slot } from "@typed/ui/Form"
|
|
817
|
+
* import { Schema } from "effect"
|
|
818
|
+
*
|
|
819
|
+
* const areaCode = slot("area", Schema.String, { length: 3, charset: /[0-9]/ })
|
|
820
|
+
* ```
|
|
821
|
+
* @since 1.0.0
|
|
822
|
+
* @category Input codecs
|
|
823
|
+
*/
|
|
824
|
+
export declare function slot<Name extends string, Value>(name: Name, codec: Schema.Codec<Value, string>, options?: Omit<MaskSlot<Name, Value>, "_tag" | "name" | "codec">): MaskSlot<Name, Value>;
|
|
825
|
+
/**
|
|
826
|
+
* Builds a bidirectional Schema codec from literal text and named slots.
|
|
827
|
+
* @remarks
|
|
828
|
+
* Strict encoding and decoding share the same parts and reject invalid length,
|
|
829
|
+
* characters, literals, or slot values. MaskedInput also uses these parts to
|
|
830
|
+
* retain drafts and format fixed-width slots with explicit charsets. Literal
|
|
831
|
+
* characters must be distinguishable from editable characters for auto-formatting;
|
|
832
|
+
* ambiguous or variable-width masks retain ordinary strict text entry.
|
|
833
|
+
* @example
|
|
834
|
+
* ```ts
|
|
835
|
+
* import { mask, slot } from "@typed/ui/Form"
|
|
836
|
+
* import { Schema } from "effect"
|
|
837
|
+
*
|
|
838
|
+
* const phone = mask("(", slot("area", Schema.String, { length: 3 }), ") ",
|
|
839
|
+
* slot("number", Schema.String, { length: 7 }))
|
|
840
|
+
* ```
|
|
841
|
+
* @since 1.0.0
|
|
842
|
+
* @category Input codecs
|
|
843
|
+
*/
|
|
844
|
+
export declare function mask<const Parts extends ReadonlyArray<MaskPart>>(...parts: Parts): Schema.Codec<MaskValue<Parts>, string>;
|
|
845
|
+
/**
|
|
846
|
+
* Options for an input decoded through a structured mask codec.
|
|
847
|
+
* @remarks
|
|
848
|
+
* A normal text input can expose a structured typed value without hiding native events or props.
|
|
849
|
+
* The control Scope owns DOM work; form state and the mask codec remain independently owned.
|
|
850
|
+
* @since 1.0.0
|
|
851
|
+
* @category Input codecs
|
|
852
|
+
*/
|
|
853
|
+
export interface MaskedInputOptions<Values extends object, Parts extends ReadonlyArray<MaskPart>> extends InputOptions<Values, MaskValue<Parts>> {
|
|
854
|
+
/**
|
|
855
|
+
* Bidirectional mask codec used for display and input decoding.
|
|
856
|
+
*/
|
|
857
|
+
readonly mask: Schema.Codec<MaskValue<Parts>, string>;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Binds a native text input to a structured mask value.
|
|
861
|
+
* @remarks
|
|
862
|
+
* A codec created by mask supplies the editable format. Fixed-width slots with
|
|
863
|
+
* explicit charsets receive literal insertion and caret-aware deletion; other
|
|
864
|
+
* codecs retain strict text entry. Incomplete drafts remain visible while decoded
|
|
865
|
+
* state keeps its previous value. Native custom validity and field error text
|
|
866
|
+
* prevent native submission of an incomplete mask. Composition is committed only
|
|
867
|
+
* after compositionend. New edits and resets supersede pending slot decoders.
|
|
868
|
+
* Each mounted input owns its draft observer and reset registration in Scope.
|
|
869
|
+
* @since 1.0.0
|
|
870
|
+
* @category Input codecs
|
|
871
|
+
*/
|
|
872
|
+
export declare function MaskedInput<const Values extends object, const Parts extends ReadonlyArray<MaskPart>, const Options extends MaskedInputOptions<Values, Parts>, const Host extends HostResult = never>(options: Options & Pick<MaskedInputOptions<Values, Parts>, "state" | "name" | "mask">, host?: Dom.HostOverride<Dom.RenderHostProps<Omit<Options, "mask">, InputProps<Values, MaskValue<Parts>>>, "", Host>): Fx<RenderEvent, Schema.SchemaError | Renderable.Error<RenderableComponentOptions<Omit<Options, "mask">> | Host>, Renderable.Services<RenderableComponentOptions<Omit<Options, "mask">> | Host> | Scope.Scope | RenderTemplate>;
|
|
873
|
+
/**
|
|
874
|
+
* Options for a state-explicit native checkbox.
|
|
875
|
+
* @remarks
|
|
876
|
+
* Boolean field inference and live `checked` binding preserve native checkbox behavior.
|
|
877
|
+
* The control Scope owns the listener/binding; form state may outlive the element.
|
|
878
|
+
* @since 1.0.0
|
|
879
|
+
* @category Component options
|
|
880
|
+
*/
|
|
881
|
+
export interface CheckboxOptions<Values extends object> extends Dom.HostOptions<HTMLInputElement> {
|
|
882
|
+
/**
|
|
883
|
+
* Renderer-independent state read and updated by the checkbox.
|
|
884
|
+
*/
|
|
885
|
+
readonly state: FormState<Values>;
|
|
886
|
+
/**
|
|
887
|
+
* Boolean field controlled by the checkbox.
|
|
888
|
+
*/
|
|
889
|
+
readonly name: BooleanFieldName<Values>;
|
|
890
|
+
}
|
|
891
|
+
declare function checkboxProps<Values extends object>(options: CheckboxOptions<Values>): () => {
|
|
892
|
+
readonly type: "checkbox";
|
|
893
|
+
readonly name: BooleanFieldName<Values>;
|
|
894
|
+
readonly "aria-describedby": RefSubject.Computed<string | undefined, Schema.SchemaError, never>;
|
|
895
|
+
readonly "aria-invalid": RefSubject.Computed<true | undefined, Schema.SchemaError, never>;
|
|
896
|
+
readonly "?checked": RefSubject.Computed<boolean, Schema.SchemaError, never>;
|
|
897
|
+
readonly ".checked": RefSubject.Computed<boolean, Schema.SchemaError, never>;
|
|
898
|
+
readonly onchange: EventHandler.EventHandler<Event, Schema.SchemaError, never>;
|
|
899
|
+
};
|
|
900
|
+
type CheckboxProps<Values extends object> = ReturnType<ReturnType<typeof checkboxProps<Values>>>;
|
|
901
|
+
/**
|
|
902
|
+
* Binds a native checkbox to a boolean form field.
|
|
903
|
+
* @remarks
|
|
904
|
+
* Both the checked attribute and live property follow state, while the browser's
|
|
905
|
+
* real change event is decoded through the field codec.
|
|
906
|
+
* The rendered Scope owns the input, listener, and subscriptions. A custom host
|
|
907
|
+
* must apply merged name, ARIA, checked, and change props.
|
|
908
|
+
* @since 1.0.0
|
|
909
|
+
* @category Native controls
|
|
910
|
+
*/
|
|
911
|
+
export declare function Checkbox<const Values extends object, const Options extends CheckboxOptions<Values>, const Host extends HostResult = never>(options: Options & Pick<CheckboxOptions<Values>, "state" | "name">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, CheckboxProps<Values>>, "", Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
912
|
+
/**
|
|
913
|
+
* Options for a state-explicit native select.
|
|
914
|
+
* @remarks
|
|
915
|
+
* Callers author ordinary option markup while the selected value binds to typed state.
|
|
916
|
+
* The control Scope owns content, listener, and binding; form state may outlive it.
|
|
917
|
+
* @since 1.0.0
|
|
918
|
+
* @category Component options
|
|
919
|
+
*/
|
|
920
|
+
export interface SelectOptions<Values extends object> extends Dom.HostOptions<HTMLSelectElement> {
|
|
921
|
+
/**
|
|
922
|
+
* Renderer-independent state read and updated by the select.
|
|
923
|
+
*/
|
|
924
|
+
readonly state: FormState<Values>;
|
|
925
|
+
/**
|
|
926
|
+
* String field controlled by the select.
|
|
927
|
+
*/
|
|
928
|
+
readonly name: FieldNameFor<Values, string>;
|
|
929
|
+
/**
|
|
930
|
+
* Native option/optgroup renderable content.
|
|
931
|
+
*/
|
|
932
|
+
readonly content: Renderable.Any;
|
|
933
|
+
}
|
|
934
|
+
declare function selectProps<Values extends object>(options: SelectOptions<Values>): () => {
|
|
935
|
+
readonly name: FieldNameFor<Values, string>;
|
|
936
|
+
readonly "aria-describedby": RefSubject.Computed<string | undefined, Schema.SchemaError, never>;
|
|
937
|
+
readonly "aria-invalid": RefSubject.Computed<true | undefined, Schema.SchemaError, never>;
|
|
938
|
+
readonly ".value": RefSubject.Computed<string, Schema.SchemaError, never>;
|
|
939
|
+
readonly onchange: EventHandler.EventHandler<Event, Schema.SchemaError, never>;
|
|
940
|
+
};
|
|
941
|
+
type SelectProps<Values extends object> = ReturnType<ReturnType<typeof selectProps<Values>>>;
|
|
942
|
+
/**
|
|
943
|
+
* Binds a native select element to a string form field.
|
|
944
|
+
* @remarks
|
|
945
|
+
* Native keyboard, accessibility, option, and form semantics remain browser-owned.
|
|
946
|
+
* The rendered Scope owns the select/content subscriptions. A custom host must
|
|
947
|
+
* preserve supplied name, ARIA, value, and change props.
|
|
948
|
+
* @since 1.0.0
|
|
949
|
+
* @category Native controls
|
|
950
|
+
*/
|
|
951
|
+
export declare function Select<const Values extends object, const Options extends SelectOptions<Values>, const Host extends HostResult = never>(options: Options & Pick<SelectOptions<Values>, "state" | "name" | "content">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, SelectProps<Values>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
952
|
+
/**
|
|
953
|
+
* Options for a native form label.
|
|
954
|
+
* @remarks
|
|
955
|
+
* Explicit `for` linkage keeps accessible naming in browser-standard markup.
|
|
956
|
+
* The label Scope owns rendered content only; it does not own the referenced control.
|
|
957
|
+
* @since 1.0.0
|
|
958
|
+
* @category Field relationships
|
|
959
|
+
*/
|
|
960
|
+
export interface LabelOptions extends Dom.HostOptions<HTMLLabelElement> {
|
|
961
|
+
/**
|
|
962
|
+
* ID of the native control labeled by this element.
|
|
963
|
+
*/
|
|
964
|
+
readonly for: string;
|
|
965
|
+
/**
|
|
966
|
+
* Human-readable label content.
|
|
967
|
+
*/
|
|
968
|
+
readonly content: Renderable.Any;
|
|
969
|
+
}
|
|
970
|
+
declare function labelProps<const Options extends LabelOptions>(options: Options): () => {
|
|
971
|
+
readonly for: string;
|
|
972
|
+
};
|
|
973
|
+
type LabelProps<Options extends LabelOptions> = ReturnType<ReturnType<typeof labelProps<Options>>>;
|
|
974
|
+
/**
|
|
975
|
+
* Renders a native label with an explicit control relationship.
|
|
976
|
+
* @remarks
|
|
977
|
+
* The browser supplies click-to-focus and accessible-name behavior with no synthetic layer.
|
|
978
|
+
* The Scope owns label output/content; the referenced element remains separately owned.
|
|
979
|
+
* @since 1.0.0
|
|
980
|
+
* @category Field relationships
|
|
981
|
+
*/
|
|
982
|
+
export declare function Label<const Options extends LabelOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, LabelProps<Options>>, Options["content"], Host>): Fx<RenderEvent, Renderable.Error<Options | Host>, Renderable.Services<Options | Host> | Scope.Scope | RenderTemplate>;
|
|
983
|
+
/**
|
|
984
|
+
* Options for descriptive form content.
|
|
985
|
+
* @remarks
|
|
986
|
+
* Provides a host-overrideable descriptive region without inventing text semantics.
|
|
987
|
+
* The host Scope owns the rendered content.
|
|
988
|
+
* @since 1.0.0
|
|
989
|
+
* @category Field relationships
|
|
990
|
+
*/
|
|
991
|
+
export interface DescriptionOptions extends Dom.HostOptions<HTMLDivElement> {
|
|
992
|
+
/**
|
|
993
|
+
* Descriptive renderable content.
|
|
994
|
+
*/
|
|
995
|
+
readonly content: Renderable.Any;
|
|
996
|
+
}
|
|
997
|
+
declare function descriptionProps(): () => {};
|
|
998
|
+
type DescriptionProps = ReturnType<ReturnType<typeof descriptionProps>>;
|
|
999
|
+
/**
|
|
1000
|
+
* Renders visible explanatory content in a neutral div.
|
|
1001
|
+
*
|
|
1002
|
+
* @remarks
|
|
1003
|
+
* No control relationship is created automatically. The current input binding owns its generated
|
|
1004
|
+
* error aria-describedby; do not assume consumer description IDs are merged into it.
|
|
1005
|
+
* @since 1.0.0
|
|
1006
|
+
* @category Field relationships
|
|
1007
|
+
*/
|
|
1008
|
+
export declare function Description<const Options extends DescriptionOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, DescriptionProps>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1009
|
+
/**
|
|
1010
|
+
* Options for a field validation alert.
|
|
1011
|
+
* @remarks
|
|
1012
|
+
* Error identity derives from form and field IDs so controls can reference it reliably.
|
|
1013
|
+
* The error host subscribes within its Scope; form state remains independently owned.
|
|
1014
|
+
* @since 1.0.0
|
|
1015
|
+
* @category Field relationships
|
|
1016
|
+
*/
|
|
1017
|
+
export interface ErrorOptions<Values extends object> extends Dom.HostOptions<HTMLDivElement> {
|
|
1018
|
+
/**
|
|
1019
|
+
* Renderer-independent state supplying validation errors.
|
|
1020
|
+
*/
|
|
1021
|
+
readonly state: FormState<Values>;
|
|
1022
|
+
/**
|
|
1023
|
+
* Field whose current message is rendered.
|
|
1024
|
+
*/
|
|
1025
|
+
readonly name: keyof Values & string;
|
|
1026
|
+
}
|
|
1027
|
+
declare function errorProps<Values extends object>(options: ErrorOptions<Values>): () => {
|
|
1028
|
+
readonly id: string;
|
|
1029
|
+
readonly role: "alert";
|
|
1030
|
+
};
|
|
1031
|
+
type ErrorProps<Values extends object> = ReturnType<ReturnType<typeof errorProps<Values>>>;
|
|
1032
|
+
/**
|
|
1033
|
+
* Renders the named field message with a generated ID and alert role.
|
|
1034
|
+
*
|
|
1035
|
+
* @remarks
|
|
1036
|
+
* Bound inputs refer to this ID through aria-describedby and expose aria-invalid when an error
|
|
1037
|
+
* exists. Keep the form ID stable and render one matching error host per field. Alert timing
|
|
1038
|
+
* still depends on the browser and assistive technology; this is not an announcement queue.
|
|
1039
|
+
* @since 1.0.0
|
|
1040
|
+
* @category Field relationships
|
|
1041
|
+
*/
|
|
1042
|
+
export declare function Error<const Values extends object, const Options extends ErrorOptions<Values>, const Host extends HostResult = never>(options: Options & Pick<ErrorOptions<Values>, "state" | "name">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, ErrorProps<Values>>, Renderable.Any, Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1043
|
+
/**
|
|
1044
|
+
* Options for a native submit button.
|
|
1045
|
+
* @remarks
|
|
1046
|
+
* Uses ordinary form submission semantics while exposing all button props/events.
|
|
1047
|
+
* The button Scope owns rendered content and listeners.
|
|
1048
|
+
* @since 1.0.0
|
|
1049
|
+
* @category Component options
|
|
1050
|
+
*/
|
|
1051
|
+
export interface SubmitOptions extends Dom.HostOptions<HTMLButtonElement> {
|
|
1052
|
+
/**
|
|
1053
|
+
* Submit button label/content.
|
|
1054
|
+
*/
|
|
1055
|
+
readonly content: Renderable.Any;
|
|
1056
|
+
}
|
|
1057
|
+
declare function submitProps(): () => {
|
|
1058
|
+
readonly type: "submit";
|
|
1059
|
+
};
|
|
1060
|
+
type SubmitProps = ReturnType<ReturnType<typeof submitProps>>;
|
|
1061
|
+
/**
|
|
1062
|
+
* Renders a native `type=submit` button.
|
|
1063
|
+
* @remarks
|
|
1064
|
+
* Keyboard activation, form association, and accessibility stay browser-standard.
|
|
1065
|
+
* The Scope owns the button/content; the surrounding Form owns submission sequencing.
|
|
1066
|
+
* @since 1.0.0
|
|
1067
|
+
* @category Form actions
|
|
1068
|
+
*/
|
|
1069
|
+
export declare function Submit<const Options extends SubmitOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, SubmitProps>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1070
|
+
/**
|
|
1071
|
+
* Options for a state-explicit reset button.
|
|
1072
|
+
* @remarks
|
|
1073
|
+
* Native reset activation can restore renderer-independent Typed state deterministically.
|
|
1074
|
+
* The click Effect runs in the button Scope; state may outlive the button.
|
|
1075
|
+
* @since 1.0.0
|
|
1076
|
+
* @category Component options
|
|
1077
|
+
*/
|
|
1078
|
+
export interface ResetOptions<Values extends object> extends Dom.HostOptions<HTMLButtonElement> {
|
|
1079
|
+
/**
|
|
1080
|
+
* Renderer-independent state restored on activation.
|
|
1081
|
+
*/
|
|
1082
|
+
readonly state: FormState<Values>;
|
|
1083
|
+
/**
|
|
1084
|
+
* Reset button label/content.
|
|
1085
|
+
*/
|
|
1086
|
+
readonly content: Renderable.Any;
|
|
1087
|
+
}
|
|
1088
|
+
declare function resetProps<Values extends object>(options: ResetOptions<Values>): () => {
|
|
1089
|
+
readonly type: "reset";
|
|
1090
|
+
readonly onclick: EventHandler.EventHandler<Event, Schema.SchemaError, never>;
|
|
1091
|
+
};
|
|
1092
|
+
type ResetProps<Values extends object> = ReturnType<ReturnType<typeof resetProps<Values>>>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Renders a native reset button that restores Typed form defaults.
|
|
1095
|
+
* @remarks
|
|
1096
|
+
* It prevents the browser's independent control mutation and resets the single
|
|
1097
|
+
* RefSubject source of truth, clearing errors, metadata, and submitting state.
|
|
1098
|
+
* The Scope owns the click handler/content. The supplied form state remains independently owned.
|
|
1099
|
+
* @since 1.0.0
|
|
1100
|
+
* @category Form actions
|
|
1101
|
+
*/
|
|
1102
|
+
export declare function Reset<const Values extends object, const Options extends ResetOptions<Values>, const Host extends HostResult = never>(options: Options & Pick<ResetOptions<Values>, "state" | "content">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, ResetProps<Values>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1103
|
+
/**
|
|
1104
|
+
* Options for an accessible group of form controls.
|
|
1105
|
+
* @remarks
|
|
1106
|
+
* Provides a native host with `role=group` and optional accessible label.
|
|
1107
|
+
* The group Scope owns child renderables but not their independent form state.
|
|
1108
|
+
* @since 1.0.0
|
|
1109
|
+
* @category Field relationships
|
|
1110
|
+
*/
|
|
1111
|
+
export interface GroupOptions extends Dom.HostOptions<HTMLDivElement> {
|
|
1112
|
+
/**
|
|
1113
|
+
* Controls or other renderable members of the group.
|
|
1114
|
+
*/
|
|
1115
|
+
readonly content: Renderable.Any;
|
|
1116
|
+
/**
|
|
1117
|
+
* Optional accessible name applied through `aria-label`.
|
|
1118
|
+
*/
|
|
1119
|
+
readonly label?: string;
|
|
1120
|
+
}
|
|
1121
|
+
declare function groupProps<const Options extends GroupOptions>(options: Options): () => {
|
|
1122
|
+
readonly role: "group";
|
|
1123
|
+
readonly "aria-label": string | undefined;
|
|
1124
|
+
};
|
|
1125
|
+
type GroupProps<Options extends GroupOptions> = ReturnType<ReturnType<typeof groupProps<Options>>>;
|
|
1126
|
+
/**
|
|
1127
|
+
* Renders an ARIA group with an optional accessible name.
|
|
1128
|
+
* @remarks
|
|
1129
|
+
* Related controls can expose their relationship without a framework-specific wrapper.
|
|
1130
|
+
* The Scope owns host/content; child controls retain their own DOM/state contracts.
|
|
1131
|
+
* @since 1.0.0
|
|
1132
|
+
* @category Field relationships
|
|
1133
|
+
*/
|
|
1134
|
+
export declare function Group<const Options extends GroupOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, GroupProps<Options>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Options for an array-field append button.
|
|
1137
|
+
* @remarks
|
|
1138
|
+
* The field name and appended item are derived from the form value type.
|
|
1139
|
+
* The click Effect runs in the button Scope; form state remains independently owned.
|
|
1140
|
+
* @since 1.0.0
|
|
1141
|
+
* @category Component options
|
|
1142
|
+
*/
|
|
1143
|
+
export interface PushOptions<Values extends object, Name extends ArrayFieldName<Values>> extends Dom.HostOptions<HTMLButtonElement> {
|
|
1144
|
+
/**
|
|
1145
|
+
* Renderer-independent state updated on activation.
|
|
1146
|
+
*/
|
|
1147
|
+
readonly state: FormState<Values>;
|
|
1148
|
+
/**
|
|
1149
|
+
* Array-valued field to append to.
|
|
1150
|
+
*/
|
|
1151
|
+
readonly name: Name;
|
|
1152
|
+
/**
|
|
1153
|
+
* Type-compatible item appended to the field.
|
|
1154
|
+
*/
|
|
1155
|
+
readonly value: ArrayFieldValue<Values, Name>;
|
|
1156
|
+
/**
|
|
1157
|
+
* Button label/content.
|
|
1158
|
+
*/
|
|
1159
|
+
readonly content: Renderable.Any;
|
|
1160
|
+
}
|
|
1161
|
+
declare function pushProps<Values extends object, Name extends ArrayFieldName<Values>>(options: PushOptions<Values, Name>): () => {
|
|
1162
|
+
readonly type: "button";
|
|
1163
|
+
readonly onclick: Effect.Effect<State<Values>, Schema.SchemaError, never>;
|
|
1164
|
+
};
|
|
1165
|
+
type PushProps<Values extends object, Name extends ArrayFieldName<Values>> = ReturnType<ReturnType<typeof pushProps<Values, Name>>>;
|
|
1166
|
+
/**
|
|
1167
|
+
* Renders a button that appends one item to an array field.
|
|
1168
|
+
* @remarks
|
|
1169
|
+
* Array mutation is immutable, typed, and marks the field dirty/touched.
|
|
1170
|
+
* The Scope owns the button handler/content; state may outlive the button.
|
|
1171
|
+
* @since 1.0.0
|
|
1172
|
+
* @category Form actions
|
|
1173
|
+
*/
|
|
1174
|
+
export declare function Push<const Values extends object, const Name extends ArrayFieldName<Values>, const Options extends PushOptions<Values, Name>, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, PushProps<Values, Name>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1175
|
+
/**
|
|
1176
|
+
* Options for an array-field removal button.
|
|
1177
|
+
* @remarks
|
|
1178
|
+
* The array field is type-checked and the local index is explicit.
|
|
1179
|
+
* The click Effect runs in the button Scope; form state remains independently owned.
|
|
1180
|
+
* @since 1.0.0
|
|
1181
|
+
* @category Component options
|
|
1182
|
+
*/
|
|
1183
|
+
export interface RemoveOptions<Values extends object, Name extends ArrayFieldName<Values>> extends Dom.HostOptions<HTMLButtonElement> {
|
|
1184
|
+
/**
|
|
1185
|
+
* Renderer-independent state updated on activation.
|
|
1186
|
+
*/
|
|
1187
|
+
readonly state: FormState<Values>;
|
|
1188
|
+
/**
|
|
1189
|
+
* Array-valued field to remove from.
|
|
1190
|
+
*/
|
|
1191
|
+
readonly name: Name;
|
|
1192
|
+
/**
|
|
1193
|
+
* Zero-based item index removed from the field.
|
|
1194
|
+
*/
|
|
1195
|
+
readonly index: number;
|
|
1196
|
+
/**
|
|
1197
|
+
* Button label/content.
|
|
1198
|
+
*/
|
|
1199
|
+
readonly content: Renderable.Any;
|
|
1200
|
+
}
|
|
1201
|
+
declare function removeProps<Values extends object, Name extends ArrayFieldName<Values>>(options: RemoveOptions<Values, Name>): () => {
|
|
1202
|
+
readonly type: "button";
|
|
1203
|
+
readonly onclick: Effect.Effect<State<Values>, Schema.SchemaError, never>;
|
|
1204
|
+
};
|
|
1205
|
+
type RemoveProps<Values extends object, Name extends ArrayFieldName<Values>> = ReturnType<ReturnType<typeof removeProps<Values, Name>>>;
|
|
1206
|
+
/**
|
|
1207
|
+
* Renders a button that removes one array item by index.
|
|
1208
|
+
* @remarks
|
|
1209
|
+
* Array mutation is immutable, typed, and marks the field dirty/touched.
|
|
1210
|
+
* The Scope owns the button handler/content; state may outlive the button.
|
|
1211
|
+
* @since 1.0.0
|
|
1212
|
+
* @category Form actions
|
|
1213
|
+
*/
|
|
1214
|
+
export declare function Remove<const Values extends object, const Name extends ArrayFieldName<Values>, const Options extends RemoveOptions<Values, Name>, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, RemoveProps<Values, Name>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
|
|
1215
|
+
/**
|
|
1216
|
+
* Assigns one decoded field value and updates dirty/touched metadata.
|
|
1217
|
+
*
|
|
1218
|
+
* @remarks
|
|
1219
|
+
* The helper does not decode or validate the supplied value and does not clear an existing field
|
|
1220
|
+
* error. Use validate for an explicit whole-form check. Dirty tracking compares against the
|
|
1221
|
+
* default field with !==; updates replace the top-level values record.
|
|
1222
|
+
* @since 1.0.0
|
|
1223
|
+
* @category State transitions
|
|
1224
|
+
*/
|
|
1225
|
+
export declare function setValue<Values extends object, Key extends keyof Values & string, E, R>(state: RefSubject.RefSubject<State<Values>, E, R>, key: Key, value: Values[Key]): Effect.Effect<State<Values>, E, R>;
|
|
1226
|
+
/**
|
|
1227
|
+
* Restores default values and clears errors, metadata, and submitting.
|
|
1228
|
+
*
|
|
1229
|
+
* @remarks
|
|
1230
|
+
* The defaultValues object is reused rather than deep-cloned. This state operation does not
|
|
1231
|
+
* cancel a running submission Effect or reset independently owned result state.
|
|
1232
|
+
* @since 1.0.0
|
|
1233
|
+
* @category State transitions
|
|
1234
|
+
*/
|
|
1235
|
+
export declare function reset<Values extends object, E, R>(state: RefSubject.RefSubject<State<Values>, E, R>): Effect.Effect<State<Values>, E, R>;
|
|
1236
|
+
/**
|
|
1237
|
+
*/
|
|
1238
|
+
export type BooleanFieldName<Values extends object> = FieldNameFor<Values, boolean>;
|
|
1239
|
+
/**
|
|
1240
|
+
*/
|
|
1241
|
+
export type ArrayFieldName<Values extends object> = {
|
|
1242
|
+
[Key in keyof Values & string]: Values[Key] extends ReadonlyArray<unknown> ? Key : never;
|
|
1243
|
+
}[keyof Values & string];
|
|
1244
|
+
/**
|
|
1245
|
+
*/
|
|
1246
|
+
export type ArrayFieldValue<Values extends object, Name extends ArrayFieldName<Values>> = Values[Name] extends ReadonlyArray<infer Value> ? Value : never;
|
|
1247
|
+
/**
|
|
1248
|
+
* Appends one item to an array field and marks it dirty and touched.
|
|
1249
|
+
* @remarks
|
|
1250
|
+
* The immutable state transition is usable in tests, commands, or any renderer.
|
|
1251
|
+
* The returned Effect performs one RefSubject update when run.
|
|
1252
|
+
* @since 1.0.0
|
|
1253
|
+
* @category State transitions
|
|
1254
|
+
*/
|
|
1255
|
+
export declare function pushValue<Values extends object, Name extends ArrayFieldName<Values>, E, R>(state: RefSubject.RefSubject<State<Values>, E, R>, name: Name, value: ArrayFieldValue<Values, Name>): Effect.Effect<State<Values>, E, R>;
|
|
1256
|
+
/**
|
|
1257
|
+
* Removes one item by index from an array field and marks it dirty and touched.
|
|
1258
|
+
* @remarks
|
|
1259
|
+
* The transition is explicit and renderer-independent; an out-of-range index leaves values unchanged.
|
|
1260
|
+
* The returned Effect performs one RefSubject update when run.
|
|
1261
|
+
* @since 1.0.0
|
|
1262
|
+
* @category State transitions
|
|
1263
|
+
*/
|
|
1264
|
+
export declare function removeValue<Values extends object, Name extends ArrayFieldName<Values>, E, R>(state: RefSubject.RefSubject<State<Values>, E, R>, name: Name, index: number): Effect.Effect<State<Values>, E, R>;
|
|
1265
|
+
/**
|
|
1266
|
+
* Handler invoked only after whole-form Schema validation succeeds.
|
|
1267
|
+
* @remarks
|
|
1268
|
+
* Callers receive decoded values and the real native SubmitEvent, and may return an Effect.
|
|
1269
|
+
* A returned Effect runs inside the form submit handler and completes before `submitting` resets.
|
|
1270
|
+
* @since 1.0.0
|
|
1271
|
+
* @category Form roots
|
|
1272
|
+
*/
|
|
1273
|
+
export type ValidSubmitHandler<Values extends object, E = never, R = never> = (values: Values, event: SubmitEvent) => void | Effect.Effect<unknown, E, R>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Options for the state-explicit form root.
|
|
1276
|
+
* @remarks
|
|
1277
|
+
* The form supplies native submit/reset behavior and Effect context while its
|
|
1278
|
+
* data remains in a standalone hydrated RefSubject.
|
|
1279
|
+
* The root Scope owns DOM handlers/content and provides `CurrentForm` to descendants.
|
|
1280
|
+
* It borrows `state`; submission Effects are finalized before `submitting` is cleared.
|
|
1281
|
+
* @since 1.0.0
|
|
1282
|
+
* @category Form roots
|
|
1283
|
+
*/
|
|
1284
|
+
export interface FormOptions<Values extends object, E = never, R = never> extends Dom.HostOptions<HTMLFormElement> {
|
|
1285
|
+
/**
|
|
1286
|
+
* Hydrated renderer-independent state owned outside the form renderer.
|
|
1287
|
+
*/
|
|
1288
|
+
readonly state: FormState<Values>;
|
|
1289
|
+
/**
|
|
1290
|
+
* Controls and other renderable form content.
|
|
1291
|
+
*/
|
|
1292
|
+
readonly content: Renderable.Any;
|
|
1293
|
+
/**
|
|
1294
|
+
* Callback invoked with decoded values only after successful validation.
|
|
1295
|
+
*/
|
|
1296
|
+
readonly onValidSubmit?: ValidSubmitHandler<Values, E, R>;
|
|
1297
|
+
}
|
|
1298
|
+
declare function formProps<const Values extends object, E, R, const Options extends FormOptions<Values, E, R>>(options: Options): () => {
|
|
1299
|
+
readonly ref: FormState<Values>;
|
|
1300
|
+
readonly onsubmit: EventHandler.EventHandler<SubmitEvent, E | Schema.SchemaError, R>;
|
|
1301
|
+
readonly onreset: EventHandler.EventHandler<Event, Schema.SchemaError, never>;
|
|
1302
|
+
};
|
|
1303
|
+
type FormProps<Values extends object, E, R, Options extends FormOptions<Values, E, R>> = ReturnType<ReturnType<typeof formProps<Values, E, R, Options>>>;
|
|
1304
|
+
/**
|
|
1305
|
+
* Renders a native form and provides its state to bound descendants.
|
|
1306
|
+
*
|
|
1307
|
+
* @remarks
|
|
1308
|
+
* The submit listener synchronously prevents browser navigation, marks submitting, validates
|
|
1309
|
+
* decoded state, and runs onValidSubmit on success. Finalization clears submitting. Native
|
|
1310
|
+
* constraint validation can prevent submit dispatch before this handler runs. The root does not
|
|
1311
|
+
* read FormData, serialize a request, cancel duplicate submissions, or infer server errors.
|
|
1312
|
+
*
|
|
1313
|
+
* @example
|
|
1314
|
+
* ```ts
|
|
1315
|
+
* import { Form, Submit, TextInput, makeState } from "@typed/ui/Form"
|
|
1316
|
+
* import { Effect, Schema } from "effect"
|
|
1317
|
+
* import { html } from "@typed/template"
|
|
1318
|
+
*
|
|
1319
|
+
* const codec = Schema.Struct({ email: Schema.String })
|
|
1320
|
+
* const view = Effect.gen(function* () {
|
|
1321
|
+
* const state = yield* makeState(codec, { id: "signup", values: { email: "" } })
|
|
1322
|
+
* return Form({
|
|
1323
|
+
* state,
|
|
1324
|
+
* content: html`${TextInput({ state, name: "email" })}${Submit({ content: "Join" })}`,
|
|
1325
|
+
* onValidSubmit: (values) => Effect.log(`Submitting ${values.email}`)
|
|
1326
|
+
* })
|
|
1327
|
+
* })
|
|
1328
|
+
* ```
|
|
1329
|
+
* @since 1.0.0
|
|
1330
|
+
* @category Form roots
|
|
1331
|
+
*/
|
|
1332
|
+
export declare function Form<const Values extends object, E, R, const Options extends FormOptions<Values, E, R>, const Host extends HostResult = never>(options: Options & Pick<FormOptions<Values, E, R>, "state" | "content">, host?: Dom.HostOverride<Dom.RenderHostProps<Options, FormProps<Values, E, R, Options>>, Options["content"], Host>): SchemaBoundRootResult<Options, Host>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Options accepted by a schema-bound form root.
|
|
1335
|
+
* @remarks
|
|
1336
|
+
* The factory names the state `form` and supplies its schema/context automatically.
|
|
1337
|
+
* The root Scope borrows `form` and owns content, listeners, and submit Effects.
|
|
1338
|
+
* @since 1.0.0
|
|
1339
|
+
* @category Form roots
|
|
1340
|
+
*/
|
|
1341
|
+
export interface BoundFormOptions<Values extends object, E = never, R = never> extends Dom.HostOptions<HTMLFormElement> {
|
|
1342
|
+
/**
|
|
1343
|
+
* State previously created by the bound API's `state` constructor.
|
|
1344
|
+
*/
|
|
1345
|
+
readonly form: FormState<Values>;
|
|
1346
|
+
/**
|
|
1347
|
+
* Schema-bound controls and other renderable form content.
|
|
1348
|
+
*/
|
|
1349
|
+
readonly content: Renderable.Any;
|
|
1350
|
+
/**
|
|
1351
|
+
* Callback invoked with decoded values only after successful validation.
|
|
1352
|
+
*/
|
|
1353
|
+
readonly onValidSubmit?: ValidSubmitHandler<Values, E, R>;
|
|
1354
|
+
}
|
|
1355
|
+
type CurrentFormIdentifier = Context.Service.Identifier<typeof CurrentForm>;
|
|
1356
|
+
/**
|
|
1357
|
+
* Fx result of a schema-bound descendant control.
|
|
1358
|
+
* @remarks
|
|
1359
|
+
* Its type makes `CurrentForm`, render services, Schema errors, Scope, and custom-host
|
|
1360
|
+
* requirements explicit.
|
|
1361
|
+
* The parent form supplies `CurrentForm`; the running Scope owns DOM work.
|
|
1362
|
+
* @since 1.0.0
|
|
1363
|
+
* @category Schema-bound components
|
|
1364
|
+
*/
|
|
1365
|
+
export type SchemaBoundComponentResult<Options, Host> = Fx<RenderEvent, Schema.SchemaError | Renderable.Error<RenderableComponentOptions<Options> | Host>, Renderable.Services<RenderableComponentOptions<Options> | Host> | CurrentFormIdentifier | Scope.Scope | RenderTemplate>;
|
|
1366
|
+
/**
|
|
1367
|
+
* Fx result of a schema-bound root after it provides `CurrentForm` internally.
|
|
1368
|
+
* @remarks
|
|
1369
|
+
* Consumers see only external render/host requirements, not the service supplied by the root itself.
|
|
1370
|
+
* The running Scope owns the service provision, listeners, and rendered range.
|
|
1371
|
+
* @since 1.0.0
|
|
1372
|
+
* @category Schema-bound components
|
|
1373
|
+
*/
|
|
1374
|
+
export type SchemaBoundRootResult<Options, Host> = Fx<RenderEvent, Schema.SchemaError | Renderable.Error<RenderableComponentOptions<Options> | Host>, Exclude<Renderable.Services<RenderableComponentOptions<Options> | Host>, CurrentFormIdentifier> | Scope.Scope | RenderTemplate>;
|
|
1375
|
+
/**
|
|
1376
|
+
* Callable schema-bound input constructor for fields with one decoded value type.
|
|
1377
|
+
* @remarks
|
|
1378
|
+
* Struct field names, errors, and services remain inferred without passing state repeatedly.
|
|
1379
|
+
* Each call borrows `CurrentForm` and returns Scope-owned render work.
|
|
1380
|
+
* @since 1.0.0
|
|
1381
|
+
* @category Schema-bound components
|
|
1382
|
+
*/
|
|
1383
|
+
export interface SchemaBoundInput<Fields extends FormFields, Value> {
|
|
1384
|
+
/**
|
|
1385
|
+
* Creates a bound native input and optionally delegates its merged props to a custom host.
|
|
1386
|
+
* @since 1.0.0
|
|
1387
|
+
* @category Schema-bound components
|
|
1388
|
+
*/
|
|
1389
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundInputOptions<Fields, Value> & Options, host?: Dom.HostOverride<Dom.HostProps<HTMLInputElement>, "", Host>): SchemaBoundComponentResult<Omit<Options, "name">, Host>;
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Callable schema-bound input using its selected field's string codec as a mask.
|
|
1393
|
+
* @remarks
|
|
1394
|
+
* Structured string encodings stay declared once in the Struct schema.
|
|
1395
|
+
* Each call borrows `CurrentForm` and returns Scope-owned render work.
|
|
1396
|
+
* @since 1.0.0
|
|
1397
|
+
* @category Schema-bound components
|
|
1398
|
+
*/
|
|
1399
|
+
export interface SchemaBoundMaskedInput<Fields extends FormFields> {
|
|
1400
|
+
/**
|
|
1401
|
+
* Creates a bound text input using the selected field's bidirectional string codec.
|
|
1402
|
+
* @since 1.0.0
|
|
1403
|
+
* @category Schema-bound components
|
|
1404
|
+
*/
|
|
1405
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundMaskedInputOptions<Fields> & Options, host?: Dom.HostOverride<Dom.HostProps<HTMLInputElement>, "", Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Callable schema-bound checkbox constructor.
|
|
1409
|
+
* @remarks
|
|
1410
|
+
* Only boolean field names are accepted and state comes from `CurrentForm`.
|
|
1411
|
+
* Each call returns Scope-owned DOM work and borrows the current form state.
|
|
1412
|
+
* @since 1.0.0
|
|
1413
|
+
* @category Schema-bound components
|
|
1414
|
+
*/
|
|
1415
|
+
export interface SchemaBoundCheckbox<Values extends object> {
|
|
1416
|
+
/**
|
|
1417
|
+
* Creates a bound native checkbox for a boolean field.
|
|
1418
|
+
* @since 1.0.0
|
|
1419
|
+
* @category Schema-bound components
|
|
1420
|
+
*/
|
|
1421
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundCheckboxOptions<Values> & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, CheckboxProps<Values>>, "", Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Callable schema-bound native select constructor.
|
|
1425
|
+
* @remarks
|
|
1426
|
+
* String field names are inferred while option content remains caller-authored.
|
|
1427
|
+
* Each call returns Scope-owned DOM/content work and borrows current form state.
|
|
1428
|
+
* @since 1.0.0
|
|
1429
|
+
* @category Schema-bound components
|
|
1430
|
+
*/
|
|
1431
|
+
export interface SchemaBoundSelect<Values extends object> {
|
|
1432
|
+
/**
|
|
1433
|
+
* Creates a bound native select and preserves caller-authored option content.
|
|
1434
|
+
* @since 1.0.0
|
|
1435
|
+
* @category Schema-bound components
|
|
1436
|
+
*/
|
|
1437
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundSelectOptions<Values> & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, SelectProps<Values>>, (SchemaBoundSelectOptions<Values> & Options)["content"], Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Callable schema-bound field-error constructor.
|
|
1441
|
+
* @remarks
|
|
1442
|
+
* Field error text and relationship IDs derive from the current form automatically.
|
|
1443
|
+
* Each call returns a Scope-owned subscription and borrows current form state.
|
|
1444
|
+
* @since 1.0.0
|
|
1445
|
+
* @category Schema-bound components
|
|
1446
|
+
*/
|
|
1447
|
+
export interface SchemaBoundError<Values extends object> {
|
|
1448
|
+
/**
|
|
1449
|
+
* Creates a bound alert region for one field's current error.
|
|
1450
|
+
* @since 1.0.0
|
|
1451
|
+
* @category Schema-bound components
|
|
1452
|
+
*/
|
|
1453
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundErrorOptions<Values> & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, ErrorProps<Values>>, Renderable.Any, Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Callable schema-bound reset-button constructor.
|
|
1457
|
+
* @remarks
|
|
1458
|
+
* Reset behavior can access the current form without a state argument.
|
|
1459
|
+
* Each call returns Scope-owned DOM work and borrows current form state.
|
|
1460
|
+
* @since 1.0.0
|
|
1461
|
+
* @category Schema-bound components
|
|
1462
|
+
*/
|
|
1463
|
+
export interface SchemaBoundReset {
|
|
1464
|
+
/**
|
|
1465
|
+
* Creates a reset button targeting the form provided by `CurrentForm`.
|
|
1466
|
+
* @since 1.0.0
|
|
1467
|
+
* @category Schema-bound components
|
|
1468
|
+
*/
|
|
1469
|
+
<const Options extends object, const Host extends HostResult = never>(options: SchemaBoundResetOptions & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, ResetProps<object>>, (SchemaBoundResetOptions & Options)["content"], Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Callable schema-bound array append-button constructor.
|
|
1473
|
+
* @remarks
|
|
1474
|
+
* Field and item types are derived from the form value.
|
|
1475
|
+
* Each call returns Scope-owned DOM work and borrows current form state.
|
|
1476
|
+
* @since 1.0.0
|
|
1477
|
+
* @category Schema-bound components
|
|
1478
|
+
*/
|
|
1479
|
+
export interface SchemaBoundPush<Values extends object> {
|
|
1480
|
+
/**
|
|
1481
|
+
* Creates an append button for a type-compatible array field and item.
|
|
1482
|
+
* @since 1.0.0
|
|
1483
|
+
* @category Schema-bound components
|
|
1484
|
+
*/
|
|
1485
|
+
<const Name extends ArrayFieldName<Values>, const Options extends object, const Host extends HostResult = never>(options: SchemaBoundPushOptions<Values, Name> & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, PushProps<Values, Name>>, (SchemaBoundPushOptions<Values, Name> & Options)["content"], Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1486
|
+
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Callable schema-bound array removal-button constructor.
|
|
1489
|
+
* @remarks
|
|
1490
|
+
* Array fields remain type-checked without passing state explicitly.
|
|
1491
|
+
* Each call returns Scope-owned DOM work and borrows current form state.
|
|
1492
|
+
* @since 1.0.0
|
|
1493
|
+
* @category Schema-bound components
|
|
1494
|
+
*/
|
|
1495
|
+
export interface SchemaBoundRemove<Values extends object> {
|
|
1496
|
+
/**
|
|
1497
|
+
* Creates a remove button for an array field and explicit item index.
|
|
1498
|
+
* @since 1.0.0
|
|
1499
|
+
* @category Schema-bound components
|
|
1500
|
+
*/
|
|
1501
|
+
<const Name extends ArrayFieldName<Values>, const Options extends object, const Host extends HostResult = never>(options: SchemaBoundRemoveOptions<Values, Name> & Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, RemoveProps<Values, Name>>, (SchemaBoundRemoveOptions<Values, Name> & Options)["content"], Host>): SchemaBoundComponentResult<Options, Host>;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Callable root constructor supplied by a schema-bound form API.
|
|
1505
|
+
* @remarks
|
|
1506
|
+
* It connects one factory-created state to native form behavior and descendant context.
|
|
1507
|
+
* The returned Fx provides `CurrentForm` for its own Scope and borrows the state.
|
|
1508
|
+
* @since 1.0.0
|
|
1509
|
+
* @category Schema-bound components
|
|
1510
|
+
*/
|
|
1511
|
+
export interface SchemaBoundRoot<Values extends object> {
|
|
1512
|
+
/**
|
|
1513
|
+
* Creates the native form root that provides its `form` state to bound descendants.
|
|
1514
|
+
* @since 1.0.0
|
|
1515
|
+
* @category Schema-bound components
|
|
1516
|
+
*/
|
|
1517
|
+
<E, R, const Options extends BoundFormOptions<Values, E, R>, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.HostProps<HTMLFormElement>, Options["content"], Host>): SchemaBoundRootResult<Options, Host>;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Optional state metadata for `SchemaBoundForm.state`.
|
|
1521
|
+
* @remarks
|
|
1522
|
+
* Callers may seed SSR identity, defaults, errors, and interaction/submission state.
|
|
1523
|
+
* Values/defaults and nested references are retained exactly; provide `id` for
|
|
1524
|
+
* deterministic SSR identity.
|
|
1525
|
+
* @since 1.0.0
|
|
1526
|
+
* @category Component options
|
|
1527
|
+
*/
|
|
1528
|
+
export interface SchemaBoundStateOptions<Values extends object> {
|
|
1529
|
+
/**
|
|
1530
|
+
* Stable hydration and accessibility relationship ID; required for deterministic SSR ordering.
|
|
1531
|
+
*/
|
|
1532
|
+
readonly id?: string;
|
|
1533
|
+
/**
|
|
1534
|
+
* Exact reset-baseline reference, defaulting to the same object passed as initial values.
|
|
1535
|
+
*/
|
|
1536
|
+
readonly defaultValues?: Values;
|
|
1537
|
+
/**
|
|
1538
|
+
* Initial field validation messages.
|
|
1539
|
+
*/
|
|
1540
|
+
readonly errors?: Partial<Record<keyof Values & string, string>>;
|
|
1541
|
+
/**
|
|
1542
|
+
* Initial dirty/touched metadata.
|
|
1543
|
+
*/
|
|
1544
|
+
readonly meta?: Partial<Record<keyof Values & string, FieldMeta>>;
|
|
1545
|
+
/**
|
|
1546
|
+
* Whether validation or the returned submit Effect is running.
|
|
1547
|
+
*/
|
|
1548
|
+
readonly submitting?: boolean;
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Schema-specialized form API returned by `make`.
|
|
1552
|
+
* @remarks
|
|
1553
|
+
* The Struct codec is declared once, then every state, field name, component,
|
|
1554
|
+
* error, and custom-host signature stays aligned with it.
|
|
1555
|
+
* The API retains the codec but acquires no Scope. Each `state` call creates a
|
|
1556
|
+
* Scope-owned hydrated RefSubject; each component call creates lazy Fx output.
|
|
1557
|
+
* @since 1.0.0
|
|
1558
|
+
* @category Schema-bound components
|
|
1559
|
+
*/
|
|
1560
|
+
export interface SchemaBoundForm<Fields extends FormFields> {
|
|
1561
|
+
/**
|
|
1562
|
+
* Struct codec shared by state construction and every bound field.
|
|
1563
|
+
*/
|
|
1564
|
+
readonly codec: Schema.Struct<Fields>;
|
|
1565
|
+
/**
|
|
1566
|
+
* Creates a Scope-owned hydrated state from decoded initial values.
|
|
1567
|
+
*/
|
|
1568
|
+
readonly state: (values: Schema.Struct.Type<Fields>, options?: SchemaBoundStateOptions<Schema.Struct.Type<Fields>>) => Effect.Effect<FormState<Schema.Struct.Type<Fields>>, Schema.SchemaError, Scope.Scope>;
|
|
1569
|
+
/**
|
|
1570
|
+
* Native form root that provides the current state to bound descendants.
|
|
1571
|
+
*/
|
|
1572
|
+
readonly Root: SchemaBoundRoot<Schema.Struct.Type<Fields>>;
|
|
1573
|
+
/**
|
|
1574
|
+
* Bound native text input for string-encoded string fields.
|
|
1575
|
+
*/
|
|
1576
|
+
readonly TextInput: SchemaBoundInput<Fields, string>;
|
|
1577
|
+
/**
|
|
1578
|
+
* Bound native search input for string-encoded string fields.
|
|
1579
|
+
*/
|
|
1580
|
+
readonly SearchInput: SchemaBoundInput<Fields, string>;
|
|
1581
|
+
/**
|
|
1582
|
+
* Bound native email input for string-encoded string fields.
|
|
1583
|
+
*/
|
|
1584
|
+
readonly EmailInput: SchemaBoundInput<Fields, string>;
|
|
1585
|
+
/**
|
|
1586
|
+
* Bound native URL input for string-encoded string fields.
|
|
1587
|
+
*/
|
|
1588
|
+
readonly UrlInput: SchemaBoundInput<Fields, string>;
|
|
1589
|
+
/**
|
|
1590
|
+
* Bound native telephone input for string-encoded string fields.
|
|
1591
|
+
*/
|
|
1592
|
+
readonly TelInput: SchemaBoundInput<Fields, string>;
|
|
1593
|
+
/**
|
|
1594
|
+
* Bound native password input for string-encoded string fields.
|
|
1595
|
+
*/
|
|
1596
|
+
readonly PasswordInput: SchemaBoundInput<Fields, string>;
|
|
1597
|
+
/**
|
|
1598
|
+
* Bound native hidden input for string-encoded string fields.
|
|
1599
|
+
*/
|
|
1600
|
+
readonly HiddenInput: SchemaBoundInput<Fields, string>;
|
|
1601
|
+
/**
|
|
1602
|
+
* Bound native color input for string-encoded string fields.
|
|
1603
|
+
*/
|
|
1604
|
+
readonly ColorInput: SchemaBoundInput<Fields, string>;
|
|
1605
|
+
/**
|
|
1606
|
+
* Bound native time input for string-encoded string fields.
|
|
1607
|
+
*/
|
|
1608
|
+
readonly TimeInput: SchemaBoundInput<Fields, string>;
|
|
1609
|
+
/**
|
|
1610
|
+
* Bound native local date-time input for string-encoded string fields.
|
|
1611
|
+
*/
|
|
1612
|
+
readonly DateTimeLocalInput: SchemaBoundInput<Fields, string>;
|
|
1613
|
+
/**
|
|
1614
|
+
* Bound native month input for string-encoded string fields.
|
|
1615
|
+
*/
|
|
1616
|
+
readonly MonthInput: SchemaBoundInput<Fields, string>;
|
|
1617
|
+
/**
|
|
1618
|
+
* Bound native week input for string-encoded string fields.
|
|
1619
|
+
*/
|
|
1620
|
+
readonly WeekInput: SchemaBoundInput<Fields, string>;
|
|
1621
|
+
/**
|
|
1622
|
+
* Bound native number input for finite-number fields encoded as strings.
|
|
1623
|
+
*/
|
|
1624
|
+
readonly NumberInput: SchemaBoundInput<Fields, number>;
|
|
1625
|
+
/**
|
|
1626
|
+
* Bound native range input for finite-number fields encoded as strings.
|
|
1627
|
+
*/
|
|
1628
|
+
readonly RangeInput: SchemaBoundInput<Fields, number>;
|
|
1629
|
+
/**
|
|
1630
|
+
* Bound native date input for Date fields encoded as strings.
|
|
1631
|
+
*/
|
|
1632
|
+
readonly DateInput: SchemaBoundInput<Fields, Date>;
|
|
1633
|
+
/**
|
|
1634
|
+
* Bound text input using the selected field's own string codec.
|
|
1635
|
+
*/
|
|
1636
|
+
readonly MaskedInput: SchemaBoundMaskedInput<Fields>;
|
|
1637
|
+
/**
|
|
1638
|
+
* Bound native checkbox limited to boolean fields.
|
|
1639
|
+
*/
|
|
1640
|
+
readonly Checkbox: SchemaBoundCheckbox<Schema.Struct.Type<Fields>>;
|
|
1641
|
+
/**
|
|
1642
|
+
* Bound native select limited to string fields.
|
|
1643
|
+
*/
|
|
1644
|
+
readonly Select: SchemaBoundSelect<Schema.Struct.Type<Fields>>;
|
|
1645
|
+
/**
|
|
1646
|
+
* Bound ARIA alert for a field's current validation message.
|
|
1647
|
+
*/
|
|
1648
|
+
readonly Error: SchemaBoundError<Schema.Struct.Type<Fields>>;
|
|
1649
|
+
/**
|
|
1650
|
+
* Bound reset button that restores the current form's defaults.
|
|
1651
|
+
*/
|
|
1652
|
+
readonly Reset: SchemaBoundReset;
|
|
1653
|
+
/**
|
|
1654
|
+
* Bound button that appends to an array field.
|
|
1655
|
+
*/
|
|
1656
|
+
readonly Push: SchemaBoundPush<Schema.Struct.Type<Fields>>;
|
|
1657
|
+
/**
|
|
1658
|
+
* Bound button that removes an item from an array field.
|
|
1659
|
+
*/
|
|
1660
|
+
readonly Remove: SchemaBoundRemove<Schema.Struct.Type<Fields>>;
|
|
1661
|
+
/**
|
|
1662
|
+
* Native label component; callers provide the target control ID.
|
|
1663
|
+
*/
|
|
1664
|
+
readonly Label: typeof Label;
|
|
1665
|
+
/**
|
|
1666
|
+
* Neutral description host for caller-linked explanatory content.
|
|
1667
|
+
*/
|
|
1668
|
+
readonly Description: typeof Description;
|
|
1669
|
+
/**
|
|
1670
|
+
* Native submit button.
|
|
1671
|
+
*/
|
|
1672
|
+
readonly Submit: typeof Submit;
|
|
1673
|
+
/**
|
|
1674
|
+
* Accessible group host for related controls.
|
|
1675
|
+
*/
|
|
1676
|
+
readonly Group: typeof Group;
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Binds a native form component family to one Struct codec.
|
|
1680
|
+
*
|
|
1681
|
+
* @remarks
|
|
1682
|
+
* state accepts decoded defaults and allocates a Scope-owned hydrated subject. Root provides
|
|
1683
|
+
* that form through CurrentForm. Bound controls select compatible field names from both decoded
|
|
1684
|
+
* and encoded schema types; their context requirement remains in the Fx until Root provides it.
|
|
1685
|
+
* Use explicit stable IDs when server rendering and hydrating.
|
|
1686
|
+
*
|
|
1687
|
+
* @example
|
|
1688
|
+
* ```ts
|
|
1689
|
+
* import { Schema } from "effect";
|
|
1690
|
+
* import { html } from "@typed/template";
|
|
1691
|
+
* import { RefSubject } from "@typed/fx";
|
|
1692
|
+
* import { component } from "@typed/template";
|
|
1693
|
+
* import * as Form from "@typed/ui/Form";
|
|
1694
|
+
*
|
|
1695
|
+
* const Order = Form.make(Schema.Struct({
|
|
1696
|
+
* copies: Schema.FiniteFromString.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
1697
|
+
* includeNotes: Schema.Boolean,
|
|
1698
|
+
* }));
|
|
1699
|
+
*
|
|
1700
|
+
* export const PrintOrder = component(function* () {
|
|
1701
|
+
* const form = yield* Order.state({ copies: 1, includeNotes: false }, { id: "print-order" });
|
|
1702
|
+
* const submitting = RefSubject.map(form, (state) => state.submitting);
|
|
1703
|
+
* const preview = yield* RefSubject.make("No print request preview yet.");
|
|
1704
|
+
* return html`<section>${Order.Root({
|
|
1705
|
+
* form,
|
|
1706
|
+
* content: [
|
|
1707
|
+
* Order.Label({ for: "order-copies", content: "Copies" }),
|
|
1708
|
+
* Order.NumberInput({ name: "copies", props: { id: "order-copies", min: 1, required: true } }),
|
|
1709
|
+
* Order.Error({ name: "copies" }),
|
|
1710
|
+
* Order.Checkbox({ name: "includeNotes", props: { id: "order-notes" } }),
|
|
1711
|
+
* Order.Label({ for: "order-notes", content: "Include speaker notes" }),
|
|
1712
|
+
* Order.Submit({ content: "Preview print request", props: { "?disabled": submitting } }),
|
|
1713
|
+
* Order.Reset({ content: "Restore defaults" }),
|
|
1714
|
+
* ],
|
|
1715
|
+
* onValidSubmit: (values) => RefSubject.set(
|
|
1716
|
+
* preview,
|
|
1717
|
+
* `${values.copies} copies; notes ${values.includeNotes ? "included" : "excluded"}.`,
|
|
1718
|
+
* ),
|
|
1719
|
+
* })}<p role="status">${preview}</p></section>`;
|
|
1720
|
+
* });
|
|
1721
|
+
* ```
|
|
1722
|
+
* @since 1.0.0
|
|
1723
|
+
* @category Schema-bound components
|
|
1724
|
+
*/
|
|
1725
|
+
export declare function make<const Fields extends FormFields>(codec: Schema.Struct<Fields>): SchemaBoundForm<Fields>;
|
|
1726
|
+
export {};
|
|
1727
|
+
//# sourceMappingURL=Form.d.ts.map
|