@samline/notify 1.0.2 → 2.0.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.
Files changed (84) hide show
  1. package/{LICENSE → LICENSE.md} +2 -2
  2. package/README.md +27 -163
  3. package/dist/_runtime.d.mts +87 -0
  4. package/dist/_runtime.d.ts +87 -0
  5. package/dist/_runtime.js +97 -0
  6. package/dist/_runtime.mjs +83 -0
  7. package/dist/browser/assets-client-B-VVPPYQ.js +114 -0
  8. package/dist/browser/assets-client-CUzxHubR.mjs +108 -0
  9. package/dist/browser/index-client-BBOQyMFk.mjs +173 -0
  10. package/dist/browser/index-client-Czb7hTpD.js +181 -0
  11. package/dist/browser/index.d.mts +134 -0
  12. package/dist/browser/index.d.ts +134 -0
  13. package/dist/browser/index.js +34 -0
  14. package/dist/browser/index.mjs +26 -0
  15. package/dist/browser/render-client-CjcQoukB.js +981 -0
  16. package/dist/browser/render-client-bGRSTd-L.mjs +974 -0
  17. package/dist/core/index.d.mts +68 -0
  18. package/dist/core/index.d.ts +68 -0
  19. package/dist/core/index.js +1 -0
  20. package/dist/core/index.mjs +1 -0
  21. package/dist/index.d.mts +131 -0
  22. package/dist/index.d.ts +131 -0
  23. package/dist/index.js +1240 -0
  24. package/dist/index.mjs +1228 -0
  25. package/dist/react/index.d.mts +158 -0
  26. package/dist/react/index.d.ts +158 -0
  27. package/dist/react/index.js +1116 -0
  28. package/dist/react/index.mjs +1107 -0
  29. package/dist/styles.css +589 -422
  30. package/dist/svelte/assets-client-B-VVPPYQ.js +114 -0
  31. package/dist/svelte/assets-client-CUzxHubR.mjs +108 -0
  32. package/dist/svelte/index-client-DbXbWMIe.js +177 -0
  33. package/dist/svelte/index-client-Dj_WfPK9.mjs +170 -0
  34. package/dist/svelte/index.d.mts +14 -0
  35. package/dist/svelte/index.d.ts +14 -0
  36. package/dist/svelte/index.js +43 -0
  37. package/dist/svelte/index.mjs +36 -0
  38. package/dist/svelte/render-client-CjcQoukB.js +981 -0
  39. package/dist/svelte/render-client-bGRSTd-L.mjs +974 -0
  40. package/dist/vue/assets-client-B-VVPPYQ.js +114 -0
  41. package/dist/vue/assets-client-CUzxHubR.mjs +108 -0
  42. package/dist/vue/index-client-DbXbWMIe.js +177 -0
  43. package/dist/vue/index-client-Dj_WfPK9.mjs +170 -0
  44. package/dist/vue/index.d.mts +50 -0
  45. package/dist/vue/index.d.ts +50 -0
  46. package/dist/vue/index.js +110 -0
  47. package/dist/vue/index.mjs +104 -0
  48. package/dist/vue/render-client-CjcQoukB.js +981 -0
  49. package/dist/vue/render-client-bGRSTd-L.mjs +974 -0
  50. package/package.json +140 -95
  51. package/dist/browser-notify.js +0 -68
  52. package/dist/cc-2Yt7NqMX.mjs +0 -21
  53. package/dist/cc-B6peeNak.mjs +0 -33
  54. package/dist/cc-BWuAzFJ6.js +0 -12
  55. package/dist/cc-CaBHsjUt.js +0 -34
  56. package/dist/cc-DGff5sSY.js +0 -21
  57. package/dist/cc-he3fHS3P.mjs +0 -12
  58. package/dist/notify.d.mts +0 -48
  59. package/dist/notify.d.mts.map +0 -1
  60. package/dist/notify.d.ts +0 -48
  61. package/dist/notify.d.ts.map +0 -1
  62. package/dist/notify.js +0 -206
  63. package/dist/notify.mjs +0 -202
  64. package/dist/react-notify-12s--2JK5UjB.mjs +0 -1244
  65. package/dist/react-notify-12s-Kv2M6zlv.js +0 -1247
  66. package/dist/react.d.mts +0 -70
  67. package/dist/react.d.mts.map +0 -1
  68. package/dist/react.d.ts +0 -70
  69. package/dist/react.d.ts.map +0 -1
  70. package/dist/react.js +0 -19
  71. package/dist/react.mjs +0 -10
  72. package/dist/render-notify-toasts.js +0 -213
  73. package/dist/svelte.d.mts +0 -49
  74. package/dist/svelte.d.mts.map +0 -1
  75. package/dist/svelte.d.ts +0 -49
  76. package/dist/svelte.d.ts.map +0 -1
  77. package/dist/svelte.js +0 -284
  78. package/dist/svelte.mjs +0 -280
  79. package/dist/vue.d.mts +0 -107
  80. package/dist/vue.d.mts.map +0 -1
  81. package/dist/vue.d.ts +0 -107
  82. package/dist/vue.d.ts.map +0 -1
  83. package/dist/vue.js +0 -2215
  84. package/dist/vue.mjs +0 -2211
@@ -1,1244 +0,0 @@
1
- 'use client';
2
- function __insertCSS(code) {
3
- if (!code || typeof document == 'undefined') return
4
- let head = document.head || document.getElementsByTagName('head')[0]
5
- let style = document.createElement('style')
6
- style.type = 'text/css'
7
- head.appendChild(style)
8
- ;style.styleSheet ? (style.styleSheet.cssText = code) : style.appendChild(document.createTextNode(code))
9
- }
10
-
11
- import { _ as _extends, a as _object_without_properties_loose } from './cc-B6peeNak.mjs';
12
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
- import { memo, useMemo, useState, useRef, useLayoutEffect, useEffect, useCallback } from 'react';
14
- import { motion } from 'motion/react';
15
-
16
- __insertCSS(":root{--notify-spring-easing:linear(\n\t\t0,\n\t\t0.002 0.6%,\n\t\t0.007 1.2%,\n\t\t0.015 1.8%,\n\t\t0.026 2.4%,\n\t\t0.041 3.1%,\n\t\t0.06 3.8%,\n\t\t0.108 5.3%,\n\t\t0.157 6.6%,\n\t\t0.214 8%,\n\t\t0.467 13.7%,\n\t\t0.577 16.3%,\n\t\t0.631 17.7%,\n\t\t0.682 19.1%,\n\t\t0.73 20.5%,\n\t\t0.771 21.8%,\n\t\t0.808 23.1%,\n\t\t0.844 24.5%,\n\t\t0.874 25.8%,\n\t\t0.903 27.2%,\n\t\t0.928 28.6%,\n\t\t0.952 30.1%,\n\t\t0.972 31.6%,\n\t\t0.988 33.1%,\n\t\t1.01 35.7%,\n\t\t1.025 38.5%,\n\t\t1.034 41.6%,\n\t\t1.038 45%,\n\t\t1.035 50.1%,\n\t\t1.012 64.2%,\n\t\t1.003 73%,\n\t\t0.999 83.7%,\n\t\t1\n\t);--notify-duration:600ms;--notify-height:40px;--notify-width:350px;--notify-state-success:oklch(0.723 0.219 142.136);--notify-state-loading:oklch(0.556 0 0);--notify-state-error:oklch(0.637 0.237 25.331);--notify-state-warning:oklch(0.795 0.184 86.047);--notify-state-info:oklch(0.685 0.169 237.323);--notify-state-action:oklch(0.623 0.214 259.815)}[data-notify-toast]{position:relative;cursor:pointer;pointer-events:auto;touch-action:none;border:0;background:0 0;padding:0;width:var(--notify-width);height:var(--_h,var(--notify-height));opacity:0;transform:translateZ(0) scale(.95);transform-origin:center;contain:layout style;overflow:visible}[data-notify-toast][data-state=loading]{cursor:default}[data-notify-toast][data-ready=true]{opacity:1;transform:translateZ(0) scale(1);transition:transform calc(var(--notify-duration) * .66) var(--notify-spring-easing),opacity calc(var(--notify-duration) * .66) var(--notify-spring-easing),margin-bottom calc(var(--notify-duration) * .66) var(--notify-spring-easing),margin-top calc(var(--notify-duration) * .66) var(--notify-spring-easing),height var(--notify-duration) var(--notify-spring-easing)}[data-notify-viewport][data-position^=top] [data-notify-toast]:not([data-ready=true]){transform:translateY(-6px) scale(.95)}[data-notify-viewport][data-position^=bottom] [data-notify-toast]:not([data-ready=true]){transform:translateY(6px) scale(.95)}[data-notify-toast][data-ready=true][data-exiting=true]{opacity:0;pointer-events:none}[data-notify-viewport][data-position^=top] [data-notify-toast][data-ready=true][data-exiting=true]{transform:translateY(-6px) scale(.95)}[data-notify-viewport][data-position^=bottom] [data-notify-toast][data-ready=true][data-exiting=true]{transform:translateY(6px) scale(.95)}[data-notify-canvas]{position:absolute;left:0;right:0;pointer-events:none;transform:translateZ(0);contain:layout style;overflow:visible}[data-sileo-canvas][data-edge=top]{bottom:0;transform:scaleY(-1) translateZ(0)}[data-sileo-canvas][data-edge=bottom]{top:0}[data-notify-svg]{overflow:visible}[data-notify-header]{position:absolute;z-index:20;display:flex;align-items:center;padding:.5rem;height:var(--sileo-height);overflow:hidden;left:var(--_px,0);transform:var(--_ht);max-width:var(--_pw)}[data-notify-toast][data-ready=true] [data-notify-header]{transition:transform var(--sileo-duration) var(--sileo-spring-easing),left var(--sileo-duration) var(--sileo-spring-easing),max-width var(--sileo-duration) var(--sileo-spring-easing)}[data-notify-header][data-edge=top]{bottom:0}[data-notify-header][data-edge=bottom]{top:0}[data-notify-header-stack]{position:relative;display:inline-flex;align-items:center;height:100%}[data-notify-header-inner]{display:flex;align-items:center;gap:.5rem;white-space:nowrap;opacity:1;filter:blur(0px);transform:translateZ(0)}[data-notify-header-inner][data-layer=current]{position:relative;z-index:1;animation:sileo-header-enter var(--sileo-duration) var(--sileo-spring-easing) both}[data-notify-header-inner][data-exiting=true],[data-notify-header-inner][data-layer=current]:not(:only-child){will-change:opacity,filter}[data-notify-header-inner][data-layer=prev]{position:absolute;left:0;top:0;z-index:0;pointer-events:none}[data-notify-header-inner][data-exiting=true]{animation:notify-header-exit calc(var(--notify-duration) * .7) ease forwards}[data-notify-badge]{display:flex;height:24px;width:24px;flex-shrink:0;align-items:center;justify-content:center;padding:2px;box-sizing:border-box;border-radius:9999px;color:var(--sileo-tone,currentColor);background-color:var(--sileo-tone-bg,transparent)}[data-notify-title]{font-size:.825rem;line-height:1rem;font-weight:500;text-transform:capitalize;color:var(--sileo-tone,currentColor)}:is([data-notify-badge],[data-notify-title],[data-notify-button])[data-state]{--_c:var(--notify-state-success)}:is(\n[data-notify-badge],[data-notify-title],[data-notify-button]\n)[data-state=loading]{--_c:var(--notify-state-loading)}:is(\n[data-notify-badge],[data-notify-title],[data-notify-button]\n)[data-state=error]{--_c:var(--notify-state-error)}:is(\n[data-notify-badge],[data-notify-title],[data-notify-button]\n)[data-state=warning]{--_c:var(--notify-state-warning)}:is(\n[data-notify-badge],[data-notify-title],[data-notify-button]\n)[data-state=info]{--_c:var(--notify-state-info)}:is(\n[data-notify-badge],[data-notify-title],[data-notify-button]\n)[data-state=action]{--_c:var(--notify-state-action)}:is([data-notify-badge],[data-notify-title])[data-state]{--notify-tone:var(--_c);--notify-tone-bg:color-mix(in oklch, var(--_c) 20%, transparent)}[data-notify-content]{position:absolute;left:0;z-index:10;width:100%;pointer-events:none;opacity:var(--_co, 0)}[data-notify-content]:not([data-visible=true]){content-visibility:hidden}[data-notify-toast][data-ready=true] [data-notify-content]{transition:opacity calc(var(--notify-duration) * .08) ease calc(var(--notify-duration) * .04)}[data-notify-content][data-edge=top]{top:0}[data-notify-content][data-edge=bottom]{top:var(--sileo-height)}[data-notify-content][data-visible=true]{pointer-events:auto}[data-notify-toast][data-ready=true] [data-notify-content][data-visible=true]{transition:opacity calc(var(--notify-duration) * .6) ease calc(var(--notify-duration) * .3)}[data-notify-description]{width:100%;text-align:left;padding:1rem;font-size:.875rem;line-height:1.25rem;contain:layout style paint;content-visibility:auto}[data-notify-button]{display:flex;align-items:center;justify-content:center;height:1.75rem;padding:0 .625rem;margin-top:.75rem;border-radius:9999px;border:0;font-size:.75rem;font-weight:500;cursor:pointer;color:var(--sileo-btn-color,currentColor);background-color:var(--sileo-btn-bg,transparent);transition:background-color 150ms ease}[data-notify-button]:hover{background-color:var(--sileo-btn-bg-hover,transparent)}[data-notify-button][data-state]{--notify-btn-color:var(--_c);--notify-btn-bg:color-mix(in oklch, var(--_c) 15%, transparent);--notify-btn-bg-hover:color-mix(in oklch, var(--_c) 25%, transparent)}[data-notify-icon=spin]{animation:notify-spin 1s linear infinite}@keyframes notify-spin{to{transform:rotate(360deg)}}@keyframes notify-header-enter{from{opacity:0;filter:blur(6px)}to{opacity:1;filter:blur(0px)}}@keyframes notify-header-exit{from{opacity:1;filter:blur(0px)}to{opacity:0;filter:blur(6px)}}[data-notify-viewport]{position:fixed;z-index:50;display:flex;gap:.75rem;padding:.75rem;pointer-events:none;max-width:calc(100vw - 1.5rem);contain:layout style}[data-notify-viewport][data-position^=top] [data-notify-toast]:not([data-ready=true]){margin-bottom:calc(-1 * (var(--notify-height) + .75rem))}[data-notify-viewport][data-position^=bottom] [data-notify-toast]:not([data-ready=true]){margin-top:calc(-1 * (var(--notify-height) + .75rem))}[data-notify-viewport][data-position^=top]{top:0;flex-direction:column-reverse}[data-notify-viewport][data-position^=bottom]{bottom:0;flex-direction:column}[data-notify-viewport][data-position$=left]{left:0;align-items:flex-start}[data-notify-viewport][data-position$=right]{right:0;align-items:flex-end}[data-notify-viewport][data-position$=center]{left:50%;transform:translateX(-50%);align-items:center}@media (prefers-reduced-motion:no-preference){[data-notify-toast][data-ready=true]:hover,[data-notify-toast][data-ready=true][data-exiting=true]{will-change:transform,opacity,height}}@media (prefers-reduced-motion:reduce){[data-notify-viewport],[data-notify-viewport] *,[data-notify-viewport] ::after,[data-notify-viewport] ::before{animation-duration:0s;animation-iteration-count:1;transition-duration:0s}}[data-notify-viewport][data-theme=dark] [data-notify-description]{color:rgba(0,0,0,.5)}[data-notify-viewport][data-theme=light] [data-notify-description]{color:rgba(255,255,255,.5)}[data-notify-toast]:has([data-notify-card]){width:auto;height:auto;background:0 0}[data-notify-card]{background:#fff;border-radius:20px;box-shadow:0 4px 24px rgba(0,0,0,.1),0 1px 4px rgba(0,0,0,.06);width:var(--notify-width);overflow:hidden}[data-notify-card] [data-notify-header]{position:relative;display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;height:auto;left:auto;max-width:none;transform:none;overflow:visible}[data-notify-card] [data-notify-content]{position:relative;opacity:1;pointer-events:auto;content-visibility:visible;border-top:1px solid rgba(0,0,0,.06)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state]{color:var(--notify-state-success)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state=error]{color:var(--notify-state-error)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state=warning]{color:var(--notify-state-warning)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state=info]{color:var(--notify-state-info)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state=loading]{color:var(--notify-state-loading)}[data-notify-card] :is([data-notify-badge],[data-notify-title])[data-state=action]{color:var(--notify-state-action)}[data-notify-card] [data-notify-description]{color:rgba(0,0,0,.6)}");
17
-
18
- /* --------------------------------- Layout --------------------------------- */ const HEIGHT = 40;
19
- const WIDTH = 350;
20
- const DEFAULT_ROUNDNESS = 16;
21
- /* --------------------------------- Timing --------------------------------- */ const DURATION_MS = 600;
22
- const DURATION_S = DURATION_MS / 1000;
23
- const DEFAULT_TOAST_DURATION = 6000;
24
- const EXIT_DURATION = DEFAULT_TOAST_DURATION * 0.1;
25
- const AUTO_EXPAND_DELAY = DEFAULT_TOAST_DURATION * 0.025;
26
- const AUTO_COLLAPSE_DELAY = DEFAULT_TOAST_DURATION - 2000;
27
- const SPRING = {
28
- type: "spring",
29
- bounce: 0.25,
30
- duration: DURATION_S
31
- };
32
- /* --------------------------------- Render --------------------------------- */ const BLUR_RATIO = 0.5;
33
- const PILL_PADDING = 10;
34
- const MIN_EXPAND_RATIO = 2.25;
35
- const SWAP_COLLAPSE_MS = 200;
36
- const HEADER_EXIT_MS = DURATION_MS * 0.7;
37
-
38
- const Icon = (_0)=>{
39
- let { title, children } = _0, props = _object_without_properties_loose(_0, [
40
- "title",
41
- "children"
42
- ]);
43
- return /*#__PURE__*/ jsxs("svg", _extends({}, props, {
44
- xmlns: "http://www.w3.org/2000/svg",
45
- width: "16",
46
- height: "16",
47
- viewBox: "0 0 24 24",
48
- fill: "none",
49
- stroke: "currentColor",
50
- strokeWidth: "2",
51
- strokeLinecap: "round",
52
- strokeLinejoin: "round",
53
- children: [
54
- /*#__PURE__*/ jsx("title", {
55
- children: title
56
- }),
57
- children
58
- ]
59
- }));
60
- };
61
- const ArrowRight = ()=>/*#__PURE__*/ jsxs(Icon, {
62
- title: "Arrow Right",
63
- children: [
64
- /*#__PURE__*/ jsx("path", {
65
- d: "M5 12h14"
66
- }),
67
- /*#__PURE__*/ jsx("path", {
68
- d: "m12 5 7 7-7 7"
69
- })
70
- ]
71
- });
72
- const LifeBuoy = ()=>/*#__PURE__*/ jsxs(Icon, {
73
- title: "Life Buoy",
74
- children: [
75
- /*#__PURE__*/ jsx("circle", {
76
- cx: "12",
77
- cy: "12",
78
- r: "10"
79
- }),
80
- /*#__PURE__*/ jsx("path", {
81
- d: "m4.93 4.93 4.24 4.24"
82
- }),
83
- /*#__PURE__*/ jsx("path", {
84
- d: "m14.83 9.17 4.24-4.24"
85
- }),
86
- /*#__PURE__*/ jsx("path", {
87
- d: "m14.83 14.83 4.24 4.24"
88
- }),
89
- /*#__PURE__*/ jsx("path", {
90
- d: "m9.17 14.83-4.24 4.24"
91
- }),
92
- /*#__PURE__*/ jsx("circle", {
93
- cx: "12",
94
- cy: "12",
95
- r: "4"
96
- })
97
- ]
98
- });
99
- const LoaderCircle = (props)=>/*#__PURE__*/ jsx(Icon, _extends({
100
- title: "Loader Circle"
101
- }, props, {
102
- children: /*#__PURE__*/ jsx("path", {
103
- d: "M21 12a9 9 0 1 1-6.219-8.56"
104
- })
105
- }));
106
- const X = ()=>/*#__PURE__*/ jsxs(Icon, {
107
- title: "X",
108
- children: [
109
- /*#__PURE__*/ jsx("path", {
110
- d: "M18 6 6 18"
111
- }),
112
- /*#__PURE__*/ jsx("path", {
113
- d: "m6 6 12 12"
114
- })
115
- ]
116
- });
117
- const CircleAlert = ()=>/*#__PURE__*/ jsxs(Icon, {
118
- title: "Circle Alert",
119
- children: [
120
- /*#__PURE__*/ jsx("circle", {
121
- cx: "12",
122
- cy: "12",
123
- r: "10"
124
- }),
125
- /*#__PURE__*/ jsx("line", {
126
- x1: "12",
127
- x2: "12",
128
- y1: "8",
129
- y2: "12"
130
- }),
131
- /*#__PURE__*/ jsx("line", {
132
- x1: "12",
133
- x2: "12.01",
134
- y1: "16",
135
- y2: "16"
136
- })
137
- ]
138
- });
139
- const Check = ()=>/*#__PURE__*/ jsx(Icon, {
140
- title: "Check",
141
- children: /*#__PURE__*/ jsx("path", {
142
- d: "M20 6 9 17l-5-5"
143
- })
144
- });
145
-
146
- /* ---------------------------------- Icons --------------------------------- */ const STATE_ICON = {
147
- success: /*#__PURE__*/ jsx(Check, {}),
148
- loading: /*#__PURE__*/ jsx(LoaderCircle, {
149
- "data-notify-icon": "spin",
150
- "aria-hidden": "true"
151
- }),
152
- error: /*#__PURE__*/ jsx(X, {}),
153
- warning: /*#__PURE__*/ jsx(CircleAlert, {}),
154
- info: /*#__PURE__*/ jsx(LifeBuoy, {}),
155
- action: /*#__PURE__*/ jsx(ArrowRight, {})
156
- };
157
- /* ----------------------------- Memoised Defs ------------------------------ */ const GooeyDefs = /*#__PURE__*/ memo(function GooeyDefs({ filterId, blur }) {
158
- return /*#__PURE__*/ jsx("defs", {
159
- children: /*#__PURE__*/ jsxs("filter", {
160
- id: filterId,
161
- x: "-20%",
162
- y: "-20%",
163
- width: "140%",
164
- height: "140%",
165
- colorInterpolationFilters: "sRGB",
166
- children: [
167
- /*#__PURE__*/ jsx("feGaussianBlur", {
168
- in: "SourceGraphic",
169
- stdDeviation: blur,
170
- result: "blur"
171
- }),
172
- /*#__PURE__*/ jsx("feColorMatrix", {
173
- in: "blur",
174
- mode: "matrix",
175
- values: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10",
176
- result: "goo"
177
- }),
178
- /*#__PURE__*/ jsx("feComposite", {
179
- in: "SourceGraphic",
180
- in2: "goo",
181
- operator: "atop"
182
- })
183
- ]
184
- })
185
- });
186
- });
187
- /* ------------------------------- Component -------------------------------- */ const Notify = /*#__PURE__*/ memo(function Notify({ id, fill = "#FFFFFF", state = "success", title = state, description, position = "left", expand = "bottom", className, icon, styles, button, roundness, exiting = false, autoExpandDelayMs, autoCollapseDelayMs, canExpand, interruptKey, refreshKey, onMouseEnter, onMouseLeave, onDismiss }) {
188
- var _headerLayer_current_view_icon, _headerLayer_prev_view_icon;
189
- var _headerLayer_current_view_styles, _headerLayer_current_view_styles1, _headerLayer_prev_view_styles, _headerLayer_prev_view_styles1, _view_styles, _view_styles1;
190
- const next = useMemo(()=>({
191
- title,
192
- description,
193
- state,
194
- icon,
195
- styles,
196
- button,
197
- fill
198
- }), [
199
- title,
200
- description,
201
- state,
202
- icon,
203
- styles,
204
- button,
205
- fill
206
- ]);
207
- const [view, setView] = useState(next);
208
- const [applied, setApplied] = useState(refreshKey);
209
- const [isExpanded, setIsExpanded] = useState(false);
210
- const [ready, setReady] = useState(false);
211
- const [pillWidth, setPillWidth] = useState(0);
212
- const [contentHeight, setContentHeight] = useState(0);
213
- const hasDesc = Boolean(view.description) || Boolean(view.button);
214
- const isLoading = view.state === "loading";
215
- const open = hasDesc && isExpanded && !isLoading;
216
- const allowExpand = isLoading ? false : canExpand != null ? canExpand : !interruptKey || interruptKey === id;
217
- const headerKey = `${view.state}-${view.title}`;
218
- const filterId = `notify-gooey-${id}`;
219
- const resolvedRoundness = Math.max(0, roundness != null ? roundness : DEFAULT_ROUNDNESS);
220
- const blur = resolvedRoundness * BLUR_RATIO;
221
- const headerRef = useRef(null);
222
- const contentRef = useRef(null);
223
- const headerExitRef = useRef(null);
224
- const autoExpandRef = useRef(null);
225
- const autoCollapseRef = useRef(null);
226
- const swapTimerRef = useRef(null);
227
- const lastRefreshKeyRef = useRef(refreshKey);
228
- const pendingRef = useRef(null);
229
- const [headerLayer, setHeaderLayer] = useState({
230
- current: {
231
- key: headerKey,
232
- view
233
- },
234
- prev: null
235
- });
236
- /* ------------------------------ Measurements ------------------------------ */ const innerRef = useRef(null);
237
- const headerPadRef = useRef(null);
238
- const pillRoRef = useRef(null);
239
- const pillRafRef = useRef(0);
240
- const pillObservedRef = useRef(null);
241
- // biome-ignore lint/correctness/useExhaustiveDependencies: headerLayer.current.key is used to force a re-render
242
- useLayoutEffect(()=>{
243
- const el = innerRef.current;
244
- const header = headerRef.current;
245
- if (!el || !header) return;
246
- if (headerPadRef.current === null) {
247
- const cs = getComputedStyle(header);
248
- headerPadRef.current = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
249
- }
250
- const px = headerPadRef.current;
251
- const measure = ()=>{
252
- const w = el.scrollWidth + px + PILL_PADDING;
253
- if (w > PILL_PADDING) {
254
- setPillWidth((prev)=>prev === w ? prev : w);
255
- }
256
- };
257
- measure();
258
- if (!pillRoRef.current) {
259
- pillRoRef.current = new ResizeObserver(()=>{
260
- cancelAnimationFrame(pillRafRef.current);
261
- pillRafRef.current = requestAnimationFrame(()=>{
262
- var _headerPadRef_current;
263
- const inner = innerRef.current;
264
- const pad = (_headerPadRef_current = headerPadRef.current) != null ? _headerPadRef_current : 0;
265
- if (!inner) return;
266
- const w = inner.scrollWidth + pad + PILL_PADDING;
267
- if (w > PILL_PADDING) {
268
- setPillWidth((prev)=>prev === w ? prev : w);
269
- }
270
- });
271
- });
272
- }
273
- if (pillObservedRef.current !== el) {
274
- if (pillObservedRef.current) {
275
- pillRoRef.current.unobserve(pillObservedRef.current);
276
- }
277
- pillRoRef.current.observe(el);
278
- pillObservedRef.current = el;
279
- }
280
- }, [
281
- headerLayer.current.key
282
- ]);
283
- useEffect(()=>{
284
- return ()=>{
285
- var _pillRoRef_current;
286
- cancelAnimationFrame(pillRafRef.current);
287
- (_pillRoRef_current = pillRoRef.current) == null ? void 0 : _pillRoRef_current.disconnect();
288
- };
289
- }, []);
290
- useLayoutEffect(()=>{
291
- if (!hasDesc) {
292
- setContentHeight(0);
293
- return;
294
- }
295
- const el = contentRef.current;
296
- if (!el) return;
297
- const measure = ()=>{
298
- const h = el.scrollHeight;
299
- setContentHeight((prev)=>prev === h ? prev : h);
300
- };
301
- measure();
302
- let rafId = 0;
303
- const ro = new ResizeObserver(()=>{
304
- cancelAnimationFrame(rafId);
305
- rafId = requestAnimationFrame(measure);
306
- });
307
- ro.observe(el);
308
- return ()=>{
309
- cancelAnimationFrame(rafId);
310
- ro.disconnect();
311
- };
312
- }, [
313
- hasDesc
314
- ]);
315
- useEffect(()=>{
316
- const raf = requestAnimationFrame(()=>setReady(true));
317
- return ()=>cancelAnimationFrame(raf);
318
- }, []);
319
- useLayoutEffect(()=>{
320
- setHeaderLayer((state)=>{
321
- if (state.current.key === headerKey) {
322
- if (state.current.view === view) return state;
323
- return _extends({}, state, {
324
- current: {
325
- key: headerKey,
326
- view
327
- }
328
- });
329
- }
330
- return {
331
- prev: state.current,
332
- current: {
333
- key: headerKey,
334
- view
335
- }
336
- };
337
- });
338
- }, [
339
- headerKey,
340
- view
341
- ]);
342
- useEffect(()=>{
343
- if (!headerLayer.prev) return;
344
- if (headerExitRef.current) {
345
- clearTimeout(headerExitRef.current);
346
- }
347
- headerExitRef.current = window.setTimeout(()=>{
348
- headerExitRef.current = null;
349
- setHeaderLayer((state)=>_extends({}, state, {
350
- prev: null
351
- }));
352
- }, HEADER_EXIT_MS);
353
- return ()=>{
354
- if (headerExitRef.current) {
355
- clearTimeout(headerExitRef.current);
356
- headerExitRef.current = null;
357
- }
358
- };
359
- }, [
360
- headerLayer.prev
361
- ]);
362
- /* ----------------------------- Sync fill ---------------------------------- */ useEffect(()=>{
363
- setView((prev)=>prev.fill === fill ? prev : _extends({}, prev, {
364
- fill
365
- }));
366
- }, [
367
- fill
368
- ]);
369
- /* ----------------------------- Refresh logic ------------------------------ */ useEffect(()=>{
370
- if (refreshKey === undefined) {
371
- setView(next);
372
- setApplied(undefined);
373
- pendingRef.current = null;
374
- lastRefreshKeyRef.current = refreshKey;
375
- return;
376
- }
377
- if (lastRefreshKeyRef.current === refreshKey) return;
378
- lastRefreshKeyRef.current = refreshKey;
379
- if (swapTimerRef.current) {
380
- clearTimeout(swapTimerRef.current);
381
- swapTimerRef.current = null;
382
- }
383
- if (open) {
384
- pendingRef.current = {
385
- key: refreshKey,
386
- payload: next
387
- };
388
- setIsExpanded(false);
389
- swapTimerRef.current = window.setTimeout(()=>{
390
- swapTimerRef.current = null;
391
- const pending = pendingRef.current;
392
- if (!pending) return;
393
- setView(pending.payload);
394
- setApplied(pending.key);
395
- pendingRef.current = null;
396
- }, SWAP_COLLAPSE_MS);
397
- } else {
398
- pendingRef.current = null;
399
- setView(next);
400
- setApplied(refreshKey);
401
- }
402
- }, [
403
- open,
404
- refreshKey,
405
- next
406
- ]);
407
- /* ----------------------------- Auto expand/collapse ----------------------- */ // biome-ignore lint/correctness/useExhaustiveDependencies: applied is used to force a re-render
408
- useEffect(()=>{
409
- if (!hasDesc) return;
410
- if (autoExpandRef.current) clearTimeout(autoExpandRef.current);
411
- if (autoCollapseRef.current) clearTimeout(autoCollapseRef.current);
412
- if (exiting || !allowExpand) {
413
- setIsExpanded(false);
414
- return;
415
- }
416
- if (autoExpandDelayMs == null && autoCollapseDelayMs == null) return;
417
- const expandDelay = autoExpandDelayMs != null ? autoExpandDelayMs : 0;
418
- const collapseDelay = autoCollapseDelayMs != null ? autoCollapseDelayMs : 0;
419
- if (expandDelay > 0) {
420
- autoExpandRef.current = window.setTimeout(()=>setIsExpanded(true), expandDelay);
421
- } else {
422
- setIsExpanded(true);
423
- }
424
- if (collapseDelay > 0) {
425
- autoCollapseRef.current = window.setTimeout(()=>setIsExpanded(false), collapseDelay);
426
- }
427
- return ()=>{
428
- if (autoExpandRef.current) clearTimeout(autoExpandRef.current);
429
- if (autoCollapseRef.current) clearTimeout(autoCollapseRef.current);
430
- };
431
- }, [
432
- autoCollapseDelayMs,
433
- autoExpandDelayMs,
434
- hasDesc,
435
- allowExpand,
436
- exiting,
437
- applied
438
- ]);
439
- /* ------------------------------ Derived values ---------------------------- */ const minExpanded = HEIGHT * MIN_EXPAND_RATIO;
440
- const rawExpanded = hasDesc ? Math.max(minExpanded, HEIGHT + contentHeight) : minExpanded;
441
- const frozenExpandedRef = useRef(rawExpanded);
442
- if (open) {
443
- frozenExpandedRef.current = rawExpanded;
444
- }
445
- const expanded = open ? rawExpanded : frozenExpandedRef.current;
446
- const svgHeight = hasDesc ? Math.max(expanded, minExpanded) : HEIGHT;
447
- const expandedContent = Math.max(0, expanded - HEIGHT);
448
- const resolvedPillWidth = Math.max(pillWidth || HEIGHT, HEIGHT);
449
- const pillHeight = HEIGHT + blur * 3;
450
- const pillX = position === "right" ? WIDTH - resolvedPillWidth : position === "center" ? (WIDTH - resolvedPillWidth) / 2 : 0;
451
- /* ------------------------------- Memoised animate targets ----------------- */ const pillAnimate = useMemo(()=>({
452
- x: pillX,
453
- width: resolvedPillWidth,
454
- height: open ? pillHeight : HEIGHT
455
- }), [
456
- pillX,
457
- resolvedPillWidth,
458
- open,
459
- pillHeight
460
- ]);
461
- const bodyAnimate = useMemo(()=>({
462
- height: open ? expandedContent : 0,
463
- opacity: open ? 1 : 0
464
- }), [
465
- open,
466
- expandedContent
467
- ]);
468
- const bodyTransition = useMemo(()=>open ? SPRING : _extends({}, SPRING, {
469
- bounce: 0
470
- }), [
471
- open
472
- ]);
473
- const pillTransition = useMemo(()=>ready ? SPRING : {
474
- duration: 0
475
- }, [
476
- ready
477
- ]);
478
- const viewBox = `0 0 ${WIDTH} ${svgHeight}`;
479
- const canvasStyle = useMemo(()=>({
480
- filter: `url(#${filterId})`
481
- }), [
482
- filterId
483
- ]);
484
- /* ------------------------------- Inline styles ---------------------------- */ const rootStyle = useMemo(()=>({
485
- "--_h": `${open ? expanded : HEIGHT}px`,
486
- "--_pw": `${resolvedPillWidth}px`,
487
- "--_px": `${pillX}px`,
488
- "--_ht": `translateY(${open ? expand === "bottom" ? 3 : -3 : 0}px) scale(${open ? 0.9 : 1})`,
489
- "--_co": `${open ? 1 : 0}`
490
- }), [
491
- open,
492
- expanded,
493
- resolvedPillWidth,
494
- pillX,
495
- expand
496
- ]);
497
- /* -------------------------------- Handlers -------------------------------- */ const handleEnter = useCallback((e)=>{
498
- onMouseEnter == null ? void 0 : onMouseEnter(e);
499
- if (hasDesc) setIsExpanded(true);
500
- }, [
501
- hasDesc,
502
- onMouseEnter
503
- ]);
504
- const handleLeave = useCallback((e)=>{
505
- onMouseLeave == null ? void 0 : onMouseLeave(e);
506
- setIsExpanded(false);
507
- }, [
508
- onMouseLeave
509
- ]);
510
- const handleTransitionEnd = useCallback((e)=>{
511
- if (e.propertyName !== "height" && e.propertyName !== "transform") return;
512
- if (open) return;
513
- const pending = pendingRef.current;
514
- if (!pending) return;
515
- if (swapTimerRef.current) {
516
- clearTimeout(swapTimerRef.current);
517
- swapTimerRef.current = null;
518
- }
519
- setView(pending.payload);
520
- setApplied(pending.key);
521
- pendingRef.current = null;
522
- }, [
523
- open
524
- ]);
525
- /* -------------------------------- Swipe ----------------------------------- */ const SWIPE_DISMISS = 30;
526
- const SWIPE_MAX = 20;
527
- const buttonRef = useRef(null);
528
- const pointerStartRef = useRef(null);
529
- const onDismissRef = useRef(onDismiss);
530
- onDismissRef.current = onDismiss;
531
- const swipeHandlersRef = useRef(null);
532
- if (!swipeHandlersRef.current) {
533
- const handlers = {
534
- onMove: (e)=>{
535
- const el = buttonRef.current;
536
- if (pointerStartRef.current === null || !el) return;
537
- const dy = e.clientY - pointerStartRef.current;
538
- const sign = dy > 0 ? 1 : -1;
539
- const clamped = Math.min(Math.abs(dy), SWIPE_MAX) * sign;
540
- el.style.transform = `translateY(${clamped}px)`;
541
- },
542
- onUp: (e)=>{
543
- const el = buttonRef.current;
544
- if (pointerStartRef.current === null || !el) return;
545
- const dy = e.clientY - pointerStartRef.current;
546
- pointerStartRef.current = null;
547
- el.style.transform = "";
548
- el.removeEventListener("pointermove", handlers.onMove);
549
- el.removeEventListener("pointerup", handlers.onUp);
550
- if (Math.abs(dy) > SWIPE_DISMISS) {
551
- onDismissRef.current == null ? void 0 : onDismissRef.current.call(onDismissRef);
552
- }
553
- }
554
- };
555
- swipeHandlersRef.current = handlers;
556
- }
557
- const handleButtonClick = useCallback((e)=>{
558
- var _view_button;
559
- e.preventDefault();
560
- e.stopPropagation();
561
- (_view_button = view.button) == null ? void 0 : _view_button.onClick();
562
- }, [
563
- view.button
564
- ]);
565
- const handlePointerDown = useCallback((e)=>{
566
- if (exiting || !onDismiss) return;
567
- const target = e.target;
568
- if (target.closest("[data-notify-button]")) return;
569
- pointerStartRef.current = e.clientY;
570
- e.currentTarget.setPointerCapture(e.pointerId);
571
- const el = buttonRef.current;
572
- const h = swipeHandlersRef.current;
573
- if (el && h) {
574
- el.addEventListener("pointermove", h.onMove, {
575
- passive: true
576
- });
577
- el.addEventListener("pointerup", h.onUp, {
578
- passive: true
579
- });
580
- }
581
- }, [
582
- exiting,
583
- onDismiss
584
- ]);
585
- /* --------------------------------- Render --------------------------------- */ return /*#__PURE__*/ jsxs("button", {
586
- ref: buttonRef,
587
- type: "button",
588
- "data-notify-toast": true,
589
- "data-ready": ready,
590
- "data-expanded": open,
591
- "data-exiting": exiting,
592
- "data-edge": expand,
593
- "data-position": position,
594
- "data-state": view.state,
595
- className: className,
596
- style: rootStyle,
597
- onMouseEnter: handleEnter,
598
- onMouseLeave: handleLeave,
599
- onTransitionEnd: handleTransitionEnd,
600
- onPointerDown: handlePointerDown,
601
- children: [
602
- /*#__PURE__*/ jsx("div", {
603
- "data-notify-canvas": true,
604
- "data-edge": expand,
605
- style: canvasStyle,
606
- children: /*#__PURE__*/ jsxs("svg", {
607
- "data-notify-svg": true,
608
- width: WIDTH,
609
- height: svgHeight,
610
- viewBox: viewBox,
611
- children: [
612
- /*#__PURE__*/ jsx("title", {
613
- children: "Notify Notification"
614
- }),
615
- /*#__PURE__*/ jsx(GooeyDefs, {
616
- filterId: filterId,
617
- blur: blur
618
- }),
619
- /*#__PURE__*/ jsx(motion.rect, {
620
- "data-notify-pill": true,
621
- rx: resolvedRoundness,
622
- ry: resolvedRoundness,
623
- fill: view.fill,
624
- initial: false,
625
- animate: pillAnimate,
626
- transition: pillTransition
627
- }),
628
- /*#__PURE__*/ jsx(motion.rect, {
629
- "data-notify-body": true,
630
- y: HEIGHT,
631
- width: WIDTH,
632
- rx: resolvedRoundness,
633
- ry: resolvedRoundness,
634
- fill: view.fill,
635
- initial: false,
636
- animate: bodyAnimate,
637
- transition: bodyTransition
638
- })
639
- ]
640
- })
641
- }),
642
- /*#__PURE__*/ jsx("div", {
643
- ref: headerRef,
644
- "data-notify-header": true,
645
- "data-edge": expand,
646
- children: /*#__PURE__*/ jsxs("div", {
647
- "data-notify-header-stack": true,
648
- children: [
649
- /*#__PURE__*/ jsxs("div", {
650
- ref: innerRef,
651
- "data-notify-header-inner": true,
652
- "data-layer": "current",
653
- children: [
654
- /*#__PURE__*/ jsx("div", {
655
- "data-notify-badge": true,
656
- "data-state": headerLayer.current.view.state,
657
- className: (_headerLayer_current_view_styles = headerLayer.current.view.styles) == null ? void 0 : _headerLayer_current_view_styles.badge,
658
- children: (_headerLayer_current_view_icon = headerLayer.current.view.icon) != null ? _headerLayer_current_view_icon : STATE_ICON[headerLayer.current.view.state]
659
- }),
660
- /*#__PURE__*/ jsx("span", {
661
- "data-notify-title": true,
662
- "data-state": headerLayer.current.view.state,
663
- className: (_headerLayer_current_view_styles1 = headerLayer.current.view.styles) == null ? void 0 : _headerLayer_current_view_styles1.title,
664
- children: headerLayer.current.view.title
665
- })
666
- ]
667
- }, headerLayer.current.key),
668
- headerLayer.prev && /*#__PURE__*/ jsxs("div", {
669
- "data-notify-header-inner": true,
670
- "data-layer": "prev",
671
- "data-exiting": "true",
672
- children: [
673
- /*#__PURE__*/ jsx("div", {
674
- "data-notify-badge": true,
675
- "data-state": headerLayer.prev.view.state,
676
- className: (_headerLayer_prev_view_styles = headerLayer.prev.view.styles) == null ? void 0 : _headerLayer_prev_view_styles.badge,
677
- children: (_headerLayer_prev_view_icon = headerLayer.prev.view.icon) != null ? _headerLayer_prev_view_icon : STATE_ICON[headerLayer.prev.view.state]
678
- }),
679
- /*#__PURE__*/ jsx("span", {
680
- "data-notify-title": true,
681
- "data-state": headerLayer.prev.view.state,
682
- className: (_headerLayer_prev_view_styles1 = headerLayer.prev.view.styles) == null ? void 0 : _headerLayer_prev_view_styles1.title,
683
- children: headerLayer.prev.view.title
684
- })
685
- ]
686
- }, headerLayer.prev.key)
687
- ]
688
- })
689
- }),
690
- hasDesc && /*#__PURE__*/ jsx("div", {
691
- "data-notify-content": true,
692
- "data-edge": expand,
693
- "data-visible": open,
694
- children: /*#__PURE__*/ jsxs("div", {
695
- ref: contentRef,
696
- "data-notify-description": true,
697
- className: (_view_styles = view.styles) == null ? void 0 : _view_styles.description,
698
- children: [
699
- view.description,
700
- view.button && // biome-ignore lint/a11y/useValidAnchor: cannot use button inside a button
701
- /*#__PURE__*/ jsx("a", {
702
- href: "#",
703
- type: "button",
704
- "data-notify-button": true,
705
- "data-state": view.state,
706
- className: (_view_styles1 = view.styles) == null ? void 0 : _view_styles1.button,
707
- onClick: handleButtonClick,
708
- children: view.button.title
709
- })
710
- ]
711
- })
712
- })
713
- ]
714
- });
715
- });
716
-
717
- const pillAlign = (pos)=>pos.includes("right") ? "right" : pos.includes("center") ? "center" : "left";
718
- const expandDir = (pos)=>pos.startsWith("top") ? "bottom" : "top";
719
- const store = {
720
- toasts: [],
721
- listeners: new Set(),
722
- position: "top-right",
723
- options: undefined,
724
- emit () {
725
- for (const fn of this.listeners)fn(this.toasts);
726
- },
727
- update (fn) {
728
- this.toasts = fn(this.toasts);
729
- this.emit();
730
- }
731
- };
732
- let idCounter = 0;
733
- const generateId = ()=>`${++idCounter}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
734
- const dismissToast = (id)=>{
735
- const item = store.toasts.find((t)=>t.id === id);
736
- if (!item || item.exiting) return;
737
- store.update((prev)=>prev.map((t)=>t.id === id ? _extends({}, t, {
738
- exiting: true
739
- }) : t));
740
- setTimeout(()=>store.update((prev)=>prev.filter((t)=>t.id !== id)), EXIT_DURATION);
741
- };
742
- const resolveAutopilot = (opts, duration)=>{
743
- var _ref, _ref1;
744
- if (opts.autopilot === false || !duration || duration <= 0) return {};
745
- const cfg = typeof opts.autopilot === "object" ? opts.autopilot : undefined;
746
- const clamp = (v)=>Math.min(duration, Math.max(0, v));
747
- return {
748
- expandDelayMs: clamp((_ref = cfg == null ? void 0 : cfg.expand) != null ? _ref : AUTO_EXPAND_DELAY),
749
- collapseDelayMs: clamp((_ref1 = cfg == null ? void 0 : cfg.collapse) != null ? _ref1 : AUTO_COLLAPSE_DELAY)
750
- };
751
- };
752
- const mergeOptions = (options)=>{
753
- var _store_options;
754
- return _extends({}, store.options, options, {
755
- styles: _extends({}, (_store_options = store.options) == null ? void 0 : _store_options.styles, options.styles)
756
- });
757
- };
758
- const buildNotifyItem = (merged, id, fallbackPosition)=>{
759
- var _merged_duration, _ref, _merged_position;
760
- const duration = (_merged_duration = merged.duration) != null ? _merged_duration : DEFAULT_TOAST_DURATION;
761
- const auto = resolveAutopilot(merged, duration);
762
- return _extends({}, merged, {
763
- id,
764
- instanceId: generateId(),
765
- position: (_ref = (_merged_position = merged.position) != null ? _merged_position : fallbackPosition) != null ? _ref : store.position,
766
- autoExpandDelayMs: auto.expandDelayMs,
767
- autoCollapseDelayMs: auto.collapseDelayMs
768
- });
769
- };
770
- const createToast = (options)=>{
771
- var _merged_id, _merged_duration;
772
- const live = store.toasts.filter((t)=>!t.exiting);
773
- const merged = mergeOptions(options);
774
- const id = (_merged_id = merged.id) != null ? _merged_id : "notify-default";
775
- const prev = live.find((t)=>t.id === id);
776
- const item = buildNotifyItem(merged, id, prev == null ? void 0 : prev.position);
777
- if (prev) {
778
- store.update((p)=>p.map((t)=>t.id === id ? item : t));
779
- } else {
780
- store.update((p)=>[
781
- ...p.filter((t)=>t.id !== id),
782
- item
783
- ]);
784
- }
785
- return {
786
- id,
787
- duration: (_merged_duration = merged.duration) != null ? _merged_duration : DEFAULT_TOAST_DURATION
788
- };
789
- };
790
- const updateToast = (id, options)=>{
791
- const existing = store.toasts.find((t)=>t.id === id);
792
- if (!existing) return;
793
- const item = buildNotifyItem(mergeOptions(options), id, existing.position);
794
- store.update((prev)=>prev.map((t)=>t.id === id ? item : t));
795
- };
796
- const notify = {
797
- show: (opts)=>createToast(_extends({}, opts, {
798
- state: opts.type
799
- })).id,
800
- success: (opts)=>createToast(_extends({}, opts, {
801
- state: "success"
802
- })).id,
803
- error: (opts)=>createToast(_extends({}, opts, {
804
- state: "error"
805
- })).id,
806
- warning: (opts)=>createToast(_extends({}, opts, {
807
- state: "warning"
808
- })).id,
809
- info: (opts)=>createToast(_extends({}, opts, {
810
- state: "info"
811
- })).id,
812
- action: (opts)=>createToast(_extends({}, opts, {
813
- state: "action"
814
- })).id,
815
- promise: (promise, opts)=>{
816
- const { id } = createToast(_extends({}, opts.loading, {
817
- state: "loading",
818
- duration: null,
819
- position: opts.position
820
- }));
821
- const p = typeof promise === "function" ? promise() : promise;
822
- p.then((data)=>{
823
- if (opts.action) {
824
- const actionOpts = typeof opts.action === "function" ? opts.action(data) : opts.action;
825
- updateToast(id, _extends({}, actionOpts, {
826
- state: "action",
827
- id
828
- }));
829
- } else {
830
- const successOpts = typeof opts.success === "function" ? opts.success(data) : opts.success;
831
- updateToast(id, _extends({}, successOpts, {
832
- state: "success",
833
- id
834
- }));
835
- }
836
- }).catch((err)=>{
837
- const errorOpts = typeof opts.error === "function" ? opts.error(err) : opts.error;
838
- updateToast(id, _extends({}, errorOpts, {
839
- state: "error",
840
- id
841
- }));
842
- });
843
- return p;
844
- },
845
- dismiss: dismissToast,
846
- clear: (position)=>store.update((prev)=>position ? prev.filter((t)=>t.position !== position) : [])
847
- };
848
- /* ------------------------------ Toaster Component ------------------------- */ // API para mostrar toast en React (similar a vanilla/vue/svelte)
849
- function showNotifyToast(options) {
850
- return notify.show(options);
851
- }
852
- const THEME_FILLS = {
853
- light: "#1a1a1a",
854
- dark: "#f2f2f2"
855
- };
856
- function useResolvedTheme(theme) {
857
- const [resolved, setResolved] = useState(()=>{
858
- if (theme === "light" || theme === "dark") return theme;
859
- if (typeof window === "undefined") return "light";
860
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
861
- });
862
- useEffect(()=>{
863
- if (theme === "light" || theme === "dark") {
864
- setResolved(theme);
865
- return;
866
- }
867
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
868
- const handler = (e)=>setResolved(e.matches ? "dark" : "light");
869
- setResolved(mq.matches ? "dark" : "light");
870
- mq.addEventListener("change", handler);
871
- return ()=>mq.removeEventListener("change", handler);
872
- }, [
873
- theme
874
- ]);
875
- return resolved;
876
- }
877
- const timeoutKey = (item)=>`${item.id}:${item.instanceId}`;
878
- function Toaster({ children, position = "top-right", offset, options, theme }) {
879
- const resolvedTheme = useResolvedTheme(theme);
880
- const [toasts, setToasts] = useState(store.toasts);
881
- const [activeId, setActiveId] = useState();
882
- const hoverRef = useRef(false);
883
- const timersRef = useRef(new Map());
884
- const listRef = useRef(toasts);
885
- const latestRef = useRef(undefined);
886
- const handlersCache = useRef(new Map());
887
- useEffect(()=>{
888
- store.position = position;
889
- store.options = options;
890
- }, [
891
- position,
892
- options
893
- ]);
894
- const clearAllTimers = useCallback(()=>{
895
- for (const t of timersRef.current.values())clearTimeout(t);
896
- timersRef.current.clear();
897
- }, []);
898
- const schedule = useCallback((items)=>{
899
- if (hoverRef.current) return;
900
- for (const item of items){
901
- var _item_duration;
902
- if (item.exiting) continue;
903
- const key = timeoutKey(item);
904
- if (timersRef.current.has(key)) continue;
905
- if (item.duration === null) continue;
906
- const dur = (_item_duration = item.duration) != null ? _item_duration : DEFAULT_TOAST_DURATION;
907
- if (dur <= 0) continue;
908
- timersRef.current.set(key, window.setTimeout(()=>dismissToast(item.id), dur));
909
- }
910
- }, []);
911
- useEffect(()=>{
912
- const listener = (next)=>setToasts(next);
913
- store.listeners.add(listener);
914
- return ()=>{
915
- store.listeners.delete(listener);
916
- clearAllTimers();
917
- };
918
- }, [
919
- clearAllTimers
920
- ]);
921
- useEffect(()=>{
922
- listRef.current = toasts;
923
- const toastKeys = new Set(toasts.map(timeoutKey));
924
- const toastIds = new Set(toasts.map((t)=>t.id));
925
- for (const [key, timer] of timersRef.current){
926
- if (!toastKeys.has(key)) {
927
- clearTimeout(timer);
928
- timersRef.current.delete(key);
929
- }
930
- }
931
- for (const id of handlersCache.current.keys()){
932
- if (!toastIds.has(id)) handlersCache.current.delete(id);
933
- }
934
- schedule(toasts);
935
- }, [
936
- toasts,
937
- schedule
938
- ]);
939
- const handleMouseEnterRef = useRef(null);
940
- const handleMouseLeaveRef = useRef(null);
941
- handleMouseEnterRef.current = useCallback(()=>{
942
- if (hoverRef.current) return;
943
- hoverRef.current = true;
944
- clearAllTimers();
945
- }, [
946
- clearAllTimers
947
- ]);
948
- handleMouseLeaveRef.current = useCallback(()=>{
949
- if (!hoverRef.current) return;
950
- hoverRef.current = false;
951
- schedule(listRef.current);
952
- }, [
953
- schedule
954
- ]);
955
- const latest = useMemo(()=>{
956
- for(let i = toasts.length - 1; i >= 0; i--){
957
- if (!toasts[i].exiting) return toasts[i].id;
958
- }
959
- return undefined;
960
- }, [
961
- toasts
962
- ]);
963
- useEffect(()=>{
964
- latestRef.current = latest;
965
- setActiveId(latest);
966
- }, [
967
- latest
968
- ]);
969
- const getHandlers = useCallback((toastId)=>{
970
- let cached = handlersCache.current.get(toastId);
971
- if (cached) return cached;
972
- cached = {
973
- enter: (e)=>{
974
- setActiveId((prev)=>prev === toastId ? prev : toastId);
975
- handleMouseEnterRef.current == null ? void 0 : handleMouseEnterRef.current.call(handleMouseEnterRef, e);
976
- },
977
- leave: (e)=>{
978
- setActiveId((prev)=>prev === latestRef.current ? prev : latestRef.current);
979
- handleMouseLeaveRef.current == null ? void 0 : handleMouseLeaveRef.current.call(handleMouseLeaveRef, e);
980
- },
981
- dismiss: ()=>dismissToast(toastId)
982
- };
983
- handlersCache.current.set(toastId, cached);
984
- return cached;
985
- }, []);
986
- const getViewportStyle = useCallback((pos)=>{
987
- if (offset === undefined) return undefined;
988
- const o = typeof offset === "object" ? offset : {
989
- top: offset,
990
- right: offset,
991
- bottom: offset,
992
- left: offset
993
- };
994
- const s = {};
995
- const px = (v)=>typeof v === "number" ? `${v}px` : v;
996
- if (pos.startsWith("top") && o.top) s.top = px(o.top);
997
- if (pos.startsWith("bottom") && o.bottom) s.bottom = px(o.bottom);
998
- if (pos.endsWith("left") && o.left) s.left = px(o.left);
999
- if (pos.endsWith("right") && o.right) s.right = px(o.right);
1000
- return s;
1001
- }, [
1002
- offset
1003
- ]);
1004
- const activePositions = useMemo(()=>{
1005
- const map = new Map();
1006
- for (const t of toasts){
1007
- var _t_position;
1008
- const pos = (_t_position = t.position) != null ? _t_position : position;
1009
- const arr = map.get(pos);
1010
- if (arr) {
1011
- arr.push(t);
1012
- } else {
1013
- map.set(pos, [
1014
- t
1015
- ]);
1016
- }
1017
- }
1018
- return map;
1019
- }, [
1020
- toasts,
1021
- position
1022
- ]);
1023
- return /*#__PURE__*/ jsxs(Fragment, {
1024
- children: [
1025
- children,
1026
- Array.from(activePositions, ([pos, items])=>{
1027
- const pill = pillAlign(pos);
1028
- const expand = expandDir(pos);
1029
- return /*#__PURE__*/ jsx("section", {
1030
- "data-notify-viewport": true,
1031
- "data-position": pos,
1032
- "data-theme": theme ? resolvedTheme : undefined,
1033
- "aria-live": "polite",
1034
- style: getViewportStyle(pos),
1035
- children: items.map((item)=>{
1036
- var _item_fill;
1037
- const h = getHandlers(item.id);
1038
- return /*#__PURE__*/ jsx(Notify, {
1039
- id: item.id,
1040
- state: item.state,
1041
- title: item.title,
1042
- description: item.description,
1043
- position: pill,
1044
- expand: expand,
1045
- icon: item.icon,
1046
- fill: (_item_fill = item.fill) != null ? _item_fill : theme ? THEME_FILLS[resolvedTheme] : undefined,
1047
- styles: item.styles,
1048
- button: item.button,
1049
- roundness: item.roundness,
1050
- exiting: item.exiting,
1051
- autoExpandDelayMs: item.autoExpandDelayMs,
1052
- autoCollapseDelayMs: item.autoCollapseDelayMs,
1053
- refreshKey: item.instanceId,
1054
- canExpand: activeId === undefined || activeId === item.id,
1055
- onMouseEnter: h.enter,
1056
- onMouseLeave: h.leave,
1057
- onDismiss: h.dismiss
1058
- }, item.id);
1059
- })
1060
- }, pos);
1061
- })
1062
- ]
1063
- });
1064
- }
1065
-
1066
- // Notify logic (no React dependencies)
1067
- // Provides toast management and utilities for VanillaJS, Vue, Svelte, etc.
1068
- class NotifyCore {
1069
- generateId() {
1070
- return `${++this.idCounter}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
1071
- }
1072
- subscribe(fn) {
1073
- this.listeners.add(fn);
1074
- fn(this.toasts);
1075
- return ()=>this.listeners.delete(fn);
1076
- }
1077
- emit() {
1078
- for (const fn of this.listeners)fn(this.toasts);
1079
- }
1080
- update(fn) {
1081
- this.toasts = fn(this.toasts);
1082
- this.emit();
1083
- }
1084
- dismiss(id) {
1085
- const item = this.toasts.find((t)=>t.id === id);
1086
- if (!item || item.exiting) return;
1087
- this.update((prev)=>prev.map((t)=>t.id === id ? _extends({}, t, {
1088
- exiting: true
1089
- }) : t));
1090
- setTimeout(()=>this.update((prev)=>prev.filter((t)=>t.id !== id)), 600);
1091
- }
1092
- show(opts) {
1093
- var _ref, _ref1, _opts_type;
1094
- // Use a unique identifier based on options (e.g., the title or a generated key)
1095
- // If not provided, use a default one
1096
- const id = opts.title ? `notify-${opts.title}` : "notify-default";
1097
- const prevItem = this.toasts.find((t)=>t.id === id);
1098
- const instanceId = (_ref = prevItem == null ? void 0 : prevItem.instanceId) != null ? _ref : this.generateId();
1099
- // Set the state correctly
1100
- const state = (_ref1 = (_opts_type = opts.type) != null ? _opts_type : prevItem == null ? void 0 : prevItem.type) != null ? _ref1 : "success";
1101
- const item = _extends({}, prevItem, opts, {
1102
- id,
1103
- instanceId,
1104
- type: state
1105
- });
1106
- this.update((prev)=>{
1107
- const filtered = prev.filter((t)=>t.id !== id);
1108
- return [
1109
- ...filtered,
1110
- item
1111
- ];
1112
- });
1113
- return id;
1114
- }
1115
- getToasts() {
1116
- return this.toasts;
1117
- }
1118
- constructor(){
1119
- this.toasts = [];
1120
- this.listeners = new Set();
1121
- this.position = "top-right";
1122
- this.options = undefined;
1123
- this.idCounter = 0;
1124
- }
1125
- }
1126
- // Global instance for multiplatform usage
1127
- const notifyCore = new NotifyCore();
1128
-
1129
- const ICONS = {
1130
- success: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg>',
1131
- error: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',
1132
- warning: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',
1133
- info: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m4.93 4.93 4.24 4.24"/><path d="m14.83 9.17 4.24-4.24"/><path d="m14.83 14.83 4.24 4.24"/><path d="m9.17 14.83-4.24 4.24"/><circle cx="12" cy="12" r="4"/></svg>',
1134
- loading: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" data-notify-icon="spin" aria-hidden="true"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>',
1135
- action: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>'
1136
- };
1137
- const EXIT_MS = 600;
1138
- function capitalize(s) {
1139
- return s ? s.charAt(0).toUpperCase() + s.slice(1) : "";
1140
- }
1141
- let viewport = null;
1142
- const toastEls = new Map();
1143
- function getOrCreateViewport(position) {
1144
- if (!viewport) {
1145
- viewport = document.createElement("div");
1146
- viewport.setAttribute("data-notify-viewport", "");
1147
- viewport.setAttribute("data-position", position);
1148
- viewport.setAttribute("data-theme", "light");
1149
- document.body.appendChild(viewport);
1150
- }
1151
- return viewport;
1152
- }
1153
- function buildToastEl(toast) {
1154
- const state = toast.type || "success";
1155
- const btn = document.createElement("button");
1156
- btn.type = "button";
1157
- btn.setAttribute("data-notify-toast", "");
1158
- btn.setAttribute("data-state", state);
1159
- btn.setAttribute("data-ready", "false");
1160
- btn.setAttribute("data-exiting", "false");
1161
- const card = document.createElement("div");
1162
- card.setAttribute("data-notify-card", "");
1163
- const header = document.createElement("div");
1164
- header.setAttribute("data-notify-header", "");
1165
- const badge = document.createElement("div");
1166
- badge.setAttribute("data-notify-badge", "");
1167
- badge.setAttribute("data-state", state);
1168
- badge.innerHTML = ICONS[state] || ICONS.success;
1169
- const titleEl = document.createElement("span");
1170
- titleEl.setAttribute("data-notify-title", "");
1171
- titleEl.setAttribute("data-state", state);
1172
- titleEl.textContent = toast.title || capitalize(state);
1173
- header.appendChild(badge);
1174
- header.appendChild(titleEl);
1175
- card.appendChild(header);
1176
- if (toast.description || toast.button) {
1177
- const content = document.createElement("div");
1178
- content.setAttribute("data-notify-content", "");
1179
- content.setAttribute("data-visible", "true");
1180
- if (toast.description) {
1181
- const desc = document.createElement("div");
1182
- desc.setAttribute("data-notify-description", "");
1183
- desc.textContent = toast.description;
1184
- content.appendChild(desc);
1185
- }
1186
- if (toast.button) {
1187
- const actionBtn = document.createElement("button");
1188
- actionBtn.setAttribute("data-notify-button", "");
1189
- actionBtn.setAttribute("data-state", state);
1190
- actionBtn.textContent = toast.button.title;
1191
- actionBtn.addEventListener("click", (e)=>{
1192
- var _toast_button;
1193
- e.stopPropagation();
1194
- (_toast_button = toast.button) == null ? void 0 : _toast_button.onClick();
1195
- notifyCore.dismiss(toast.id);
1196
- });
1197
- content.appendChild(actionBtn);
1198
- }
1199
- card.appendChild(content);
1200
- }
1201
- btn.appendChild(card);
1202
- btn.addEventListener("click", ()=>notifyCore.dismiss(toast.id));
1203
- requestAnimationFrame(()=>{
1204
- requestAnimationFrame(()=>{
1205
- btn.setAttribute("data-ready", "true");
1206
- });
1207
- });
1208
- return btn;
1209
- }
1210
- function updateToastEl(el, toast) {
1211
- const state = toast.type || "success";
1212
- el.setAttribute("data-state", state);
1213
- if (toast.exiting) {
1214
- el.setAttribute("data-exiting", "true");
1215
- }
1216
- }
1217
- function renderNotifyToasts(options = {}) {
1218
- var _options_position;
1219
- const position = (_options_position = options.position) != null ? _options_position : "top-right";
1220
- const vp = getOrCreateViewport(position);
1221
- return notifyCore.subscribe((toasts)=>{
1222
- const liveIds = new Set(toasts.map((t)=>t.id));
1223
- for (const [id, el] of toastEls){
1224
- if (!liveIds.has(id)) {
1225
- el.setAttribute("data-exiting", "true");
1226
- setTimeout(()=>{
1227
- el.remove();
1228
- toastEls.delete(id);
1229
- }, EXIT_MS);
1230
- }
1231
- }
1232
- for (const toast of toasts){
1233
- if (toastEls.has(toast.id)) {
1234
- updateToastEl(toastEls.get(toast.id), toast);
1235
- } else {
1236
- const el = buildToastEl(toast);
1237
- toastEls.set(toast.id, el);
1238
- vp.appendChild(el);
1239
- }
1240
- }
1241
- });
1242
- }
1243
-
1244
- export { Toaster as T, notify as n, renderNotifyToasts as r, showNotifyToast as s };