@foldkit/ui 0.160.0 → 0.161.0-canary.01b0aab09684

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 (49) hide show
  1. package/dist/calendar/index.d.ts +407 -19
  2. package/dist/calendar/index.d.ts.map +1 -1
  3. package/dist/calendar/index.js +21 -24
  4. package/dist/calendar/public.d.ts +1 -1
  5. package/dist/calendar/public.d.ts.map +1 -1
  6. package/dist/combobox/multi.d.ts +2 -0
  7. package/dist/combobox/multi.d.ts.map +1 -1
  8. package/dist/combobox/public.d.ts +1 -1
  9. package/dist/combobox/public.d.ts.map +1 -1
  10. package/dist/combobox/shared.d.ts +4 -0
  11. package/dist/combobox/shared.d.ts.map +1 -1
  12. package/dist/combobox/shared.js +52 -36
  13. package/dist/combobox/single.d.ts +2 -0
  14. package/dist/combobox/single.d.ts.map +1 -1
  15. package/dist/datePicker/index.d.ts +386 -31
  16. package/dist/datePicker/index.d.ts.map +1 -1
  17. package/dist/datePicker/index.js +37 -1
  18. package/dist/dialog/index.d.ts +57 -22
  19. package/dist/dialog/index.d.ts.map +1 -1
  20. package/dist/dialog/index.js +130 -42
  21. package/dist/dialog/public.d.ts +1 -1
  22. package/dist/dialog/public.d.ts.map +1 -1
  23. package/dist/dialog/public.js +1 -1
  24. package/dist/disclosure/index.d.ts +15 -2
  25. package/dist/disclosure/index.d.ts.map +1 -1
  26. package/dist/disclosure/index.js +20 -14
  27. package/dist/disclosure/public.d.ts +1 -1
  28. package/dist/disclosure/public.d.ts.map +1 -1
  29. package/dist/dragAndDrop/index.d.ts +39 -0
  30. package/dist/dragAndDrop/index.d.ts.map +1 -1
  31. package/dist/dragAndDrop/index.js +2 -1
  32. package/dist/dragAndDrop/public.d.ts +1 -1
  33. package/dist/dragAndDrop/public.d.ts.map +1 -1
  34. package/dist/dragAndDrop/public.js +1 -1
  35. package/dist/listbox/shared.js +1 -1
  36. package/dist/menu/index.js +1 -1
  37. package/dist/popover/index.js +1 -1
  38. package/dist/tabs/index.d.ts +10 -1
  39. package/dist/tabs/index.d.ts.map +1 -1
  40. package/dist/tabs/index.js +8 -2
  41. package/dist/tabs/public.d.ts +1 -1
  42. package/dist/tabs/public.d.ts.map +1 -1
  43. package/dist/tabs/public.js +1 -1
  44. package/dist/test/apps/disabledButton.d.ts +6 -0
  45. package/dist/test/apps/disabledButton.d.ts.map +1 -1
  46. package/dist/test/apps/disabledButton.js +1 -1
  47. package/dist/toast/index.d.ts.map +1 -1
  48. package/dist/toast/index.js +4 -6
  49. package/package.json +4 -4
@@ -1,6 +1,7 @@
1
1
  import { Effect, Option, Schema } from 'effect';
2
2
  import * as Command from 'foldkit/command';
3
3
  import { type ChildAttribute, type Html } from 'foldkit/html';
4
+ import * as Mount from 'foldkit/mount';
4
5
  import * as Update from 'foldkit/update';
5
6
  /** Schema for the dialog component's state, tracking its unique ID, open/closed status, animation support, and animation lifecycle phase. */
6
7
  export declare const Model: Schema.Struct<{
@@ -21,6 +22,8 @@ export declare const Message: import("foldkit/message").MessageUnion<{
21
22
  readonly RequestedClose: {};
22
23
  readonly SucceededShowDialog: {};
23
24
  readonly FailedShowDialog: {};
25
+ readonly SucceededAcquireResources: {};
26
+ readonly FailedAcquireResources: {};
24
27
  readonly CompletedCloseDialog: {};
25
28
  readonly Unmounted: {};
26
29
  readonly CompletedReleaseDialogResources: {};
@@ -37,6 +40,8 @@ export type RequestedOpen = typeof Message.RequestedOpen.Type;
37
40
  export type RequestedClose = typeof Message.RequestedClose.Type;
38
41
  export type SucceededShowDialog = typeof Message.SucceededShowDialog.Type;
39
42
  export type FailedShowDialog = typeof Message.FailedShowDialog.Type;
43
+ export type SucceededAcquireResources = typeof Message.SucceededAcquireResources.Type;
44
+ export type FailedAcquireResources = typeof Message.FailedAcquireResources.Type;
40
45
  export type CompletedCloseDialog = typeof Message.CompletedCloseDialog.Type;
41
46
  export type Unmounted = typeof Message.Unmounted.Type;
42
47
  export type CompletedReleaseDialogResources = typeof Message.CompletedReleaseDialogResources.Type;
@@ -60,7 +65,6 @@ export type OutMessage = typeof OutMessage.Type;
60
65
  * elements rather than constructing those ids yourself. */
61
66
  export type InitConfig = Readonly<{
62
67
  id: string;
63
- isOpen?: boolean;
64
68
  isAnimated?: boolean;
65
69
  /** CSS selector for the element that receives focus when the dialog opens.
66
70
  * A selector-based override of the `initialFocus` RenderInfo marker, for the
@@ -69,7 +73,8 @@ export type InitConfig = Readonly<{
69
73
  * neither set, focus falls to the first focusable element. */
70
74
  focusSelector?: string;
71
75
  }>;
72
- /** Creates an initial dialog model from a config. Defaults to closed and non-animated. */
76
+ /** Creates a closed dialog model from a config. Use `boot` when the Dialog
77
+ * should open as the application starts. */
73
78
  export declare const init: (config: InitConfig) => Model;
74
79
  /** Data attribute the dialog places on the `initialFocus` RenderInfo group and
75
80
  * focuses on open. */
@@ -78,18 +83,20 @@ export declare const initialFocusMarkerAttribute = "foldkit-dialog-initial-focus
78
83
  * dialog when no `focusSelector` is configured. */
79
84
  export declare const initialFocusMarkerSelector = "[data-foldkit-dialog-initial-focus]";
80
85
  type UpdateReturn = Update.ReturnWithOutMessage<Model, Message, OutMessage>;
81
- /** Locks page scroll and opens the native dialog element through
82
- * `Dom.showDialog`, which calls `show()` (not native `showModal()`) so other
83
- * high-z-index overlays stay interactive. It layers the dialog with a high
84
- * z-index and traps focus. For an unhandled Escape on the topmost Dialog, the
86
+ /** Opens the native dialog element through `Dom.showDialog`, then locks page
87
+ * scroll when that call acquired the dialog resources. `Dom.showDialog`
88
+ * makes the background inert while leaving DevTools available as a separate
89
+ * developer overlay. It calls `show()` rather than `showModal()` so DevTools
90
+ * can stay interactive, layers the dialog with a high z-index, and traps
91
+ * focus. For an unhandled Escape on the topmost Dialog, the
85
92
  * helper dispatches a `CustomEvent` named `cancel`; the Dialog view maps that
86
93
  * signal to `RequestedClose` while suppressing native `cancel` events. The
87
94
  * Dialog component supplies its own backdrop. If the dialog element is gone
88
- * by the time the show runs, the lock is released and the Command reports
89
- * `FailedShowDialog`. A closed dialog has no `OnUnmount`, so nothing else
90
- * would release the lock. The update function then closes the Model. Without
91
- * this close, the dialog would render open with no lock and no focus trap.
92
- * The lock is also released if the Command is interrupted while it waits. */
95
+ * by the time the show runs, the Command reports `FailedShowDialog` without
96
+ * taking the scroll lock. The update function then closes the Model. The
97
+ * acquisition becomes uninterruptible after the committed element is found,
98
+ * so modal resources and the scroll lock cannot split. A concurrent
99
+ * lifecycle acquisition reuses the resources already held by the id. */
93
100
  export declare const ShowDialog: Command.CommandDefinitionWithArgs<"ShowDialog", {
94
101
  id: Schema.String;
95
102
  focusSelector: Schema.String;
@@ -98,6 +105,19 @@ export declare const ShowDialog: Command.CommandDefinitionWithArgs<"ShowDialog",
98
105
  } | {
99
106
  readonly _tag: "FailedShowDialog";
100
107
  }, never, never>>;
108
+ /** Reacquires an initially visible Dialog's framework resources when its
109
+ * element mounts, including after development Model preservation restores an
110
+ * open Dialog without replaying initialization Commands. A successful
111
+ * acquisition also resumes a preserved animation transition from its current
112
+ * phase. */
113
+ export declare const AcquireResources: Mount.MountDefinitionWithArgs<"AcquireResources", {
114
+ id: Schema.String;
115
+ focusSelector: Schema.String;
116
+ }, {
117
+ readonly _tag: "SucceededAcquireResources";
118
+ } | {
119
+ readonly _tag: "FailedAcquireResources";
120
+ }>;
101
121
  /** Calls `close()` on the native dialog element and unlocks page scroll when
102
122
  * the close released the resources `ShowDialog` installed. A close that runs
103
123
  * before the show has installed them leaves the lock alone. When the show
@@ -105,16 +125,16 @@ export declare const ShowDialog: Command.CommandDefinitionWithArgs<"ShowDialog",
105
125
  * closes the dialog again. If the dialog element is gone by the time the
106
126
  * close runs, the Command calls `Dom.releaseDialogResources` instead. That
107
127
  * releases the scroll lock, focus trap, return focus, and stack entry if the
108
- * dialog still holds them. */
128
+ * dialog still holds them. The background is restored before return focus. */
109
129
  export declare const CloseDialog: Command.CommandDefinitionWithArgs<"CloseDialog", {
110
130
  id: Schema.String;
111
131
  }, Effect.Effect<{
112
132
  readonly _tag: "CompletedCloseDialog";
113
133
  }, never, never>>;
114
134
  /** Releases the framework hygiene the dialog holds while open (scroll lock,
115
- * focus trap, return focus, stack entry) when the element unmounts without a
116
- * purposeful close. Idempotent: a no-op if the dialog already released its
117
- * resources through `CloseDialog`. */
135
+ * focus trap, return focus, stack entry, background isolation) when the
136
+ * element unmounts without a purposeful close. Calling it after
137
+ * `CloseDialog` released those resources is a no-op. */
118
138
  export declare const ReleaseDialogResources: Command.CommandDefinitionWithArgs<"ReleaseDialogResources", {
119
139
  id: Schema.String;
120
140
  }, Effect.Effect<{
@@ -141,6 +161,10 @@ export declare const update: (model: Model, message: Message) => Readonly<{
141
161
  readonly _tag: "SucceededShowDialog";
142
162
  } | {
143
163
  readonly _tag: "FailedShowDialog";
164
+ } | {
165
+ readonly _tag: "SucceededAcquireResources";
166
+ } | {
167
+ readonly _tag: "FailedAcquireResources";
144
168
  } | {
145
169
  readonly _tag: "CompletedCloseDialog";
146
170
  } | {
@@ -165,6 +189,11 @@ export declare const update: (model: Model, message: Message) => Readonly<{
165
189
  readonly _tag: "Closed";
166
190
  };
167
191
  }>;
192
+ /** Creates a Dialog and opens it through the normal update path. Use the
193
+ * returned Model and Commands during application initialization so the
194
+ * initially visible Dialog acquires modal isolation, scroll locking, focus
195
+ * management, stack registration, and runtime-owned cleanup. */
196
+ export declare const boot: (config: InitConfig) => UpdateReturn;
168
197
  /** Programmatically opens the dialog. */
169
198
  export declare const open: (model: Model) => UpdateReturn;
170
199
  /** Programmatically closes the dialog. */
@@ -192,11 +221,13 @@ export declare const descriptionId: (model: Model) => string;
192
221
  /** Render-time payload published to the consumer's `toView`.
193
222
  *
194
223
  * - `dialog`: attributes for the native `<dialog>` element. Carries
195
- * the id, ARIA labelling, `open` prop, positioning style, a `cancel` handler
224
+ * the id, ARIA labelling and modal state, `open` prop, positioning style, a `cancel` handler
196
225
  * that prevents a file picker's native cancellation from closing the dialog
197
226
  * while mapping `Dom.showDialog`'s Escape signal to `RequestedClose`,
198
- * and an `OnUnmount` backstop that releases framework hygiene (scroll lock,
199
- * focus trap, return focus) if the element is removed from the DOM while
227
+ * an `OnMount` acquisition that restores modal resources for an initially
228
+ * visible or development-preserved Dialog, and an `OnUnmount` backstop that
229
+ * releases framework hygiene (scroll lock, focus trap, background
230
+ * isolation, return focus) if the element is removed from the DOM while
200
231
  * still open, such as navigating away from a route-keyed subtree.
201
232
  * The consumer MUST render an `h.dialog(...)` element so the framework
202
233
  * can open and close it, and so the unmount backstop can fire.
@@ -243,10 +274,10 @@ export type ViewInputs = Readonly<{
243
274
  toView: (render: RenderInfo) => Html;
244
275
  hasDescription?: boolean;
245
276
  }>;
246
- /** Renders a headless dialog component backed by the native `<dialog>`
247
- * element. `ShowDialog` opens it through `Dom.showDialog`, which uses `show()`
248
- * (not native `showModal()`) with a high z-index, a focus trap, a
249
- * component-supplied backdrop, and topmost-only Escape handling. */
277
+ /** Renders a headless modal dialog backed by the native `<dialog>` element.
278
+ * `ShowDialog` and the dialog's Mount open it through `Dom.showDialog`,
279
+ * isolate the background, trap focus, and handle Escape on the topmost
280
+ * dialog. The component supplies its own backdrop. */
250
281
  export declare const view: import("foldkit/submodel").View<{
251
282
  readonly id: string;
252
283
  readonly isOpen: boolean;
@@ -265,6 +296,10 @@ export declare const view: import("foldkit/submodel").View<{
265
296
  readonly _tag: "SucceededShowDialog";
266
297
  } | {
267
298
  readonly _tag: "FailedShowDialog";
299
+ } | {
300
+ readonly _tag: "SucceededAcquireResources";
301
+ } | {
302
+ readonly _tag: "FailedAcquireResources";
268
303
  } | {
269
304
  readonly _tag: "CompletedCloseDialog";
270
305
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dialog/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dialog/index.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
1
  import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
2
2
  import { Effect, Match, Option, Schema, pipe } from 'effect';
3
3
  import * as Command from 'foldkit/command';
4
+ import { DEVTOOLS_HOST_ID } from 'foldkit/devtools-host';
4
5
  import * as Dom from 'foldkit/dom';
5
6
  import { childAttributes } from 'foldkit/html';
6
7
  import { defineMessageUnion } from 'foldkit/message';
8
+ import * as Mount from 'foldkit/mount';
7
9
  import { evo } from 'foldkit/struct';
8
10
  import { defineView } from 'foldkit/submodel';
9
11
  import * as Update from 'foldkit/update';
@@ -11,7 +13,7 @@ import * as Update from 'foldkit/update';
11
13
  // dependency: animation → html → runtime → devtools → dialog → animation.
12
14
  // The barrel (../animation) imports from html, which starts the cycle.
13
15
  import * as Animation from '../animation/schema.js';
14
- import { defaultLeaveCommand as animationDefaultLeaveCommand, hide as animationHide, show as animationShow, update as animationUpdate, } from '../animation/update.js';
16
+ import * as AnimationUpdate from '../animation/update.js';
15
17
  import { idSelector } from '../internal/selectors.js';
16
18
  // MODEL
17
19
  /** Schema for the dialog component's state, tracking its unique ID, open/closed status, animation support, and animation lifecycle phase. */
@@ -29,6 +31,8 @@ export const Message = defineMessageUnion({
29
31
  RequestedClose: {},
30
32
  SucceededShowDialog: {},
31
33
  FailedShowDialog: {},
34
+ SucceededAcquireResources: {},
35
+ FailedAcquireResources: {},
32
36
  CompletedCloseDialog: {},
33
37
  Unmounted: {},
34
38
  CompletedReleaseDialogResources: {},
@@ -40,14 +44,14 @@ export const OutMessage = defineMessageUnion({
40
44
  Opened: {},
41
45
  Closed: {},
42
46
  });
43
- /** Creates an initial dialog model from a config. Defaults to closed and non-animated. */
47
+ /** Creates a closed dialog model from a config. Use `boot` when the Dialog
48
+ * should open as the application starts. */
44
49
  export const init = (config) => (__foldkitBrandViewResult(({
45
50
  id: config.id,
46
- isOpen: config.isOpen ?? false,
51
+ isOpen: false,
47
52
  isAnimated: config.isAnimated ?? false,
48
53
  animation: Animation.init({
49
54
  id: `${config.id}-panel`,
50
- ...(config.isOpen !== undefined ? { isShowing: config.isOpen } : {}),
51
55
  }),
52
56
  maybeFocusSelector: Option.fromNullishOr(config.focusSelector),
53
57
  }), "@foldkit/ui/dialog/index.js#init"));
@@ -59,22 +63,54 @@ export const initialFocusMarkerAttribute = 'foldkit-dialog-initial-focus';
59
63
  /** Selector for {@link initialFocusMarkerAttribute}, focused against the open
60
64
  * dialog when no `focusSelector` is configured. */
61
65
  export const initialFocusMarkerSelector = `[data-${initialFocusMarkerAttribute}]`;
62
- /** Locks page scroll and opens the native dialog element through
63
- * `Dom.showDialog`, which calls `show()` (not native `showModal()`) so other
64
- * high-z-index overlays stay interactive. It layers the dialog with a high
65
- * z-index and traps focus. For an unhandled Escape on the topmost Dialog, the
66
+ const acquireDialogResources = (id, focusSelector) => __foldkitBrandViewResult((Effect.uninterruptibleMask(restore => __foldkitBrandViewResult((restore(Dom.showDialog(dialogSelector(id), {
67
+ focusSelector,
68
+ isModal: true,
69
+ allowedOutsideSelectors: [`#${DEVTOOLS_HOST_ID}`],
70
+ })).pipe(Effect.tap(isAcquired => (__foldkitBrandViewResult((isAcquired ? Dom.lockScroll : Effect.void), "@foldkit/ui/dialog/index.js#anonymous~2"))))), "@foldkit/ui/dialog/index.js#anonymous"))), "@foldkit/ui/dialog/index.js#acquireDialogResources");
71
+ const acquireDialogResourcesResult = (id, focusSelector) => __foldkitBrandViewResult((acquireDialogResources(id, focusSelector).pipe(Effect.as(Message.SucceededShowDialog()), Effect.catch(() => __foldkitBrandViewResult((Effect.succeed(Message.FailedShowDialog())), "@foldkit/ui/dialog/index.js#anonymous~3")))), "@foldkit/ui/dialog/index.js#acquireDialogResourcesResult");
72
+ /** Opens the native dialog element through `Dom.showDialog`, then locks page
73
+ * scroll when that call acquired the dialog resources. `Dom.showDialog`
74
+ * makes the background inert while leaving DevTools available as a separate
75
+ * developer overlay. It calls `show()` rather than `showModal()` so DevTools
76
+ * can stay interactive, layers the dialog with a high z-index, and traps
77
+ * focus. For an unhandled Escape on the topmost Dialog, the
66
78
  * helper dispatches a `CustomEvent` named `cancel`; the Dialog view maps that
67
79
  * signal to `RequestedClose` while suppressing native `cancel` events. The
68
80
  * Dialog component supplies its own backdrop. If the dialog element is gone
69
- * by the time the show runs, the lock is released and the Command reports
70
- * `FailedShowDialog`. A closed dialog has no `OnUnmount`, so nothing else
71
- * would release the lock. The update function then closes the Model. Without
72
- * this close, the dialog would render open with no lock and no focus trap.
73
- * The lock is also released if the Command is interrupted while it waits. */
81
+ * by the time the show runs, the Command reports `FailedShowDialog` without
82
+ * taking the scroll lock. The update function then closes the Model. The
83
+ * acquisition becomes uninterruptible after the committed element is found,
84
+ * so modal resources and the scroll lock cannot split. A concurrent
85
+ * lifecycle acquisition reuses the resources already held by the id. */
74
86
  export const ShowDialog = Command.define('ShowDialog', {
75
87
  args: { id: Schema.String, focusSelector: Schema.String },
76
88
  messages: [Message.SucceededShowDialog, Message.FailedShowDialog],
77
- execute: ({ id, focusSelector }) => __foldkitBrandViewResult((Dom.lockScroll.pipe(Effect.andThen(() => __foldkitBrandViewResult((Dom.showDialog(dialogSelector(id), { focusSelector }).pipe(Effect.onError(() => __foldkitBrandViewResult((Dom.unlockScroll), "@foldkit/ui/dialog/index.js#anonymous~2")), Effect.as(Message.SucceededShowDialog()), Effect.catch(() => __foldkitBrandViewResult((Effect.succeed(Message.FailedShowDialog())), "@foldkit/ui/dialog/index.js#anonymous~3")))), "@foldkit/ui/dialog/index.js#anonymous")))), "@foldkit/ui/dialog/index.js#execute"),
89
+ execute: ({ id, focusSelector }) => __foldkitBrandViewResult((acquireDialogResourcesResult(id, focusSelector)), "@foldkit/ui/dialog/index.js#execute"),
90
+ });
91
+ /** Reacquires an initially visible Dialog's framework resources when its
92
+ * element mounts, including after development Model preservation restores an
93
+ * open Dialog without replaying initialization Commands. A successful
94
+ * acquisition also resumes a preserved animation transition from its current
95
+ * phase. */
96
+ export const AcquireResources = Mount.define('AcquireResources', {
97
+ args: { id: Schema.String, focusSelector: Schema.String },
98
+ messages: [Message.SucceededAcquireResources, Message.FailedAcquireResources],
99
+ execute: ({ element, id, focusSelector }) => {
100
+ if (!(element instanceof HTMLDialogElement) || element.id !== id) {
101
+ return __foldkitBrandViewResult((Effect.succeed(Message.FailedAcquireResources())), "@foldkit/ui/dialog/index.js#execute~2");
102
+ }
103
+ const acquisition = acquireDialogResources(id, focusSelector).pipe(Effect.map(isAcquired => (__foldkitBrandViewResult(({
104
+ isAcquired,
105
+ message: Message.SucceededAcquireResources(),
106
+ }), "@foldkit/ui/dialog/index.js#anonymous~4"))), Effect.catch(() => __foldkitBrandViewResult((Effect.succeed({
107
+ isAcquired: false,
108
+ message: Message.FailedAcquireResources(),
109
+ })), "@foldkit/ui/dialog/index.js#anonymous~5")));
110
+ return __foldkitBrandViewResult((Effect.acquireRelease(acquisition, ({ isAcquired }) => __foldkitBrandViewResult((isAcquired
111
+ ? Dom.releaseDialogResources(id).pipe(Effect.ignore)
112
+ : Effect.void), "@foldkit/ui/dialog/index.js#anonymous~6")).pipe(Effect.map(({ message }) => __foldkitBrandViewResult((message), "@foldkit/ui/dialog/index.js#anonymous~7")))), "@foldkit/ui/dialog/index.js#execute~2");
113
+ },
78
114
  });
79
115
  /** Calls `close()` on the native dialog element and unlocks page scroll when
80
116
  * the close released the resources `ShowDialog` installed. A close that runs
@@ -83,20 +119,20 @@ export const ShowDialog = Command.define('ShowDialog', {
83
119
  * closes the dialog again. If the dialog element is gone by the time the
84
120
  * close runs, the Command calls `Dom.releaseDialogResources` instead. That
85
121
  * releases the scroll lock, focus trap, return focus, and stack entry if the
86
- * dialog still holds them. */
122
+ * dialog still holds them. The background is restored before return focus. */
87
123
  export const CloseDialog = Command.define('CloseDialog', {
88
124
  args: { id: Schema.String },
89
125
  messages: [Message.CompletedCloseDialog],
90
- execute: ({ id }) => __foldkitBrandViewResult((Dom.closeDialog(dialogSelector(id)).pipe(Effect.andThen(isReleased => __foldkitBrandViewResult((isReleased ? Dom.unlockScroll : Effect.void), "@foldkit/ui/dialog/index.js#anonymous~4")), Effect.catch(() => __foldkitBrandViewResult((Dom.releaseDialogResources(id)), "@foldkit/ui/dialog/index.js#anonymous~5")), Effect.as(Message.CompletedCloseDialog()))), "@foldkit/ui/dialog/index.js#execute~2"),
126
+ execute: ({ id }) => __foldkitBrandViewResult((Dom.closeDialog(dialogSelector(id)).pipe(Effect.andThen(isReleased => __foldkitBrandViewResult((isReleased ? Dom.unlockScroll : Effect.void), "@foldkit/ui/dialog/index.js#anonymous~8")), Effect.catch(() => __foldkitBrandViewResult((Dom.releaseDialogResources(id)), "@foldkit/ui/dialog/index.js#anonymous~9")), Effect.as(Message.CompletedCloseDialog()))), "@foldkit/ui/dialog/index.js#execute~3"),
91
127
  });
92
128
  /** Releases the framework hygiene the dialog holds while open (scroll lock,
93
- * focus trap, return focus, stack entry) when the element unmounts without a
94
- * purposeful close. Idempotent: a no-op if the dialog already released its
95
- * resources through `CloseDialog`. */
129
+ * focus trap, return focus, stack entry, background isolation) when the
130
+ * element unmounts without a purposeful close. Calling it after
131
+ * `CloseDialog` released those resources is a no-op. */
96
132
  export const ReleaseDialogResources = Command.define('ReleaseDialogResources', {
97
133
  args: { id: Schema.String },
98
134
  messages: [Message.CompletedReleaseDialogResources],
99
- execute: ({ id }) => __foldkitBrandViewResult((Dom.releaseDialogResources(id).pipe(Effect.ignore, Effect.as(Message.CompletedReleaseDialogResources()))), "@foldkit/ui/dialog/index.js#execute~3"),
135
+ execute: ({ id }) => __foldkitBrandViewResult((Dom.releaseDialogResources(id).pipe(Effect.ignore, Effect.as(Message.CompletedReleaseDialogResources()))), "@foldkit/ui/dialog/index.js#execute~4"),
100
136
  });
101
137
  const isLeaving = (model) => __foldkitBrandViewResult((model.animation.transitionState === 'LeaveStart' ||
102
138
  model.animation.transitionState === 'LeaveAnimating'), "@foldkit/ui/dialog/index.js#isLeaving");
@@ -106,31 +142,54 @@ const resetToClosed = (model) => __foldkitBrandViewResult((evo(model, {
106
142
  animation: () => __foldkitBrandViewResult((Animation.init({ id: `${model.id}-panel` })), "@foldkit/ui/dialog/index.js#animation"),
107
143
  })), "@foldkit/ui/dialog/index.js#resetToClosed");
108
144
  const wrapAnimationMessage = (message) => __foldkitBrandViewResult((Message.GotAnimationMessage({ message })), "@foldkit/ui/dialog/index.js#wrapAnimationMessage");
145
+ const resumeAnimationAfterAcquisition = (model) => __foldkitBrandViewResult((Match.value(model.animation.transitionState).pipe(Match.withReturnType(), Match.when('Idle', () => (__foldkitBrandViewResult(({ model }), "@foldkit/ui/dialog/index.js#anonymous~10"))), Match.when('EnterStart', () => (__foldkitBrandViewResult(({
146
+ model,
147
+ commands: [
148
+ Command.mapMessage(AnimationUpdate.WaitForPaint(), wrapAnimationMessage),
149
+ ],
150
+ }), "@foldkit/ui/dialog/index.js#anonymous~11"))), Match.when('EnterAnimating', () => (__foldkitBrandViewResult(({
151
+ model,
152
+ commands: [
153
+ Command.mapMessage(AnimationUpdate.WaitForAnimationSettled({ id: model.animation.id }), wrapAnimationMessage),
154
+ ],
155
+ }), "@foldkit/ui/dialog/index.js#anonymous~12"))), Match.when('LeaveStart', () => (__foldkitBrandViewResult(({
156
+ model,
157
+ commands: [
158
+ Command.mapMessage(AnimationUpdate.WaitForPaint(), wrapAnimationMessage),
159
+ ],
160
+ }), "@foldkit/ui/dialog/index.js#anonymous~13"))), Match.when('LeaveAnimating', () => (__foldkitBrandViewResult(({
161
+ model,
162
+ commands: [
163
+ Command.mapMessage(AnimationUpdate.WaitForAnimationSettled({ id: model.animation.id }), wrapAnimationMessage),
164
+ ],
165
+ }), "@foldkit/ui/dialog/index.js#anonymous~14"))), Match.exhaustive)), "@foldkit/ui/dialog/index.js#resumeAnimationAfterAcquisition");
109
166
  const foldAnimationOutMessage = (outMessage, { liftCommand }) => __foldkitBrandViewResult((Animation.OutMessage.match(outMessage, {
110
167
  StartedLeaveAnimating: () => __foldkitBrandViewResult((model => (__foldkitBrandViewResult(({
111
168
  model,
112
- commands: [liftCommand(animationDefaultLeaveCommand(model.animation))],
113
- }), "@foldkit/ui/dialog/index.js#anonymous~6"))), "@foldkit/ui/dialog/index.js#StartedLeaveAnimating"),
169
+ commands: [
170
+ liftCommand(AnimationUpdate.defaultLeaveCommand(model.animation)),
171
+ ],
172
+ }), "@foldkit/ui/dialog/index.js#anonymous~15"))), "@foldkit/ui/dialog/index.js#StartedLeaveAnimating"),
114
173
  TransitionedOut: () => __foldkitBrandViewResult((model => (__foldkitBrandViewResult(({
115
174
  model,
116
175
  commands: [CloseDialog({ id: model.id })],
117
- }), "@foldkit/ui/dialog/index.js#anonymous~7"))), "@foldkit/ui/dialog/index.js#TransitionedOut"),
176
+ }), "@foldkit/ui/dialog/index.js#anonymous~16"))), "@foldkit/ui/dialog/index.js#TransitionedOut"),
118
177
  })), "@foldkit/ui/dialog/index.js#foldAnimationOutMessage");
119
178
  const foldAnimation = Update.foldChild({
120
- update: animationUpdate,
179
+ update: AnimationUpdate.update,
121
180
  read: (model) => __foldkitBrandViewResult((Option.some(model.animation)), "@foldkit/ui/dialog/index.js#read"),
122
181
  write: (model, nextAnimation) => __foldkitBrandViewResult((evo(model, { animation: () => __foldkitBrandViewResult((nextAnimation), "@foldkit/ui/dialog/index.js#animation~2") })), "@foldkit/ui/dialog/index.js#write"),
123
182
  toParentMessage: wrapAnimationMessage,
124
183
  foldOutMessage: foldAnimationOutMessage,
125
184
  });
126
185
  const foldAnimationShow = Update.foldChildStep({
127
- update: animationShow,
186
+ update: AnimationUpdate.show,
128
187
  read: (model) => __foldkitBrandViewResult((Option.some(model.animation)), "@foldkit/ui/dialog/index.js#read~2"),
129
188
  write: (model, nextAnimation) => __foldkitBrandViewResult((evo(model, { animation: () => __foldkitBrandViewResult((nextAnimation), "@foldkit/ui/dialog/index.js#animation~3") })), "@foldkit/ui/dialog/index.js#write~2"),
130
189
  toParentMessage: wrapAnimationMessage,
131
190
  });
132
191
  const foldAnimationHide = Update.foldChildStep({
133
- update: animationHide,
192
+ update: AnimationUpdate.hide,
134
193
  read: (model) => __foldkitBrandViewResult((Option.some(model.animation)), "@foldkit/ui/dialog/index.js#read~3"),
135
194
  write: (model, nextAnimation) => __foldkitBrandViewResult((evo(model, { animation: () => __foldkitBrandViewResult((nextAnimation), "@foldkit/ui/dialog/index.js#animation~4") })), "@foldkit/ui/dialog/index.js#write~3"),
136
195
  toParentMessage: wrapAnimationMessage,
@@ -141,16 +200,16 @@ export const update = (model, message) => __foldkitBrandViewResult((Message.matc
141
200
  const wasClosed = !model.isOpen;
142
201
  const maybeShow = Option.liftPredicate(ShowDialog({
143
202
  id: model.id,
144
- focusSelector: Option.getOrElse(model.maybeFocusSelector, () => __foldkitBrandViewResult((initialFocusMarkerSelector), "@foldkit/ui/dialog/index.js#anonymous~8")),
145
- }), () => __foldkitBrandViewResult((wasClosed), "@foldkit/ui/dialog/index.js#anonymous~9"));
203
+ focusSelector: Option.getOrElse(model.maybeFocusSelector, () => __foldkitBrandViewResult((initialFocusMarkerSelector), "@foldkit/ui/dialog/index.js#anonymous~17")),
204
+ }), () => __foldkitBrandViewResult((wasClosed), "@foldkit/ui/dialog/index.js#anonymous~18"));
146
205
  const commands = Option.toArray(maybeShow);
147
206
  const dialogOpen = model.isAnimated
148
207
  ? Update.combine(model, [
149
- stepModel => (__foldkitBrandViewResult(({ model: stepModel, commands }), "@foldkit/ui/dialog/index.js#anonymous~10")),
208
+ stepModel => (__foldkitBrandViewResult(({ model: stepModel, commands }), "@foldkit/ui/dialog/index.js#anonymous~19")),
150
209
  foldAnimationShow,
151
210
  stepModel => (__foldkitBrandViewResult(({
152
211
  model: evo(stepModel, { isOpen: () => __foldkitBrandViewResult((true), "@foldkit/ui/dialog/index.js#isOpen~2") }),
153
- }), "@foldkit/ui/dialog/index.js#anonymous~11")),
212
+ }), "@foldkit/ui/dialog/index.js#anonymous~20")),
154
213
  ])
155
214
  : { model: evo(model, { isOpen: () => __foldkitBrandViewResult((true), "@foldkit/ui/dialog/index.js#isOpen~3") }), commands };
156
215
  return __foldkitBrandViewResult((wasClosed
@@ -166,14 +225,14 @@ export const update = (model, message) => __foldkitBrandViewResult((Message.matc
166
225
  const dialogClose = Update.combine(model, [
167
226
  stepModel => (__foldkitBrandViewResult(({
168
227
  model: evo(stepModel, { isOpen: () => __foldkitBrandViewResult((false), "@foldkit/ui/dialog/index.js#isOpen~4") }),
169
- }), "@foldkit/ui/dialog/index.js#anonymous~12")),
228
+ }), "@foldkit/ui/dialog/index.js#anonymous~21")),
170
229
  foldAnimationHide,
171
230
  ]);
172
231
  return __foldkitBrandViewResult((wasOpen
173
232
  ? pipe(dialogClose, Update.withOutMessage(OutMessage.Closed()))
174
233
  : dialogClose), "@foldkit/ui/dialog/index.js#RequestedClose");
175
234
  }
176
- const maybeClose = Option.liftPredicate(CloseDialog({ id: model.id }), () => __foldkitBrandViewResult((wasOpen), "@foldkit/ui/dialog/index.js#anonymous~13"));
235
+ const maybeClose = Option.liftPredicate(CloseDialog({ id: model.id }), () => __foldkitBrandViewResult((wasOpen), "@foldkit/ui/dialog/index.js#anonymous~22"));
177
236
  const commands = Option.toArray(maybeClose);
178
237
  const dialogClose = {
179
238
  model: evo(model, { isOpen: () => __foldkitBrandViewResult((false), "@foldkit/ui/dialog/index.js#isOpen~5") }),
@@ -211,9 +270,30 @@ export const update = (model, message) => __foldkitBrandViewResult((Message.matc
211
270
  return __foldkitBrandViewResult(({ model }), "@foldkit/ui/dialog/index.js#FailedShowDialog");
212
271
  }
213
272
  },
273
+ SucceededAcquireResources: () => {
274
+ if (model.isOpen || isLeaving(model)) {
275
+ return __foldkitBrandViewResult((resumeAnimationAfterAcquisition(model)), "@foldkit/ui/dialog/index.js#SucceededAcquireResources");
276
+ }
277
+ else {
278
+ return __foldkitBrandViewResult(({ model, commands: [CloseDialog({ id: model.id })] }), "@foldkit/ui/dialog/index.js#SucceededAcquireResources");
279
+ }
280
+ },
281
+ FailedAcquireResources: () => {
282
+ if (isOpenOrAnimating(model)) {
283
+ return __foldkitBrandViewResult(({ model: resetToClosed(model) }), "@foldkit/ui/dialog/index.js#FailedAcquireResources");
284
+ }
285
+ else {
286
+ return __foldkitBrandViewResult(({ model }), "@foldkit/ui/dialog/index.js#FailedAcquireResources");
287
+ }
288
+ },
214
289
  CompletedCloseDialog: () => (__foldkitBrandViewResult(({ model }), "@foldkit/ui/dialog/index.js#CompletedCloseDialog")),
215
290
  CompletedReleaseDialogResources: () => (__foldkitBrandViewResult(({ model }), "@foldkit/ui/dialog/index.js#CompletedReleaseDialogResources")),
216
291
  })), "@foldkit/ui/dialog/index.js#update");
292
+ /** Creates a Dialog and opens it through the normal update path. Use the
293
+ * returned Model and Commands during application initialization so the
294
+ * initially visible Dialog acquires modal isolation, scroll locking, focus
295
+ * management, stack registration, and runtime-owned cleanup. */
296
+ export const boot = (config) => __foldkitBrandViewResult((update(init(config), Message.RequestedOpen())), "@foldkit/ui/dialog/index.js#boot");
217
297
  /** Programmatically opens the dialog. */
218
298
  export const open = (model) => __foldkitBrandViewResult((update(model, Message.RequestedOpen())), "@foldkit/ui/dialog/index.js#open");
219
299
  /** Programmatically closes the dialog. */
@@ -239,10 +319,10 @@ export const titleId = (model) => __foldkitBrandViewResult((`${model.id}-dialog-
239
319
  * `ViewInputs.hasDescription` so the dialog points at this id. Do not
240
320
  * hand-roll the id string. */
241
321
  export const descriptionId = (model) => __foldkitBrandViewResult((`${model.id}-dialog-description`), "@foldkit/ui/dialog/index.js#descriptionId");
242
- /** Renders a headless dialog component backed by the native `<dialog>`
243
- * element. `ShowDialog` opens it through `Dom.showDialog`, which uses `show()`
244
- * (not native `showModal()`) with a high z-index, a focus trap, a
245
- * component-supplied backdrop, and topmost-only Escape handling. */
322
+ /** Renders a headless modal dialog backed by the native `<dialog>` element.
323
+ * `ShowDialog` and the dialog's Mount open it through `Dom.showDialog`,
324
+ * isolate the background, trap focus, and handle Escape on the topmost
325
+ * dialog. The component supplies its own backdrop. */
246
326
  export const view = defineView((model, viewInputs, h) => {
247
327
  const { id, isOpen, animation: { transitionState }, } = model;
248
328
  const { toView, hasDescription = false } = viewInputs;
@@ -251,17 +331,17 @@ export const view = defineView((model, viewInputs, h) => {
251
331
  h.DataAttribute('closed', ''),
252
332
  h.DataAttribute('enter', ''),
253
333
  h.DataAttribute('transition', ''),
254
- ]), "@foldkit/ui/dialog/index.js#anonymous~15")), Match.when('EnterAnimating', () => __foldkitBrandViewResult(([
334
+ ]), "@foldkit/ui/dialog/index.js#anonymous~24")), Match.when('EnterAnimating', () => __foldkitBrandViewResult(([
255
335
  h.DataAttribute('enter', ''),
256
336
  h.DataAttribute('transition', ''),
257
- ]), "@foldkit/ui/dialog/index.js#anonymous~16")), Match.when('LeaveStart', () => __foldkitBrandViewResult(([
337
+ ]), "@foldkit/ui/dialog/index.js#anonymous~25")), Match.when('LeaveStart', () => __foldkitBrandViewResult(([
258
338
  h.DataAttribute('leave', ''),
259
339
  h.DataAttribute('transition', ''),
260
- ]), "@foldkit/ui/dialog/index.js#anonymous~17")), Match.when('LeaveAnimating', () => __foldkitBrandViewResult(([
340
+ ]), "@foldkit/ui/dialog/index.js#anonymous~26")), Match.when('LeaveAnimating', () => __foldkitBrandViewResult(([
261
341
  h.DataAttribute('closed', ''),
262
342
  h.DataAttribute('leave', ''),
263
343
  h.DataAttribute('transition', ''),
264
- ]), "@foldkit/ui/dialog/index.js#anonymous~18")), Match.orElse(() => __foldkitBrandViewResult(([]), "@foldkit/ui/dialog/index.js#anonymous~19")));
344
+ ]), "@foldkit/ui/dialog/index.js#anonymous~27")), Match.orElse(() => __foldkitBrandViewResult(([]), "@foldkit/ui/dialog/index.js#anonymous~28")));
265
345
  const describedByAttributes = hasDescription
266
346
  ? [h.AriaDescribedBy(descriptionId(model))]
267
347
  : [];
@@ -269,6 +349,7 @@ export const view = defineView((model, viewInputs, h) => {
269
349
  h.Id(id),
270
350
  h.AriaLabelledBy(titleId(model)),
271
351
  ...describedByAttributes,
352
+ ...(isVisible ? [h.AriaModal(true)] : []),
272
353
  // NOTE: Chromium reports canceling a file picker as a native `cancel`
273
354
  // event observed by the containing dialog. Dom.showDialog uses a
274
355
  // CustomEvent for its unhandled-Escape signal, so the two are separable.
@@ -287,7 +368,14 @@ export const view = defineView((model, viewInputs, h) => {
287
368
  : {}),
288
369
  }),
289
370
  ...(isVisible
290
- ? [h.DataAttribute('open', ''), h.OnUnmount(Message.Unmounted())]
371
+ ? [
372
+ h.DataAttribute('open', ''),
373
+ h.OnMount(AcquireResources({
374
+ id,
375
+ focusSelector: Option.getOrElse(model.maybeFocusSelector, () => __foldkitBrandViewResult((initialFocusMarkerSelector), "@foldkit/ui/dialog/index.js#anonymous~29")),
376
+ })),
377
+ h.OnUnmount(Message.Unmounted()),
378
+ ]
291
379
  : []),
292
380
  ];
293
381
  const backdropAttributes = [
@@ -314,5 +402,5 @@ export const view = defineView((model, viewInputs, h) => {
314
402
  initialFocus: childAttributes(initialFocusAttributes),
315
403
  closeButton: childAttributes(closeButtonAttributes),
316
404
  isVisible,
317
- })), "@foldkit/ui/dialog/index.js#anonymous~14");
405
+ })), "@foldkit/ui/dialog/index.js#anonymous~23");
318
406
  });
@@ -1,3 +1,3 @@
1
- export { init, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, type Opened, type Closed, type RequestedOpen, type RequestedClose, type SucceededShowDialog, type FailedShowDialog, type CompletedCloseDialog, type Unmounted, type CompletedReleaseDialogResources, ShowDialog, CloseDialog, ReleaseDialogResources, } from './index.js';
1
+ export { init, boot, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, type Opened, type Closed, type RequestedOpen, type RequestedClose, type SucceededShowDialog, type FailedShowDialog, type SucceededAcquireResources, type FailedAcquireResources, type CompletedCloseDialog, type Unmounted, type CompletedReleaseDialogResources, ShowDialog, AcquireResources, CloseDialog, ReleaseDialogResources, } from './index.js';
2
2
  export type { InitConfig, ViewInputs, RenderInfo } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,+BAA+B,EACpC,UAAU,EACV,WAAW,EACX,sBAAsB,GACvB,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,+BAA+B,EACpC,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,sBAAsB,GACvB,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { init, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, ShowDialog, CloseDialog, ReleaseDialogResources, } from './index.js';
1
+ export { init, boot, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, ShowDialog, AcquireResources, CloseDialog, ReleaseDialogResources, } from './index.js';
@@ -22,8 +22,21 @@ export type DisclosureAttributes<Message> = Readonly<{
22
22
  * disclosure opens and closes. The panel stays mounted while collapsed, so
23
23
  * the transition has something to animate from and to. Spread the `panel`
24
24
  * bundle onto the element you pass in, and render it unconditionally rather
25
- * than gating on `isOpen`. The collapsed content is marked `aria-hidden`. */
26
- animatePanel: (content: Html) => Html;
25
+ * than gating on `isOpen`.
26
+ *
27
+ * Without options the collapsed panel is fully hidden. With `peek`, it keeps
28
+ * that height as a visual preview of its content. In either case, the
29
+ * collapsed content is inert and hidden from assistive technology until the
30
+ * disclosure opens. */
31
+ animatePanel: (content: Html, options?: AnimatePanelOptions) => Html;
32
+ }>;
33
+ /** Options for {@link DisclosureAttributes.animatePanel}.
34
+ *
35
+ * - `peek`: a CSS height the collapsed panel keeps, such as `'7.5em'` for
36
+ * five lines at a 1.5 leading. The visible content is an inert preview;
37
+ * content becomes accessible and interactive when the disclosure opens. */
38
+ export type AnimatePanelOptions = Readonly<{
39
+ peek?: string;
27
40
  }>;
28
41
  /** Per-render view configuration for the stateless controlled {@link view}.
29
42
  * Generic over `Message` (the message `onToggle` dispatches).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/disclosure/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAIhE;;;mCAGmC;AACnC,eAAO,MAAM,QAAQ,OAAQ,MAAM,KAAG,MAAwB,CAAA;AAM9D;;;;;;;;;sEASsE;AACtE,MAAM,MAAM,oBAAoB,CAAC,OAAO,IAAI,QAAQ,CAAC;IACnD,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC;;;;;kFAK8E;IAC9E,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,CAAA;CACtC,CAAC,CAAA;AAEF;;;;;;;;;;oBAUoB;AACpB,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;IACtC,MAAM,EAAE,CAAC,UAAU,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;UAsBU;AACV,eAAO,MAAM,IAAI,GAAI,OAAO,UAClB,UAAU,CAAC,OAAO,CAAC,KACxB,WAAW,CAAC,OAAO,CAAC,KACtB,IAiFF,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/disclosure/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAIhE;;;mCAGmC;AACnC,eAAO,MAAM,QAAQ,OAAQ,MAAM,KAAG,MAAwB,CAAA;AAM9D;;;;;;;;;sEASsE;AACtE,MAAM,MAAM,oBAAoB,CAAC,OAAO,IAAI,QAAQ,CAAC;IACnD,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC;;;;;;;;;;4BAUwB;IACxB,YAAY,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAA;CACrE,CAAC,CAAA;AAEF;;;;8EAI8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF;;;;;;;;;;oBAUoB;AACpB,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;IACtC,MAAM,EAAE,CAAC,UAAU,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;UAsBU;AACV,eAAO,MAAM,IAAI,GAAI,OAAO,UAClB,UAAU,CAAC,OAAO,CAAC,KACxB,WAAW,CAAC,OAAO,CAAC,KACtB,IA0FF,CAAA"}