@kazee-ds/react 0.4.0 → 0.5.1
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.js +706 -2
- package/dist/index.js.map +1 -1
- package/dist/types/Toast.d.ts +32 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/toast-model.d.ts +64 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Button as Button$1, ButtonContext } from "react-aria-components/Button";
|
|
3
|
-
import { Children, Fragment, cloneElement, createContext, forwardRef, isValidElement, useContext, useEffect, useId, useImperativeHandle, useRef, useState } from "react";
|
|
3
|
+
import { Children, Fragment, cloneElement, createContext, forwardRef, isValidElement, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { ProgressBarContext } from "react-aria-components/ProgressBar";
|
|
5
5
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { ToggleButton as ToggleButton$1 } from "react-aria-components/ToggleButton";
|
|
@@ -25,6 +25,7 @@ import { Tooltip as Tooltip$1, TooltipTrigger } from "react-aria-components/Tool
|
|
|
25
25
|
import { Button as Button$4, ComboBox, Input as Input$3, Label as Label$6, ListBox as ListBox$2, ListBoxItem as ListBoxItem$2, Popover as Popover$3 } from "react-aria-components/ComboBox";
|
|
26
26
|
import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading, RangeCalendar, RangeCalendarStateContext } from "react-aria-components/RangeCalendar";
|
|
27
27
|
import { GregorianCalendar, endOfMonth, getLocalTimeZone, parseDate, startOfMonth, startOfWeek, today } from "@internationalized/date";
|
|
28
|
+
import { Button as Button$5, I18nProvider as I18nProvider$1, Text as Text$3, UNSTABLE_Toast, UNSTABLE_ToastContent, UNSTABLE_ToastList, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion } from "react-aria-components";
|
|
28
29
|
//#region src/Button.tsx
|
|
29
30
|
function PendingLabelAnchor() {
|
|
30
31
|
const context = useContext(ProgressBarContext);
|
|
@@ -2731,6 +2732,709 @@ function DateRangePicker(props) {
|
|
|
2731
2732
|
});
|
|
2732
2733
|
}
|
|
2733
2734
|
//#endregion
|
|
2734
|
-
|
|
2735
|
+
//#region src/toast-model.ts
|
|
2736
|
+
var EMPTY = Object.freeze([]);
|
|
2737
|
+
var messageOptions = (message) => typeof message === "string" ? { title: message } : message;
|
|
2738
|
+
var milliseconds = (value, fallback) => Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
2739
|
+
/** Complete required notifications/cleanup before reporting user callback failures. */
|
|
2740
|
+
var complete = (operations) => {
|
|
2741
|
+
const errors = [];
|
|
2742
|
+
for (const operation of operations) try {
|
|
2743
|
+
operation();
|
|
2744
|
+
} catch (error) {
|
|
2745
|
+
errors.push(error);
|
|
2746
|
+
}
|
|
2747
|
+
if (errors.length === 1) throw errors[0];
|
|
2748
|
+
if (errors.length > 1) throw new AggregateError(errors, "Toast lifecycle callbacks failed.");
|
|
2749
|
+
};
|
|
2750
|
+
/** Create per application/provider; no browser globals or timers are used until attached. */
|
|
2751
|
+
function createToastManager(options = {}) {
|
|
2752
|
+
const maxVisible = Math.max(1, Math.floor(options.maxVisible ?? 3));
|
|
2753
|
+
const maxPending = Math.max(0, Math.floor(options.maxPending ?? 50));
|
|
2754
|
+
const duration = milliseconds(options.duration ?? 5e3, 5e3);
|
|
2755
|
+
const exitDuration = milliseconds(options.exitDuration ?? 200, 200);
|
|
2756
|
+
const records = /* @__PURE__ */ new Map();
|
|
2757
|
+
const visible = [];
|
|
2758
|
+
const pending = [];
|
|
2759
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2760
|
+
const pauses = /* @__PURE__ */ new Map();
|
|
2761
|
+
let snapshot = EMPTY;
|
|
2762
|
+
let attached = false;
|
|
2763
|
+
let disposed = false;
|
|
2764
|
+
let sequence = 0;
|
|
2765
|
+
let generation = 0;
|
|
2766
|
+
const paused = () => !attached || pauses.size > 0;
|
|
2767
|
+
const freeze = (entry) => Object.freeze({
|
|
2768
|
+
...entry,
|
|
2769
|
+
action: entry.action ? Object.freeze({ ...entry.action }) : void 0,
|
|
2770
|
+
cancel: entry.cancel ? Object.freeze({ ...entry.cancel }) : void 0
|
|
2771
|
+
});
|
|
2772
|
+
const publish = () => {
|
|
2773
|
+
const next = visible.map((id) => records.get(id).entry);
|
|
2774
|
+
if (next.length === snapshot.length && next.every((entry, index) => entry === snapshot[index])) return;
|
|
2775
|
+
snapshot = Object.freeze(next);
|
|
2776
|
+
complete([...listeners]);
|
|
2777
|
+
};
|
|
2778
|
+
const stop = (record) => {
|
|
2779
|
+
if (record.timer !== void 0) clearTimeout(record.timer);
|
|
2780
|
+
record.timer = void 0;
|
|
2781
|
+
if (record.startedAt !== null) {
|
|
2782
|
+
const elapsed = Math.max(0, Date.now() - record.startedAt);
|
|
2783
|
+
if (record.entry.state === "closing") record.exitRemaining = Math.max(0, record.exitRemaining - elapsed);
|
|
2784
|
+
else record.entry = freeze({
|
|
2785
|
+
...record.entry,
|
|
2786
|
+
remaining: Math.max(0, record.entry.remaining - elapsed)
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
record.startedAt = null;
|
|
2790
|
+
};
|
|
2791
|
+
const promote = () => {
|
|
2792
|
+
while (visible.length < maxVisible && pending.length) {
|
|
2793
|
+
const id = pending.shift();
|
|
2794
|
+
const record = records.get(id);
|
|
2795
|
+
visible.push(id);
|
|
2796
|
+
record.entry = freeze({
|
|
2797
|
+
...record.entry,
|
|
2798
|
+
visibleAt: Date.now(),
|
|
2799
|
+
paused: paused()
|
|
2800
|
+
});
|
|
2801
|
+
start(record);
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
const remove = (id) => {
|
|
2805
|
+
const record = records.get(id);
|
|
2806
|
+
if (!record) return;
|
|
2807
|
+
stop(record);
|
|
2808
|
+
records.delete(id);
|
|
2809
|
+
const index = visible.indexOf(id);
|
|
2810
|
+
if (index >= 0) visible.splice(index, 1);
|
|
2811
|
+
const waiting = pending.indexOf(id);
|
|
2812
|
+
if (waiting >= 0) pending.splice(waiting, 1);
|
|
2813
|
+
promote();
|
|
2814
|
+
publish();
|
|
2815
|
+
};
|
|
2816
|
+
const start = (record) => {
|
|
2817
|
+
if (!attached || record.entry.visibleAt === null || record.timer !== void 0) return;
|
|
2818
|
+
const closing = record.entry.state === "closing";
|
|
2819
|
+
if (!closing && (paused() || record.entry.isLoading || record.entry.duration === 0)) return;
|
|
2820
|
+
record.startedAt = Date.now();
|
|
2821
|
+
record.timer = setTimeout(() => {
|
|
2822
|
+
record.timer = void 0;
|
|
2823
|
+
record.startedAt = null;
|
|
2824
|
+
if (closing) remove(record.entry.id);
|
|
2825
|
+
else manager.dismiss(record.entry.id, "timeout");
|
|
2826
|
+
}, closing ? record.exitRemaining : record.entry.remaining);
|
|
2827
|
+
};
|
|
2828
|
+
const refreshPause = () => {
|
|
2829
|
+
for (const id of visible) {
|
|
2830
|
+
const record = records.get(id);
|
|
2831
|
+
stop(record);
|
|
2832
|
+
record.entry = freeze({
|
|
2833
|
+
...record.entry,
|
|
2834
|
+
paused: paused() || record.entry.state === "closing"
|
|
2835
|
+
});
|
|
2836
|
+
start(record);
|
|
2837
|
+
}
|
|
2838
|
+
publish();
|
|
2839
|
+
};
|
|
2840
|
+
const update = (id, changes, invalidate, onGeneration) => {
|
|
2841
|
+
const record = records.get(id);
|
|
2842
|
+
if (!record || record.entry.state === "closing" || disposed) return false;
|
|
2843
|
+
stop(record);
|
|
2844
|
+
const before = record.entry;
|
|
2845
|
+
const settled = before.isLoading && changes.isLoading === false;
|
|
2846
|
+
const nextDuration = changes.duration !== void 0 ? milliseconds(changes.duration, duration) : settled ? duration : before.duration;
|
|
2847
|
+
record.entry = freeze({
|
|
2848
|
+
...before,
|
|
2849
|
+
...changes,
|
|
2850
|
+
id,
|
|
2851
|
+
tone: changes.tone ?? before.tone,
|
|
2852
|
+
duration: nextDuration,
|
|
2853
|
+
isLoading: changes.isLoading ?? before.isLoading,
|
|
2854
|
+
remaining: changes.duration !== void 0 || settled ? nextDuration : before.remaining,
|
|
2855
|
+
generation: invalidate ? ++generation : before.generation
|
|
2856
|
+
});
|
|
2857
|
+
onGeneration?.(record.entry.generation);
|
|
2858
|
+
start(record);
|
|
2859
|
+
publish();
|
|
2860
|
+
return true;
|
|
2861
|
+
};
|
|
2862
|
+
const add = (value, onGeneration) => {
|
|
2863
|
+
if (disposed) return null;
|
|
2864
|
+
if (value.id !== void 0 && records.has(value.id)) return update(value.id, value, true, onGeneration) ? value.id : null;
|
|
2865
|
+
if (visible.length >= maxVisible && pending.length >= maxPending) return null;
|
|
2866
|
+
let id = value.id;
|
|
2867
|
+
if (id === void 0) do
|
|
2868
|
+
id = `toast-${++sequence}`;
|
|
2869
|
+
while (records.has(id));
|
|
2870
|
+
const entry = freeze({
|
|
2871
|
+
...value,
|
|
2872
|
+
id,
|
|
2873
|
+
tone: value.tone ?? "neutral",
|
|
2874
|
+
duration: milliseconds(value.duration ?? duration, duration),
|
|
2875
|
+
isLoading: value.isLoading ?? false,
|
|
2876
|
+
generation: ++generation,
|
|
2877
|
+
state: "open",
|
|
2878
|
+
createdAt: Date.now(),
|
|
2879
|
+
visibleAt: visible.length < maxVisible ? Date.now() : null,
|
|
2880
|
+
remaining: milliseconds(value.duration ?? duration, duration),
|
|
2881
|
+
paused: paused()
|
|
2882
|
+
});
|
|
2883
|
+
const record = {
|
|
2884
|
+
entry,
|
|
2885
|
+
startedAt: null,
|
|
2886
|
+
exitRemaining: exitDuration
|
|
2887
|
+
};
|
|
2888
|
+
records.set(id, record);
|
|
2889
|
+
if (visible.length < maxVisible) {
|
|
2890
|
+
visible.push(id);
|
|
2891
|
+
start(record);
|
|
2892
|
+
} else pending.push(id);
|
|
2893
|
+
onGeneration?.(entry.generation);
|
|
2894
|
+
publish();
|
|
2895
|
+
return id;
|
|
2896
|
+
};
|
|
2897
|
+
const manager = {
|
|
2898
|
+
add,
|
|
2899
|
+
update: (id, changes) => update(id, changes, true),
|
|
2900
|
+
dismiss(id, reason = "dismiss") {
|
|
2901
|
+
const record = records.get(id);
|
|
2902
|
+
if (!record || record.entry.state === "closing") return;
|
|
2903
|
+
stop(record);
|
|
2904
|
+
record.entry = freeze({
|
|
2905
|
+
...record.entry,
|
|
2906
|
+
state: "closing",
|
|
2907
|
+
paused: true,
|
|
2908
|
+
remaining: reason === "timeout" ? 0 : record.entry.remaining
|
|
2909
|
+
});
|
|
2910
|
+
complete([() => {
|
|
2911
|
+
if (record.entry.visibleAt === null) remove(id);
|
|
2912
|
+
else {
|
|
2913
|
+
start(record);
|
|
2914
|
+
publish();
|
|
2915
|
+
}
|
|
2916
|
+
}, () => record.entry.onClose?.(reason)]);
|
|
2917
|
+
},
|
|
2918
|
+
clear(reason = "clear") {
|
|
2919
|
+
complete([...pending, ...visible].map((id) => () => manager.dismiss(id, reason)));
|
|
2920
|
+
},
|
|
2921
|
+
pause(reason) {
|
|
2922
|
+
if (disposed) return;
|
|
2923
|
+
pauses.set(reason, (pauses.get(reason) ?? 0) + 1);
|
|
2924
|
+
if (pauses.size === 1 && pauses.get(reason) === 1) refreshPause();
|
|
2925
|
+
},
|
|
2926
|
+
resume(reason) {
|
|
2927
|
+
const count = pauses.get(reason);
|
|
2928
|
+
if (!count || disposed) return;
|
|
2929
|
+
if (count === 1) pauses.delete(reason);
|
|
2930
|
+
else pauses.set(reason, count - 1);
|
|
2931
|
+
if (!pauses.size) refreshPause();
|
|
2932
|
+
},
|
|
2933
|
+
attach() {
|
|
2934
|
+
if (disposed) throw new Error("Cannot attach a disposed ToastManager.");
|
|
2935
|
+
if (attached) throw new Error("A ToastManager may attach to only one provider.");
|
|
2936
|
+
attached = true;
|
|
2937
|
+
try {
|
|
2938
|
+
refreshPause();
|
|
2939
|
+
} catch (error) {
|
|
2940
|
+
attached = false;
|
|
2941
|
+
complete([() => {
|
|
2942
|
+
throw error;
|
|
2943
|
+
}, refreshPause]);
|
|
2944
|
+
}
|
|
2945
|
+
let detached = false;
|
|
2946
|
+
return () => {
|
|
2947
|
+
if (detached || disposed) return;
|
|
2948
|
+
detached = true;
|
|
2949
|
+
attached = false;
|
|
2950
|
+
refreshPause();
|
|
2951
|
+
};
|
|
2952
|
+
},
|
|
2953
|
+
dispose() {
|
|
2954
|
+
if (disposed) return;
|
|
2955
|
+
disposed = true;
|
|
2956
|
+
attached = false;
|
|
2957
|
+
const closing = [...records.values()].filter((record) => record.entry.state === "open");
|
|
2958
|
+
for (const record of records.values()) stop(record);
|
|
2959
|
+
records.clear();
|
|
2960
|
+
visible.length = 0;
|
|
2961
|
+
pending.length = 0;
|
|
2962
|
+
pauses.clear();
|
|
2963
|
+
complete([
|
|
2964
|
+
publish,
|
|
2965
|
+
() => listeners.clear(),
|
|
2966
|
+
...closing.map((record) => () => record.entry.onClose?.("unmount"))
|
|
2967
|
+
]);
|
|
2968
|
+
},
|
|
2969
|
+
subscribe(listener) {
|
|
2970
|
+
if (!disposed) listeners.add(listener);
|
|
2971
|
+
return () => {
|
|
2972
|
+
listeners.delete(listener);
|
|
2973
|
+
};
|
|
2974
|
+
},
|
|
2975
|
+
getSnapshot: () => snapshot,
|
|
2976
|
+
getServerSnapshot: () => EMPTY,
|
|
2977
|
+
promise(task, messages, promiseOptions = {}) {
|
|
2978
|
+
let expected;
|
|
2979
|
+
const id = add({
|
|
2980
|
+
...promiseOptions,
|
|
2981
|
+
...messageOptions(messages.loading),
|
|
2982
|
+
isLoading: true
|
|
2983
|
+
}, (value) => {
|
|
2984
|
+
expected = value;
|
|
2985
|
+
});
|
|
2986
|
+
const settle = (message, tone) => {
|
|
2987
|
+
if (id === null || records.get(id)?.entry.generation !== expected || records.get(id)?.entry.state !== "open") return;
|
|
2988
|
+
const content = typeof message === "function" ? message() : message;
|
|
2989
|
+
if (records.get(id)?.entry.generation !== expected || records.get(id)?.entry.state !== "open") return;
|
|
2990
|
+
update(id, {
|
|
2991
|
+
tone,
|
|
2992
|
+
duration: promiseOptions.duration ?? duration,
|
|
2993
|
+
...messageOptions(content),
|
|
2994
|
+
isLoading: false
|
|
2995
|
+
}, false);
|
|
2996
|
+
};
|
|
2997
|
+
return {
|
|
2998
|
+
id,
|
|
2999
|
+
promise: task.then((value) => {
|
|
3000
|
+
const message = messages.success;
|
|
3001
|
+
settle(typeof message === "function" ? () => message(value) : message, "success");
|
|
3002
|
+
return value;
|
|
3003
|
+
}, (error) => {
|
|
3004
|
+
const message = messages.error;
|
|
3005
|
+
settle(typeof message === "function" ? () => message(error) : message, "danger");
|
|
3006
|
+
throw error;
|
|
3007
|
+
})
|
|
3008
|
+
};
|
|
3009
|
+
}
|
|
3010
|
+
};
|
|
3011
|
+
return manager;
|
|
3012
|
+
}
|
|
3013
|
+
//#endregion
|
|
3014
|
+
//#region src/Toast.tsx
|
|
3015
|
+
/** Keeps upstream accessibility/focus behavior while Kazee owns every timer and queue decision. */
|
|
3016
|
+
var QueueAdapter = class extends UNSTABLE_ToastQueue {
|
|
3017
|
+
manager;
|
|
3018
|
+
regionPaused = false;
|
|
3019
|
+
constructor(manager) {
|
|
3020
|
+
super();
|
|
3021
|
+
this.manager = manager;
|
|
3022
|
+
this.refresh();
|
|
3023
|
+
}
|
|
3024
|
+
refresh() {
|
|
3025
|
+
this.visibleToasts = this.manager.getSnapshot().map((content) => ({
|
|
3026
|
+
key: content.id,
|
|
3027
|
+
content
|
|
3028
|
+
}));
|
|
3029
|
+
}
|
|
3030
|
+
subscribe(listener) {
|
|
3031
|
+
return this.manager.subscribe(() => {
|
|
3032
|
+
this.refresh();
|
|
3033
|
+
listener();
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
add(content) {
|
|
3037
|
+
return this.manager.add(content) ?? "";
|
|
3038
|
+
}
|
|
3039
|
+
close(key) {
|
|
3040
|
+
this.manager.dismiss(key);
|
|
3041
|
+
}
|
|
3042
|
+
clear() {
|
|
3043
|
+
this.manager.clear();
|
|
3044
|
+
}
|
|
3045
|
+
pauseAll() {
|
|
3046
|
+
if (!this.regionPaused) {
|
|
3047
|
+
this.regionPaused = true;
|
|
3048
|
+
this.manager.pause("region");
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
resumeAll() {
|
|
3052
|
+
if (this.regionPaused) {
|
|
3053
|
+
this.regionPaused = false;
|
|
3054
|
+
this.manager.resume("region");
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
};
|
|
3058
|
+
var ToastContext = createContext(null);
|
|
3059
|
+
function ToastProvider({ children, manager: suppliedManager, placement = "bottom-end", label = "Notifikasi / Notifications", closeLabel = "Tutup notifikasi / Close notification", hotkey = ["Alt", "t"], dir = "ltr", showProgress = false, showCloseButton = false, swipeThreshold = 50, renderToast }) {
|
|
3060
|
+
const [ownedManager] = useState(() => createToastManager());
|
|
3061
|
+
const manager = suppliedManager ?? ownedManager;
|
|
3062
|
+
const queue = useMemo(() => new QueueAdapter(manager), [manager]);
|
|
3063
|
+
const region = useRef(null);
|
|
3064
|
+
const entries = useSyncExternalStore(manager.subscribe, manager.getSnapshot, manager.getServerSnapshot);
|
|
3065
|
+
const positions = useRef(/* @__PURE__ */ new Map());
|
|
3066
|
+
useLayoutEffect(() => {
|
|
3067
|
+
const nodes = region.current?.querySelectorAll(".toast");
|
|
3068
|
+
const previous = positions.current;
|
|
3069
|
+
const next = /* @__PURE__ */ new Map();
|
|
3070
|
+
const animations = [];
|
|
3071
|
+
const regionTop = region.current?.getBoundingClientRect().top ?? 0;
|
|
3072
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3073
|
+
for (const node of nodes ?? []) {
|
|
3074
|
+
const id = node.dataset.toastId;
|
|
3075
|
+
if (!id) continue;
|
|
3076
|
+
const top = node.offsetTop + regionTop;
|
|
3077
|
+
next.set(id, top);
|
|
3078
|
+
const before = previous.get(id);
|
|
3079
|
+
if (before !== void 0 && before !== top && node.dataset.state === "open" && !reducedMotion && node.animate) {
|
|
3080
|
+
const style = getComputedStyle(node);
|
|
3081
|
+
const token = style.getPropertyValue("--ds-motion-duration-normal").trim();
|
|
3082
|
+
const duration = token.endsWith("ms") ? parseFloat(token) : parseFloat(token) * 1e3;
|
|
3083
|
+
animations.push(node.animate([{ translate: `0 ${before - top}px` }, { translate: "0 0" }], {
|
|
3084
|
+
duration: Number.isFinite(duration) ? duration : 160,
|
|
3085
|
+
easing: style.getPropertyValue("--ds-motion-ease-standard").trim() || "ease-out"
|
|
3086
|
+
}));
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
positions.current = next;
|
|
3090
|
+
return () => {
|
|
3091
|
+
for (const animation of animations) animation.cancel();
|
|
3092
|
+
};
|
|
3093
|
+
}, [entries]);
|
|
3094
|
+
const lastFocused = useRef(null);
|
|
3095
|
+
const lifetime = useRef({ generation: 0 });
|
|
3096
|
+
const hotkeySignature = hotkey.join("+");
|
|
3097
|
+
useEffect(() => {
|
|
3098
|
+
const keys = hotkeySignature ? hotkeySignature.split("+") : [];
|
|
3099
|
+
const detach = manager.attach();
|
|
3100
|
+
let documentPaused = false;
|
|
3101
|
+
let windowPaused = false;
|
|
3102
|
+
const visibility = () => {
|
|
3103
|
+
if (document.hidden && !documentPaused) {
|
|
3104
|
+
documentPaused = true;
|
|
3105
|
+
manager.pause("document");
|
|
3106
|
+
} else if (!document.hidden && documentPaused) {
|
|
3107
|
+
documentPaused = false;
|
|
3108
|
+
manager.resume("document");
|
|
3109
|
+
}
|
|
3110
|
+
};
|
|
3111
|
+
const blur = () => {
|
|
3112
|
+
if (!windowPaused) {
|
|
3113
|
+
windowPaused = true;
|
|
3114
|
+
manager.pause("window");
|
|
3115
|
+
}
|
|
3116
|
+
};
|
|
3117
|
+
const focus = () => {
|
|
3118
|
+
if (windowPaused) {
|
|
3119
|
+
windowPaused = false;
|
|
3120
|
+
manager.resume("window");
|
|
3121
|
+
}
|
|
3122
|
+
};
|
|
3123
|
+
visibility();
|
|
3124
|
+
const keydown = (event) => {
|
|
3125
|
+
if (event.defaultPrevented) return;
|
|
3126
|
+
if (event.key === "Escape" && region.current?.contains(event.target)) {
|
|
3127
|
+
const target = event.target;
|
|
3128
|
+
if (target.closest("input,textarea,select,[contenteditable=\"true\"]")) return;
|
|
3129
|
+
const focused = target.closest(".toast[data-state=\"open\"]");
|
|
3130
|
+
const latest = [...manager.getSnapshot()].reverse().find((entry) => entry.state === "open");
|
|
3131
|
+
const id = focused?.dataset.toastId ?? latest?.id;
|
|
3132
|
+
if (id) {
|
|
3133
|
+
event.preventDefault();
|
|
3134
|
+
event.stopPropagation();
|
|
3135
|
+
manager.dismiss(id);
|
|
3136
|
+
}
|
|
3137
|
+
return;
|
|
3138
|
+
}
|
|
3139
|
+
if (!keys.length) return;
|
|
3140
|
+
const key = keys[keys.length - 1].toLowerCase();
|
|
3141
|
+
const modifiers = keys.slice(0, -1).map((value) => value.toLowerCase());
|
|
3142
|
+
if (event.key.toLowerCase() === key && event.altKey === modifiers.includes("alt") && event.ctrlKey === modifiers.includes("control") && event.metaKey === modifiers.includes("meta") && event.shiftKey === modifiers.includes("shift")) {
|
|
3143
|
+
const target = region.current?.querySelector(".toast[data-state=\"open\"]");
|
|
3144
|
+
if (target) {
|
|
3145
|
+
event.preventDefault();
|
|
3146
|
+
target.focus();
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
const focusIn = (event) => {
|
|
3151
|
+
if (region.current?.contains(event.target) && !region.current.contains(event.relatedTarget)) lastFocused.current = event.relatedTarget;
|
|
3152
|
+
};
|
|
3153
|
+
document.addEventListener("focusin", focusIn);
|
|
3154
|
+
document.addEventListener("visibilitychange", visibility);
|
|
3155
|
+
document.addEventListener("keydown", keydown);
|
|
3156
|
+
window.addEventListener("blur", blur);
|
|
3157
|
+
window.addEventListener("focus", focus);
|
|
3158
|
+
return () => {
|
|
3159
|
+
document.removeEventListener("focusin", focusIn);
|
|
3160
|
+
document.removeEventListener("visibilitychange", visibility);
|
|
3161
|
+
document.removeEventListener("keydown", keydown);
|
|
3162
|
+
window.removeEventListener("blur", blur);
|
|
3163
|
+
window.removeEventListener("focus", focus);
|
|
3164
|
+
detach();
|
|
3165
|
+
if (documentPaused) manager.resume("document");
|
|
3166
|
+
if (windowPaused) manager.resume("window");
|
|
3167
|
+
queue.resumeAll();
|
|
3168
|
+
};
|
|
3169
|
+
}, [
|
|
3170
|
+
manager,
|
|
3171
|
+
hotkeySignature,
|
|
3172
|
+
queue
|
|
3173
|
+
]);
|
|
3174
|
+
useEffect(() => {
|
|
3175
|
+
const lifecycle = lifetime.current;
|
|
3176
|
+
const token = ++lifecycle.generation;
|
|
3177
|
+
return () => {
|
|
3178
|
+
queueMicrotask(() => {
|
|
3179
|
+
if (lifecycle.generation === token) ownedManager.dispose();
|
|
3180
|
+
});
|
|
3181
|
+
};
|
|
3182
|
+
}, [ownedManager]);
|
|
3183
|
+
const context = {
|
|
3184
|
+
manager,
|
|
3185
|
+
closeLabel,
|
|
3186
|
+
placement,
|
|
3187
|
+
dir,
|
|
3188
|
+
showProgress,
|
|
3189
|
+
showCloseButton,
|
|
3190
|
+
swipeThreshold,
|
|
3191
|
+
restoreFocus: () => {
|
|
3192
|
+
const next = region.current?.querySelector(".toast[data-state=\"open\"]");
|
|
3193
|
+
if (next) next.focus();
|
|
3194
|
+
else if (lastFocused.current?.isConnected) lastFocused.current.focus();
|
|
3195
|
+
}
|
|
3196
|
+
};
|
|
3197
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, {
|
|
3198
|
+
value: context,
|
|
3199
|
+
children: [children, /* @__PURE__ */ jsx(I18nProvider$1, {
|
|
3200
|
+
locale: dir === "rtl" ? "ar" : "en",
|
|
3201
|
+
children: /* @__PURE__ */ jsx(UNSTABLE_ToastRegion, {
|
|
3202
|
+
queue,
|
|
3203
|
+
ref: region,
|
|
3204
|
+
className: "toast-region",
|
|
3205
|
+
"data-placement": placement,
|
|
3206
|
+
"aria-label": label,
|
|
3207
|
+
"aria-keyshortcuts": hotkey.length ? hotkey.join("+") : void 0,
|
|
3208
|
+
children: /* @__PURE__ */ jsx(UNSTABLE_ToastList, {
|
|
3209
|
+
className: "toast-list",
|
|
3210
|
+
children: ({ toast }) => /* @__PURE__ */ jsx(Fragment$1, { children: renderToast ? renderToast(toast.content) : /* @__PURE__ */ jsx(Toast, { entry: toast.content }) })
|
|
3211
|
+
})
|
|
3212
|
+
})
|
|
3213
|
+
})]
|
|
3214
|
+
});
|
|
3215
|
+
}
|
|
3216
|
+
function useToast() {
|
|
3217
|
+
const context = useContext(ToastContext);
|
|
3218
|
+
if (!context) throw new Error("useToast must be used within a ToastProvider.");
|
|
3219
|
+
return context.manager;
|
|
3220
|
+
}
|
|
3221
|
+
function Indicator({ entry }) {
|
|
3222
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
3223
|
+
viewBox: "0 0 24 24",
|
|
3224
|
+
width: "20",
|
|
3225
|
+
height: "20",
|
|
3226
|
+
fill: "none",
|
|
3227
|
+
stroke: "currentColor",
|
|
3228
|
+
strokeWidth: "1.8",
|
|
3229
|
+
"aria-hidden": "true",
|
|
3230
|
+
children: entry.isLoading ? /* @__PURE__ */ jsx("circle", {
|
|
3231
|
+
cx: "12",
|
|
3232
|
+
cy: "12",
|
|
3233
|
+
r: "8",
|
|
3234
|
+
strokeDasharray: "36 14"
|
|
3235
|
+
}) : entry.tone === "success" ? /* @__PURE__ */ jsx("path", { d: "m5 12 4 4L19 6" }) : entry.tone === "warning" || entry.tone === "danger" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "m12 3 10 18H2L12 3Z" }), /* @__PURE__ */ jsx("path", { d: "M12 9v5m0 3v1" })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("circle", {
|
|
3236
|
+
cx: "12",
|
|
3237
|
+
cy: "12",
|
|
3238
|
+
r: "9"
|
|
3239
|
+
}), /* @__PURE__ */ jsx("path", { d: "M12 10v7m0-11v1" })] })
|
|
3240
|
+
});
|
|
3241
|
+
}
|
|
3242
|
+
function Toast({ entry, indicator, children, className, showCloseButton: closeOverride, showProgress: progressOverride }) {
|
|
3243
|
+
const actionDescriptionId = useId();
|
|
3244
|
+
const cancelDescriptionId = useId();
|
|
3245
|
+
const context = useContext(ToastContext);
|
|
3246
|
+
if (!context) throw new Error("Toast must be used within a ToastProvider region.");
|
|
3247
|
+
const { manager, closeLabel, placement, dir, swipeThreshold, restoreFocus } = context;
|
|
3248
|
+
const showCloseButton = closeOverride ?? context.showCloseButton;
|
|
3249
|
+
const showProgress = progressOverride ?? context.showProgress;
|
|
3250
|
+
const ref = useRef(null);
|
|
3251
|
+
const drag = useRef(null);
|
|
3252
|
+
const [offset, setOffset] = useState(0);
|
|
3253
|
+
const [swipe, setSwipe] = useState();
|
|
3254
|
+
const closing = entry.state === "closing";
|
|
3255
|
+
const direction = (placement.endsWith("start") ? -1 : 1) * (dir === "rtl" ? -1 : 1);
|
|
3256
|
+
useEffect(() => {
|
|
3257
|
+
if (closing && ref.current?.contains(document.activeElement)) restoreFocus?.();
|
|
3258
|
+
}, [closing, restoreFocus]);
|
|
3259
|
+
const action = (item, reason) => {
|
|
3260
|
+
item.onAction();
|
|
3261
|
+
if (item.dismiss !== false) manager.dismiss(entry.id, reason);
|
|
3262
|
+
};
|
|
3263
|
+
const finishSwipe = (commit) => {
|
|
3264
|
+
const current = drag.current;
|
|
3265
|
+
drag.current = null;
|
|
3266
|
+
if (!current) return;
|
|
3267
|
+
if (current && !current.cancelled) manager.resume("swipe");
|
|
3268
|
+
if (commit && !current.cancelled && current.offset * direction >= swipeThreshold) {
|
|
3269
|
+
setSwipe("end");
|
|
3270
|
+
setOffset(current.offset);
|
|
3271
|
+
manager.dismiss(entry.id, "swipe");
|
|
3272
|
+
} else {
|
|
3273
|
+
setSwipe("cancel");
|
|
3274
|
+
setOffset(0);
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
useEffect(() => {
|
|
3278
|
+
const node = ref.current;
|
|
3279
|
+
if (!node) return;
|
|
3280
|
+
const handlers = {
|
|
3281
|
+
pointerdown: (event) => {
|
|
3282
|
+
if (closing || drag.current || event.button !== 0 || event.target.closest("button,a,input,textarea,select,[role=\"button\"],[contenteditable=\"true\"]")) return;
|
|
3283
|
+
if (event.pointerType === "mouse") event.preventDefault();
|
|
3284
|
+
drag.current = {
|
|
3285
|
+
x: event.clientX,
|
|
3286
|
+
y: event.clientY,
|
|
3287
|
+
id: event.pointerId,
|
|
3288
|
+
cancelled: false,
|
|
3289
|
+
offset: 0
|
|
3290
|
+
};
|
|
3291
|
+
ref.current?.setPointerCapture?.(event.pointerId);
|
|
3292
|
+
manager.pause("swipe");
|
|
3293
|
+
},
|
|
3294
|
+
selectstart: (event) => {
|
|
3295
|
+
if (drag.current && !drag.current.cancelled) event.preventDefault();
|
|
3296
|
+
},
|
|
3297
|
+
dragstart: (event) => {
|
|
3298
|
+
if (drag.current && !drag.current.cancelled) event.preventDefault();
|
|
3299
|
+
},
|
|
3300
|
+
pointermove: (event) => {
|
|
3301
|
+
const current = drag.current;
|
|
3302
|
+
if (!current || current.id !== event.pointerId || current.cancelled) return;
|
|
3303
|
+
const x = event.clientX - current.x;
|
|
3304
|
+
const y = event.clientY - current.y;
|
|
3305
|
+
if (Math.abs(y) > Math.abs(x) && Math.abs(y) > 8) {
|
|
3306
|
+
current.cancelled = true;
|
|
3307
|
+
setOffset(0);
|
|
3308
|
+
manager.resume("swipe");
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
if (Math.abs(x) > 8) {
|
|
3312
|
+
current.offset = Math.max(0, x * direction) * direction;
|
|
3313
|
+
setSwipe("move");
|
|
3314
|
+
setOffset(current.offset);
|
|
3315
|
+
}
|
|
3316
|
+
},
|
|
3317
|
+
pointerup: () => finishSwipe(true),
|
|
3318
|
+
pointercancel: () => finishSwipe(false),
|
|
3319
|
+
lostpointercapture: () => {
|
|
3320
|
+
if (drag.current) finishSwipe(false);
|
|
3321
|
+
}
|
|
3322
|
+
};
|
|
3323
|
+
for (const [name, handler] of Object.entries(handlers)) node.addEventListener(name, handler);
|
|
3324
|
+
return () => {
|
|
3325
|
+
for (const [name, handler] of Object.entries(handlers)) node.removeEventListener(name, handler);
|
|
3326
|
+
};
|
|
3327
|
+
});
|
|
3328
|
+
useEffect(() => () => {
|
|
3329
|
+
if (drag.current) {
|
|
3330
|
+
const active = !drag.current.cancelled;
|
|
3331
|
+
drag.current = null;
|
|
3332
|
+
if (active) manager.resume("swipe");
|
|
3333
|
+
}
|
|
3334
|
+
}, [manager]);
|
|
3335
|
+
return /* @__PURE__ */ jsxs(UNSTABLE_Toast, {
|
|
3336
|
+
toast: {
|
|
3337
|
+
key: entry.id,
|
|
3338
|
+
content: entry
|
|
3339
|
+
},
|
|
3340
|
+
ref,
|
|
3341
|
+
className: `toast${className ? ` ${className}` : ""}`,
|
|
3342
|
+
"data-toast-id": entry.id,
|
|
3343
|
+
"data-tone": entry.tone,
|
|
3344
|
+
"data-has-close": showCloseButton || void 0,
|
|
3345
|
+
"data-loading": entry.isLoading || void 0,
|
|
3346
|
+
"data-state": entry.state,
|
|
3347
|
+
"data-placement": placement,
|
|
3348
|
+
"data-paused": entry.paused || void 0,
|
|
3349
|
+
"data-swipe": swipe,
|
|
3350
|
+
inert: closing || void 0,
|
|
3351
|
+
"aria-hidden": closing || void 0,
|
|
3352
|
+
style: {
|
|
3353
|
+
"--toast-swipe-x": `${offset}px`,
|
|
3354
|
+
touchAction: "pan-y"
|
|
3355
|
+
},
|
|
3356
|
+
children: [
|
|
3357
|
+
/* @__PURE__ */ jsx("span", {
|
|
3358
|
+
className: "toast__indicator",
|
|
3359
|
+
"aria-hidden": "true",
|
|
3360
|
+
children: indicator ?? /* @__PURE__ */ jsx(Indicator, { entry })
|
|
3361
|
+
}),
|
|
3362
|
+
/* @__PURE__ */ jsxs(UNSTABLE_ToastContent, {
|
|
3363
|
+
className: "toast__body",
|
|
3364
|
+
role: "status",
|
|
3365
|
+
"aria-live": "polite",
|
|
3366
|
+
children: [
|
|
3367
|
+
/* @__PURE__ */ jsx(Text$3, {
|
|
3368
|
+
slot: "title",
|
|
3369
|
+
className: "toast__title",
|
|
3370
|
+
children: entry.title
|
|
3371
|
+
}),
|
|
3372
|
+
entry.description && /* @__PURE__ */ jsx(Text$3, {
|
|
3373
|
+
slot: "description",
|
|
3374
|
+
className: "toast__description",
|
|
3375
|
+
children: entry.description
|
|
3376
|
+
}),
|
|
3377
|
+
children,
|
|
3378
|
+
(entry.action || entry.cancel) && /* @__PURE__ */ jsxs("div", {
|
|
3379
|
+
className: "toast__actions",
|
|
3380
|
+
children: [
|
|
3381
|
+
entry.action && /* @__PURE__ */ jsx("span", {
|
|
3382
|
+
id: actionDescriptionId,
|
|
3383
|
+
hidden: true,
|
|
3384
|
+
children: entry.action.altText
|
|
3385
|
+
}),
|
|
3386
|
+
entry.cancel && /* @__PURE__ */ jsx("span", {
|
|
3387
|
+
id: cancelDescriptionId,
|
|
3388
|
+
hidden: true,
|
|
3389
|
+
children: entry.cancel.altText
|
|
3390
|
+
}),
|
|
3391
|
+
entry.action && /* @__PURE__ */ jsx(Button$5, {
|
|
3392
|
+
className: "toast__action",
|
|
3393
|
+
"aria-describedby": actionDescriptionId,
|
|
3394
|
+
isDisabled: closing,
|
|
3395
|
+
onPress: () => action(entry.action, "action"),
|
|
3396
|
+
children: entry.action.label
|
|
3397
|
+
}),
|
|
3398
|
+
entry.cancel && /* @__PURE__ */ jsx(Button$5, {
|
|
3399
|
+
className: "toast__action",
|
|
3400
|
+
"data-cancel": true,
|
|
3401
|
+
"aria-describedby": cancelDescriptionId,
|
|
3402
|
+
isDisabled: closing,
|
|
3403
|
+
onPress: () => action(entry.cancel, "cancel"),
|
|
3404
|
+
children: entry.cancel.label
|
|
3405
|
+
})
|
|
3406
|
+
]
|
|
3407
|
+
})
|
|
3408
|
+
]
|
|
3409
|
+
}),
|
|
3410
|
+
showCloseButton && /* @__PURE__ */ jsx(Button$5, {
|
|
3411
|
+
slot: "close",
|
|
3412
|
+
className: "toast__close",
|
|
3413
|
+
"aria-label": closeLabel,
|
|
3414
|
+
isDisabled: closing,
|
|
3415
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
3416
|
+
viewBox: "0 0 24 24",
|
|
3417
|
+
width: "16",
|
|
3418
|
+
height: "16",
|
|
3419
|
+
fill: "none",
|
|
3420
|
+
stroke: "currentColor",
|
|
3421
|
+
strokeWidth: "2",
|
|
3422
|
+
"aria-hidden": "true",
|
|
3423
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 6 12 12M6 18 18 6" })
|
|
3424
|
+
})
|
|
3425
|
+
}),
|
|
3426
|
+
showProgress && entry.duration > 0 && !entry.isLoading && /* @__PURE__ */ jsx("span", {
|
|
3427
|
+
className: "toast__progress",
|
|
3428
|
+
"aria-hidden": "true",
|
|
3429
|
+
style: {
|
|
3430
|
+
"--toast-progress": entry.remaining / entry.duration,
|
|
3431
|
+
"--toast-remaining": `${entry.remaining}ms`
|
|
3432
|
+
}
|
|
3433
|
+
}, `${entry.generation}-${entry.remaining}-${entry.paused}`)
|
|
3434
|
+
]
|
|
3435
|
+
});
|
|
3436
|
+
}
|
|
3437
|
+
//#endregion
|
|
3438
|
+
export { Alert, Badge, Breadcrumb, Button, ButtonGroup, ButtonGroupSeparator, Card, Chart, Checkbox, Combobox, DataTable, DateRangePicker, Dialog, DropdownMenu, Empty, Field, Form, Input, Label, Listbox, NumberField, Pagination, Popover, RadioGroup, Select, SelectGroup, Separator, Sidebar, Skeleton, Spinner, Switch, Table, Tabs, Textarea, Toast, ToastProvider, ToggleButton, ToggleButtonGroup, ToggleGroup, Tooltip, createDateRangePresets, createToastManager, rangeText as formatDateRange, useToast };
|
|
2735
3439
|
|
|
2736
3440
|
//# sourceMappingURL=index.js.map
|