@typed/ui 1.0.0-beta.0 → 1.0.0-beta.10
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 +78 -26
- 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 +199 -56
- 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 +47 -14
- package/src/HttpRouter.test.ts +0 -294
- package/src/HttpRouter.ts +0 -168
- package/src/Link.test.ts +0 -85
- package/src/Link.ts +0 -107
- package/src/index.ts +0 -2
- package/tsconfig.json +0 -6
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
import { RefSubject } from "@typed/fx";
|
|
4
|
+
import { EventHandler, html, } from "@typed/template";
|
|
5
|
+
import * as Dom from "./Dom.js";
|
|
6
|
+
import * as NativeDetails from "./NativeDetails.js";
|
|
7
|
+
/** Schema for disclosure hydration state.
|
|
8
|
+
* @remarks
|
|
9
|
+
* ## Why
|
|
10
|
+
* Shared encoding keeps server and browser state compatible.
|
|
11
|
+
* ## Ownership and lifetime
|
|
12
|
+
* The immutable schema acquires no resources.
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
* @category Open state
|
|
15
|
+
*/
|
|
16
|
+
export const StateSchema = Schema.Struct({ open: Schema.Boolean });
|
|
17
|
+
/** Creates hydrated disclosure state.
|
|
18
|
+
* @remarks
|
|
19
|
+
* ## Why
|
|
20
|
+
* Applications can own and test open-state transitions independently of UI.
|
|
21
|
+
* ## Ownership and lifetime
|
|
22
|
+
* The calling Effect Scope owns the returned RefSubject.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { Effect } from "effect"
|
|
26
|
+
* import * as Disclosure from "@typed/ui/Disclosure"
|
|
27
|
+
*
|
|
28
|
+
* const program = Effect.gen(function* () {
|
|
29
|
+
* return yield* Disclosure.makeState({ open: true })
|
|
30
|
+
* })
|
|
31
|
+
* ```
|
|
32
|
+
* @since 1.0.0
|
|
33
|
+
* @category Open state
|
|
34
|
+
*/
|
|
35
|
+
export function makeState(initial = {}) {
|
|
36
|
+
return RefSubject.hydrate(StateSchema, { open: initial.open ?? false });
|
|
37
|
+
}
|
|
38
|
+
/** Sets disclosure visibility.
|
|
39
|
+
* @remarks
|
|
40
|
+
* ## Why
|
|
41
|
+
* Explicit state transitions remain composable with Effect and outside renderers.
|
|
42
|
+
* ## Ownership and lifetime
|
|
43
|
+
* The Effect reuses the existing state lifetime and acquires no resource.
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { Effect } from "effect"
|
|
47
|
+
* import * as Disclosure from "@typed/ui/Disclosure"
|
|
48
|
+
*
|
|
49
|
+
* const program = Effect.gen(function* () {
|
|
50
|
+
* const state = yield* Disclosure.makeState()
|
|
51
|
+
* yield* Disclosure.setOpen(state, true)
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
* @category Open state
|
|
56
|
+
*/
|
|
57
|
+
export function setOpen(state, open) {
|
|
58
|
+
return RefSubject.update(state, (current) => ({ ...current, open }));
|
|
59
|
+
}
|
|
60
|
+
function buttonInternalProps() {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
/** Renders a native `<summary>` disclosure trigger.
|
|
64
|
+
* @remarks
|
|
65
|
+
* ## Why
|
|
66
|
+
* The browser owns activation and toggling; Typed does not emulate them with
|
|
67
|
+
* click handlers or synthetic events.
|
|
68
|
+
* ## Ownership and lifetime
|
|
69
|
+
* Running the Fx owns dynamic content in its Scope. A custom host must remain a
|
|
70
|
+
* valid summary participant inside the associated details element.
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { Button } from "@typed/ui/Disclosure"
|
|
74
|
+
*
|
|
75
|
+
* const summary = Button({ content: "Advanced settings" })
|
|
76
|
+
* ```
|
|
77
|
+
* @since 1.0.0
|
|
78
|
+
* @category Summary activation
|
|
79
|
+
*/
|
|
80
|
+
export function Button(options, host) {
|
|
81
|
+
return Dom.renderHost()(options, host, buttonInternalProps, options.content, (props, content) => html `<summary ...${props}>${content}</summary>`);
|
|
82
|
+
}
|
|
83
|
+
function contentInternalProps(options) {
|
|
84
|
+
return () => ({
|
|
85
|
+
ontoggle: EventHandler.make(Effect.fn((event) => setOpen(options.state, Dom.currentTarget(event).open))),
|
|
86
|
+
ref: Dom.composeRefs(options.state, NativeDetails.ref(options.state)),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Renders native details content synchronized with hydrated state.
|
|
90
|
+
* @remarks
|
|
91
|
+
* ## Why
|
|
92
|
+
* Native disclosure behavior, semantics, and `toggle` events stay intact while
|
|
93
|
+
* Effect state can control or observe visibility.
|
|
94
|
+
* ## Ownership and lifetime
|
|
95
|
+
* Running the Fx owns the native listener and scoped observer. A custom host
|
|
96
|
+
* must preserve the toggle handler and exactly one composed hydration ref.
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { Effect } from "effect"
|
|
100
|
+
* import * as Disclosure from "@typed/ui/Disclosure"
|
|
101
|
+
*
|
|
102
|
+
* const program = Effect.gen(function* () {
|
|
103
|
+
* const state = yield* Disclosure.makeState()
|
|
104
|
+
* return Disclosure.Content({
|
|
105
|
+
* state,
|
|
106
|
+
* content: Disclosure.Button({ content: "More" })
|
|
107
|
+
* })
|
|
108
|
+
* })
|
|
109
|
+
* ```
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
* @category Native content host
|
|
112
|
+
*/
|
|
113
|
+
export function Content(options, host) {
|
|
114
|
+
return Dom.renderHost()(options, host, contentInternalProps(options), options.content, (props, content) => {
|
|
115
|
+
return html `<details ...${props}>${content}</details>`;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/** Canonical alias for `Content`.
|
|
119
|
+
* @remarks
|
|
120
|
+
* ## Why
|
|
121
|
+
* The widget name remains convenient while `Content` identifies its role in
|
|
122
|
+
* compound composition.
|
|
123
|
+
* ## Ownership and lifetime
|
|
124
|
+
* It has exactly the same Scope and details-element ownership as `Content`.
|
|
125
|
+
* @since 1.0.0
|
|
126
|
+
* @category Native content host
|
|
127
|
+
*/
|
|
128
|
+
export const Disclosure = Content;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { EventHandler } from "@typed/template";
|
|
2
|
+
import type { EventHandlerInput, EventHandlerProperty } from "./Types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Combines a user handler with component-required behavior for one native event.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* ## Why
|
|
8
|
+
* Component hosts must combine user and required behavior without hiding the
|
|
9
|
+
* precise Effect boundary. User callback invocation constructs the user Effect
|
|
10
|
+
* first. Internal callback invocation may then construct an internal Effect;
|
|
11
|
+
* only execution of that returned Effect is sequenced after the user Effect.
|
|
12
|
+
*
|
|
13
|
+
* ## Ownership and lifetime
|
|
14
|
+
* The returned `EventHandler` owns no listener by itself. The rendering Scope
|
|
15
|
+
* installs it and removes it; `once` and AbortSignal state are honored for each
|
|
16
|
+
* input independently. Capture and passive options are conservatively merged.
|
|
17
|
+
*
|
|
18
|
+
* ## DOM behavior
|
|
19
|
+
* The user handler receives a retained `Proxy` around the browser event so a
|
|
20
|
+
* `preventDefault()` call made while its Effect runs can still cancel the
|
|
21
|
+
* internal step. The proxy is not identity-equal to the native event. Its
|
|
22
|
+
* properties—including `currentTarget`—are read from that native event, so
|
|
23
|
+
* `currentTarget` becomes null after browser dispatch exactly as it normally
|
|
24
|
+
* does. The internal handler receives the original native event, never the
|
|
25
|
+
* proxy.
|
|
26
|
+
*
|
|
27
|
+
* ## Invocation and Effect sequencing
|
|
28
|
+
* `userHandler.handler(proxy)` is called first to construct `userEffect`. If
|
|
29
|
+
* that invocation has already called `preventDefault()`—for example through an
|
|
30
|
+
* EventHandler option—the internal handler is not invoked. Otherwise,
|
|
31
|
+
* `internalHandler.handler(nativeEvent)` is called immediately to construct
|
|
32
|
+
* `internalEffect`, before `userEffect` runs. A void-returning internal callback
|
|
33
|
+
* therefore performs its callback body eagerly and cannot be undone by a later
|
|
34
|
+
* `preventDefault()` inside `userEffect`. The composed Effect runs `userEffect`,
|
|
35
|
+
* checks tracked default prevention again, and only then runs a returned
|
|
36
|
+
* `internalEffect` when it is still allowed.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { chainEvent } from "@typed/ui/Dom/Events"
|
|
41
|
+
* import { EventHandler } from "@typed/template"
|
|
42
|
+
* import { Effect } from "effect"
|
|
43
|
+
*
|
|
44
|
+
* const calls: Array<string> = []
|
|
45
|
+
* const handler = chainEvent(
|
|
46
|
+
* EventHandler.make((event: MouseEvent) =>
|
|
47
|
+
* Effect.sync(() => {
|
|
48
|
+
* calls.push("user effect")
|
|
49
|
+
* event.preventDefault()
|
|
50
|
+
* })),
|
|
51
|
+
* EventHandler.make(() => {
|
|
52
|
+
* calls.push("internal callback") // runs while constructing the Effect
|
|
53
|
+
* return Effect.sync(() => calls.push("internal effect"))
|
|
54
|
+
* })
|
|
55
|
+
* )!
|
|
56
|
+
*
|
|
57
|
+
* const program = handler.handler(new MouseEvent("click", { cancelable: true }))
|
|
58
|
+
* // calls is now ["internal callback"]
|
|
59
|
+
* await Effect.runPromise(program)
|
|
60
|
+
* // calls is ["internal callback", "user effect"];
|
|
61
|
+
* // the returned internal Effect was gated by preventDefault.
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @since 1.0.0
|
|
65
|
+
* @category Event composition
|
|
66
|
+
*/
|
|
67
|
+
export declare function chainEvent<Ev extends Event, E1 = never, R1 = never, E2 = never, R2 = never>(user: EventHandlerInput<Ev, E1, R1>, internal: EventHandlerInput<Ev, E2, R2>): EventHandler.EventHandler<Ev, E1 | E2, R1 | R2> | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Tests whether a prop name uses Typed's native event conventions.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
* ## Why
|
|
73
|
+
* Host forwarding and merging treat `on*` and `@*` keys as handlers rather
|
|
74
|
+
* than ordinary attributes.
|
|
75
|
+
*
|
|
76
|
+
* ## Ownership and lifetime
|
|
77
|
+
* Pure predicate; it installs no listener and retains no key.
|
|
78
|
+
*
|
|
79
|
+
* @since 1.0.0
|
|
80
|
+
* @category Event inspection
|
|
81
|
+
*/
|
|
82
|
+
export declare function isEventKey(key: string): key is EventHandlerProperty;
|
|
83
|
+
/**
|
|
84
|
+
* Reads a native event's non-null current target during handler execution.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* ## Why
|
|
88
|
+
* The DOM types `currentTarget` as nullable because the browser clears it after
|
|
89
|
+
* dispatch. This helper makes the temporal constraint explicit and preserves a
|
|
90
|
+
* caller-selected target type.
|
|
91
|
+
*
|
|
92
|
+
* ## Ownership and lifetime
|
|
93
|
+
* The returned target is borrowed from the live dispatch. Do not treat it as a
|
|
94
|
+
* component-owned node; the helper throws after the handler window closes.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* import { currentTarget } from "@typed/ui/Dom/Events"
|
|
99
|
+
*
|
|
100
|
+
* const read = (event: Event) => currentTarget<HTMLInputElement>(event).value
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @since 1.0.0
|
|
104
|
+
* @category Event inspection
|
|
105
|
+
*/
|
|
106
|
+
export declare function currentTarget<Target extends EventTarget>(event: Event): Target;
|
|
107
|
+
/**
|
|
108
|
+
* Reads the standards-based `ToggleEvent.newState` value when present.
|
|
109
|
+
*
|
|
110
|
+
* @remarks
|
|
111
|
+
* ## Why
|
|
112
|
+
* Popover and details components can follow the browser's real toggle event
|
|
113
|
+
* while remaining usable with DOM libraries whose Event types lag the platform.
|
|
114
|
+
*
|
|
115
|
+
* ## Ownership and lifetime
|
|
116
|
+
* Pure read of the current event; no state or listener is retained.
|
|
117
|
+
*
|
|
118
|
+
* @since 1.0.0
|
|
119
|
+
* @category Event inspection
|
|
120
|
+
*/
|
|
121
|
+
export declare function toggleState(event: Event): "open" | "closed" | undefined;
|
|
122
|
+
//# sourceMappingURL=Events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Events.d.ts","sourceRoot":"","sources":["../../src/Dom/Events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,wBAAgB,UAAU,CAAC,EAAE,SAAS,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EACzF,IAAI,EAAE,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACnC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GACtC,YAAY,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,CA0C7D;AA2BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAEnE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAO9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAGvE"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { EventHandler } from "@typed/template";
|
|
3
|
+
/**
|
|
4
|
+
* Combines a user handler with component-required behavior for one native event.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* ## Why
|
|
8
|
+
* Component hosts must combine user and required behavior without hiding the
|
|
9
|
+
* precise Effect boundary. User callback invocation constructs the user Effect
|
|
10
|
+
* first. Internal callback invocation may then construct an internal Effect;
|
|
11
|
+
* only execution of that returned Effect is sequenced after the user Effect.
|
|
12
|
+
*
|
|
13
|
+
* ## Ownership and lifetime
|
|
14
|
+
* The returned `EventHandler` owns no listener by itself. The rendering Scope
|
|
15
|
+
* installs it and removes it; `once` and AbortSignal state are honored for each
|
|
16
|
+
* input independently. Capture and passive options are conservatively merged.
|
|
17
|
+
*
|
|
18
|
+
* ## DOM behavior
|
|
19
|
+
* The user handler receives a retained `Proxy` around the browser event so a
|
|
20
|
+
* `preventDefault()` call made while its Effect runs can still cancel the
|
|
21
|
+
* internal step. The proxy is not identity-equal to the native event. Its
|
|
22
|
+
* properties—including `currentTarget`—are read from that native event, so
|
|
23
|
+
* `currentTarget` becomes null after browser dispatch exactly as it normally
|
|
24
|
+
* does. The internal handler receives the original native event, never the
|
|
25
|
+
* proxy.
|
|
26
|
+
*
|
|
27
|
+
* ## Invocation and Effect sequencing
|
|
28
|
+
* `userHandler.handler(proxy)` is called first to construct `userEffect`. If
|
|
29
|
+
* that invocation has already called `preventDefault()`—for example through an
|
|
30
|
+
* EventHandler option—the internal handler is not invoked. Otherwise,
|
|
31
|
+
* `internalHandler.handler(nativeEvent)` is called immediately to construct
|
|
32
|
+
* `internalEffect`, before `userEffect` runs. A void-returning internal callback
|
|
33
|
+
* therefore performs its callback body eagerly and cannot be undone by a later
|
|
34
|
+
* `preventDefault()` inside `userEffect`. The composed Effect runs `userEffect`,
|
|
35
|
+
* checks tracked default prevention again, and only then runs a returned
|
|
36
|
+
* `internalEffect` when it is still allowed.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { chainEvent } from "@typed/ui/Dom/Events"
|
|
41
|
+
* import { EventHandler } from "@typed/template"
|
|
42
|
+
* import { Effect } from "effect"
|
|
43
|
+
*
|
|
44
|
+
* const calls: Array<string> = []
|
|
45
|
+
* const handler = chainEvent(
|
|
46
|
+
* EventHandler.make((event: MouseEvent) =>
|
|
47
|
+
* Effect.sync(() => {
|
|
48
|
+
* calls.push("user effect")
|
|
49
|
+
* event.preventDefault()
|
|
50
|
+
* })),
|
|
51
|
+
* EventHandler.make(() => {
|
|
52
|
+
* calls.push("internal callback") // runs while constructing the Effect
|
|
53
|
+
* return Effect.sync(() => calls.push("internal effect"))
|
|
54
|
+
* })
|
|
55
|
+
* )!
|
|
56
|
+
*
|
|
57
|
+
* const program = handler.handler(new MouseEvent("click", { cancelable: true }))
|
|
58
|
+
* // calls is now ["internal callback"]
|
|
59
|
+
* await Effect.runPromise(program)
|
|
60
|
+
* // calls is ["internal callback", "user effect"];
|
|
61
|
+
* // the returned internal Effect was gated by preventDefault.
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @since 1.0.0
|
|
65
|
+
* @category Event composition
|
|
66
|
+
*/
|
|
67
|
+
export function chainEvent(user, internal) {
|
|
68
|
+
const userHandler = toEventHandler(user);
|
|
69
|
+
const internalHandler = toEventHandler(internal);
|
|
70
|
+
if (!userHandler)
|
|
71
|
+
return internalHandler;
|
|
72
|
+
if (!internalHandler)
|
|
73
|
+
return userHandler;
|
|
74
|
+
let userActive = true;
|
|
75
|
+
let internalActive = true;
|
|
76
|
+
const passive = userHandler.options?.preventDefault === true ||
|
|
77
|
+
internalHandler.options?.preventDefault === true ||
|
|
78
|
+
userHandler.options?.passive === false ||
|
|
79
|
+
internalHandler.options?.passive === false
|
|
80
|
+
? false
|
|
81
|
+
: (userHandler.options?.passive ?? internalHandler.options?.passive);
|
|
82
|
+
const options = {
|
|
83
|
+
capture: userHandler.options?.capture ?? internalHandler.options?.capture,
|
|
84
|
+
passive,
|
|
85
|
+
};
|
|
86
|
+
return EventHandler.make((event) => {
|
|
87
|
+
const tracked = trackPreventDefault(event);
|
|
88
|
+
const userEffect = userActive && userHandler.options?.signal?.aborted !== true
|
|
89
|
+
? userHandler.handler(tracked.event)
|
|
90
|
+
: Effect.void;
|
|
91
|
+
if (userActive && userHandler.options?.signal?.aborted !== true) {
|
|
92
|
+
if (userHandler.options?.once === true)
|
|
93
|
+
userActive = false;
|
|
94
|
+
}
|
|
95
|
+
if (tracked.defaultPrevented() ||
|
|
96
|
+
!internalActive ||
|
|
97
|
+
internalHandler.options?.signal?.aborted === true) {
|
|
98
|
+
return userEffect;
|
|
99
|
+
}
|
|
100
|
+
if (internalHandler.options?.once === true)
|
|
101
|
+
internalActive = false;
|
|
102
|
+
const internalEffect = internalHandler.handler(event);
|
|
103
|
+
return Effect.andThen(userEffect, () => tracked.defaultPrevented() ? Effect.void : internalEffect);
|
|
104
|
+
}, options);
|
|
105
|
+
}
|
|
106
|
+
function trackPreventDefault(event) {
|
|
107
|
+
let defaultPrevented = event.defaultPrevented;
|
|
108
|
+
return {
|
|
109
|
+
event: new Proxy(event, {
|
|
110
|
+
get(target, property) {
|
|
111
|
+
if (property === "defaultPrevented")
|
|
112
|
+
return defaultPrevented;
|
|
113
|
+
if (property === "preventDefault") {
|
|
114
|
+
return () => {
|
|
115
|
+
defaultPrevented = true;
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const value = Reflect.get(target, property);
|
|
120
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
defaultPrevented: () => defaultPrevented,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Tests whether a prop name uses Typed's native event conventions.
|
|
128
|
+
*
|
|
129
|
+
* @remarks
|
|
130
|
+
* ## Why
|
|
131
|
+
* Host forwarding and merging treat `on*` and `@*` keys as handlers rather
|
|
132
|
+
* than ordinary attributes.
|
|
133
|
+
*
|
|
134
|
+
* ## Ownership and lifetime
|
|
135
|
+
* Pure predicate; it installs no listener and retains no key.
|
|
136
|
+
*
|
|
137
|
+
* @since 1.0.0
|
|
138
|
+
* @category Event inspection
|
|
139
|
+
*/
|
|
140
|
+
export function isEventKey(key) {
|
|
141
|
+
return key[0] === "@" || (key[0] === "o" && key[1] === "n");
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reads a native event's non-null current target during handler execution.
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* ## Why
|
|
148
|
+
* The DOM types `currentTarget` as nullable because the browser clears it after
|
|
149
|
+
* dispatch. This helper makes the temporal constraint explicit and preserves a
|
|
150
|
+
* caller-selected target type.
|
|
151
|
+
*
|
|
152
|
+
* ## Ownership and lifetime
|
|
153
|
+
* The returned target is borrowed from the live dispatch. Do not treat it as a
|
|
154
|
+
* component-owned node; the helper throws after the handler window closes.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* import { currentTarget } from "@typed/ui/Dom/Events"
|
|
159
|
+
*
|
|
160
|
+
* const read = (event: Event) => currentTarget<HTMLInputElement>(event).value
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* @since 1.0.0
|
|
164
|
+
* @category Event inspection
|
|
165
|
+
*/
|
|
166
|
+
export function currentTarget(event) {
|
|
167
|
+
if (event.currentTarget === null) {
|
|
168
|
+
throw new TypeError("An event handler can only read its current target while handling an event");
|
|
169
|
+
}
|
|
170
|
+
return event.currentTarget;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Reads the standards-based `ToggleEvent.newState` value when present.
|
|
174
|
+
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* ## Why
|
|
177
|
+
* Popover and details components can follow the browser's real toggle event
|
|
178
|
+
* while remaining usable with DOM libraries whose Event types lag the platform.
|
|
179
|
+
*
|
|
180
|
+
* ## Ownership and lifetime
|
|
181
|
+
* Pure read of the current event; no state or listener is retained.
|
|
182
|
+
*
|
|
183
|
+
* @since 1.0.0
|
|
184
|
+
* @category Event inspection
|
|
185
|
+
*/
|
|
186
|
+
export function toggleState(event) {
|
|
187
|
+
const value = Reflect.get(event, "newState");
|
|
188
|
+
return value === "open" || value === "closed" ? value : undefined;
|
|
189
|
+
}
|
|
190
|
+
function toEventHandler(handler) {
|
|
191
|
+
return handler == null ? undefined : EventHandler.fromEffectOrEventHandler(handler);
|
|
192
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { EventHandler, Renderable } from "@typed/template";
|
|
2
|
+
import { type ComposedRef } from "./Refs.js";
|
|
3
|
+
import type { EventHandlerProperty, EventOf, InternalPropsHelpers, Property } from "./Types.js";
|
|
4
|
+
type ObjectValue<Value> = Value extends object ? Value : Record<never, never>;
|
|
5
|
+
type PropsRef<Props> = Property<Props, "ref">;
|
|
6
|
+
type MergedEventKeys<User, Internal> = Extract<keyof ObjectValue<User> | keyof ObjectValue<Internal>, EventHandlerProperty>;
|
|
7
|
+
type MergedEvents<User, Internal> = {
|
|
8
|
+
readonly [Key in MergedEventKeys<User, Internal>]?: EventHandler.EventHandler<EventOf<Property<User, Key> | Property<Internal, Key>>, Renderable.Error<Property<User, Key> | Property<Internal, Key>>, Renderable.Services<Property<User, Key> | Property<Internal, Key>>>;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Type-level result of merging user and component-owned host props.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* ## Why
|
|
15
|
+
* Required internal values win, events compose, and refs compose while
|
|
16
|
+
* unrelated user props pass through unchanged.
|
|
17
|
+
*
|
|
18
|
+
* ## Ownership and lifetime
|
|
19
|
+
* The resulting event/ref work is owned by the host's rendering Scope.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
* @category Prop composition
|
|
23
|
+
*/
|
|
24
|
+
export type MergedHostProps<User, Internal> = Omit<ObjectValue<User>, keyof ObjectValue<Internal> | EventHandlerProperty | "ref"> & Omit<ObjectValue<Internal>, EventHandlerProperty | "ref"> & MergedEvents<User, Internal> & {
|
|
25
|
+
readonly ref?: ComposedRef<PropsRef<Internal>, PropsRef<User>>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Option keys forwarded directly to a component host.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* ## Why
|
|
32
|
+
* Top-level refs and events remain ergonomic while other DOM props stay under `props`.
|
|
33
|
+
*
|
|
34
|
+
* ## Ownership and lifetime
|
|
35
|
+
* Type-only; the rendered host owns listener/ref lifetime.
|
|
36
|
+
*
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
* @category Prop forwarding
|
|
39
|
+
*/
|
|
40
|
+
export type ForwardedHostKeys<Options> = Extract<keyof ObjectValue<Options>, EventHandlerProperty | "ref">;
|
|
41
|
+
/**
|
|
42
|
+
* Top-level event and ref props selected from component options.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* ## Why
|
|
46
|
+
* Provides the exact forwarded subset used by `renderHost`.
|
|
47
|
+
*
|
|
48
|
+
* ## Ownership and lifetime
|
|
49
|
+
* Type-only; the rendered host owns listener/ref lifetime.
|
|
50
|
+
*
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
* @category Prop forwarding
|
|
53
|
+
*/
|
|
54
|
+
export type ForwardedHostProps<Options> = Pick<ObjectValue<Options>, ForwardedHostKeys<Options>>;
|
|
55
|
+
/**
|
|
56
|
+
* User host props after combining nested `props` with top-level refs/events.
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* ## Why
|
|
60
|
+
* Gives both supported authoring forms one deterministic merge model.
|
|
61
|
+
*
|
|
62
|
+
* ## Ownership and lifetime
|
|
63
|
+
* Type-only; runtime ownership begins when the host renders.
|
|
64
|
+
*
|
|
65
|
+
* @since 1.0.0
|
|
66
|
+
* @category Prop composition
|
|
67
|
+
*/
|
|
68
|
+
export type HostOptionProps<Options> = MergedHostProps<Property<Options, "props">, ForwardedHostProps<Options>>;
|
|
69
|
+
/**
|
|
70
|
+
* Final props delivered to a default or custom host renderer.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* ## Why
|
|
74
|
+
* Custom hosts receive the same accessibility, event, disabled, and ref
|
|
75
|
+
* contract as Typed's default element.
|
|
76
|
+
*
|
|
77
|
+
* ## Ownership and lifetime
|
|
78
|
+
* The rendering Scope owns composed listeners and refs.
|
|
79
|
+
*
|
|
80
|
+
* @since 1.0.0
|
|
81
|
+
* @category Prop composition
|
|
82
|
+
*/
|
|
83
|
+
export type RenderHostProps<Options, Internal> = MergedHostProps<HostOptionProps<Options>, Internal>;
|
|
84
|
+
/**
|
|
85
|
+
* Merges user host props with component-required internal props.
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* ## Why
|
|
89
|
+
* Internal accessibility/state props must remain authoritative, but user
|
|
90
|
+
* events still run first and may cancel component behavior. Disabled hosts
|
|
91
|
+
* suppress user activation handlers. Refs compose instead of overwriting one
|
|
92
|
+
* another.
|
|
93
|
+
*
|
|
94
|
+
* ## Ownership and lifetime
|
|
95
|
+
* The function allocates only a merged object. Listener and ref effects are
|
|
96
|
+
* run by the eventual template Scope. `composeRefs` rejects two hydration
|
|
97
|
+
* owners because one element can restore only one hydration protocol.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* import { mergeProps } from "@typed/ui/Dom/Props"
|
|
102
|
+
* import { EventHandler } from "@typed/template"
|
|
103
|
+
* import { Effect } from "effect"
|
|
104
|
+
*
|
|
105
|
+
* const props = mergeProps(
|
|
106
|
+
* {
|
|
107
|
+
* class: "external",
|
|
108
|
+
* onclick: EventHandler.make(() => Effect.log("user activation"))
|
|
109
|
+
* },
|
|
110
|
+
* { role: "button", "aria-disabled": false }
|
|
111
|
+
* )
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @since 1.0.0
|
|
115
|
+
* @category Prop composition
|
|
116
|
+
*/
|
|
117
|
+
export declare function mergeProps<const User extends object | undefined, const Internal extends object>(user: User, internal: Internal): MergedHostProps<User, Internal>;
|
|
118
|
+
/**
|
|
119
|
+
* Reads a property from an unknown generic value without throwing on nullish input.
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* ## Why
|
|
123
|
+
* Generic option construction needs runtime behavior matching the public `Property` type.
|
|
124
|
+
*
|
|
125
|
+
* ## Ownership and lifetime
|
|
126
|
+
* Pure read; no value is retained.
|
|
127
|
+
*
|
|
128
|
+
* @since 1.0.0
|
|
129
|
+
* @category Property inspection
|
|
130
|
+
*/
|
|
131
|
+
export declare function getProperty<const Value, const Key extends PropertyKey>(value: Value, key: Key): Property<Value, Key>;
|
|
132
|
+
/**
|
|
133
|
+
* Builds typed fallback helpers for component-owned host props.
|
|
134
|
+
*
|
|
135
|
+
* @remarks
|
|
136
|
+
* ## Why
|
|
137
|
+
* Components can distinguish an absent option from valid falsy values.
|
|
138
|
+
*
|
|
139
|
+
* ## Ownership and lifetime
|
|
140
|
+
* The helper closes over `options` only during synchronous prop construction.
|
|
141
|
+
*
|
|
142
|
+
* @since 1.0.0
|
|
143
|
+
* @category Internal prop defaults
|
|
144
|
+
*/
|
|
145
|
+
export declare function makeInternalPropsHelpers<const Options>(options: Options): InternalPropsHelpers<Options>;
|
|
146
|
+
/**
|
|
147
|
+
* Extracts top-level refs and event handlers from component options.
|
|
148
|
+
*
|
|
149
|
+
* @remarks
|
|
150
|
+
* ## Why
|
|
151
|
+
* Convenience event/ref options can enter the same deterministic host merge as `props`.
|
|
152
|
+
*
|
|
153
|
+
* ## Ownership and lifetime
|
|
154
|
+
* Returns a shallow object. The rendering Scope owns any contained listener/ref work.
|
|
155
|
+
*
|
|
156
|
+
* @since 1.0.0
|
|
157
|
+
* @category Prop forwarding
|
|
158
|
+
*/
|
|
159
|
+
export declare function forwardHostProps<const Options extends object>(options: Options): ForwardedHostProps<Options>;
|
|
160
|
+
export {};
|
|
161
|
+
//# sourceMappingURL=Props.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Props.d.ts","sourceRoot":"","sources":["../../src/Dom/Props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EAEV,oBAAoB,EACpB,OAAO,EACP,oBAAoB,EAEpB,QAAQ,EACT,MAAM,YAAY,CAAC;AAEpB,KAAK,WAAW,CAAC,KAAK,IAAI,KAAK,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC9E,KAAK,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC9C,KAAK,eAAe,CAAC,IAAI,EAAE,QAAQ,IAAI,OAAO,CAC5C,MAAM,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,EACrD,oBAAoB,CACrB,CAAC;AACF,KAAK,YAAY,CAAC,IAAI,EAAE,QAAQ,IAAI;IAClC,QAAQ,EAAE,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,YAAY,CAC3E,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,EACtD,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,EAC/D,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CACnE;CACF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,CAChD,WAAW,CAAC,IAAI,CAAC,EACjB,MAAM,WAAW,CAAC,QAAQ,CAAC,GAAG,oBAAoB,GAAG,KAAK,CAC3D,GACC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,oBAAoB,GAAG,KAAK,CAAC,GACzD,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;CAChE,CAAC;AAEJ;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI,OAAO,CAC9C,MAAM,WAAW,CAAC,OAAO,CAAC,EAC1B,oBAAoB,GAAG,KAAK,CAC7B,CAAC;AACF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;AAEjG;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,IAAI,eAAe,CACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,EAC1B,kBAAkB,CAAC,OAAO,CAAC,CAC5B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,EAAE,QAAQ,IAAI,eAAe,CAC9D,eAAe,CAAC,OAAO,CAAC,EACxB,QAAQ,CACT,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,QAAQ,SAAS,MAAM,EAC7F,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,GACjB,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAwBjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,SAAS,WAAW,EACpE,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,GAAG,GACP,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAItB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,CAAC,OAAO,EACpD,OAAO,EAAE,OAAO,GACf,oBAAoB,CAAC,OAAO,CAAC,CAS/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,OAAO,SAAS,MAAM,EAC3D,OAAO,EAAE,OAAO,GACf,kBAAkB,CAAC,OAAO,CAAC,CAM7B"}
|