foldkit 0.69.0 → 0.71.0

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.
@@ -0,0 +1,158 @@
1
+ import { Match as M } from 'effect';
2
+ import { createLazy, html } from '../../html';
3
+ import { Dismissed, DismissedAll, ElapsedDuration, GotTransitionMessage, HoveredEntry, LeftEntry, Position, Variant, } from './schema';
4
+ import { DismissAfter, makeRuntime } from './update';
5
+ export { Variant, Position, Dismissed, DismissedAll, ElapsedDuration, HoveredEntry, LeftEntry, GotTransitionMessage, DismissAfter, };
6
+ const variantToRole = (variant) => M.value(variant).pipe(M.withReturnType(), M.when('Info', () => 'status'), M.when('Success', () => 'status'), M.when('Warning', () => 'alert'), M.when('Error', () => 'alert'), M.exhaustive);
7
+ const positionToContainerStyle = (position) => {
8
+ const base = {
9
+ position: 'fixed',
10
+ display: 'flex',
11
+ gap: '8px',
12
+ padding: '16px',
13
+ margin: '0',
14
+ listStyle: 'none',
15
+ pointerEvents: 'none',
16
+ zIndex: '2147483600',
17
+ };
18
+ return M.value(position).pipe(M.withReturnType(), M.when('TopLeft', () => ({
19
+ ...base,
20
+ top: '0',
21
+ left: '0',
22
+ flexDirection: 'column-reverse',
23
+ })), M.when('TopCenter', () => ({
24
+ ...base,
25
+ top: '0',
26
+ left: '50%',
27
+ transform: 'translateX(-50%)',
28
+ flexDirection: 'column-reverse',
29
+ })), M.when('TopRight', () => ({
30
+ ...base,
31
+ top: '0',
32
+ right: '0',
33
+ flexDirection: 'column-reverse',
34
+ })), M.when('BottomLeft', () => ({
35
+ ...base,
36
+ bottom: '0',
37
+ left: '0',
38
+ flexDirection: 'column',
39
+ })), M.when('BottomCenter', () => ({
40
+ ...base,
41
+ bottom: '0',
42
+ left: '50%',
43
+ transform: 'translateX(-50%)',
44
+ flexDirection: 'column',
45
+ })), M.when('BottomRight', () => ({
46
+ ...base,
47
+ bottom: '0',
48
+ right: '0',
49
+ flexDirection: 'column',
50
+ })), M.exhaustive);
51
+ };
52
+ const DEFAULT_ARIA_LABEL = 'Notifications';
53
+ /** Factory that binds `Ui.Toast` to a user-provided payload schema. The
54
+ * returned module contains everything needed to wire a toast stack into an
55
+ * app: `Model`, `Message`, `Entry`, `Added`, `init`, `update`, `show` /
56
+ * `dismiss` / `dismissAll` helpers, and the headless `view`.
57
+ *
58
+ * The payload is whatever content shape the consumer supplies via Schema.
59
+ * The component never reads it — it flows through to `renderEntry`. The
60
+ * component itself owns only lifecycle and a11y fields (id, variant,
61
+ * transition, dismiss timer, hover state).
62
+ *
63
+ * Consume the bound module's exports everywhere — `Toast.Model` in your app
64
+ * Model, `Toast.Message` in your parent Message union, `Toast.show` /
65
+ * `Toast.dismiss` in your update, `Toast.view` in your view. The top-level
66
+ * exports (`Variant`, `Position`, static message tags, `DismissAfter`) are
67
+ * payload-independent and safe to reference when you need them without a
68
+ * bound module, but the typical path is through the factory return.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const ToastPayload = S.Struct({
73
+ * bodyText: S.String,
74
+ * maybeLink: S.OptionFromSelf(S.Struct({
75
+ * href: S.String,
76
+ * text: S.String,
77
+ * })),
78
+ * })
79
+ * export const Toast = Ui.Toast.make(ToastPayload)
80
+ * ```
81
+ */
82
+ export const make = (payloadSchema) => {
83
+ const runtime = makeRuntime(payloadSchema);
84
+ /** Renders a headless toast stack. The `<ol>` container is always present
85
+ * in the DOM so screen readers can observe its `aria-live` region from
86
+ * page load. Each entry becomes an `<li>` keyed by its id, with
87
+ * transition data attributes (`data-enter`, `data-leave`,
88
+ * `data-transition`, `data-closed`) and `data-variant` reflecting the
89
+ * entry's variant. */
90
+ const view = (config) => {
91
+ const { AriaAtomic, AriaLabel, AriaLive, Class, DataAttribute, Id, OnMouseEnter, OnMouseLeave, Role, Style, keyed, } = html();
92
+ const { model: { id, entries }, position, toParentMessage, renderEntry, ariaLabel = DEFAULT_ARIA_LABEL, className, attributes = [], entryClassName, entryAttributes = [], } = config;
93
+ const containerAttributes = [
94
+ Id(id),
95
+ Role('region'),
96
+ AriaLabel(ariaLabel),
97
+ AriaLive('polite'),
98
+ Style(positionToContainerStyle(position)),
99
+ ...(className ? [Class(className)] : []),
100
+ ...attributes,
101
+ ];
102
+ const renderEntryItem = (entry) => {
103
+ const { transitionState } = entry.transition;
104
+ const transitionAttributes = M.value(transitionState).pipe(M.when('EnterStart', () => [
105
+ DataAttribute('closed', ''),
106
+ DataAttribute('enter', ''),
107
+ DataAttribute('transition', ''),
108
+ ]), M.when('EnterAnimating', () => [
109
+ DataAttribute('enter', ''),
110
+ DataAttribute('transition', ''),
111
+ ]), M.when('LeaveStart', () => [
112
+ DataAttribute('leave', ''),
113
+ DataAttribute('transition', ''),
114
+ ]), M.when('LeaveAnimating', () => [
115
+ DataAttribute('closed', ''),
116
+ DataAttribute('leave', ''),
117
+ DataAttribute('transition', ''),
118
+ ]), M.orElse(() => []));
119
+ const handlers = {
120
+ dismiss: toParentMessage(Dismissed({ entryId: entry.id })),
121
+ };
122
+ const itemAttributes = [
123
+ Id(entry.id),
124
+ Role(variantToRole(entry.variant)),
125
+ AriaAtomic(true),
126
+ DataAttribute('variant', entry.variant),
127
+ Style({ pointerEvents: 'auto' }),
128
+ OnMouseEnter(toParentMessage(HoveredEntry({ entryId: entry.id }))),
129
+ OnMouseLeave(toParentMessage(LeftEntry({ entryId: entry.id }))),
130
+ ...transitionAttributes,
131
+ ...(entryClassName ? [Class(entryClassName)] : []),
132
+ ...entryAttributes,
133
+ ];
134
+ return keyed('li')(entry.id, itemAttributes, [
135
+ renderEntry(entry, handlers),
136
+ ]);
137
+ };
138
+ return keyed('ol')(id, containerAttributes, entries.map(renderEntryItem));
139
+ };
140
+ /** Creates a memoized toast container view. Static config (className,
141
+ * entryClassName, etc.) is captured in a closure. Dynamic fields —
142
+ * `model`, `toParentMessage`, and `renderEntry` — are compared by
143
+ * reference per render via `createLazy`. */
144
+ const lazy = (staticConfig) => {
145
+ const lazyView = createLazy();
146
+ return (model, toParentMessage, renderEntry) => lazyView((currentModel, currentToMessage, currentRenderEntry) => view({
147
+ ...staticConfig,
148
+ model: currentModel,
149
+ toParentMessage: currentToMessage,
150
+ renderEntry: currentRenderEntry,
151
+ }), [model, toParentMessage, renderEntry]);
152
+ };
153
+ return {
154
+ ...runtime,
155
+ view,
156
+ lazy,
157
+ };
158
+ };
@@ -0,0 +1,4 @@
1
+ export { make, Variant, Position, Dismissed, DismissedAll, ElapsedDuration, HoveredEntry, LeftEntry, GotTransitionMessage, DismissAfter, } from './index';
2
+ export type { EntryHandlers } from './index';
3
+ export type { InitConfig, ShowInput } from './index';
4
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/toast/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,SAAS,EACT,oBAAoB,EACpB,YAAY,GACb,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export { make, Variant, Position, Dismissed, DismissedAll, ElapsedDuration, HoveredEntry, LeftEntry, GotTransitionMessage, DismissAfter, } from './index';
@@ -0,0 +1,143 @@
1
+ import { Duration, Schema as S } from 'effect';
2
+ /** Semantic category of a toast. Drives the default ARIA role: `status` for
3
+ * `Info` / `Success`, `alert` for `Warning` / `Error`. Also surfaced as
4
+ * `data-variant` on each entry for per-variant CSS. This is the only
5
+ * content-adjacent field the component owns — the rest of the entry's
6
+ * content lives in the user-provided payload. */
7
+ export declare const Variant: S.Literal<["Info", "Success", "Warning", "Error"]>;
8
+ export type Variant = typeof Variant.Type;
9
+ /** Where the toast viewport is anchored on the screen and how entries stack. */
10
+ export declare const Position: S.Literal<["TopLeft", "TopCenter", "TopRight", "BottomLeft", "BottomCenter", "BottomRight"]>;
11
+ export type Position = typeof Position.Type;
12
+ /** Schema factory for a single toast entry. `payloadSchema` is user-provided
13
+ * and defines the shape of per-entry content — whatever the consumer wants
14
+ * to encode. The component itself owns only lifecycle + a11y fields: `id`,
15
+ * `variant` (for ARIA role), `transition`, `maybeDuration`,
16
+ * `pendingDismissVersion` (for cancellable auto-dismiss), and `isHovered`
17
+ * (for pause-on-hover). */
18
+ export declare const makeEntry: <A, I>(payloadSchema: S.Schema<A, I>) => S.Struct<{
19
+ id: typeof S.String;
20
+ variant: S.Literal<["Info", "Success", "Warning", "Error"]>;
21
+ transition: S.Struct<{
22
+ id: typeof S.String;
23
+ isShowing: typeof S.Boolean;
24
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
25
+ }>;
26
+ maybeDuration: S.OptionFromSelf<typeof S.DurationFromMillis>;
27
+ pendingDismissVersion: typeof S.Number;
28
+ isHovered: typeof S.Boolean;
29
+ payload: S.Schema<A, I, never>;
30
+ }>;
31
+ /** Schema factory for the toast container's state. `nextEntryKey` is a
32
+ * monotonic counter used to generate unique entry IDs purely from Model
33
+ * state. Thread the updated model through successive `show()` calls —
34
+ * calling `show()` twice against the same pre-update model in the same tick
35
+ * will produce duplicate entry IDs. */
36
+ export declare const makeModel: <A, I>(payloadSchema: S.Schema<A, I>) => S.Struct<{
37
+ id: typeof S.String;
38
+ defaultDuration: typeof S.DurationFromMillis;
39
+ entries: S.Array$<S.Struct<{
40
+ id: typeof S.String;
41
+ variant: S.Literal<["Info", "Success", "Warning", "Error"]>;
42
+ transition: S.Struct<{
43
+ id: typeof S.String;
44
+ isShowing: typeof S.Boolean;
45
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
46
+ }>;
47
+ maybeDuration: S.OptionFromSelf<typeof S.DurationFromMillis>;
48
+ pendingDismissVersion: typeof S.Number;
49
+ isHovered: typeof S.Boolean;
50
+ payload: S.Schema<A, I, never>;
51
+ }>>;
52
+ nextEntryKey: typeof S.Number;
53
+ }>;
54
+ /** Sent when an entry should begin dismissing. Starts the leave animation;
55
+ * the entry is removed from the stack when `TransitionedOut` fires. */
56
+ export declare const Dismissed: import("../../schema").CallableTaggedStruct<"Dismissed", {
57
+ entryId: typeof S.String;
58
+ }>;
59
+ /** Sent when every currently-visible entry should begin dismissing. */
60
+ export declare const DismissedAll: import("../../schema").CallableTaggedStruct<"DismissedAll", {}>;
61
+ /** Sent when an entry's auto-dismiss timer fires. Carries a version echoed
62
+ * from the scheduling moment so stale timers (from hover or manual dismiss)
63
+ * are discarded. */
64
+ export declare const ElapsedDuration: import("../../schema").CallableTaggedStruct<"ElapsedDuration", {
65
+ entryId: typeof S.String;
66
+ version: typeof S.Number;
67
+ }>;
68
+ /** Sent when the pointer enters an entry. Pauses the auto-dismiss timer by
69
+ * advancing the entry's version. */
70
+ export declare const HoveredEntry: import("../../schema").CallableTaggedStruct<"HoveredEntry", {
71
+ entryId: typeof S.String;
72
+ }>;
73
+ /** Sent when the pointer leaves an entry. Restarts the auto-dismiss timer
74
+ * with the entry's full duration. */
75
+ export declare const LeftEntry: import("../../schema").CallableTaggedStruct<"LeftEntry", {
76
+ entryId: typeof S.String;
77
+ }>;
78
+ /** Wraps a single entry's Transition submodel message for delegation. */
79
+ export declare const GotTransitionMessage: import("../../schema").CallableTaggedStruct<"GotTransitionMessage", {
80
+ entryId: typeof S.String;
81
+ message: S.Union<[import("../../schema").CallableTaggedStruct<"Showed", {}>, import("../../schema").CallableTaggedStruct<"Hid", {}>, import("../../schema").CallableTaggedStruct<"AdvancedTransitionFrame", {}>, import("../../schema").CallableTaggedStruct<"EndedTransition", {}>]>;
82
+ }>;
83
+ export type Dismissed = typeof Dismissed.Type;
84
+ export type DismissedAll = typeof DismissedAll.Type;
85
+ export type ElapsedDuration = typeof ElapsedDuration.Type;
86
+ export type HoveredEntry = typeof HoveredEntry.Type;
87
+ export type LeftEntry = typeof LeftEntry.Type;
88
+ export type GotTransitionMessage = typeof GotTransitionMessage.Type;
89
+ /** Factory for the `Added` message, which carries a fully-constructed entry
90
+ * whose shape depends on the user-provided payload. */
91
+ export declare const makeAdded: <A, I>(payloadSchema: S.Schema<A, I>) => import("../../schema").CallableTaggedStruct<"Added", {
92
+ entry: S.Struct<{
93
+ id: typeof S.String;
94
+ variant: S.Literal<["Info", "Success", "Warning", "Error"]>;
95
+ transition: S.Struct<{
96
+ id: typeof S.String;
97
+ isShowing: typeof S.Boolean;
98
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
99
+ }>;
100
+ maybeDuration: S.OptionFromSelf<typeof S.DurationFromMillis>;
101
+ pendingDismissVersion: typeof S.Number;
102
+ isHovered: typeof S.Boolean;
103
+ payload: S.Schema<A, I, never>;
104
+ }>;
105
+ }>;
106
+ /** Factory for the union of all messages the toast component can produce. */
107
+ export declare const makeMessage: <A, I>(payloadSchema: S.Schema<A, I>) => S.Union<[import("../../schema").CallableTaggedStruct<"Added", {
108
+ entry: S.Struct<{
109
+ id: typeof S.String;
110
+ variant: S.Literal<["Info", "Success", "Warning", "Error"]>;
111
+ transition: S.Struct<{
112
+ id: typeof S.String;
113
+ isShowing: typeof S.Boolean;
114
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
115
+ }>;
116
+ maybeDuration: S.OptionFromSelf<typeof S.DurationFromMillis>;
117
+ pendingDismissVersion: typeof S.Number;
118
+ isHovered: typeof S.Boolean;
119
+ payload: S.Schema<A, I, never>;
120
+ }>;
121
+ }>, import("../../schema").CallableTaggedStruct<"Dismissed", {
122
+ entryId: typeof S.String;
123
+ }>, import("../../schema").CallableTaggedStruct<"DismissedAll", {}>, import("../../schema").CallableTaggedStruct<"ElapsedDuration", {
124
+ entryId: typeof S.String;
125
+ version: typeof S.Number;
126
+ }>, import("../../schema").CallableTaggedStruct<"HoveredEntry", {
127
+ entryId: typeof S.String;
128
+ }>, import("../../schema").CallableTaggedStruct<"LeftEntry", {
129
+ entryId: typeof S.String;
130
+ }>, import("../../schema").CallableTaggedStruct<"GotTransitionMessage", {
131
+ entryId: typeof S.String;
132
+ message: S.Union<[import("../../schema").CallableTaggedStruct<"Showed", {}>, import("../../schema").CallableTaggedStruct<"Hid", {}>, import("../../schema").CallableTaggedStruct<"AdvancedTransitionFrame", {}>, import("../../schema").CallableTaggedStruct<"EndedTransition", {}>]>;
133
+ }>]>;
134
+ /** Configuration for creating a toast container model. `defaultDuration` is
135
+ * applied to any `show()` call that doesn't provide its own `duration` or
136
+ * pass `sticky: true`. Accepts any Effect Duration input; a bare number is
137
+ * interpreted as milliseconds. */
138
+ export type InitConfig = Readonly<{
139
+ id: string;
140
+ defaultDuration?: Duration.DurationInput;
141
+ }>;
142
+ export declare const DEFAULT_DURATION: Duration.Duration;
143
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/ui/toast/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAU9C;;;;kDAIkD;AAClD,eAAO,MAAM,OAAO,oDAAmD,CAAA;AACvE,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,gFAAgF;AAChF,eAAO,MAAM,QAAQ,8FAOpB,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAI3C;;;;;4BAK4B;AAC5B,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;;;;;;;;EASzD,CAAA;AAIJ;;;;wCAIwC;AACxC,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;;;;;;;;;;;;;EAMzD,CAAA;AAIJ;wEACwE;AACxE,eAAO,MAAM,SAAS;;EAAwC,CAAA;AAC9D,uEAAuE;AACvE,eAAO,MAAM,YAAY,iEAAoB,CAAA;AAC7C;;qBAEqB;AACrB,eAAO,MAAM,eAAe;;;EAG1B,CAAA;AACF;qCACqC;AACrC,eAAO,MAAM,YAAY;;EAA2C,CAAA;AACpE;sCACsC;AACtC,eAAO,MAAM,SAAS;;EAAwC,CAAA;AAC9D,yEAAyE;AACzE,eAAO,MAAM,oBAAoB;;;EAG/B,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAC7C,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AACnD,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AACzD,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AACnD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAC7C,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAA;AAEnE;wDACwD;AACxD,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;;;;;;;;;;EACZ,CAAA;AAEjD,6EAA6E;AAC7E,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;IAS5D,CAAA;AAIH;;;mCAGmC;AACnC,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,eAAe,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;CACzC,CAAC,CAAA;AAEF,eAAO,MAAM,gBAAgB,mBAAsB,CAAA"}
@@ -0,0 +1,71 @@
1
+ import { Duration, Schema as S } from 'effect';
2
+ import { m } from '../../message';
3
+ import { Message as TransitionMessage, Model as TransitionModel, } from '../transition/schema';
4
+ // VARIANT
5
+ /** Semantic category of a toast. Drives the default ARIA role: `status` for
6
+ * `Info` / `Success`, `alert` for `Warning` / `Error`. Also surfaced as
7
+ * `data-variant` on each entry for per-variant CSS. This is the only
8
+ * content-adjacent field the component owns — the rest of the entry's
9
+ * content lives in the user-provided payload. */
10
+ export const Variant = S.Literal('Info', 'Success', 'Warning', 'Error');
11
+ // POSITION
12
+ /** Where the toast viewport is anchored on the screen and how entries stack. */
13
+ export const Position = S.Literal('TopLeft', 'TopCenter', 'TopRight', 'BottomLeft', 'BottomCenter', 'BottomRight');
14
+ // ENTRY
15
+ /** Schema factory for a single toast entry. `payloadSchema` is user-provided
16
+ * and defines the shape of per-entry content — whatever the consumer wants
17
+ * to encode. The component itself owns only lifecycle + a11y fields: `id`,
18
+ * `variant` (for ARIA role), `transition`, `maybeDuration`,
19
+ * `pendingDismissVersion` (for cancellable auto-dismiss), and `isHovered`
20
+ * (for pause-on-hover). */
21
+ export const makeEntry = (payloadSchema) => S.Struct({
22
+ id: S.String,
23
+ variant: Variant,
24
+ transition: TransitionModel,
25
+ maybeDuration: S.OptionFromSelf(S.DurationFromMillis),
26
+ pendingDismissVersion: S.Number,
27
+ isHovered: S.Boolean,
28
+ payload: payloadSchema,
29
+ });
30
+ // MODEL
31
+ /** Schema factory for the toast container's state. `nextEntryKey` is a
32
+ * monotonic counter used to generate unique entry IDs purely from Model
33
+ * state. Thread the updated model through successive `show()` calls —
34
+ * calling `show()` twice against the same pre-update model in the same tick
35
+ * will produce duplicate entry IDs. */
36
+ export const makeModel = (payloadSchema) => S.Struct({
37
+ id: S.String,
38
+ defaultDuration: S.DurationFromMillis,
39
+ entries: S.Array(makeEntry(payloadSchema)),
40
+ nextEntryKey: S.Number,
41
+ });
42
+ // MESSAGE
43
+ /** Sent when an entry should begin dismissing. Starts the leave animation;
44
+ * the entry is removed from the stack when `TransitionedOut` fires. */
45
+ export const Dismissed = m('Dismissed', { entryId: S.String });
46
+ /** Sent when every currently-visible entry should begin dismissing. */
47
+ export const DismissedAll = m('DismissedAll');
48
+ /** Sent when an entry's auto-dismiss timer fires. Carries a version echoed
49
+ * from the scheduling moment so stale timers (from hover or manual dismiss)
50
+ * are discarded. */
51
+ export const ElapsedDuration = m('ElapsedDuration', {
52
+ entryId: S.String,
53
+ version: S.Number,
54
+ });
55
+ /** Sent when the pointer enters an entry. Pauses the auto-dismiss timer by
56
+ * advancing the entry's version. */
57
+ export const HoveredEntry = m('HoveredEntry', { entryId: S.String });
58
+ /** Sent when the pointer leaves an entry. Restarts the auto-dismiss timer
59
+ * with the entry's full duration. */
60
+ export const LeftEntry = m('LeftEntry', { entryId: S.String });
61
+ /** Wraps a single entry's Transition submodel message for delegation. */
62
+ export const GotTransitionMessage = m('GotTransitionMessage', {
63
+ entryId: S.String,
64
+ message: TransitionMessage,
65
+ });
66
+ /** Factory for the `Added` message, which carries a fully-constructed entry
67
+ * whose shape depends on the user-provided payload. */
68
+ export const makeAdded = (payloadSchema) => m('Added', { entry: makeEntry(payloadSchema) });
69
+ /** Factory for the union of all messages the toast component can produce. */
70
+ export const makeMessage = (payloadSchema) => S.Union(makeAdded(payloadSchema), Dismissed, DismissedAll, ElapsedDuration, HoveredEntry, LeftEntry, GotTransitionMessage);
71
+ export const DEFAULT_DURATION = Duration.seconds(4);