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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/Alert.d.ts +35 -41
  2. package/dist/Alert.d.ts.map +1 -1
  3. package/dist/Alert.js +23 -20
  4. package/dist/Button.d.ts +34 -78
  5. package/dist/Button.d.ts.map +1 -1
  6. package/dist/Button.js +16 -12
  7. package/dist/Carousel.d.ts +35 -236
  8. package/dist/Carousel.d.ts.map +1 -1
  9. package/dist/Carousel.js +13 -136
  10. package/dist/Checkbox.d.ts +55 -90
  11. package/dist/Checkbox.d.ts.map +1 -1
  12. package/dist/Checkbox.js +44 -38
  13. package/dist/Collection.d.ts +15 -15
  14. package/dist/Collection.js +7 -7
  15. package/dist/Combobox.d.ts +38 -187
  16. package/dist/Combobox.d.ts.map +1 -1
  17. package/dist/Combobox.js +9 -80
  18. package/dist/Component.d.ts +30 -24
  19. package/dist/Component.d.ts.map +1 -1
  20. package/dist/Component.js +23 -12
  21. package/dist/Composite.d.ts +50 -50
  22. package/dist/Composite.js +20 -20
  23. package/dist/Dialog.d.ts +34 -34
  24. package/dist/Dialog.d.ts.map +1 -1
  25. package/dist/Dialog.js +16 -14
  26. package/dist/Disclosure.d.ts +15 -15
  27. package/dist/Disclosure.js +6 -6
  28. package/dist/Dom/Events.d.ts +4 -4
  29. package/dist/Dom/Events.js +4 -4
  30. package/dist/Dom/Props.d.ts +9 -9
  31. package/dist/Dom/Props.js +4 -4
  32. package/dist/Dom/Refs.d.ts +2 -2
  33. package/dist/Dom/Refs.js +1 -1
  34. package/dist/Dom/Render.d.ts +2 -2
  35. package/dist/Dom/Render.js +2 -2
  36. package/dist/Dom/Types.d.ts +33 -33
  37. package/dist/Dom/index.d.ts +5 -5
  38. package/dist/Dom/index.d.ts.map +1 -1
  39. package/dist/Dom/index.js +4 -4
  40. package/dist/Dom.d.ts +1 -1
  41. package/dist/Dom.js +1 -1
  42. package/dist/Focusable.d.ts +5 -5
  43. package/dist/Focusable.js +1 -1
  44. package/dist/Form.d.ts +565 -533
  45. package/dist/Form.d.ts.map +1 -1
  46. package/dist/Form.js +350 -195
  47. package/dist/Grid.d.ts +39 -220
  48. package/dist/Grid.d.ts.map +1 -1
  49. package/dist/Grid.js +12 -107
  50. package/dist/Group.d.ts +50 -69
  51. package/dist/Group.d.ts.map +1 -1
  52. package/dist/Group.js +33 -25
  53. package/dist/Heading.d.ts +41 -40
  54. package/dist/Heading.d.ts.map +1 -1
  55. package/dist/Heading.js +26 -16
  56. package/dist/Hovercard.d.ts +18 -18
  57. package/dist/Hovercard.js +6 -6
  58. package/dist/HttpRouter.d.ts +3 -3
  59. package/dist/HttpRouter.js +5 -5
  60. package/dist/Link.d.ts +17 -21
  61. package/dist/Link.d.ts.map +1 -1
  62. package/dist/Link.js +11 -0
  63. package/dist/Listbox.d.ts +31 -163
  64. package/dist/Listbox.d.ts.map +1 -1
  65. package/dist/Listbox.js +9 -80
  66. package/dist/Menu.d.ts +67 -376
  67. package/dist/Menu.d.ts.map +1 -1
  68. package/dist/Menu.js +17 -179
  69. package/dist/Menubar.d.ts +24 -142
  70. package/dist/Menubar.d.ts.map +1 -1
  71. package/dist/Menubar.js +8 -66
  72. package/dist/Meter.d.ts +72 -132
  73. package/dist/Meter.d.ts.map +1 -1
  74. package/dist/Meter.js +35 -42
  75. package/dist/NativeDetails.d.ts +1 -1
  76. package/dist/NativeDetails.js +1 -1
  77. package/dist/NativeDialog.d.ts +7 -5
  78. package/dist/NativeDialog.d.ts.map +1 -1
  79. package/dist/NativeDialog.js +42 -4
  80. package/dist/NativePopover.d.ts +6 -4
  81. package/dist/NativePopover.d.ts.map +1 -1
  82. package/dist/NativePopover.js +43 -5
  83. package/dist/Popover.d.ts +18 -19
  84. package/dist/Popover.d.ts.map +1 -1
  85. package/dist/Popover.js +7 -8
  86. package/dist/RadioGroup.d.ts +86 -188
  87. package/dist/RadioGroup.d.ts.map +1 -1
  88. package/dist/RadioGroup.js +55 -105
  89. package/dist/Role.d.ts +4 -4
  90. package/dist/Role.js +1 -1
  91. package/dist/Select.d.ts +109 -220
  92. package/dist/Select.d.ts.map +1 -1
  93. package/dist/Select.js +67 -117
  94. package/dist/Separator.d.ts +30 -26
  95. package/dist/Separator.d.ts.map +1 -1
  96. package/dist/Separator.js +16 -10
  97. package/dist/Slider.d.ts +64 -111
  98. package/dist/Slider.d.ts.map +1 -1
  99. package/dist/Slider.js +47 -42
  100. package/dist/SpinButton.d.ts +64 -111
  101. package/dist/SpinButton.d.ts.map +1 -1
  102. package/dist/SpinButton.js +47 -42
  103. package/dist/Storybook.d.ts +2 -2
  104. package/dist/Storybook.js +1 -1
  105. package/dist/Switch.d.ts +52 -91
  106. package/dist/Switch.d.ts.map +1 -1
  107. package/dist/Switch.js +30 -36
  108. package/dist/Tabs.d.ts +44 -224
  109. package/dist/Tabs.d.ts.map +1 -1
  110. package/dist/Tabs.js +10 -94
  111. package/dist/Toolbar.d.ts +24 -142
  112. package/dist/Toolbar.d.ts.map +1 -1
  113. package/dist/Toolbar.js +8 -66
  114. package/dist/Tooltip.d.ts +20 -20
  115. package/dist/Tooltip.js +6 -6
  116. package/dist/Tree.d.ts +43 -229
  117. package/dist/Tree.d.ts.map +1 -1
  118. package/dist/Tree.js +12 -113
  119. package/dist/TreeGrid.d.ts +45 -264
  120. package/dist/TreeGrid.d.ts.map +1 -1
  121. package/dist/TreeGrid.js +13 -125
  122. package/dist/VisuallyHidden.d.ts +41 -27
  123. package/dist/VisuallyHidden.d.ts.map +1 -1
  124. package/dist/VisuallyHidden.js +27 -10
  125. package/dist/WindowSplitter.d.ts +68 -108
  126. package/dist/WindowSplitter.d.ts.map +1 -1
  127. package/dist/WindowSplitter.js +106 -23
  128. package/package.json +9 -8
package/dist/Meter.d.ts CHANGED
@@ -1,68 +1,43 @@
1
+ /**
2
+ * A non-interactive native measurement within a known range.
3
+ * Threshold options communicate preferred regions; they do not execute alert policies.
4
+ *
5
+ * Read the [Meter guide](/explore/ui-meter) for a complete example.
6
+ *
7
+ * [APG interaction reference](https://www.w3.org/WAI/ARIA/apg/patterns/meter/).
8
+ * @since 1.0.0
9
+ * @category Overview
10
+ * @packageDocumentation
11
+ */
1
12
  import * as Effect from "effect/Effect";
2
13
  import * as Schema from "effect/Schema";
3
14
  import { RefSubject } from "@typed/fx";
4
15
  import { type Renderable } from "@typed/template";
5
16
  import * as Dom from "./Dom.js";
6
17
  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
18
+ /**
15
19
  */
16
20
  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
21
+ /**
25
22
  */
26
23
  readonly value: number;
27
24
  }
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
25
+ /**
36
26
  */
37
27
  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
28
+ /**
46
29
  */
47
30
  readonly value: number;
48
31
  }
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
32
+ /**
57
33
  */
58
34
  export declare const StateSchema: Schema.Struct<{
59
35
  readonly value: Schema.Finite;
60
36
  }>;
61
- /** Creates hydrated meter state.
37
+ /**
38
+ * Creates hydrated meter state.
62
39
  * @remarks
63
- * ## Why
64
40
  * The state remains testable and reusable without rendering a UI component.
65
- * ## Ownership and lifetime
66
41
  * The caller's Effect Scope owns the hydrated RefSubject.
67
42
  * @example
68
43
  * ```ts
@@ -74,110 +49,64 @@ export declare const StateSchema: Schema.Struct<{
74
49
  * })
75
50
  * ```
76
51
  * @since 1.0.0
77
- * @category constructors
52
+ * @category State construction
78
53
  */
79
54
  export declare function makeState(initial: InitialState): Effect.Effect<RefSubject.HydratedRefSubject<{
80
55
  readonly value: number;
81
56
  }, 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"
57
+ /**
58
+ * Assigns the displayed measurement without clamping it to the meter range.
92
59
  *
93
- * const program = Effect.gen(function* () {
94
- * const state = yield* Meter.makeState({ value: 0 })
95
- * yield* Meter.setValue(state, 0.75)
96
- * })
97
- * ```
60
+ * @remarks
61
+ * Keep measurement units consistent with min/max and threshold options. This operation does not
62
+ * execute threshold actions or validate the preferred range.
98
63
  * @since 1.0.0
99
- * @category state
64
+ * @category State transitions
100
65
  */
101
66
  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
67
+ /**
111
68
  */
112
69
  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.
70
+ /**
71
+ * Hydrated value state borrowed by the element.
119
72
  * @since 1.0.0
120
- * @category state
73
+ * @category State connection
121
74
  */
122
75
  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.
76
+ /**
77
+ * Lower bound of the measured range.
129
78
  * @since 1.0.0
130
- * @category attributes
79
+ * @category Numeric bounds
131
80
  */
132
81
  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.
82
+ /**
83
+ * Upper bound of the measured range.
139
84
  * @since 1.0.0
140
- * @category attributes
85
+ * @category Numeric bounds
141
86
  */
142
87
  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.
88
+ /**
89
+ * Boundary below which values are considered low.
149
90
  * @since 1.0.0
150
- * @category attributes
91
+ * @category Measurement thresholds
151
92
  */
152
93
  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.
94
+ /**
95
+ * Boundary above which values are considered high.
159
96
  * @since 1.0.0
160
- * @category attributes
97
+ * @category Measurement thresholds
161
98
  */
162
99
  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.
100
+ /**
101
+ * Preferred value within the meter range.
169
102
  * @since 1.0.0
170
- * @category attributes
103
+ * @category Measurement thresholds
171
104
  */
172
105
  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.
106
+ /**
107
+ * Fallback content rendered inside the meter.
179
108
  * @since 1.0.0
180
- * @category content
109
+ * @category Rendered content
181
110
  */
182
111
  readonly content?: Renderable.Any;
183
112
  }
@@ -191,26 +120,37 @@ declare function internalProps<const Options extends MeterOptions>(options: Opti
191
120
  readonly ref: RefSubject.HydratedRefSubject<State, Schema.SchemaError, never, never>;
192
121
  };
193
122
  type MeterInternalProps<Options extends MeterOptions> = ReturnType<ReturnType<typeof internalProps<Options>>>;
194
- /** Renders a native `<meter>` synchronized with hydrated state.
123
+ /**
124
+ * Renders a native meter for a measurement within a known range.
125
+ *
195
126
  * @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.
127
+ * Supply a label and coherent min/max/low/high/optimum values. The browser presents thresholds;
128
+ * the component does not trigger alerts when they are crossed. Use a slider for editing or a
129
+ * progress element for operation completion. The meter has no keyboard action.
130
+ *
202
131
  * @example
203
132
  * ```ts
204
- * import { Effect } from "effect"
205
- * import * as Meter from "@typed/ui/Meter"
133
+ * import { RefSubject } from "@typed/fx";
134
+ * import { html } from "@typed/template";
135
+ * import { component } from "@typed/ui/Component";
136
+ * import * as Meter from "@typed/ui/Meter";
206
137
  *
207
- * const program = Effect.gen(function* () {
208
- * const state = yield* Meter.makeState({ value: 64 })
209
- * return Meter.Meter({ state, min: 0, max: 100 })
210
- * })
138
+ * export const StorageUsage = component(function* () {
139
+ * const state = yield* Meter.makeState({ value: 64 });
140
+ * const description = RefSubject.map(state, ({ value }) => `${value} GB of 100 GB used`);
141
+ * return html`<section>
142
+ * <label for="storage-meter">Storage used</label>
143
+ * ${Meter.Meter({
144
+ * state, min: 0, max: 100, low: 60, high: 85, optimum: 0,
145
+ * content: description,
146
+ * props: { id: "storage-meter", "aria-valuetext": description },
147
+ * })}
148
+ * <p>${description}</p>
149
+ * </section>`;
150
+ * });
211
151
  * ```
212
152
  * @since 1.0.0
213
- * @category components
153
+ * @category Controls
214
154
  */
215
155
  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
156
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Meter.d.ts","sourceRoot":"","sources":["../src/Meter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Meter.d.ts","sourceRoot":"","sources":["../src/Meter.ts"],"names":[],"mappings":"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"}
package/dist/Meter.js CHANGED
@@ -2,21 +2,13 @@ import * as Schema from "effect/Schema";
2
2
  import { RefSubject } from "@typed/fx";
3
3
  import { html } from "@typed/template";
4
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
5
+ /**
13
6
  */
14
7
  export const StateSchema = Schema.Struct({ value: Schema.Finite });
15
- /** Creates hydrated meter state.
8
+ /**
9
+ * Creates hydrated meter state.
16
10
  * @remarks
17
- * ## Why
18
11
  * The state remains testable and reusable without rendering a UI component.
19
- * ## Ownership and lifetime
20
12
  * The caller's Effect Scope owns the hydrated RefSubject.
21
13
  * @example
22
14
  * ```ts
@@ -28,29 +20,19 @@ export const StateSchema = Schema.Struct({ value: Schema.Finite });
28
20
  * })
29
21
  * ```
30
22
  * @since 1.0.0
31
- * @category constructors
23
+ * @category State construction
32
24
  */
33
25
  export function makeState(initial) {
34
26
  return RefSubject.hydrate(StateSchema, initial);
35
27
  }
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"
28
+ /**
29
+ * Assigns the displayed measurement without clamping it to the meter range.
46
30
  *
47
- * const program = Effect.gen(function* () {
48
- * const state = yield* Meter.makeState({ value: 0 })
49
- * yield* Meter.setValue(state, 0.75)
50
- * })
51
- * ```
31
+ * @remarks
32
+ * Keep measurement units consistent with min/max and threshold options. This operation does not
33
+ * execute threshold actions or validate the preferred range.
52
34
  * @since 1.0.0
53
- * @category state
35
+ * @category State transitions
54
36
  */
55
37
  export function setValue(state, value) {
56
38
  return RefSubject.update(state, (current) => ({ ...current, value }));
@@ -66,26 +48,37 @@ function internalProps(options) {
66
48
  ref: options.state,
67
49
  });
68
50
  }
69
- /** Renders a native `<meter>` synchronized with hydrated state.
51
+ /**
52
+ * Renders a native meter for a measurement within a known range.
53
+ *
70
54
  * @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.
55
+ * Supply a label and coherent min/max/low/high/optimum values. The browser presents thresholds;
56
+ * the component does not trigger alerts when they are crossed. Use a slider for editing or a
57
+ * progress element for operation completion. The meter has no keyboard action.
58
+ *
77
59
  * @example
78
60
  * ```ts
79
- * import { Effect } from "effect"
80
- * import * as Meter from "@typed/ui/Meter"
61
+ * import { RefSubject } from "@typed/fx";
62
+ * import { html } from "@typed/template";
63
+ * import { component } from "@typed/ui/Component";
64
+ * import * as Meter from "@typed/ui/Meter";
81
65
  *
82
- * const program = Effect.gen(function* () {
83
- * const state = yield* Meter.makeState({ value: 64 })
84
- * return Meter.Meter({ state, min: 0, max: 100 })
85
- * })
66
+ * export const StorageUsage = component(function* () {
67
+ * const state = yield* Meter.makeState({ value: 64 });
68
+ * const description = RefSubject.map(state, ({ value }) => `${value} GB of 100 GB used`);
69
+ * return html`<section>
70
+ * <label for="storage-meter">Storage used</label>
71
+ * ${Meter.Meter({
72
+ * state, min: 0, max: 100, low: 60, high: 85, optimum: 0,
73
+ * content: description,
74
+ * props: { id: "storage-meter", "aria-valuetext": description },
75
+ * })}
76
+ * <p>${description}</p>
77
+ * </section>`;
78
+ * });
86
79
  * ```
87
80
  * @since 1.0.0
88
- * @category components
81
+ * @category Controls
89
82
  */
90
83
  export function Meter(options, host) {
91
84
  return Dom.renderHost()(options, host, internalProps(options), options.content ?? "", (props, content) => {
@@ -34,7 +34,7 @@ interface State {
34
34
  * ```
35
35
  *
36
36
  * @since 1.0.0
37
- * @category refs
37
+ * @category Native synchronization
38
38
  */
39
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
40
  export {};
@@ -30,7 +30,7 @@ import { Fx } from "@typed/fx";
30
30
  * ```
31
31
  *
32
32
  * @since 1.0.0
33
- * @category refs
33
+ * @category Native synchronization
34
34
  */
35
35
  export function ref(state) {
36
36
  return Effect.fn((element) => Effect.asVoid(Effect.forkScoped(Fx.observe(state, Effect.fn((value) => Effect.sync(() => {
@@ -12,7 +12,7 @@ interface State {
12
12
  * ## Ownership and lifetime
13
13
  * Options are inert and retain no resources.
14
14
  * @since 1.0.0
15
- * @category models
15
+ * @category Native display options
16
16
  */
17
17
  export interface Options {
18
18
  /** Whether opening uses the modal top layer; defaults to true.
@@ -23,7 +23,7 @@ export interface Options {
23
23
  * ## Ownership and lifetime
24
24
  * The flag is read during synchronization and retains no resources.
25
25
  * @since 1.0.0
26
- * @category behavior
26
+ * @category Native display options
27
27
  */
28
28
  readonly modal?: boolean;
29
29
  }
@@ -39,8 +39,10 @@ export interface Options {
39
39
  *
40
40
  * ## Ownership and lifetime
41
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
42
+ * Applying the ref forks an observer in the current Effect Scope. Modal opening
43
+ * waits for a detached host to connect; a newer state or Scope finalization cancels
44
+ * that pending connection check. Hidden documents may defer the check until animation
45
+ * frames resume. Finalization does not close state owned elsewhere or remove
44
46
  * the element. `Dialog.Content` handles native `cancel`, `close`, and `toggle`
45
47
  * events and composes exactly one hydration owner.
46
48
  *
@@ -57,7 +59,7 @@ export interface Options {
57
59
  * ```
58
60
  *
59
61
  * @since 1.0.0
60
- * @category refs
62
+ * @category Native synchronization
61
63
  */
62
64
  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
65
  export {};
@@ -1 +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"}
1
+ {"version":3,"file":"NativeDialog.d.ts","sourceRoot":"","sources":["../src/NativeDialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;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,CAqBzE"}
@@ -1,4 +1,5 @@
1
1
  import * as Effect from "effect/Effect";
2
+ import * as Fiber from "effect/Fiber";
2
3
  import { Fx } from "@typed/fx";
3
4
  /**
4
5
  * Creates a scoped ref that drives a real `HTMLDialogElement` from state.
@@ -12,8 +13,10 @@ import { Fx } from "@typed/fx";
12
13
  *
13
14
  * ## Ownership and lifetime
14
15
  *
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
16
+ * Applying the ref forks an observer in the current Effect Scope. Modal opening
17
+ * waits for a detached host to connect; a newer state or Scope finalization cancels
18
+ * that pending connection check. Hidden documents may defer the check until animation
19
+ * frames resume. Finalization does not close state owned elsewhere or remove
17
20
  * the element. `Dialog.Content` handles native `cancel`, `close`, and `toggle`
18
21
  * events and composes exactly one hydration owner.
19
22
  *
@@ -30,10 +33,45 @@ import { Fx } from "@typed/fx";
30
33
  * ```
31
34
  *
32
35
  * @since 1.0.0
33
- * @category refs
36
+ * @category Native synchronization
34
37
  */
35
38
  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)))))));
39
+ return Effect.fn(function* (element) {
40
+ let pending;
41
+ yield* Effect.forkScoped(Fx.observe(state, Effect.fn(function* (value) {
42
+ if (pending !== undefined) {
43
+ const previous = pending;
44
+ pending = undefined;
45
+ yield* Fiber.interrupt(previous);
46
+ }
47
+ const update = Effect.sync(() => synchronize(element, value.open, options));
48
+ if (value.open && options.modal !== false && !element.isConnected) {
49
+ pending = yield* Effect.forkScoped(Effect.andThen(whenConnected(element), update));
50
+ }
51
+ else {
52
+ // Complete connected transitions before queued native lifecycle events
53
+ // can reflect an older open state back into the application.
54
+ yield* update;
55
+ }
56
+ })));
57
+ });
58
+ }
59
+ // Template refs run before their host is inserted. Native showModal requires a connected element.
60
+ function whenConnected(element) {
61
+ return Effect.callback((resume) => {
62
+ if (element.isConnected) {
63
+ resume(Effect.void);
64
+ return;
65
+ }
66
+ const check = () => {
67
+ if (element.isConnected)
68
+ resume(Effect.void);
69
+ else
70
+ frame = requestAnimationFrame(check);
71
+ };
72
+ let frame = requestAnimationFrame(check);
73
+ return Effect.sync(() => cancelAnimationFrame(frame));
74
+ });
37
75
  }
38
76
  function synchronize(element, open, options) {
39
77
  if (open) {
@@ -16,9 +16,11 @@ interface State {
16
16
  *
17
17
  * ## Ownership and lifetime
18
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`
19
+ * Applying the ref forks one observer in the current Effect Scope. Opening
20
+ * waits for a detached host to connect. A newer state or Scope finalization
21
+ * cancels that pending connection check; hidden documents may defer it until
22
+ * animation frames resume. Closing the Scope interrupts observation without
23
+ * removing the host or closing caller-owned state. The host must support the Popover API and retain its `popover`
22
24
  * attribute. Only one hydration owner may be composed for the element.
23
25
  *
24
26
  * @example
@@ -34,7 +36,7 @@ interface State {
34
36
  * ```
35
37
  *
36
38
  * @since 1.0.0
37
- * @category refs
39
+ * @category Native synchronization
38
40
  */
39
41
  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
42
  export {};
@@ -1 +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"}
1
+ {"version":3,"file":"NativePopover.d.ts","sourceRoot":"","sources":["../src/NativePopover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;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,CAqBnE"}
@@ -1,4 +1,5 @@
1
1
  import * as Effect from "effect/Effect";
2
+ import * as Fiber from "effect/Fiber";
2
3
  import { Fx } from "@typed/fx";
3
4
  /**
4
5
  * Creates a scoped ref that synchronizes state with the native Popover API.
@@ -12,9 +13,11 @@ import { Fx } from "@typed/fx";
12
13
  *
13
14
  * ## Ownership and lifetime
14
15
  *
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`
16
+ * Applying the ref forks one observer in the current Effect Scope. Opening
17
+ * waits for a detached host to connect. A newer state or Scope finalization
18
+ * cancels that pending connection check; hidden documents may defer it until
19
+ * animation frames resume. Closing the Scope interrupts observation without
20
+ * removing the host or closing caller-owned state. The host must support the Popover API and retain its `popover`
18
21
  * attribute. Only one hydration owner may be composed for the element.
19
22
  *
20
23
  * @example
@@ -30,10 +33,45 @@ import { Fx } from "@typed/fx";
30
33
  * ```
31
34
  *
32
35
  * @since 1.0.0
33
- * @category refs
36
+ * @category Native synchronization
34
37
  */
35
38
  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)))))));
39
+ return Effect.fn(function* (element) {
40
+ let pending;
41
+ yield* Effect.forkScoped(Fx.observe(state, Effect.fn(function* (value) {
42
+ if (pending !== undefined) {
43
+ const previous = pending;
44
+ pending = undefined;
45
+ yield* Fiber.interrupt(previous);
46
+ }
47
+ const update = Effect.sync(() => synchronize(element, value.open));
48
+ if (value.open && !element.isConnected) {
49
+ pending = yield* Effect.forkScoped(Effect.andThen(whenConnected(element), update));
50
+ }
51
+ else {
52
+ // Connected transitions stay in the observer: Menu/Select can focus
53
+ // their now-visible items immediately after updating open state.
54
+ yield* update;
55
+ }
56
+ })));
57
+ });
58
+ }
59
+ // Template refs run before insertion; native showPopover requires a connected host.
60
+ function whenConnected(element) {
61
+ return Effect.callback((resume) => {
62
+ if (element.isConnected) {
63
+ resume(Effect.void);
64
+ return;
65
+ }
66
+ const check = () => {
67
+ if (element.isConnected)
68
+ resume(Effect.void);
69
+ else
70
+ frame = requestAnimationFrame(check);
71
+ };
72
+ let frame = requestAnimationFrame(check);
73
+ return Effect.sync(() => cancelAnimationFrame(frame));
74
+ });
37
75
  }
38
76
  function synchronize(element, open) {
39
77
  if (open) {