@typed/ui 1.0.0-beta.4 → 1.0.0-beta.6

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.
Files changed (157) hide show
  1. package/README.md +53 -9
  2. package/dist/Alert.d.ts +78 -0
  3. package/dist/Alert.d.ts.map +1 -0
  4. package/dist/Alert.js +37 -0
  5. package/dist/Button.d.ts +144 -0
  6. package/dist/Button.d.ts.map +1 -0
  7. package/dist/Button.js +38 -0
  8. package/dist/Carousel.d.ts +547 -0
  9. package/dist/Carousel.d.ts.map +1 -0
  10. package/dist/Carousel.js +387 -0
  11. package/dist/Checkbox.d.ts +203 -0
  12. package/dist/Checkbox.d.ts.map +1 -0
  13. package/dist/Checkbox.js +140 -0
  14. package/dist/Collection.d.ts +254 -0
  15. package/dist/Collection.d.ts.map +1 -0
  16. package/dist/Collection.js +218 -0
  17. package/dist/Combobox.d.ts +516 -0
  18. package/dist/Combobox.d.ts.map +1 -0
  19. package/dist/Combobox.js +371 -0
  20. package/dist/Component.d.ts +127 -0
  21. package/dist/Component.d.ts.map +1 -0
  22. package/dist/Component.js +60 -0
  23. package/dist/Composite.d.ts +823 -0
  24. package/dist/Composite.d.ts.map +1 -0
  25. package/dist/Composite.js +615 -0
  26. package/dist/Dialog.d.ts +544 -0
  27. package/dist/Dialog.d.ts.map +1 -0
  28. package/dist/Dialog.js +355 -0
  29. package/dist/Disclosure.d.ts +219 -0
  30. package/dist/Disclosure.d.ts.map +1 -0
  31. package/dist/Disclosure.js +128 -0
  32. package/dist/Dom/Events.d.ts +122 -0
  33. package/dist/Dom/Events.d.ts.map +1 -0
  34. package/dist/Dom/Events.js +192 -0
  35. package/dist/Dom/Props.d.ts +161 -0
  36. package/dist/Dom/Props.d.ts.map +1 -0
  37. package/dist/Dom/Props.js +110 -0
  38. package/dist/Dom/Refs.d.ts +58 -0
  39. package/dist/Dom/Refs.d.ts.map +1 -0
  40. package/dist/Dom/Refs.js +61 -0
  41. package/dist/Dom/Render.d.ts +59 -0
  42. package/dist/Dom/Render.d.ts.map +1 -0
  43. package/dist/Dom/Render.js +71 -0
  44. package/dist/Dom/Types.d.ts +570 -0
  45. package/dist/Dom/Types.d.ts.map +1 -0
  46. package/dist/Dom/Types.js +1 -0
  47. package/dist/Dom/index.d.ts +20 -0
  48. package/dist/Dom/index.d.ts.map +1 -0
  49. package/dist/Dom/index.js +8 -0
  50. package/dist/Dom.d.ts +14 -0
  51. package/dist/Dom.d.ts.map +1 -0
  52. package/dist/Dom.js +13 -0
  53. package/dist/Focusable.d.ts +85 -0
  54. package/dist/Focusable.d.ts.map +1 -0
  55. package/dist/Focusable.js +35 -0
  56. package/dist/Form.d.ts +1695 -0
  57. package/dist/Form.d.ts.map +1 -0
  58. package/dist/Form.js +987 -0
  59. package/dist/Grid.d.ts +569 -0
  60. package/dist/Grid.d.ts.map +1 -0
  61. package/dist/Grid.js +379 -0
  62. package/dist/Group.d.ts +147 -0
  63. package/dist/Group.d.ts.map +1 -0
  64. package/dist/Group.js +63 -0
  65. package/dist/Heading.d.ts +86 -0
  66. package/dist/Heading.d.ts.map +1 -0
  67. package/dist/Heading.js +48 -0
  68. package/dist/Hovercard.d.ts +297 -0
  69. package/dist/Hovercard.d.ts.map +1 -0
  70. package/dist/Hovercard.js +188 -0
  71. package/dist/HttpRouter.d.ts +129 -6
  72. package/dist/HttpRouter.d.ts.map +1 -1
  73. package/dist/HttpRouter.js +196 -53
  74. package/dist/Link.d.ts +67 -28
  75. package/dist/Link.d.ts.map +1 -1
  76. package/dist/Link.js +91 -37
  77. package/dist/Listbox.d.ts +437 -0
  78. package/dist/Listbox.d.ts.map +1 -0
  79. package/dist/Listbox.js +316 -0
  80. package/dist/Menu.d.ts +972 -0
  81. package/dist/Menu.d.ts.map +1 -0
  82. package/dist/Menu.js +731 -0
  83. package/dist/Menubar.d.ts +367 -0
  84. package/dist/Menubar.d.ts.map +1 -0
  85. package/dist/Menubar.js +265 -0
  86. package/dist/Meter.d.ts +217 -0
  87. package/dist/Meter.d.ts.map +1 -0
  88. package/dist/Meter.js +94 -0
  89. package/dist/NativeDetails.d.ts +41 -0
  90. package/dist/NativeDetails.d.ts.map +1 -0
  91. package/dist/NativeDetails.js +40 -0
  92. package/dist/NativeDialog.d.ts +64 -0
  93. package/dist/NativeDialog.d.ts.map +1 -0
  94. package/dist/NativeDialog.js +50 -0
  95. package/dist/NativePopover.d.ts +41 -0
  96. package/dist/NativePopover.d.ts.map +1 -0
  97. package/dist/NativePopover.js +46 -0
  98. package/dist/Popover.d.ts +241 -0
  99. package/dist/Popover.d.ts.map +1 -0
  100. package/dist/Popover.js +141 -0
  101. package/dist/RadioGroup.d.ts +432 -0
  102. package/dist/RadioGroup.d.ts.map +1 -0
  103. package/dist/RadioGroup.js +291 -0
  104. package/dist/Role.d.ts +64 -0
  105. package/dist/Role.d.ts.map +1 -0
  106. package/dist/Role.js +27 -0
  107. package/dist/Select.d.ts +529 -0
  108. package/dist/Select.d.ts.map +1 -0
  109. package/dist/Select.js +407 -0
  110. package/dist/Separator.d.ts +54 -0
  111. package/dist/Separator.d.ts.map +1 -0
  112. package/dist/Separator.js +26 -0
  113. package/dist/Slider.d.ts +188 -0
  114. package/dist/Slider.d.ts.map +1 -0
  115. package/dist/Slider.js +96 -0
  116. package/dist/SpinButton.d.ts +188 -0
  117. package/dist/SpinButton.d.ts.map +1 -0
  118. package/dist/SpinButton.js +96 -0
  119. package/dist/Storybook.d.ts +76 -0
  120. package/dist/Storybook.d.ts.map +1 -0
  121. package/dist/Storybook.js +102 -0
  122. package/dist/Switch.d.ts +187 -0
  123. package/dist/Switch.d.ts.map +1 -0
  124. package/dist/Switch.js +116 -0
  125. package/dist/Tab.d.ts +26 -0
  126. package/dist/Tab.d.ts.map +1 -0
  127. package/dist/Tab.js +25 -0
  128. package/dist/Tabs.d.ts +591 -0
  129. package/dist/Tabs.d.ts.map +1 -0
  130. package/dist/Tabs.js +346 -0
  131. package/dist/Toolbar.d.ts +366 -0
  132. package/dist/Toolbar.d.ts.map +1 -0
  133. package/dist/Toolbar.js +245 -0
  134. package/dist/Tooltip.d.ts +296 -0
  135. package/dist/Tooltip.d.ts.map +1 -0
  136. package/dist/Tooltip.js +172 -0
  137. package/dist/Tree.d.ts +591 -0
  138. package/dist/Tree.d.ts.map +1 -0
  139. package/dist/Tree.js +434 -0
  140. package/dist/TreeGrid.d.ts +645 -0
  141. package/dist/TreeGrid.d.ts.map +1 -0
  142. package/dist/TreeGrid.js +420 -0
  143. package/dist/VisuallyHidden.d.ts +54 -0
  144. package/dist/VisuallyHidden.d.ts.map +1 -0
  145. package/dist/VisuallyHidden.js +27 -0
  146. package/dist/WindowSplitter.d.ts +376 -0
  147. package/dist/WindowSplitter.d.ts.map +1 -0
  148. package/dist/WindowSplitter.js +222 -0
  149. package/dist/index.d.ts +49 -0
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +49 -0
  152. package/package.json +45 -18
  153. package/src/HttpRouter.test.ts +0 -256
  154. package/src/HttpRouter.ts +0 -165
  155. package/src/Link.test.ts +0 -84
  156. package/src/Link.ts +0 -107
  157. package/src/index.ts +0 -2
@@ -0,0 +1,217 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Schema from "effect/Schema";
3
+ import { RefSubject } from "@typed/fx";
4
+ import { type Renderable } from "@typed/template";
5
+ import * as Dom from "./Dom.js";
6
+ import type { HostResult } from "./Dom/Types.js";
7
+ /** Current value displayed by the meter.
8
+ * @remarks
9
+ * ## Why
10
+ * Renderer-independent state can be updated and tested before a meter mounts.
11
+ * ## Ownership and lifetime
12
+ * Plain state acquires no resources; the hydrated RefSubject owns observation.
13
+ * @since 1.0.0
14
+ * @category state
15
+ */
16
+ export interface State {
17
+ /** Finite scalar reflected to the native meter value.
18
+ * @remarks
19
+ * ## Why
20
+ * One value drives DOM output and state consumers consistently.
21
+ * ## Ownership and lifetime
22
+ * Plain data retains no resources.
23
+ * @since 1.0.0
24
+ * @category state
25
+ */
26
+ readonly value: number;
27
+ }
28
+ /** Initial finite meter value.
29
+ * @remarks
30
+ * ## Why
31
+ * Explicit input makes the hydration snapshot deterministic.
32
+ * ## Ownership and lifetime
33
+ * Configuration is inert and copied into state.
34
+ * @since 1.0.0
35
+ * @category state
36
+ */
37
+ export interface InitialState {
38
+ /** Value used for the initial snapshot.
39
+ * @remarks
40
+ * ## Why
41
+ * The native meter needs a concrete value independent of its range metadata.
42
+ * ## Ownership and lifetime
43
+ * Plain data acquires no resources.
44
+ * @since 1.0.0
45
+ * @category state
46
+ */
47
+ readonly value: number;
48
+ }
49
+ /** Schema for serializing finite meter state.
50
+ * @remarks
51
+ * ## Why
52
+ * Rejecting non-finite values keeps SSR and native DOM output valid.
53
+ * ## Ownership and lifetime
54
+ * The immutable schema acquires no resources.
55
+ * @since 1.0.0
56
+ * @category schemas
57
+ */
58
+ export declare const StateSchema: Schema.Struct<{
59
+ readonly value: Schema.Finite;
60
+ }>;
61
+ /** Creates hydrated meter state.
62
+ * @remarks
63
+ * ## Why
64
+ * The state remains testable and reusable without rendering a UI component.
65
+ * ## Ownership and lifetime
66
+ * The caller's Effect Scope owns the hydrated RefSubject.
67
+ * @example
68
+ * ```ts
69
+ * import { Effect } from "effect"
70
+ * import * as Meter from "@typed/ui/Meter"
71
+ *
72
+ * const program = Effect.gen(function* () {
73
+ * return yield* Meter.makeState({ value: 0.72 })
74
+ * })
75
+ * ```
76
+ * @since 1.0.0
77
+ * @category constructors
78
+ */
79
+ export declare function makeState(initial: InitialState): Effect.Effect<RefSubject.HydratedRefSubject<{
80
+ readonly value: number;
81
+ }, Schema.SchemaError, never, never>, never, import("effect/Scope").Scope>;
82
+ /** Updates the displayed meter value.
83
+ * @remarks
84
+ * ## Why
85
+ * State transitions stay outside rendering and preserve typed error/services.
86
+ * ## Ownership and lifetime
87
+ * The Effect uses the existing RefSubject lifetime and acquires no resource.
88
+ * @example
89
+ * ```ts
90
+ * import { Effect } from "effect"
91
+ * import * as Meter from "@typed/ui/Meter"
92
+ *
93
+ * const program = Effect.gen(function* () {
94
+ * const state = yield* Meter.makeState({ value: 0 })
95
+ * yield* Meter.setValue(state, 0.75)
96
+ * })
97
+ * ```
98
+ * @since 1.0.0
99
+ * @category state
100
+ */
101
+ export declare function setValue<E, R>(state: RefSubject.RefSubject<State, E, R>, value: number): Effect.Effect<State, E, R>;
102
+ /** Native meter range, threshold, content, and state options.
103
+ * @remarks
104
+ * ## Why
105
+ * These mirror the platform meter element rather than reimplementing its
106
+ * accessibility and range interpretation.
107
+ * ## Ownership and lifetime
108
+ * Options are inert; rendering owns reactive subscriptions by Scope.
109
+ * @since 1.0.0
110
+ * @category models
111
+ */
112
+ export interface MeterOptions extends Dom.HostOptions<HTMLMeterElement> {
113
+ /** Hydrated value state borrowed by the element.
114
+ * @remarks
115
+ * ## Why
116
+ * One source keeps the native value and application state aligned.
117
+ * ## Ownership and lifetime
118
+ * Its original Scope owns it; the component only subscribes while mounted.
119
+ * @since 1.0.0
120
+ * @category state
121
+ */
122
+ readonly state: RefSubject.HydratedRefSubject<State, Schema.SchemaError>;
123
+ /** Lower bound of the measured range.
124
+ * @remarks
125
+ * ## Why
126
+ * Native meter semantics use the bound to interpret `value`.
127
+ * ## Ownership and lifetime
128
+ * Dynamic attributes follow the component Scope.
129
+ * @since 1.0.0
130
+ * @category attributes
131
+ */
132
+ readonly min?: Renderable.Any<number | null | undefined>;
133
+ /** Upper bound of the measured range.
134
+ * @remarks
135
+ * ## Why
136
+ * Native meter semantics use the bound to interpret `value`.
137
+ * ## Ownership and lifetime
138
+ * Dynamic attributes follow the component Scope.
139
+ * @since 1.0.0
140
+ * @category attributes
141
+ */
142
+ readonly max?: Renderable.Any<number | null | undefined>;
143
+ /** Boundary below which values are considered low.
144
+ * @remarks
145
+ * ## Why
146
+ * The browser uses this native threshold with `high` and `optimum`.
147
+ * ## Ownership and lifetime
148
+ * Dynamic attributes follow the component Scope.
149
+ * @since 1.0.0
150
+ * @category attributes
151
+ */
152
+ readonly low?: Renderable.Any<number | null | undefined>;
153
+ /** Boundary above which values are considered high.
154
+ * @remarks
155
+ * ## Why
156
+ * It preserves native threshold semantics and accessibility exposure.
157
+ * ## Ownership and lifetime
158
+ * Dynamic attributes follow the component Scope.
159
+ * @since 1.0.0
160
+ * @category attributes
161
+ */
162
+ readonly high?: Renderable.Any<number | null | undefined>;
163
+ /** Preferred value within the meter range.
164
+ * @remarks
165
+ * ## Why
166
+ * Native rendering interprets threshold quality relative to this value.
167
+ * ## Ownership and lifetime
168
+ * Dynamic attributes follow the component Scope.
169
+ * @since 1.0.0
170
+ * @category attributes
171
+ */
172
+ readonly optimum?: Renderable.Any<number | null | undefined>;
173
+ /** Fallback content rendered inside the meter.
174
+ * @remarks
175
+ * ## Why
176
+ * Text content provides useful output where meter rendering is unavailable.
177
+ * ## Ownership and lifetime
178
+ * Dynamic content follows the component Scope.
179
+ * @since 1.0.0
180
+ * @category content
181
+ */
182
+ readonly content?: Renderable.Any;
183
+ }
184
+ declare function internalProps<const Options extends MeterOptions>(options: Options): ({ property }: Dom.InternalPropsHelpers<Options>) => {
185
+ readonly value: RefSubject.Computed<number, Schema.SchemaError, never>;
186
+ readonly min: Exclude<Dom.Property<Options, "min">, Dom.Nullish> | undefined;
187
+ readonly max: Exclude<Dom.Property<Options, "max">, Dom.Nullish> | undefined;
188
+ readonly low: Exclude<Dom.Property<Options, "low">, Dom.Nullish> | undefined;
189
+ readonly high: Exclude<Dom.Property<Options, "high">, Dom.Nullish> | undefined;
190
+ readonly optimum: Exclude<Dom.Property<Options, "optimum">, Dom.Nullish> | undefined;
191
+ readonly ref: RefSubject.HydratedRefSubject<State, Schema.SchemaError, never, never>;
192
+ };
193
+ type MeterInternalProps<Options extends MeterOptions> = ReturnType<ReturnType<typeof internalProps<Options>>>;
194
+ /** Renders a native `<meter>` synchronized with hydrated state.
195
+ * @remarks
196
+ * ## Why
197
+ * The platform owns range semantics and accessibility while Typed composes
198
+ * reactive state and custom hosts around the real element.
199
+ * ## Ownership and lifetime
200
+ * Running the Fx owns attribute/state subscriptions until its Scope closes. A
201
+ * custom host must preserve native meter attributes and the hydration ref.
202
+ * @example
203
+ * ```ts
204
+ * import { Effect } from "effect"
205
+ * import * as Meter from "@typed/ui/Meter"
206
+ *
207
+ * const program = Effect.gen(function* () {
208
+ * const state = yield* Meter.makeState({ value: 64 })
209
+ * return Meter.Meter({ state, min: 0, max: 100 })
210
+ * })
211
+ * ```
212
+ * @since 1.0.0
213
+ * @category components
214
+ */
215
+ export declare function Meter<const Options extends MeterOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, MeterInternalProps<Options>>, Options["content"], Host>): import("./Dom/Types.js").HostComponent<Host | Options>;
216
+ export {};
217
+ //# sourceMappingURL=Meter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Meter.d.ts","sourceRoot":"","sources":["../src/Meter.ts"],"names":[],"mappings":"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"}
package/dist/Meter.js ADDED
@@ -0,0 +1,94 @@
1
+ import * as Schema from "effect/Schema";
2
+ import { RefSubject } from "@typed/fx";
3
+ import { html } from "@typed/template";
4
+ import * as Dom from "./Dom.js";
5
+ /** Schema for serializing finite meter state.
6
+ * @remarks
7
+ * ## Why
8
+ * Rejecting non-finite values keeps SSR and native DOM output valid.
9
+ * ## Ownership and lifetime
10
+ * The immutable schema acquires no resources.
11
+ * @since 1.0.0
12
+ * @category schemas
13
+ */
14
+ export const StateSchema = Schema.Struct({ value: Schema.Finite });
15
+ /** Creates hydrated meter state.
16
+ * @remarks
17
+ * ## Why
18
+ * The state remains testable and reusable without rendering a UI component.
19
+ * ## Ownership and lifetime
20
+ * The caller's Effect Scope owns the hydrated RefSubject.
21
+ * @example
22
+ * ```ts
23
+ * import { Effect } from "effect"
24
+ * import * as Meter from "@typed/ui/Meter"
25
+ *
26
+ * const program = Effect.gen(function* () {
27
+ * return yield* Meter.makeState({ value: 0.72 })
28
+ * })
29
+ * ```
30
+ * @since 1.0.0
31
+ * @category constructors
32
+ */
33
+ export function makeState(initial) {
34
+ return RefSubject.hydrate(StateSchema, initial);
35
+ }
36
+ /** Updates the displayed meter value.
37
+ * @remarks
38
+ * ## Why
39
+ * State transitions stay outside rendering and preserve typed error/services.
40
+ * ## Ownership and lifetime
41
+ * The Effect uses the existing RefSubject lifetime and acquires no resource.
42
+ * @example
43
+ * ```ts
44
+ * import { Effect } from "effect"
45
+ * import * as Meter from "@typed/ui/Meter"
46
+ *
47
+ * const program = Effect.gen(function* () {
48
+ * const state = yield* Meter.makeState({ value: 0 })
49
+ * yield* Meter.setValue(state, 0.75)
50
+ * })
51
+ * ```
52
+ * @since 1.0.0
53
+ * @category state
54
+ */
55
+ export function setValue(state, value) {
56
+ return RefSubject.update(state, (current) => ({ ...current, value }));
57
+ }
58
+ function internalProps(options) {
59
+ return ({ property }) => ({
60
+ value: RefSubject.map(options.state, (state) => state.value),
61
+ min: property("min", undefined),
62
+ max: property("max", undefined),
63
+ low: property("low", undefined),
64
+ high: property("high", undefined),
65
+ optimum: property("optimum", undefined),
66
+ ref: options.state,
67
+ });
68
+ }
69
+ /** Renders a native `<meter>` synchronized with hydrated state.
70
+ * @remarks
71
+ * ## Why
72
+ * The platform owns range semantics and accessibility while Typed composes
73
+ * reactive state and custom hosts around the real element.
74
+ * ## Ownership and lifetime
75
+ * Running the Fx owns attribute/state subscriptions until its Scope closes. A
76
+ * custom host must preserve native meter attributes and the hydration ref.
77
+ * @example
78
+ * ```ts
79
+ * import { Effect } from "effect"
80
+ * import * as Meter from "@typed/ui/Meter"
81
+ *
82
+ * const program = Effect.gen(function* () {
83
+ * const state = yield* Meter.makeState({ value: 64 })
84
+ * return Meter.Meter({ state, min: 0, max: 100 })
85
+ * })
86
+ * ```
87
+ * @since 1.0.0
88
+ * @category components
89
+ */
90
+ export function Meter(options, host) {
91
+ return Dom.renderHost()(options, host, internalProps(options), options.content ?? "", (props, content) => {
92
+ return html `<meter ...${props}>${content}</meter>`;
93
+ });
94
+ }
@@ -0,0 +1,41 @@
1
+ import * as Effect from "effect/Effect";
2
+ import type * as Scope from "effect/Scope";
3
+ import { RefSubject } from "@typed/fx";
4
+ interface State {
5
+ readonly open: boolean;
6
+ }
7
+ /**
8
+ * Creates a scoped ref that synchronizes state to a native `<details>` element.
9
+ *
10
+ * @remarks
11
+ * ## Why
12
+ *
13
+ * `<details>` already owns disclosure rendering and keyboard behavior. This ref
14
+ * only applies pushed `open` state to that real element; the public Disclosure
15
+ * component listens to native `toggle` events for the reverse direction.
16
+ *
17
+ * ## Ownership and lifetime
18
+ *
19
+ * Applying the ref forks one observer in the current Effect Scope. Scope
20
+ * finalization interrupts it; the state remains owned by its original Scope and
21
+ * the DOM element remains owned by its renderer. Use only one hydration ref
22
+ * owner for an element.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { Effect } from "effect"
27
+ * import * as Disclosure from "@typed/ui/Disclosure"
28
+ * import * as NativeDetails from "@typed/ui/NativeDetails"
29
+ *
30
+ * const program = Effect.gen(function* () {
31
+ * const state = yield* Disclosure.makeState()
32
+ * return NativeDetails.ref(state)
33
+ * })
34
+ * ```
35
+ *
36
+ * @since 1.0.0
37
+ * @category refs
38
+ */
39
+ export declare function ref<S extends State, E, R>(state: RefSubject.RefSubject<S, E, R>): (element: HTMLDetailsElement) => Effect.Effect<void, E, R | Scope.Scope>;
40
+ export {};
41
+ //# sourceMappingURL=NativeDetails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeDetails.d.ts","sourceRoot":"","sources":["../src/NativeDetails.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAM,UAAU,EAAE,MAAM,WAAW,CAAC;AAE3C,UAAU,KAAK;IACb,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,CAAC,EACvC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GACpC,CAAC,OAAO,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAe1E"}
@@ -0,0 +1,40 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { Fx } from "@typed/fx";
3
+ /**
4
+ * Creates a scoped ref that synchronizes state to a native `<details>` element.
5
+ *
6
+ * @remarks
7
+ * ## Why
8
+ *
9
+ * `<details>` already owns disclosure rendering and keyboard behavior. This ref
10
+ * only applies pushed `open` state to that real element; the public Disclosure
11
+ * component listens to native `toggle` events for the reverse direction.
12
+ *
13
+ * ## Ownership and lifetime
14
+ *
15
+ * Applying the ref forks one observer in the current Effect Scope. Scope
16
+ * finalization interrupts it; the state remains owned by its original Scope and
17
+ * the DOM element remains owned by its renderer. Use only one hydration ref
18
+ * owner for an element.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { Effect } from "effect"
23
+ * import * as Disclosure from "@typed/ui/Disclosure"
24
+ * import * as NativeDetails from "@typed/ui/NativeDetails"
25
+ *
26
+ * const program = Effect.gen(function* () {
27
+ * const state = yield* Disclosure.makeState()
28
+ * return NativeDetails.ref(state)
29
+ * })
30
+ * ```
31
+ *
32
+ * @since 1.0.0
33
+ * @category refs
34
+ */
35
+ export function ref(state) {
36
+ return Effect.fn((element) => Effect.asVoid(Effect.forkScoped(Fx.observe(state, Effect.fn((value) => Effect.sync(() => {
37
+ if (element.open !== value.open)
38
+ element.open = value.open;
39
+ }))))));
40
+ }
@@ -0,0 +1,64 @@
1
+ import * as Effect from "effect/Effect";
2
+ import type * as Scope from "effect/Scope";
3
+ import { RefSubject } from "@typed/fx";
4
+ interface State {
5
+ readonly open: boolean;
6
+ }
7
+ /** Native dialog synchronization mode.
8
+ * @remarks
9
+ * ## Why
10
+ * The choice maps directly to `showModal()` or `show()` rather than simulating
11
+ * modality in application code.
12
+ * ## Ownership and lifetime
13
+ * Options are inert and retain no resources.
14
+ * @since 1.0.0
15
+ * @category models
16
+ */
17
+ export interface Options {
18
+ /** Whether opening uses the modal top layer; defaults to true.
19
+ * @remarks
20
+ * ## Why
21
+ * Modal and non-modal dialogs have different focus, inertness, and dismissal
22
+ * behavior owned by the browser.
23
+ * ## Ownership and lifetime
24
+ * The flag is read during synchronization and retains no resources.
25
+ * @since 1.0.0
26
+ * @category behavior
27
+ */
28
+ readonly modal?: boolean;
29
+ }
30
+ /**
31
+ * Creates a scoped ref that drives a real `HTMLDialogElement` from state.
32
+ *
33
+ * @remarks
34
+ * ## Why
35
+ *
36
+ * The ref delegates open/close, top-layer placement, focus handling, and modal
37
+ * inertness to `showModal()`, `show()`, and `close()`. It does not reproduce a
38
+ * dialog with ordinary divs or synthetic events.
39
+ *
40
+ * ## Ownership and lifetime
41
+ *
42
+ * Applying the ref forks an observer in the current Effect Scope. Finalization
43
+ * interrupts that observer but does not close state owned elsewhere or remove
44
+ * the element. `Dialog.Content` handles native `cancel`, `close`, and `toggle`
45
+ * events and composes exactly one hydration owner.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { Effect } from "effect"
50
+ * import * as Dialog from "@typed/ui/Dialog"
51
+ * import * as NativeDialog from "@typed/ui/NativeDialog"
52
+ *
53
+ * const program = Effect.gen(function* () {
54
+ * const state = yield* Dialog.makeState()
55
+ * return NativeDialog.ref(state, { modal: true })
56
+ * })
57
+ * ```
58
+ *
59
+ * @since 1.0.0
60
+ * @category refs
61
+ */
62
+ export declare function ref<S extends State, E, R>(state: RefSubject.RefSubject<S, E, R>, options?: Options): (element: HTMLDialogElement) => Effect.Effect<void, E, R | Scope.Scope>;
63
+ export {};
64
+ //# sourceMappingURL=NativeDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeDialog.d.ts","sourceRoot":"","sources":["../src/NativeDialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAM,UAAU,EAAE,MAAM,WAAW,CAAC;AAE3C,UAAU,KAAK;IACb,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,CAAC,EACvC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACrC,OAAO,GAAE,OAAY,GACpB,CAAC,OAAO,EAAE,iBAAiB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAWzE"}
@@ -0,0 +1,50 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { Fx } from "@typed/fx";
3
+ /**
4
+ * Creates a scoped ref that drives a real `HTMLDialogElement` from state.
5
+ *
6
+ * @remarks
7
+ * ## Why
8
+ *
9
+ * The ref delegates open/close, top-layer placement, focus handling, and modal
10
+ * inertness to `showModal()`, `show()`, and `close()`. It does not reproduce a
11
+ * dialog with ordinary divs or synthetic events.
12
+ *
13
+ * ## Ownership and lifetime
14
+ *
15
+ * Applying the ref forks an observer in the current Effect Scope. Finalization
16
+ * interrupts that observer but does not close state owned elsewhere or remove
17
+ * the element. `Dialog.Content` handles native `cancel`, `close`, and `toggle`
18
+ * events and composes exactly one hydration owner.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { Effect } from "effect"
23
+ * import * as Dialog from "@typed/ui/Dialog"
24
+ * import * as NativeDialog from "@typed/ui/NativeDialog"
25
+ *
26
+ * const program = Effect.gen(function* () {
27
+ * const state = yield* Dialog.makeState()
28
+ * return NativeDialog.ref(state, { modal: true })
29
+ * })
30
+ * ```
31
+ *
32
+ * @since 1.0.0
33
+ * @category refs
34
+ */
35
+ export function ref(state, options = {}) {
36
+ return Effect.fn((element) => Effect.asVoid(Effect.forkScoped(Fx.observe(state, Effect.fn((value) => Effect.sync(() => synchronize(element, value.open, options)))))));
37
+ }
38
+ function synchronize(element, open, options) {
39
+ if (open) {
40
+ if (element.open)
41
+ return;
42
+ if (options.modal === false)
43
+ element.show();
44
+ else
45
+ element.showModal();
46
+ }
47
+ else if (element.open) {
48
+ element.close();
49
+ }
50
+ }
@@ -0,0 +1,41 @@
1
+ import * as Effect from "effect/Effect";
2
+ import type * as Scope from "effect/Scope";
3
+ import { RefSubject } from "@typed/fx";
4
+ interface State {
5
+ readonly open: boolean;
6
+ }
7
+ /**
8
+ * Creates a scoped ref that synchronizes state with the native Popover API.
9
+ *
10
+ * @remarks
11
+ * ## Why
12
+ *
13
+ * The browser owns top-layer placement and popover lifecycle. The ref checks
14
+ * `:popover-open` before calling `showPopover()` or `hidePopover()`, avoiding
15
+ * invalid duplicate transitions while preserving native toggle events.
16
+ *
17
+ * ## Ownership and lifetime
18
+ *
19
+ * Applying the ref forks one observer in the current Effect Scope. Closing the
20
+ * Scope interrupts it; it does not remove the host or close the caller-owned
21
+ * state. The host must support the Popover API and retain its `popover`
22
+ * attribute. Only one hydration owner may be composed for the element.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { Effect } from "effect"
27
+ * import * as NativePopover from "@typed/ui/NativePopover"
28
+ * import * as Popover from "@typed/ui/Popover"
29
+ *
30
+ * const program = Effect.gen(function* () {
31
+ * const state = yield* Popover.makeState()
32
+ * return NativePopover.ref(state)
33
+ * })
34
+ * ```
35
+ *
36
+ * @since 1.0.0
37
+ * @category refs
38
+ */
39
+ export declare function ref<S extends State, E, R>(state: RefSubject.RefSubject<S, E, R>): (element: HTMLElement) => Effect.Effect<void, E, R | Scope.Scope>;
40
+ export {};
41
+ //# sourceMappingURL=NativePopover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativePopover.d.ts","sourceRoot":"","sources":["../src/NativePopover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAM,UAAU,EAAE,MAAM,WAAW,CAAC;AAE3C,UAAU,KAAK;IACb,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,CAAC,EACvC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GACpC,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAWnE"}
@@ -0,0 +1,46 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { Fx } from "@typed/fx";
3
+ /**
4
+ * Creates a scoped ref that synchronizes state with the native Popover API.
5
+ *
6
+ * @remarks
7
+ * ## Why
8
+ *
9
+ * The browser owns top-layer placement and popover lifecycle. The ref checks
10
+ * `:popover-open` before calling `showPopover()` or `hidePopover()`, avoiding
11
+ * invalid duplicate transitions while preserving native toggle events.
12
+ *
13
+ * ## Ownership and lifetime
14
+ *
15
+ * Applying the ref forks one observer in the current Effect Scope. Closing the
16
+ * Scope interrupts it; it does not remove the host or close the caller-owned
17
+ * state. The host must support the Popover API and retain its `popover`
18
+ * attribute. Only one hydration owner may be composed for the element.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { Effect } from "effect"
23
+ * import * as NativePopover from "@typed/ui/NativePopover"
24
+ * import * as Popover from "@typed/ui/Popover"
25
+ *
26
+ * const program = Effect.gen(function* () {
27
+ * const state = yield* Popover.makeState()
28
+ * return NativePopover.ref(state)
29
+ * })
30
+ * ```
31
+ *
32
+ * @since 1.0.0
33
+ * @category refs
34
+ */
35
+ export function ref(state) {
36
+ return Effect.fn((element) => Effect.asVoid(Effect.forkScoped(Fx.observe(state, Effect.fn((value) => Effect.sync(() => synchronize(element, value.open)))))));
37
+ }
38
+ function synchronize(element, open) {
39
+ if (open) {
40
+ if (!element.matches(":popover-open"))
41
+ element.showPopover();
42
+ }
43
+ else if (element.matches(":popover-open")) {
44
+ element.hidePopover();
45
+ }
46
+ }