@zag-js/toast 0.23.0 → 0.25.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.
- package/dist/index.d.mts +34 -47
- package/dist/index.d.ts +34 -47
- package/dist/index.js +59 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -82
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +4 -13
- package/src/toast-group.connect.ts +68 -78
- package/src/toast-group.machine.ts +6 -3
- package/src/toast.connect.ts +1 -15
- package/src/toast.dom.ts +1 -2
- package/src/toast.types.ts +37 -45
|
@@ -3,16 +3,7 @@ import type { NormalizeProps, PropTypes } from "@zag-js/types"
|
|
|
3
3
|
import { runIfFn, uuid } from "@zag-js/utils"
|
|
4
4
|
import { parts } from "./toast.anatomy"
|
|
5
5
|
import { dom } from "./toast.dom"
|
|
6
|
-
import type {
|
|
7
|
-
GroupMachineApi,
|
|
8
|
-
GroupMachineContext,
|
|
9
|
-
GroupProps,
|
|
10
|
-
GroupSend,
|
|
11
|
-
GroupState,
|
|
12
|
-
Options,
|
|
13
|
-
Placement,
|
|
14
|
-
PromiseOptions,
|
|
15
|
-
} from "./toast.types"
|
|
6
|
+
import type { GroupMachineApi, GroupSend, GroupState, Options } from "./toast.types"
|
|
16
7
|
import { getGroupPlacementStyle, getToastsByPlacement } from "./toast.utils"
|
|
17
8
|
|
|
18
9
|
export let toaster = {} as GroupMachineApi
|
|
@@ -23,112 +14,115 @@ export function groupConnect<T extends PropTypes>(
|
|
|
23
14
|
normalize: NormalizeProps<T>,
|
|
24
15
|
): GroupMachineApi<T> {
|
|
25
16
|
//
|
|
26
|
-
const
|
|
27
|
-
count: state.context.count,
|
|
28
|
-
toasts: state.context.toasts,
|
|
29
|
-
toastsByPlacement: getToastsByPlacement(state.context.toasts),
|
|
30
|
-
isVisible(id: string) {
|
|
31
|
-
if (!state.context.toasts.length) return false
|
|
32
|
-
return !!state.context.toasts.find((toast) => toast.id == id)
|
|
33
|
-
},
|
|
17
|
+
const toastsByPlacement = getToastsByPlacement(state.context.toasts)
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
19
|
+
function isVisible(id: string) {
|
|
20
|
+
if (!state.context.toasts.length) return false
|
|
21
|
+
return !!state.context.toasts.find((toast) => toast.id == id)
|
|
22
|
+
}
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
function create(options: Options) {
|
|
25
|
+
const uid = `toast:${uuid()}`
|
|
26
|
+
const id = options.id ? options.id : uid
|
|
41
27
|
|
|
42
|
-
|
|
43
|
-
}
|
|
28
|
+
if (isVisible(id)) return
|
|
29
|
+
send({ type: "ADD_TOAST", toast: { ...options, id } })
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const isVisible = id ? group.isVisible(id) : false
|
|
48
|
-
if (isVisible && id != null) {
|
|
49
|
-
return group.update(id, options)
|
|
50
|
-
} else {
|
|
51
|
-
return group.create(options)
|
|
52
|
-
}
|
|
53
|
-
},
|
|
31
|
+
return id
|
|
32
|
+
}
|
|
54
33
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
34
|
+
function update(id: string, options: Options) {
|
|
35
|
+
if (!isVisible(id)) return
|
|
36
|
+
send({ type: "UPDATE_TOAST", id, toast: options })
|
|
37
|
+
return id
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function upsert(options: Options) {
|
|
41
|
+
const { id } = options
|
|
42
|
+
const visible = id ? isVisible(id) : false
|
|
43
|
+
if (visible && id != null) {
|
|
44
|
+
return update(id, options)
|
|
45
|
+
} else {
|
|
46
|
+
return create(options)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
62
49
|
|
|
63
|
-
|
|
50
|
+
function dismiss(id?: string) {
|
|
51
|
+
if (id == null) {
|
|
52
|
+
send("DISMISS_ALL")
|
|
53
|
+
} else if (isVisible(id)) {
|
|
54
|
+
send({ type: "DISMISS_TOAST", id })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
count: state.context.count,
|
|
60
|
+
toasts: state.context.toasts,
|
|
61
|
+
toastsByPlacement,
|
|
62
|
+
isVisible,
|
|
63
|
+
|
|
64
|
+
create,
|
|
65
|
+
update,
|
|
66
|
+
upsert,
|
|
67
|
+
dismiss,
|
|
68
|
+
|
|
69
|
+
remove(id) {
|
|
64
70
|
if (id == null) {
|
|
65
71
|
send("REMOVE_ALL")
|
|
66
|
-
} else if (
|
|
72
|
+
} else if (isVisible(id)) {
|
|
67
73
|
send({ type: "REMOVE_TOAST", id })
|
|
68
74
|
}
|
|
69
75
|
},
|
|
70
76
|
|
|
71
|
-
dismissByPlacement(placement
|
|
72
|
-
const toasts =
|
|
77
|
+
dismissByPlacement(placement) {
|
|
78
|
+
const toasts = toastsByPlacement[placement]
|
|
73
79
|
if (toasts) {
|
|
74
|
-
toasts.forEach((toast) =>
|
|
80
|
+
toasts.forEach((toast) => dismiss(toast.id))
|
|
75
81
|
}
|
|
76
82
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!group.isVisible(id)) return
|
|
80
|
-
send({ type: "UPDATE_TOAST", id, toast: options })
|
|
81
|
-
return id
|
|
83
|
+
loading(options) {
|
|
84
|
+
return upsert({ ...options, type: "loading" })
|
|
82
85
|
},
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
options.type = "loading"
|
|
86
|
-
return group.upsert(options)
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
success(options: Options) {
|
|
90
|
-
options.type = "success"
|
|
91
|
-
return group.upsert(options)
|
|
86
|
+
success(options) {
|
|
87
|
+
return upsert({ ...options, type: "success" })
|
|
92
88
|
},
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
options.type = "error"
|
|
96
|
-
return group.upsert(options)
|
|
89
|
+
error(options) {
|
|
90
|
+
return upsert({ ...options, type: "error" })
|
|
97
91
|
},
|
|
98
92
|
|
|
99
|
-
promise
|
|
100
|
-
const id =
|
|
93
|
+
promise(promise, options, shared = {}) {
|
|
94
|
+
const id = upsert({ ...shared, ...options.loading, type: "loading" })
|
|
101
95
|
|
|
102
96
|
promise
|
|
103
97
|
.then((response) => {
|
|
104
98
|
const successOptions = runIfFn(options.success, response)
|
|
105
|
-
|
|
99
|
+
upsert({ ...shared, ...successOptions, id, type: "success" })
|
|
106
100
|
})
|
|
107
101
|
.catch((error) => {
|
|
108
102
|
const errorOptions = runIfFn(options.error, error)
|
|
109
|
-
|
|
103
|
+
upsert({ ...shared, ...errorOptions, id, type: "error" })
|
|
110
104
|
})
|
|
111
105
|
|
|
112
106
|
return promise
|
|
113
107
|
},
|
|
114
108
|
|
|
115
|
-
pause(id
|
|
109
|
+
pause(id) {
|
|
116
110
|
if (id == null) {
|
|
117
111
|
send("PAUSE_ALL")
|
|
118
|
-
} else if (
|
|
112
|
+
} else if (isVisible(id)) {
|
|
119
113
|
send({ type: "PAUSE_TOAST", id })
|
|
120
114
|
}
|
|
121
115
|
},
|
|
122
116
|
|
|
123
|
-
resume(id
|
|
117
|
+
resume(id) {
|
|
124
118
|
if (id == null) {
|
|
125
119
|
send("RESUME_ALL")
|
|
126
|
-
} else if (
|
|
120
|
+
} else if (isVisible(id)) {
|
|
127
121
|
send({ type: "RESUME_TOAST", id })
|
|
128
122
|
}
|
|
129
123
|
},
|
|
130
124
|
|
|
131
|
-
getGroupProps(options
|
|
125
|
+
getGroupProps(options) {
|
|
132
126
|
const { placement, label = "Notifications" } = options
|
|
133
127
|
return normalize.element({
|
|
134
128
|
...parts.group.attrs,
|
|
@@ -142,12 +136,8 @@ export function groupConnect<T extends PropTypes>(
|
|
|
142
136
|
})
|
|
143
137
|
},
|
|
144
138
|
|
|
145
|
-
subscribe(fn
|
|
139
|
+
subscribe(fn) {
|
|
146
140
|
return subscribe(state.context.toasts, () => fn(state.context.toasts))
|
|
147
141
|
},
|
|
148
142
|
}
|
|
149
|
-
|
|
150
|
-
Object.assign(toaster, group)
|
|
151
|
-
|
|
152
|
-
return group
|
|
153
143
|
}
|
|
@@ -2,7 +2,7 @@ import { createMachine } from "@zag-js/core"
|
|
|
2
2
|
import { MAX_Z_INDEX } from "@zag-js/dom-query"
|
|
3
3
|
import { compact } from "@zag-js/utils"
|
|
4
4
|
import { createToastMachine } from "./toast.machine"
|
|
5
|
-
import type { GroupMachineContext, UserDefinedGroupContext } from "./toast.types"
|
|
5
|
+
import type { GroupMachineContext, MachineContext, UserDefinedGroupContext } from "./toast.types"
|
|
6
6
|
|
|
7
7
|
export function groupMachine(userContext: UserDefinedGroupContext) {
|
|
8
8
|
const ctx = compact(userContext)
|
|
@@ -55,8 +55,11 @@ export function groupMachine(userContext: UserDefinedGroupContext) {
|
|
|
55
55
|
ADD_TOAST: {
|
|
56
56
|
guard: (ctx) => ctx.toasts.length < ctx.max,
|
|
57
57
|
actions: (ctx, evt, { self }) => {
|
|
58
|
-
const options = {
|
|
59
|
-
|
|
58
|
+
const options: MachineContext = {
|
|
59
|
+
placement: ctx.placement,
|
|
60
|
+
duration: ctx.duration,
|
|
61
|
+
removeDelay: ctx.removeDelay,
|
|
62
|
+
render: ctx.render,
|
|
60
63
|
...evt.toast,
|
|
61
64
|
pauseOnPageIdle: ctx.pauseOnPageIdle,
|
|
62
65
|
pauseOnInteraction: ctx.pauseOnInteraction,
|
package/src/toast.connect.ts
CHANGED
|
@@ -8,7 +8,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
8
8
|
const isPaused = state.hasTag("paused")
|
|
9
9
|
|
|
10
10
|
const pauseOnInteraction = state.context.pauseOnInteraction
|
|
11
|
-
const placement = state.context.placement
|
|
11
|
+
const placement = state.context.placement!
|
|
12
12
|
|
|
13
13
|
return {
|
|
14
14
|
type: state.context.type,
|
|
@@ -31,20 +31,6 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
31
31
|
send("DISMISS")
|
|
32
32
|
},
|
|
33
33
|
|
|
34
|
-
render() {
|
|
35
|
-
return state.context.render?.({
|
|
36
|
-
id: state.context.id,
|
|
37
|
-
type: state.context.type,
|
|
38
|
-
duration: state.context.duration,
|
|
39
|
-
title: state.context.title,
|
|
40
|
-
placement: state.context.placement,
|
|
41
|
-
description: state.context.description,
|
|
42
|
-
dismiss() {
|
|
43
|
-
send("DISMISS")
|
|
44
|
-
},
|
|
45
|
-
})
|
|
46
|
-
},
|
|
47
|
-
|
|
48
34
|
rootProps: normalize.element({
|
|
49
35
|
...parts.root.attrs,
|
|
50
36
|
dir: state.context.dir,
|
package/src/toast.dom.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createScope } from "@zag-js/dom-query"
|
|
2
|
-
import type {
|
|
2
|
+
import type { MachineContext as Ctx, Placement } from "./toast.types"
|
|
3
3
|
|
|
4
4
|
export const dom = createScope({
|
|
5
5
|
getGroupId: (placement: Placement) => `toast-group:${placement}`,
|
|
@@ -7,5 +7,4 @@ export const dom = createScope({
|
|
|
7
7
|
getTitleId: (ctx: Ctx) => `toast:${ctx.id}:title`,
|
|
8
8
|
getDescriptionId: (ctx: Ctx) => `toast:${ctx.id}:description`,
|
|
9
9
|
getCloseTriggerId: (ctx: Ctx) => `toast${ctx.id}:close`,
|
|
10
|
-
getPortalId: (ctx: GroupCtx) => `toast-portal:${ctx.id}`,
|
|
11
10
|
})
|
package/src/toast.types.ts
CHANGED
|
@@ -9,44 +9,59 @@ import type {
|
|
|
9
9
|
RootProperties,
|
|
10
10
|
} from "@zag-js/types"
|
|
11
11
|
|
|
12
|
+
/* -----------------------------------------------------------------------------
|
|
13
|
+
* Base types
|
|
14
|
+
* -----------------------------------------------------------------------------*/
|
|
15
|
+
|
|
12
16
|
export type Type = "success" | "error" | "loading" | "info" | "custom"
|
|
13
17
|
|
|
14
18
|
export type Placement = "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end"
|
|
15
19
|
|
|
16
|
-
export interface
|
|
20
|
+
export interface BaseOptions {
|
|
17
21
|
/**
|
|
18
|
-
*
|
|
22
|
+
* Whether to pause toast when the user leaves the browser tab
|
|
19
23
|
*/
|
|
20
|
-
|
|
24
|
+
pauseOnPageIdle?: boolean
|
|
21
25
|
/**
|
|
22
|
-
*
|
|
26
|
+
* Whether to pause the toast when interacted with
|
|
23
27
|
*/
|
|
24
|
-
|
|
28
|
+
pauseOnInteraction?: boolean
|
|
29
|
+
/**
|
|
30
|
+
* The duration the toast will be visible
|
|
31
|
+
*/
|
|
32
|
+
duration?: number
|
|
33
|
+
/**
|
|
34
|
+
* The duration for the toast to kept alive before it is removed.
|
|
35
|
+
* Useful for exit transitions.
|
|
36
|
+
*/
|
|
37
|
+
removeDelay?: number
|
|
25
38
|
/**
|
|
26
39
|
* The placement of the toast
|
|
27
40
|
*/
|
|
28
|
-
placement
|
|
41
|
+
placement?: Placement
|
|
29
42
|
/**
|
|
30
|
-
*
|
|
43
|
+
* Custom function to render the toast element.
|
|
31
44
|
*/
|
|
32
|
-
|
|
45
|
+
render?: (options: MachineApi<any>) => any
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ToastOptions {
|
|
33
49
|
/**
|
|
34
|
-
* The
|
|
50
|
+
* The unique id of the toast
|
|
35
51
|
*/
|
|
36
|
-
|
|
52
|
+
id: string
|
|
37
53
|
/**
|
|
38
|
-
* The
|
|
54
|
+
* The type of the toast
|
|
39
55
|
*/
|
|
40
|
-
|
|
56
|
+
type: Type
|
|
41
57
|
/**
|
|
42
|
-
*
|
|
58
|
+
* The message of the toast
|
|
43
59
|
*/
|
|
44
|
-
|
|
60
|
+
title?: string
|
|
45
61
|
/**
|
|
46
|
-
* The
|
|
47
|
-
* Useful for exit transitions.
|
|
62
|
+
* The description of the toast
|
|
48
63
|
*/
|
|
49
|
-
|
|
64
|
+
description?: string
|
|
50
65
|
/**
|
|
51
66
|
* Function called when the toast has been closed and removed
|
|
52
67
|
*/
|
|
@@ -65,34 +80,14 @@ export interface ToastOptions {
|
|
|
65
80
|
onUpdate?: VoidFunction
|
|
66
81
|
}
|
|
67
82
|
|
|
68
|
-
export type Options = Partial<ToastOptions>
|
|
69
|
-
|
|
70
|
-
export type RenderOptions = Omit<ToastOptions, "render"> & {
|
|
71
|
-
dismiss(): void
|
|
72
|
-
}
|
|
83
|
+
export type Options = Partial<ToastOptions & BaseOptions>
|
|
73
84
|
|
|
74
85
|
/* -----------------------------------------------------------------------------
|
|
75
86
|
* Machine context
|
|
76
87
|
* -----------------------------------------------------------------------------*/
|
|
77
88
|
|
|
78
|
-
interface SharedContext {
|
|
79
|
-
/**
|
|
80
|
-
* Whether to pause toast when the user leaves the browser tab
|
|
81
|
-
*/
|
|
82
|
-
pauseOnPageIdle?: boolean
|
|
83
|
-
/**
|
|
84
|
-
* Whether to pause the toast when interacted with
|
|
85
|
-
*/
|
|
86
|
-
pauseOnInteraction?: boolean
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* The default options for the toast
|
|
90
|
-
*/
|
|
91
|
-
defaultOptions?: Partial<Pick<ToastOptions, "duration" | "removeDelay" | "placement">>
|
|
92
|
-
}
|
|
93
|
-
|
|
94
89
|
export interface MachineContext
|
|
95
|
-
extends
|
|
90
|
+
extends BaseOptions,
|
|
96
91
|
RootProperties,
|
|
97
92
|
CommonProperties,
|
|
98
93
|
Omit<ToastOptions, "removeDelay"> {
|
|
@@ -126,7 +121,7 @@ export type Send = S.Send
|
|
|
126
121
|
|
|
127
122
|
export type Service = Machine<MachineContext, MachineState>
|
|
128
123
|
|
|
129
|
-
interface GroupPublicContext extends
|
|
124
|
+
interface GroupPublicContext extends BaseOptions, DirectionProperty, CommonProperties {
|
|
130
125
|
/**
|
|
131
126
|
* The gutter or spacing between toasts
|
|
132
127
|
*/
|
|
@@ -254,7 +249,7 @@ export interface GroupMachineApi<T extends PropTypes = PropTypes> {
|
|
|
254
249
|
* - When the promise resolves, the toast will be updated with the success options.
|
|
255
250
|
* - When the promise rejects, the toast will be updated with the error options.
|
|
256
251
|
*/
|
|
257
|
-
promise<T>(promise: Promise<T>, options: PromiseOptions<T>, shared?: ToastOptions): Promise<T>
|
|
252
|
+
promise<T>(promise: Promise<T>, options: PromiseOptions<T>, shared?: Partial<ToastOptions>): Promise<T>
|
|
258
253
|
/**
|
|
259
254
|
* Function to subscribe to the toast group.
|
|
260
255
|
*/
|
|
@@ -303,10 +298,7 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
303
298
|
* Function to instantly dismiss the toast.
|
|
304
299
|
*/
|
|
305
300
|
dismiss(): void
|
|
306
|
-
|
|
307
|
-
* Function render the toast in the DOM (based on the defined `render` property)
|
|
308
|
-
*/
|
|
309
|
-
render(): any
|
|
301
|
+
|
|
310
302
|
rootProps: T["element"]
|
|
311
303
|
titleProps: T["element"]
|
|
312
304
|
descriptionProps: T["element"]
|