@nation-a/ui 0.9.2 → 0.10.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import { forwardRef, useMemo, createElement, createContext as createContext$1, useContext, useRef, useLayoutEffect, useEffect, useState, memo as memo$1, Children, isValidElement, cloneElement, useCallback, useId, useSyncExternalStore } from "react";
3
+ import React__default, { forwardRef, useMemo, createElement, createContext as createContext$1, useContext, useRef, useLayoutEffect, useEffect, useState, memo as memo$1, Children, isValidElement, cloneElement, useCallback, useId, useSyncExternalStore } from "react";
4
4
  import { flushSync, createPortal, unstable_batchedUpdates } from "react-dom";
5
5
  function withPolymorphicComponent(Component) {
6
6
  const PolymorphicComponent = React.forwardRef(
@@ -772,12 +772,23 @@ var isString = (v2) => typeof v2 === "string";
772
772
  var isFunction = (v2) => typeof v2 === "function";
773
773
  var fnToString = Function.prototype.toString;
774
774
  fnToString.call(Object);
775
+ var runIfFn = (v2, ...a) => {
776
+ const res = typeof v2 === "function" ? v2(...a) : v2;
777
+ return res ?? void 0;
778
+ };
775
779
  var identity = (v2) => v2();
776
780
  var callAll = (...fns2) => (...a) => {
777
781
  fns2.forEach(function(fn) {
778
782
  fn == null ? void 0 : fn(...a);
779
783
  });
780
784
  };
785
+ var uuid = /* @__PURE__ */ (() => {
786
+ let id = 0;
787
+ return () => {
788
+ id++;
789
+ return id.toString(36);
790
+ };
791
+ })();
781
792
  function compact(obj) {
782
793
  if (!isPlainObject2(obj) || obj === void 0) return obj;
783
794
  const keys = Reflect.ownKeys(obj).filter((key) => typeof key === "string");
@@ -793,6 +804,19 @@ function compact(obj) {
793
804
  var isPlainObject2 = (v2) => {
794
805
  return v2 && typeof v2 === "object" && v2.constructor === Object;
795
806
  };
807
+ function setRafTimeout(callback, delay2) {
808
+ const start2 = performance.now();
809
+ let handle;
810
+ function loop2(now) {
811
+ handle = requestAnimationFrame(loop2);
812
+ const delta = now - start2;
813
+ if (delta >= delay2) {
814
+ callback();
815
+ }
816
+ }
817
+ handle = requestAnimationFrame(loop2);
818
+ return () => cancelAnimationFrame(handle);
819
+ }
796
820
  function warn(...a) {
797
821
  const m2 = a.length === 1 ? a[0] : a[1];
798
822
  const c = a.length === 2 ? a[0] : true;
@@ -803,7 +827,16 @@ function warn(...a) {
803
827
  function ensure(c, m2) {
804
828
  if (c == null) throw new Error(m2);
805
829
  }
830
+ function ensureProps(props, keys, scope) {
831
+ let missingKeys = [];
832
+ for (const key of keys) {
833
+ if (props[key] == null) missingKeys.push(key);
834
+ }
835
+ if (missingKeys.length > 0)
836
+ throw new Error(`[zag-js${` > ${scope}`}] missing required props: ${missingKeys.join(", ")}`);
837
+ }
806
838
  var isObject = (v2) => typeof v2 === "object" && v2 !== null;
839
+ var MAX_Z_INDEX = 2147483647;
807
840
  var dataAttr = (guard) => guard ? "" : void 0;
808
841
  var ELEMENT_NODE = 1;
809
842
  var DOCUMENT_NODE = 9;
@@ -2078,6 +2111,27 @@ function trackDismissableElement(nodeOrFn, options) {
2078
2111
  cleanups2.forEach((fn) => fn == null ? void 0 : fn());
2079
2112
  };
2080
2113
  }
2114
+ function trackDismissableBranch(nodeOrFn, options = {}) {
2115
+ const { defer } = options;
2116
+ const func = defer ? raf$2 : (v2) => v2();
2117
+ const cleanups2 = [];
2118
+ cleanups2.push(
2119
+ func(() => {
2120
+ const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn;
2121
+ if (!node) {
2122
+ warn("[@zag-js/dismissable] branch node is `null` or `undefined`");
2123
+ return;
2124
+ }
2125
+ layerStack.addBranch(node);
2126
+ cleanups2.push(() => {
2127
+ layerStack.removeBranch(node);
2128
+ });
2129
+ })
2130
+ );
2131
+ return () => {
2132
+ cleanups2.forEach((fn) => fn == null ? void 0 : fn());
2133
+ };
2134
+ }
2081
2135
  const [RenderStrategyPropsProvider, useRenderStrategyPropsContext] = createContext({
2082
2136
  name: "RenderStrategyContext",
2083
2137
  hookName: "useRenderStrategyContext",
@@ -2111,7 +2165,7 @@ const [PresenceProvider, usePresenceContext] = createContext({
2111
2165
  providerName: "<PresenceProvider />"
2112
2166
  });
2113
2167
  const splitPresenceProps = (props) => createSplitProps()(props, ["immediate", "lazyMount", "onExitComplete", "present", "unmountOnExit"]);
2114
- function connect$2(service, _normalize) {
2168
+ function connect$3(service, _normalize) {
2115
2169
  const { state, send, context: context2 } = service;
2116
2170
  const present = state.matches("mounted", "unmountSuspended");
2117
2171
  return {
@@ -2126,7 +2180,7 @@ function connect$2(service, _normalize) {
2126
2180
  }
2127
2181
  };
2128
2182
  }
2129
- var machine$2 = createMachine({
2183
+ var machine$3 = createMachine({
2130
2184
  props({ props: props2 }) {
2131
2185
  return { ...props2, present: !!props2.present };
2132
2186
  },
@@ -2293,8 +2347,8 @@ const usePresence = (props = {}) => {
2293
2347
  present,
2294
2348
  onExitComplete: useEvent(props.onExitComplete)
2295
2349
  };
2296
- const service = useMachine(machine$2, machineProps);
2297
- const api = connect$2(service);
2350
+ const service = useMachine(machine$3, machineProps);
2351
+ const api = connect$3(service);
2298
2352
  if (api.present) {
2299
2353
  wasEverPresent.current = true;
2300
2354
  }
@@ -2910,7 +2964,7 @@ var FocusTrap = class {
2910
2964
  nextTabbableNode
2911
2965
  };
2912
2966
  });
2913
- this.state.tabbableGroups = this.state.containerGroups.filter((group) => group.tabbableNodes.length > 0);
2967
+ this.state.tabbableGroups = this.state.containerGroups.filter((group2) => group2.tabbableNodes.length > 0);
2914
2968
  if (this.state.tabbableGroups.length <= 0 && !this.getNodeForOption("fallbackFocus")) {
2915
2969
  throw new Error(
2916
2970
  "Your focus-trap must have at least one container with at least one tabbable node in it at all times"
@@ -3073,7 +3127,7 @@ function preventBodyScroll(_document) {
3073
3127
  body.removeAttribute(LOCK_CLASSNAME);
3074
3128
  };
3075
3129
  }
3076
- var anatomy$1 = createAnatomy("dialog").parts(
3130
+ var anatomy$2 = createAnatomy("dialog").parts(
3077
3131
  "trigger",
3078
3132
  "backdrop",
3079
3133
  "positioner",
@@ -3082,7 +3136,7 @@ var anatomy$1 = createAnatomy("dialog").parts(
3082
3136
  "description",
3083
3137
  "closeTrigger"
3084
3138
  );
3085
- var parts$1 = anatomy$1.build();
3139
+ var parts$2 = anatomy$2.build();
3086
3140
  var getPositionerId = (ctx2) => {
3087
3141
  var _a;
3088
3142
  return ((_a = ctx2.ids) == null ? void 0 : _a.positioner) ?? `dialog:${ctx2.id}:positioner`;
@@ -3099,15 +3153,15 @@ var getTriggerId$1 = (ctx2) => {
3099
3153
  var _a;
3100
3154
  return ((_a = ctx2.ids) == null ? void 0 : _a.trigger) ?? `dialog:${ctx2.id}:trigger`;
3101
3155
  };
3102
- var getTitleId = (ctx2) => {
3156
+ var getTitleId$1 = (ctx2) => {
3103
3157
  var _a;
3104
3158
  return ((_a = ctx2.ids) == null ? void 0 : _a.title) ?? `dialog:${ctx2.id}:title`;
3105
3159
  };
3106
- var getDescriptionId = (ctx2) => {
3160
+ var getDescriptionId$1 = (ctx2) => {
3107
3161
  var _a;
3108
3162
  return ((_a = ctx2.ids) == null ? void 0 : _a.description) ?? `dialog:${ctx2.id}:description`;
3109
3163
  };
3110
- var getCloseTriggerId = (ctx2) => {
3164
+ var getCloseTriggerId$1 = (ctx2) => {
3111
3165
  var _a;
3112
3166
  return ((_a = ctx2.ids) == null ? void 0 : _a.closeTrigger) ?? `dialog:${ctx2.id}:close`;
3113
3167
  };
@@ -3115,10 +3169,10 @@ var getContentEl$1 = (ctx2) => ctx2.getById(getContentId$1(ctx2));
3115
3169
  var getPositionerEl = (ctx2) => ctx2.getById(getPositionerId(ctx2));
3116
3170
  var getBackdropEl = (ctx2) => ctx2.getById(getBackdropId(ctx2));
3117
3171
  var getTriggerEl$1 = (ctx2) => ctx2.getById(getTriggerId$1(ctx2));
3118
- var getTitleEl = (ctx2) => ctx2.getById(getTitleId(ctx2));
3119
- var getDescriptionEl = (ctx2) => ctx2.getById(getDescriptionId(ctx2));
3120
- var getCloseTriggerEl = (ctx2) => ctx2.getById(getCloseTriggerId(ctx2));
3121
- function connect$1(service, normalize) {
3172
+ var getTitleEl = (ctx2) => ctx2.getById(getTitleId$1(ctx2));
3173
+ var getDescriptionEl = (ctx2) => ctx2.getById(getDescriptionId$1(ctx2));
3174
+ var getCloseTriggerEl = (ctx2) => ctx2.getById(getCloseTriggerId$1(ctx2));
3175
+ function connect$2(service, normalize) {
3122
3176
  const { state, send, context: context2, prop, scope } = service;
3123
3177
  const ariaLabel = prop("aria-label");
3124
3178
  const open = state.matches("open");
@@ -3131,7 +3185,7 @@ function connect$1(service, normalize) {
3131
3185
  },
3132
3186
  getTriggerProps() {
3133
3187
  return normalize.button({
3134
- ...parts$1.trigger.attrs,
3188
+ ...parts$2.trigger.attrs,
3135
3189
  dir: prop("dir"),
3136
3190
  id: getTriggerId$1(scope),
3137
3191
  "aria-haspopup": "dialog",
@@ -3147,7 +3201,7 @@ function connect$1(service, normalize) {
3147
3201
  },
3148
3202
  getBackdropProps() {
3149
3203
  return normalize.element({
3150
- ...parts$1.backdrop.attrs,
3204
+ ...parts$2.backdrop.attrs,
3151
3205
  dir: prop("dir"),
3152
3206
  hidden: !open,
3153
3207
  id: getBackdropId(scope),
@@ -3156,7 +3210,7 @@ function connect$1(service, normalize) {
3156
3210
  },
3157
3211
  getPositionerProps() {
3158
3212
  return normalize.element({
3159
- ...parts$1.positioner.attrs,
3213
+ ...parts$2.positioner.attrs,
3160
3214
  dir: prop("dir"),
3161
3215
  id: getPositionerId(scope),
3162
3216
  style: {
@@ -3167,7 +3221,7 @@ function connect$1(service, normalize) {
3167
3221
  getContentProps() {
3168
3222
  const rendered = context2.get("rendered");
3169
3223
  return normalize.element({
3170
- ...parts$1.content.attrs,
3224
+ ...parts$2.content.attrs,
3171
3225
  dir: prop("dir"),
3172
3226
  role: prop("role"),
3173
3227
  hidden: !open,
@@ -3176,29 +3230,29 @@ function connect$1(service, normalize) {
3176
3230
  "data-state": open ? "open" : "closed",
3177
3231
  "aria-modal": true,
3178
3232
  "aria-label": ariaLabel || void 0,
3179
- "aria-labelledby": ariaLabel || !rendered.title ? void 0 : getTitleId(scope),
3180
- "aria-describedby": rendered.description ? getDescriptionId(scope) : void 0
3233
+ "aria-labelledby": ariaLabel || !rendered.title ? void 0 : getTitleId$1(scope),
3234
+ "aria-describedby": rendered.description ? getDescriptionId$1(scope) : void 0
3181
3235
  });
3182
3236
  },
3183
3237
  getTitleProps() {
3184
3238
  return normalize.element({
3185
- ...parts$1.title.attrs,
3239
+ ...parts$2.title.attrs,
3186
3240
  dir: prop("dir"),
3187
- id: getTitleId(scope)
3241
+ id: getTitleId$1(scope)
3188
3242
  });
3189
3243
  },
3190
3244
  getDescriptionProps() {
3191
3245
  return normalize.element({
3192
- ...parts$1.description.attrs,
3246
+ ...parts$2.description.attrs,
3193
3247
  dir: prop("dir"),
3194
- id: getDescriptionId(scope)
3248
+ id: getDescriptionId$1(scope)
3195
3249
  });
3196
3250
  },
3197
3251
  getCloseTriggerProps() {
3198
3252
  return normalize.button({
3199
- ...parts$1.closeTrigger.attrs,
3253
+ ...parts$2.closeTrigger.attrs,
3200
3254
  dir: prop("dir"),
3201
- id: getCloseTriggerId(scope),
3255
+ id: getCloseTriggerId$1(scope),
3202
3256
  type: "button",
3203
3257
  onClick(event) {
3204
3258
  if (event.defaultPrevented) return;
@@ -3209,7 +3263,7 @@ function connect$1(service, normalize) {
3209
3263
  }
3210
3264
  };
3211
3265
  }
3212
- var machine$1 = createMachine({
3266
+ var machine$2 = createMachine({
3213
3267
  props({ props: props2, scope }) {
3214
3268
  const alertDialog = props2.role === "alertdialog";
3215
3269
  const initialFocusEl = alertDialog ? () => getCloseTriggerEl(scope) : void 0;
@@ -3428,8 +3482,8 @@ const useDialog = (props) => {
3428
3482
  dir,
3429
3483
  ...props
3430
3484
  };
3431
- const service = useMachine(machine$1, machineProps);
3432
- return connect$1(service, normalizeProps);
3485
+ const service = useMachine(machine$2, machineProps);
3486
+ return connect$2(service, normalizeProps);
3433
3487
  };
3434
3488
  const DialogRoot = (props) => {
3435
3489
  const [presenceProps, { children, ...localProps }] = splitPresenceProps(props);
@@ -3503,9 +3557,9 @@ const TabTrigger = forwardRef((props, ref) => {
3503
3557
  return /* @__PURE__ */ jsx(ark.button, { ...mergedProps, ref });
3504
3558
  });
3505
3559
  TabTrigger.displayName = "TabTrigger";
3506
- var anatomy = createAnatomy("tabs").parts("root", "list", "trigger", "content", "indicator");
3507
- var parts = anatomy.build();
3508
- var getRootId = (ctx2) => {
3560
+ var anatomy$1 = createAnatomy("tabs").parts("root", "list", "trigger", "content", "indicator");
3561
+ var parts$1 = anatomy$1.build();
3562
+ var getRootId$1 = (ctx2) => {
3509
3563
  var _a;
3510
3564
  return ((_a = ctx2.ids) == null ? void 0 : _a.root) ?? `tabs:${ctx2.id}`;
3511
3565
  };
@@ -3556,7 +3610,7 @@ var resolveRect = (rect) => ({
3556
3610
  left: `${rect.left}px`,
3557
3611
  top: `${rect.top}px`
3558
3612
  });
3559
- function connect(service, normalize) {
3613
+ function connect$1(service, normalize) {
3560
3614
  const { state, send, context: context2, prop, scope } = service;
3561
3615
  const translations = prop("translations");
3562
3616
  const focused = state.matches("focused");
@@ -3602,8 +3656,8 @@ function connect(service, normalize) {
3602
3656
  },
3603
3657
  getRootProps() {
3604
3658
  return normalize.element({
3605
- ...parts.root.attrs,
3606
- id: getRootId(scope),
3659
+ ...parts$1.root.attrs,
3660
+ id: getRootId$1(scope),
3607
3661
  "data-orientation": prop("orientation"),
3608
3662
  "data-focus": dataAttr(focused),
3609
3663
  dir: prop("dir")
@@ -3611,7 +3665,7 @@ function connect(service, normalize) {
3611
3665
  },
3612
3666
  getListProps() {
3613
3667
  return normalize.element({
3614
- ...parts.list.attrs,
3668
+ ...parts$1.list.attrs,
3615
3669
  id: getListId(scope),
3616
3670
  role: "tablist",
3617
3671
  dir: prop("dir"),
@@ -3667,7 +3721,7 @@ function connect(service, normalize) {
3667
3721
  const { value, disabled } = props2;
3668
3722
  const triggerState = getTriggerState(props2);
3669
3723
  return normalize.button({
3670
- ...parts.trigger.attrs,
3724
+ ...parts$1.trigger.attrs,
3671
3725
  role: "tab",
3672
3726
  type: "button",
3673
3727
  disabled,
@@ -3707,7 +3761,7 @@ function connect(service, normalize) {
3707
3761
  const { value } = props2;
3708
3762
  const selected = context2.get("value") === value;
3709
3763
  return normalize.element({
3710
- ...parts.content.attrs,
3764
+ ...parts$1.content.attrs,
3711
3765
  dir: prop("dir"),
3712
3766
  id: getContentId(scope, value),
3713
3767
  tabIndex: composite ? 0 : -1,
@@ -3724,7 +3778,7 @@ function connect(service, normalize) {
3724
3778
  const indicatorTransition = context2.get("indicatorTransition");
3725
3779
  return normalize.element({
3726
3780
  id: getIndicatorId(scope),
3727
- ...parts.indicator.attrs,
3781
+ ...parts$1.indicator.attrs,
3728
3782
  dir: prop("dir"),
3729
3783
  "data-orientation": prop("orientation"),
3730
3784
  style: {
@@ -3744,8 +3798,8 @@ function connect(service, normalize) {
3744
3798
  }
3745
3799
  };
3746
3800
  }
3747
- var { not } = createGuards();
3748
- var machine = createMachine({
3801
+ var { not: not$1 } = createGuards();
3802
+ var machine$1 = createMachine({
3749
3803
  props({ props: props2 }) {
3750
3804
  return {
3751
3805
  dir: "ltr",
@@ -3868,7 +3922,7 @@ var machine = createMachine({
3868
3922
  }
3869
3923
  ],
3870
3924
  ENTER: {
3871
- guard: not("selectOnFocus"),
3925
+ guard: not$1("selectOnFocus"),
3872
3926
  actions: ["selectFocusedTab"]
3873
3927
  },
3874
3928
  TAB_FOCUS: {
@@ -4049,8 +4103,8 @@ const useTabs = (props) => {
4049
4103
  getRootNode,
4050
4104
  ...props
4051
4105
  };
4052
- const service = useMachine(machine, machineProps);
4053
- return connect(service, normalizeProps);
4106
+ const service = useMachine(machine$1, machineProps);
4107
+ return connect$1(service, normalizeProps);
4054
4108
  };
4055
4109
  const TabsRoot = forwardRef((props, ref) => {
4056
4110
  const [renderStrategyProps, tabsProps] = splitRenderStrategyProps(props);
@@ -4074,6 +4128,1089 @@ const TabsRoot = forwardRef((props, ref) => {
4074
4128
  return /* @__PURE__ */ jsx(TabsProvider, { value: tabs, children: /* @__PURE__ */ jsx(RenderStrategyPropsProvider, { value: renderStrategyProps, children: /* @__PURE__ */ jsx(ark.div, { ...mergedProps, ref }) }) });
4075
4129
  });
4076
4130
  TabsRoot.displayName = "TabsRoot";
4131
+ var anatomy = createAnatomy("toast").parts(
4132
+ "group",
4133
+ "root",
4134
+ "title",
4135
+ "description",
4136
+ "actionTrigger",
4137
+ "closeTrigger"
4138
+ );
4139
+ var parts = anatomy.build();
4140
+ var getRegionId = (placement) => `toast-group:${placement}`;
4141
+ var getRegionEl = (ctx2, placement) => ctx2.getById(`toast-group:${placement}`);
4142
+ var getRootId = (ctx2) => `toast:${ctx2.id}`;
4143
+ var getRootEl = (ctx2) => ctx2.getById(getRootId(ctx2));
4144
+ var getTitleId = (ctx2) => `toast:${ctx2.id}:title`;
4145
+ var getDescriptionId = (ctx2) => `toast:${ctx2.id}:description`;
4146
+ var getCloseTriggerId = (ctx2) => `toast${ctx2.id}:close`;
4147
+ var defaultTimeouts = {
4148
+ info: 5e3,
4149
+ error: 5e3,
4150
+ success: 2e3,
4151
+ loading: Infinity,
4152
+ DEFAULT: 5e3
4153
+ };
4154
+ function getToastDuration(duration, type) {
4155
+ return duration ?? defaultTimeouts[type] ?? defaultTimeouts.DEFAULT;
4156
+ }
4157
+ var getOffsets = (offsets) => typeof offsets === "string" ? { left: offsets, right: offsets, bottom: offsets, top: offsets } : offsets;
4158
+ function getGroupPlacementStyle(service, placement) {
4159
+ var _a;
4160
+ const { prop, computed, context: context2 } = service;
4161
+ const { offsets, gap } = prop("store").attrs;
4162
+ const heights = context2.get("heights");
4163
+ const computedOffset = getOffsets(offsets);
4164
+ const rtl = prop("dir") === "rtl";
4165
+ const computedPlacement = placement.replace("-start", rtl ? "-right" : "-left").replace("-end", rtl ? "-left" : "-right");
4166
+ const isRighty = computedPlacement.includes("right");
4167
+ const isLefty = computedPlacement.includes("left");
4168
+ const styles = {
4169
+ position: "fixed",
4170
+ pointerEvents: computed("count") > 0 ? void 0 : "none",
4171
+ display: "flex",
4172
+ flexDirection: "column",
4173
+ "--gap": `${gap}px`,
4174
+ "--first-height": `${((_a = heights[0]) == null ? void 0 : _a.height) || 0}px`,
4175
+ zIndex: MAX_Z_INDEX
4176
+ };
4177
+ let alignItems = "center";
4178
+ if (isRighty) alignItems = "flex-end";
4179
+ if (isLefty) alignItems = "flex-start";
4180
+ styles.alignItems = alignItems;
4181
+ if (computedPlacement.includes("top")) {
4182
+ const offset = computedOffset.top;
4183
+ styles.top = `max(env(safe-area-inset-top, 0px), ${offset})`;
4184
+ }
4185
+ if (computedPlacement.includes("bottom")) {
4186
+ const offset = computedOffset.bottom;
4187
+ styles.bottom = `max(env(safe-area-inset-bottom, 0px), ${offset})`;
4188
+ }
4189
+ if (!computedPlacement.includes("left")) {
4190
+ const offset = computedOffset.right;
4191
+ styles.insetInlineEnd = `calc(env(safe-area-inset-right, 0px) + ${offset})`;
4192
+ }
4193
+ if (!computedPlacement.includes("right")) {
4194
+ const offset = computedOffset.left;
4195
+ styles.insetInlineStart = `calc(env(safe-area-inset-left, 0px) + ${offset})`;
4196
+ }
4197
+ return styles;
4198
+ }
4199
+ function getPlacementStyle(service, visible) {
4200
+ const { prop, context: context2, computed } = service;
4201
+ const parent = prop("parent");
4202
+ const placement = parent.computed("placement");
4203
+ const { gap } = parent.prop("store").attrs;
4204
+ const [side] = placement.split("-");
4205
+ const mounted = context2.get("mounted");
4206
+ const remainingTime = context2.get("remainingTime");
4207
+ const height = computed("height");
4208
+ const frontmost = computed("frontmost");
4209
+ const sibling = !frontmost;
4210
+ const overlap = !prop("stacked");
4211
+ const stacked = prop("stacked");
4212
+ const type = prop("type");
4213
+ const duration = type === "loading" ? Number.MAX_SAFE_INTEGER : remainingTime;
4214
+ const offset = computed("heightIndex") * gap + computed("heightBefore");
4215
+ const styles = {
4216
+ position: "absolute",
4217
+ pointerEvents: "auto",
4218
+ "--opacity": "0",
4219
+ "--remove-delay": `${prop("removeDelay")}ms`,
4220
+ "--duration": `${duration}ms`,
4221
+ "--initial-height": `${height}px`,
4222
+ "--offset": `${offset}px`,
4223
+ "--index": prop("index"),
4224
+ "--z-index": computed("zIndex"),
4225
+ "--lift-amount": "calc(var(--lift) * var(--gap))",
4226
+ "--y": "100%",
4227
+ "--x": "0"
4228
+ };
4229
+ const assign2 = (overrides) => Object.assign(styles, overrides);
4230
+ if (side === "top") {
4231
+ assign2({
4232
+ top: "0",
4233
+ "--sign": "-1",
4234
+ "--y": "-100%",
4235
+ "--lift": "1"
4236
+ });
4237
+ } else if (side === "bottom") {
4238
+ assign2({
4239
+ bottom: "0",
4240
+ "--sign": "1",
4241
+ "--y": "100%",
4242
+ "--lift": "-1"
4243
+ });
4244
+ }
4245
+ if (mounted) {
4246
+ assign2({
4247
+ "--y": "0",
4248
+ "--opacity": "1"
4249
+ });
4250
+ if (stacked) {
4251
+ assign2({
4252
+ "--y": "calc(var(--lift) * var(--offset))",
4253
+ "--height": "var(--initial-height)"
4254
+ });
4255
+ }
4256
+ }
4257
+ if (!visible) {
4258
+ assign2({
4259
+ "--opacity": "0",
4260
+ pointerEvents: "none"
4261
+ });
4262
+ }
4263
+ if (sibling && overlap) {
4264
+ assign2({
4265
+ "--base-scale": "var(--index) * 0.05 + 1",
4266
+ "--y": "calc(var(--lift-amount) * var(--index))",
4267
+ "--scale": "calc(-1 * var(--base-scale))",
4268
+ "--height": "var(--first-height)"
4269
+ });
4270
+ if (!visible) {
4271
+ assign2({
4272
+ "--y": "calc(var(--sign) * 40%)"
4273
+ });
4274
+ }
4275
+ }
4276
+ if (sibling && stacked && !visible) {
4277
+ assign2({
4278
+ "--y": "calc(var(--lift) * var(--offset) + var(--lift) * -100%)"
4279
+ });
4280
+ }
4281
+ if (frontmost && !visible) {
4282
+ assign2({
4283
+ "--y": "calc(var(--lift) * -100%)"
4284
+ });
4285
+ }
4286
+ return styles;
4287
+ }
4288
+ function getGhostBeforeStyle(service, visible) {
4289
+ const { computed } = service;
4290
+ const styles = {
4291
+ position: "absolute",
4292
+ inset: "0",
4293
+ scale: "1 2",
4294
+ pointerEvents: visible ? "none" : "auto"
4295
+ };
4296
+ const assign2 = (overrides) => Object.assign(styles, overrides);
4297
+ if (computed("frontmost") && !visible) {
4298
+ assign2({
4299
+ height: "calc(var(--initial-height) + 80%)"
4300
+ });
4301
+ }
4302
+ return styles;
4303
+ }
4304
+ function getGhostAfterStyle() {
4305
+ return {
4306
+ position: "absolute",
4307
+ left: "0",
4308
+ height: "calc(var(--gap) + 2px)",
4309
+ bottom: "100%",
4310
+ width: "100%"
4311
+ };
4312
+ }
4313
+ function groupConnect(service, normalize) {
4314
+ const { context: context2, prop, send, refs, computed } = service;
4315
+ return {
4316
+ getCount() {
4317
+ return context2.get("toasts").length;
4318
+ },
4319
+ getToasts() {
4320
+ return context2.get("toasts");
4321
+ },
4322
+ getGroupProps(options = {}) {
4323
+ const { label = "Notifications" } = options;
4324
+ const { hotkey } = prop("store").attrs;
4325
+ const hotkeyLabel = hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
4326
+ const placement = computed("placement");
4327
+ const [side, align = "center"] = placement.split("-");
4328
+ return normalize.element({
4329
+ ...parts.group.attrs,
4330
+ dir: prop("dir"),
4331
+ tabIndex: -1,
4332
+ "aria-label": `${placement} ${label} ${hotkeyLabel}`,
4333
+ id: getRegionId(placement),
4334
+ "data-placement": placement,
4335
+ "data-side": side,
4336
+ "data-align": align,
4337
+ "aria-live": "polite",
4338
+ role: "region",
4339
+ style: getGroupPlacementStyle(service, placement),
4340
+ onMouseMove() {
4341
+ send({ type: "REGION.POINTER_ENTER", placement });
4342
+ },
4343
+ onMouseLeave() {
4344
+ send({ type: "REGION.POINTER_LEAVE", placement });
4345
+ },
4346
+ onFocus(event) {
4347
+ send({ type: "REGION.FOCUS", target: event.relatedTarget });
4348
+ },
4349
+ onBlur(event) {
4350
+ if (refs.get("isFocusWithin") && !contains(event.currentTarget, event.relatedTarget)) {
4351
+ queueMicrotask(() => send({ type: "REGION.BLUR" }));
4352
+ }
4353
+ }
4354
+ });
4355
+ },
4356
+ subscribe(fn) {
4357
+ const store = prop("store");
4358
+ return store.subscribe(() => fn(context2.get("toasts")));
4359
+ }
4360
+ };
4361
+ }
4362
+ var groupMachine = createMachine({
4363
+ props({ props }) {
4364
+ return {
4365
+ dir: "ltr",
4366
+ id: uuid(),
4367
+ ...props,
4368
+ store: props.store
4369
+ };
4370
+ },
4371
+ initialState({ prop }) {
4372
+ return prop("store").attrs.overlap ? "overlap" : "stack";
4373
+ },
4374
+ refs() {
4375
+ return {
4376
+ lastFocusedEl: null,
4377
+ isFocusWithin: false,
4378
+ dismissableCleanup: void 0
4379
+ };
4380
+ },
4381
+ context({ bindable }) {
4382
+ return {
4383
+ toasts: bindable(() => ({
4384
+ defaultValue: [],
4385
+ sync: true,
4386
+ hash: (toasts) => toasts.map((t) => t.id).join(",")
4387
+ })),
4388
+ heights: bindable(() => ({
4389
+ defaultValue: [],
4390
+ sync: true
4391
+ }))
4392
+ };
4393
+ },
4394
+ computed: {
4395
+ count: ({ context: context2 }) => context2.get("toasts").length,
4396
+ overlap: ({ prop }) => prop("store").attrs.overlap,
4397
+ placement: ({ prop }) => prop("store").attrs.placement
4398
+ },
4399
+ effects: ["subscribeToStore", "trackDocumentVisibility", "trackHotKeyPress"],
4400
+ watch({ track, context: context2, action }) {
4401
+ track([() => context2.hash("toasts")], () => {
4402
+ queueMicrotask(() => {
4403
+ action(["collapsedIfEmpty", "setDismissableBranch"]);
4404
+ });
4405
+ });
4406
+ },
4407
+ exit: ["clearDismissableBranch", "clearLastFocusedEl"],
4408
+ on: {
4409
+ "DOC.HOTKEY": {
4410
+ actions: ["focusRegionEl"]
4411
+ },
4412
+ "REGION.BLUR": [
4413
+ {
4414
+ guard: "isOverlapping",
4415
+ target: "overlap",
4416
+ actions: ["collapseToasts", "resumeToasts", "restoreLastFocusedEl"]
4417
+ },
4418
+ {
4419
+ target: "stack",
4420
+ actions: ["resumeToasts", "restoreLastFocusedEl"]
4421
+ }
4422
+ ],
4423
+ "TOAST.REMOVE": {
4424
+ actions: ["removeToast", "removeHeight"]
4425
+ },
4426
+ "TOAST.PAUSE": {
4427
+ actions: ["pauseToasts"]
4428
+ }
4429
+ },
4430
+ states: {
4431
+ stack: {
4432
+ on: {
4433
+ "REGION.POINTER_LEAVE": [
4434
+ {
4435
+ guard: "isOverlapping",
4436
+ target: "overlap",
4437
+ actions: ["resumeToasts", "collapseToasts"]
4438
+ },
4439
+ {
4440
+ actions: ["resumeToasts"]
4441
+ }
4442
+ ],
4443
+ "REGION.OVERLAP": {
4444
+ target: "overlap",
4445
+ actions: ["collapseToasts"]
4446
+ },
4447
+ "REGION.FOCUS": {
4448
+ actions: ["setLastFocusedEl", "pauseToasts"]
4449
+ },
4450
+ "REGION.POINTER_ENTER": {
4451
+ actions: ["pauseToasts"]
4452
+ }
4453
+ }
4454
+ },
4455
+ overlap: {
4456
+ on: {
4457
+ "REGION.STACK": {
4458
+ target: "stack",
4459
+ actions: ["expandToasts"]
4460
+ },
4461
+ "REGION.POINTER_ENTER": {
4462
+ target: "stack",
4463
+ actions: ["pauseToasts", "expandToasts"]
4464
+ },
4465
+ "REGION.FOCUS": {
4466
+ target: "stack",
4467
+ actions: ["setLastFocusedEl", "pauseToasts", "expandToasts"]
4468
+ }
4469
+ }
4470
+ }
4471
+ },
4472
+ implementations: {
4473
+ guards: {
4474
+ isOverlapping: ({ computed }) => computed("overlap")
4475
+ },
4476
+ effects: {
4477
+ subscribeToStore({ context: context2, prop }) {
4478
+ return prop("store").subscribe((toast2) => {
4479
+ if (toast2.dismiss) {
4480
+ context2.set("toasts", (prev) => prev.filter((t) => t.id !== toast2.id));
4481
+ return;
4482
+ }
4483
+ context2.set("toasts", (prev) => {
4484
+ const index2 = prev.findIndex((t) => t.id === toast2.id);
4485
+ if (index2 !== -1) {
4486
+ return [...prev.slice(0, index2), { ...prev[index2], ...toast2 }, ...prev.slice(index2 + 1)];
4487
+ }
4488
+ return [toast2, ...prev];
4489
+ });
4490
+ });
4491
+ },
4492
+ trackHotKeyPress({ prop, send }) {
4493
+ const handleKeyDown = (event) => {
4494
+ const { hotkey } = prop("store").attrs;
4495
+ const isHotkeyPressed = hotkey.every((key) => event[key] || event.code === key);
4496
+ if (!isHotkeyPressed) return;
4497
+ send({ type: "DOC.HOTKEY" });
4498
+ };
4499
+ return addDomEvent(document, "keydown", handleKeyDown, { capture: true });
4500
+ },
4501
+ trackDocumentVisibility({ prop, send, scope }) {
4502
+ const { pauseOnPageIdle } = prop("store").attrs;
4503
+ if (!pauseOnPageIdle) return;
4504
+ const doc = scope.getDoc();
4505
+ return addDomEvent(doc, "visibilitychange", () => {
4506
+ const isHidden = doc.visibilityState === "hidden";
4507
+ send({ type: isHidden ? "PAUSE_ALL" : "RESUME_ALL" });
4508
+ });
4509
+ }
4510
+ },
4511
+ actions: {
4512
+ setDismissableBranch({ refs, context: context2, computed, scope }) {
4513
+ var _a;
4514
+ const toasts = context2.get("toasts");
4515
+ const placement = computed("placement");
4516
+ const hasToasts = toasts.length > 0;
4517
+ if (!hasToasts) {
4518
+ (_a = refs.get("dismissableCleanup")) == null ? void 0 : _a();
4519
+ return;
4520
+ }
4521
+ if (hasToasts && refs.get("dismissableCleanup")) {
4522
+ return;
4523
+ }
4524
+ const groupEl = () => getRegionEl(scope, placement);
4525
+ const cleanup = trackDismissableBranch(groupEl, { defer: true });
4526
+ refs.set("dismissableCleanup", cleanup);
4527
+ },
4528
+ clearDismissableBranch({ refs }) {
4529
+ var _a;
4530
+ (_a = refs.get("dismissableCleanup")) == null ? void 0 : _a();
4531
+ },
4532
+ focusRegionEl({ scope, computed }) {
4533
+ queueMicrotask(() => {
4534
+ var _a;
4535
+ (_a = getRegionEl(scope, computed("placement"))) == null ? void 0 : _a.focus();
4536
+ });
4537
+ },
4538
+ pauseToasts({ prop }) {
4539
+ prop("store").pause();
4540
+ },
4541
+ resumeToasts({ prop }) {
4542
+ prop("store").resume();
4543
+ },
4544
+ expandToasts({ prop }) {
4545
+ prop("store").expand();
4546
+ },
4547
+ collapseToasts({ prop }) {
4548
+ prop("store").collapse();
4549
+ },
4550
+ removeToast({ prop, event }) {
4551
+ prop("store").remove(event.id);
4552
+ },
4553
+ removeHeight({ event, context: context2 }) {
4554
+ if ((event == null ? void 0 : event.id) == null) return;
4555
+ queueMicrotask(() => {
4556
+ context2.set("heights", (heights) => heights.filter((height) => height.id !== event.id));
4557
+ });
4558
+ },
4559
+ collapsedIfEmpty({ send, computed }) {
4560
+ if (!computed("overlap") || computed("count") > 1) return;
4561
+ send({ type: "REGION.OVERLAP" });
4562
+ },
4563
+ setLastFocusedEl({ refs, event }) {
4564
+ if (refs.get("isFocusWithin") || !event.target) return;
4565
+ refs.set("isFocusWithin", true);
4566
+ refs.set("lastFocusedEl", event.target);
4567
+ },
4568
+ restoreLastFocusedEl({ refs }) {
4569
+ var _a;
4570
+ if (!refs.get("lastFocusedEl")) return;
4571
+ (_a = refs.get("lastFocusedEl")) == null ? void 0 : _a.focus({ preventScroll: true });
4572
+ refs.set("lastFocusedEl", null);
4573
+ refs.set("isFocusWithin", false);
4574
+ },
4575
+ clearLastFocusedEl({ refs }) {
4576
+ var _a;
4577
+ if (!refs.get("lastFocusedEl")) return;
4578
+ (_a = refs.get("lastFocusedEl")) == null ? void 0 : _a.focus({ preventScroll: true });
4579
+ refs.set("lastFocusedEl", null);
4580
+ refs.set("isFocusWithin", false);
4581
+ }
4582
+ }
4583
+ }
4584
+ });
4585
+ function connect(service, normalize) {
4586
+ const { state, send, prop, scope, context: context2, computed } = service;
4587
+ const visible = state.hasTag("visible");
4588
+ const paused = state.hasTag("paused");
4589
+ const mounted = context2.get("mounted");
4590
+ const frontmost = computed("frontmost");
4591
+ const placement = prop("parent").computed("placement");
4592
+ const type = prop("type");
4593
+ const stacked = prop("stacked");
4594
+ const title = prop("title");
4595
+ const description = prop("description");
4596
+ const action = prop("action");
4597
+ const [side, align = "center"] = placement.split("-");
4598
+ return {
4599
+ type,
4600
+ title,
4601
+ description,
4602
+ placement,
4603
+ visible,
4604
+ paused,
4605
+ closable: !!prop("closable"),
4606
+ pause() {
4607
+ send({ type: "PAUSE" });
4608
+ },
4609
+ resume() {
4610
+ send({ type: "RESUME" });
4611
+ },
4612
+ dismiss() {
4613
+ send({ type: "DISMISS", src: "programmatic" });
4614
+ },
4615
+ getRootProps() {
4616
+ return normalize.element({
4617
+ ...parts.root.attrs,
4618
+ dir: prop("dir"),
4619
+ id: getRootId(scope),
4620
+ "data-state": visible ? "open" : "closed",
4621
+ "data-type": type,
4622
+ "data-placement": placement,
4623
+ "data-align": align,
4624
+ "data-side": side,
4625
+ "data-mounted": dataAttr(mounted),
4626
+ "data-paused": dataAttr(paused),
4627
+ "data-first": dataAttr(frontmost),
4628
+ "data-sibling": dataAttr(!frontmost),
4629
+ "data-stack": dataAttr(stacked),
4630
+ "data-overlap": dataAttr(!stacked),
4631
+ role: "status",
4632
+ "aria-atomic": "true",
4633
+ "aria-describedby": description ? getDescriptionId(scope) : void 0,
4634
+ "aria-labelledby": title ? getTitleId(scope) : void 0,
4635
+ tabIndex: 0,
4636
+ style: getPlacementStyle(service, visible),
4637
+ onKeyDown(event) {
4638
+ if (event.defaultPrevented) return;
4639
+ if (event.key == "Escape") {
4640
+ send({ type: "DISMISS", src: "keyboard" });
4641
+ event.preventDefault();
4642
+ }
4643
+ }
4644
+ });
4645
+ },
4646
+ /* Leave a ghost div to avoid setting hover to false when transitioning out */
4647
+ getGhostBeforeProps() {
4648
+ return normalize.element({
4649
+ "data-ghost": "before",
4650
+ style: getGhostBeforeStyle(service, visible)
4651
+ });
4652
+ },
4653
+ /* Needed to avoid setting hover to false when in between toasts */
4654
+ getGhostAfterProps() {
4655
+ return normalize.element({
4656
+ "data-ghost": "after",
4657
+ style: getGhostAfterStyle()
4658
+ });
4659
+ },
4660
+ getTitleProps() {
4661
+ return normalize.element({
4662
+ ...parts.title.attrs,
4663
+ id: getTitleId(scope)
4664
+ });
4665
+ },
4666
+ getDescriptionProps() {
4667
+ return normalize.element({
4668
+ ...parts.description.attrs,
4669
+ id: getDescriptionId(scope)
4670
+ });
4671
+ },
4672
+ getActionTriggerProps() {
4673
+ return normalize.button({
4674
+ ...parts.actionTrigger.attrs,
4675
+ type: "button",
4676
+ onClick(event) {
4677
+ var _a;
4678
+ if (event.defaultPrevented) return;
4679
+ (_a = action == null ? void 0 : action.onClick) == null ? void 0 : _a.call(action);
4680
+ send({ type: "DISMISS", src: "user" });
4681
+ }
4682
+ });
4683
+ },
4684
+ getCloseTriggerProps() {
4685
+ return normalize.button({
4686
+ id: getCloseTriggerId(scope),
4687
+ ...parts.closeTrigger.attrs,
4688
+ type: "button",
4689
+ "aria-label": "Dismiss notification",
4690
+ onClick(event) {
4691
+ if (event.defaultPrevented) return;
4692
+ send({ type: "DISMISS", src: "user" });
4693
+ }
4694
+ });
4695
+ }
4696
+ };
4697
+ }
4698
+ var { not } = createGuards();
4699
+ var machine = createMachine({
4700
+ props({ props }) {
4701
+ ensureProps(props, ["id", "type", "parent", "removeDelay"], "toast");
4702
+ return {
4703
+ closable: true,
4704
+ ...props,
4705
+ duration: getToastDuration(props.duration, props.type)
4706
+ };
4707
+ },
4708
+ initialState({ prop }) {
4709
+ const persist = prop("type") === "loading" || prop("duration") === Infinity;
4710
+ return persist ? "visible:persist" : "visible";
4711
+ },
4712
+ context({ prop, bindable }) {
4713
+ return {
4714
+ remainingTime: bindable(() => ({
4715
+ defaultValue: getToastDuration(prop("duration"), prop("type"))
4716
+ })),
4717
+ createdAt: bindable(() => ({
4718
+ defaultValue: Date.now()
4719
+ })),
4720
+ mounted: bindable(() => ({
4721
+ defaultValue: false
4722
+ })),
4723
+ initialHeight: bindable(() => ({
4724
+ defaultValue: 0
4725
+ }))
4726
+ };
4727
+ },
4728
+ refs() {
4729
+ return {
4730
+ closeTimerStartTime: Date.now(),
4731
+ lastCloseStartTimerStartTime: 0
4732
+ };
4733
+ },
4734
+ computed: {
4735
+ zIndex: ({ prop }) => {
4736
+ const toasts = prop("parent").context.get("toasts");
4737
+ const index2 = toasts.findIndex((toast2) => toast2.id === prop("id"));
4738
+ return toasts.length - index2;
4739
+ },
4740
+ height: ({ prop }) => {
4741
+ const heights = prop("parent").context.get("heights");
4742
+ const height = heights.find((height2) => height2.id === prop("id"));
4743
+ return (height == null ? void 0 : height.height) ?? 0;
4744
+ },
4745
+ heightIndex: ({ prop }) => {
4746
+ const heights = prop("parent").context.get("heights");
4747
+ return heights.findIndex((height) => height.id === prop("id"));
4748
+ },
4749
+ frontmost: ({ prop }) => prop("index") === 0,
4750
+ heightBefore: ({ prop }) => {
4751
+ const heights = prop("parent").context.get("heights");
4752
+ const heightIndex = heights.findIndex((height) => height.id === prop("id"));
4753
+ return heights.reduce((prev, curr, reducerIndex) => {
4754
+ if (reducerIndex >= heightIndex) return prev;
4755
+ return prev + curr.height;
4756
+ }, 0);
4757
+ },
4758
+ shouldPersist: ({ prop }) => prop("type") === "loading" || prop("duration") === Infinity
4759
+ },
4760
+ watch({ track, prop, send }) {
4761
+ track([() => prop("message")], () => {
4762
+ const message = prop("message");
4763
+ if (message) send({ type: message, src: "programmatic" });
4764
+ });
4765
+ track([() => prop("type"), () => prop("duration")], () => {
4766
+ send({ type: "UPDATE" });
4767
+ });
4768
+ },
4769
+ on: {
4770
+ UPDATE: [
4771
+ {
4772
+ guard: "shouldPersist",
4773
+ target: "visible:persist",
4774
+ actions: ["resetCloseTimer"]
4775
+ },
4776
+ {
4777
+ target: "visible:updating",
4778
+ actions: ["resetCloseTimer"]
4779
+ }
4780
+ ],
4781
+ MEASURE: {
4782
+ actions: ["measureHeight"]
4783
+ }
4784
+ },
4785
+ entry: ["setMounted", "measureHeight", "invokeOnVisible"],
4786
+ effects: ["trackHeight"],
4787
+ states: {
4788
+ "visible:updating": {
4789
+ tags: ["visible", "updating"],
4790
+ effects: ["waitForNextTick"],
4791
+ on: {
4792
+ SHOW: {
4793
+ target: "visible"
4794
+ }
4795
+ }
4796
+ },
4797
+ "visible:persist": {
4798
+ tags: ["visible", "paused"],
4799
+ on: {
4800
+ RESUME: {
4801
+ guard: not("isLoadingType"),
4802
+ target: "visible",
4803
+ actions: ["setCloseTimer"]
4804
+ },
4805
+ DISMISS: {
4806
+ target: "dismissing"
4807
+ }
4808
+ }
4809
+ },
4810
+ visible: {
4811
+ tags: ["visible"],
4812
+ effects: ["waitForDuration"],
4813
+ on: {
4814
+ DISMISS: {
4815
+ target: "dismissing"
4816
+ },
4817
+ PAUSE: {
4818
+ target: "visible:persist",
4819
+ actions: ["syncRemainingTime"]
4820
+ }
4821
+ }
4822
+ },
4823
+ dismissing: {
4824
+ entry: ["invokeOnDismiss"],
4825
+ effects: ["waitForRemoveDelay"],
4826
+ on: {
4827
+ REMOVE: {
4828
+ target: "unmounted",
4829
+ actions: ["notifyParentToRemove"]
4830
+ }
4831
+ }
4832
+ },
4833
+ unmounted: {
4834
+ entry: ["invokeOnUnmount"]
4835
+ }
4836
+ },
4837
+ implementations: {
4838
+ effects: {
4839
+ waitForRemoveDelay({ prop, send }) {
4840
+ return setRafTimeout(() => {
4841
+ send({ type: "REMOVE", src: "timer" });
4842
+ }, prop("removeDelay"));
4843
+ },
4844
+ waitForDuration({ send, context: context2, computed }) {
4845
+ if (computed("shouldPersist")) return;
4846
+ return setRafTimeout(() => {
4847
+ send({ type: "DISMISS", src: "timer" });
4848
+ }, context2.get("remainingTime"));
4849
+ },
4850
+ waitForNextTick({ send }) {
4851
+ return setRafTimeout(() => {
4852
+ send({ type: "SHOW", src: "timer" });
4853
+ }, 0);
4854
+ },
4855
+ trackHeight({ scope, prop }) {
4856
+ let cleanup;
4857
+ raf$2(() => {
4858
+ const rootEl = getRootEl(scope);
4859
+ if (!rootEl) return;
4860
+ const syncHeight = () => {
4861
+ const originalHeight = rootEl.style.height;
4862
+ rootEl.style.height = "auto";
4863
+ const height = rootEl.getBoundingClientRect().height;
4864
+ rootEl.style.height = originalHeight;
4865
+ const item = { id: prop("id"), height };
4866
+ setHeight(prop("parent"), item);
4867
+ };
4868
+ const win = scope.getWin();
4869
+ const observer = new win.MutationObserver(syncHeight);
4870
+ observer.observe(rootEl, {
4871
+ childList: true,
4872
+ subtree: true,
4873
+ characterData: true
4874
+ });
4875
+ cleanup = () => observer.disconnect();
4876
+ });
4877
+ return () => cleanup == null ? void 0 : cleanup();
4878
+ }
4879
+ },
4880
+ guards: {
4881
+ isLoadingType: ({ prop }) => prop("type") === "loading",
4882
+ shouldPersist: ({ computed }) => computed("shouldPersist")
4883
+ },
4884
+ actions: {
4885
+ setMounted({ context: context2 }) {
4886
+ raf$2(() => {
4887
+ context2.set("mounted", true);
4888
+ });
4889
+ },
4890
+ measureHeight({ scope, prop, context: context2 }) {
4891
+ queueMicrotask(() => {
4892
+ const rootEl = getRootEl(scope);
4893
+ if (!rootEl) return;
4894
+ const originalHeight = rootEl.style.height;
4895
+ rootEl.style.height = "auto";
4896
+ const height = rootEl.getBoundingClientRect().height;
4897
+ rootEl.style.height = originalHeight;
4898
+ context2.set("initialHeight", height);
4899
+ const item = { id: prop("id"), height };
4900
+ setHeight(prop("parent"), item);
4901
+ });
4902
+ },
4903
+ setCloseTimer({ refs }) {
4904
+ refs.set("closeTimerStartTime", Date.now());
4905
+ },
4906
+ resetCloseTimer({ context: context2, refs, prop }) {
4907
+ refs.set("closeTimerStartTime", Date.now());
4908
+ context2.set("remainingTime", getToastDuration(prop("duration"), prop("type")));
4909
+ },
4910
+ syncRemainingTime({ context: context2, refs }) {
4911
+ context2.set("remainingTime", (prev) => {
4912
+ const closeTimerStartTime = refs.get("closeTimerStartTime");
4913
+ const elapsedTime = Date.now() - closeTimerStartTime;
4914
+ refs.set("lastCloseStartTimerStartTime", Date.now());
4915
+ return prev - elapsedTime;
4916
+ });
4917
+ },
4918
+ notifyParentToRemove({ prop }) {
4919
+ const parent = prop("parent");
4920
+ parent.send({ type: "TOAST.REMOVE", id: prop("id") });
4921
+ },
4922
+ invokeOnDismiss({ prop, event }) {
4923
+ var _a;
4924
+ (_a = prop("onStatusChange")) == null ? void 0 : _a({ status: "dismissing", src: event.src });
4925
+ },
4926
+ invokeOnUnmount({ prop }) {
4927
+ var _a;
4928
+ (_a = prop("onStatusChange")) == null ? void 0 : _a({ status: "unmounted" });
4929
+ },
4930
+ invokeOnVisible({ prop }) {
4931
+ var _a;
4932
+ (_a = prop("onStatusChange")) == null ? void 0 : _a({ status: "visible" });
4933
+ }
4934
+ }
4935
+ }
4936
+ });
4937
+ function setHeight(parent, item) {
4938
+ const { id, height } = item;
4939
+ parent.context.set("heights", (prev) => {
4940
+ const alreadyExists = prev.find((i) => i.id === id);
4941
+ if (!alreadyExists) {
4942
+ return [{ id, height }, ...prev];
4943
+ } else {
4944
+ return prev.map((i) => i.id === id ? { ...i, height } : i);
4945
+ }
4946
+ });
4947
+ }
4948
+ var withDefaults = (options, defaults2) => {
4949
+ return { ...defaults2, ...options };
4950
+ };
4951
+ function createToastStore(props) {
4952
+ const attrs = withDefaults(props, {
4953
+ placement: "bottom",
4954
+ overlap: false,
4955
+ max: 24,
4956
+ gap: 16,
4957
+ offsets: "1rem",
4958
+ hotkey: ["altKey", "KeyT"],
4959
+ removeDelay: 200,
4960
+ pauseOnPageIdle: true
4961
+ });
4962
+ let subscribers = [];
4963
+ let toasts = [];
4964
+ let dismissedToasts = /* @__PURE__ */ new Set();
4965
+ const subscribe2 = (subscriber) => {
4966
+ subscribers.push(subscriber);
4967
+ return () => {
4968
+ const index2 = subscribers.indexOf(subscriber);
4969
+ subscribers.splice(index2, 1);
4970
+ };
4971
+ };
4972
+ const publish = (data) => {
4973
+ subscribers.forEach((subscriber) => subscriber(data));
4974
+ return data;
4975
+ };
4976
+ const addToast = (data) => {
4977
+ if (toasts.length >= attrs.max) return;
4978
+ publish(data);
4979
+ toasts.unshift(data);
4980
+ };
4981
+ const create = (data) => {
4982
+ const id = data.id ?? `toast:${uuid()}`;
4983
+ const exists = toasts.find((toast2) => toast2.id === id);
4984
+ if (dismissedToasts.has(id)) dismissedToasts.delete(id);
4985
+ if (exists) {
4986
+ toasts = toasts.map((toast2) => {
4987
+ if (toast2.id === id) {
4988
+ return publish({ ...toast2, ...data, id });
4989
+ }
4990
+ return toast2;
4991
+ });
4992
+ } else {
4993
+ addToast({
4994
+ id,
4995
+ duration: attrs.duration,
4996
+ removeDelay: attrs.removeDelay,
4997
+ type: "info",
4998
+ ...data,
4999
+ stacked: !attrs.overlap,
5000
+ gap: attrs.gap
5001
+ });
5002
+ }
5003
+ return id;
5004
+ };
5005
+ const remove = (id) => {
5006
+ dismissedToasts.add(id);
5007
+ if (!id) {
5008
+ toasts.forEach((toast2) => {
5009
+ subscribers.forEach((subscriber) => subscriber({ id: toast2.id, dismiss: true }));
5010
+ });
5011
+ toasts = [];
5012
+ } else {
5013
+ subscribers.forEach((subscriber) => subscriber({ id, dismiss: true }));
5014
+ toasts = toasts.filter((toast2) => toast2.id !== id);
5015
+ }
5016
+ return id;
5017
+ };
5018
+ const error = (data) => {
5019
+ return create({ ...data, type: "error" });
5020
+ };
5021
+ const success = (data) => {
5022
+ return create({ ...data, type: "success" });
5023
+ };
5024
+ const info = (data) => {
5025
+ return create({ ...data, type: "info" });
5026
+ };
5027
+ const warning = (data) => {
5028
+ return create({ ...data, type: "warning" });
5029
+ };
5030
+ const loading = (data) => {
5031
+ return create({ ...data, type: "loading" });
5032
+ };
5033
+ const getVisibleToasts = () => {
5034
+ return toasts.filter((toast2) => !dismissedToasts.has(toast2.id));
5035
+ };
5036
+ const getCount = () => {
5037
+ return toasts.length;
5038
+ };
5039
+ const promise = (promise2, options, shared = {}) => {
5040
+ if (!options) return;
5041
+ let id = void 0;
5042
+ if (options.loading !== void 0) {
5043
+ id = create({
5044
+ ...shared,
5045
+ ...options.loading,
5046
+ promise: promise2,
5047
+ type: "loading"
5048
+ });
5049
+ }
5050
+ let removable = id !== void 0;
5051
+ let result;
5052
+ const prom = runIfFn(promise2).then(async (response) => {
5053
+ result = ["resolve", response];
5054
+ if (isHttpResponse(response) && !response.ok) {
5055
+ removable = false;
5056
+ const errorOptions = runIfFn(options.error, `HTTP Error! status: ${response.status}`);
5057
+ create({ ...shared, ...errorOptions, id, type: "error" });
5058
+ } else if (options.success !== void 0) {
5059
+ removable = false;
5060
+ const successOptions = runIfFn(options.success, response);
5061
+ create({ ...shared, ...successOptions, id, type: "success" });
5062
+ }
5063
+ }).catch(async (error2) => {
5064
+ result = ["reject", error2];
5065
+ if (options.error !== void 0) {
5066
+ removable = false;
5067
+ const errorOptions = runIfFn(options.error, error2);
5068
+ create({ ...shared, ...errorOptions, id, type: "error" });
5069
+ }
5070
+ }).finally(() => {
5071
+ var _a;
5072
+ if (removable) {
5073
+ remove(id);
5074
+ id = void 0;
5075
+ }
5076
+ (_a = options.finally) == null ? void 0 : _a.call(options);
5077
+ });
5078
+ const unwrap = () => new Promise(
5079
+ (resolve, reject) => prom.then(() => result[0] === "reject" ? reject(result[1]) : resolve(result[1])).catch(reject)
5080
+ );
5081
+ return { id, unwrap };
5082
+ };
5083
+ const update2 = (id, data) => {
5084
+ return create({ id, ...data });
5085
+ };
5086
+ const pause = (id) => {
5087
+ if (id != null) {
5088
+ toasts = toasts.map((toast2) => {
5089
+ if (toast2.id === id) return publish({ ...toast2, message: "PAUSE" });
5090
+ return toast2;
5091
+ });
5092
+ } else {
5093
+ toasts = toasts.map((toast2) => publish({ ...toast2, message: "PAUSE" }));
5094
+ }
5095
+ };
5096
+ const resume = (id) => {
5097
+ if (id != null) {
5098
+ toasts = toasts.map((toast2) => {
5099
+ if (toast2.id === id) return publish({ ...toast2, message: "RESUME" });
5100
+ return toast2;
5101
+ });
5102
+ } else {
5103
+ toasts = toasts.map((toast2) => publish({ ...toast2, message: "RESUME" }));
5104
+ }
5105
+ };
5106
+ const dismiss = (id) => {
5107
+ if (id != null) {
5108
+ toasts = toasts.map((toast2) => {
5109
+ if (toast2.id === id) return publish({ ...toast2, message: "DISMISS" });
5110
+ return toast2;
5111
+ });
5112
+ } else {
5113
+ toasts = toasts.map((toast2) => publish({ ...toast2, message: "DISMISS" }));
5114
+ }
5115
+ };
5116
+ const isVisible = (id) => {
5117
+ return !dismissedToasts.has(id) && !!toasts.find((toast2) => toast2.id === id);
5118
+ };
5119
+ const isDismissed = (id) => {
5120
+ return dismissedToasts.has(id);
5121
+ };
5122
+ const expand = () => {
5123
+ toasts = toasts.map((toast2) => publish({ ...toast2, stacked: true }));
5124
+ };
5125
+ const collapse = () => {
5126
+ toasts = toasts.map((toast2) => publish({ ...toast2, stacked: false }));
5127
+ };
5128
+ return {
5129
+ attrs,
5130
+ subscribe: subscribe2,
5131
+ create,
5132
+ update: update2,
5133
+ remove,
5134
+ dismiss,
5135
+ error,
5136
+ success,
5137
+ info,
5138
+ warning,
5139
+ loading,
5140
+ getVisibleToasts,
5141
+ getCount,
5142
+ promise,
5143
+ pause,
5144
+ resume,
5145
+ isVisible,
5146
+ isDismissed,
5147
+ expand,
5148
+ collapse
5149
+ };
5150
+ }
5151
+ var isHttpResponse = (data) => {
5152
+ return data && typeof data === "object" && "ok" in data && typeof data.ok === "boolean" && "status" in data && typeof data.status === "number";
5153
+ };
5154
+ var group = {
5155
+ connect: groupConnect,
5156
+ machine: groupMachine
5157
+ };
5158
+ const createToaster = (props) => {
5159
+ return createToastStore(props);
5160
+ };
5161
+ const [ToastProvider$1, useToastContext] = createContext({
5162
+ name: "ToastContext",
5163
+ hookName: "useToastContext",
5164
+ providerName: "<ToastProvider />"
5165
+ });
5166
+ const ToastActionTrigger = forwardRef((props, ref) => {
5167
+ const toast2 = useToastContext();
5168
+ const mergedProps = mergeProps(toast2.getActionTriggerProps(), props);
5169
+ return /* @__PURE__ */ jsx(ark.button, { ...mergedProps, ref });
5170
+ });
5171
+ ToastActionTrigger.displayName = "ToastActionTrigger";
5172
+ const ToastDescription = forwardRef((props, ref) => {
5173
+ const toast2 = useToastContext();
5174
+ const mergedProps = mergeProps(toast2.getDescriptionProps(), props);
5175
+ return /* @__PURE__ */ jsx(ark.div, { ...mergedProps, ref });
5176
+ });
5177
+ ToastDescription.displayName = "ToastDescription";
5178
+ const ToastRoot = forwardRef((props, ref) => {
5179
+ const toast2 = useToastContext();
5180
+ const mergedProps = mergeProps(toast2.getRootProps(), props);
5181
+ return /* @__PURE__ */ jsxs("div", { ...mergedProps, ref, children: [
5182
+ /* @__PURE__ */ jsx("div", { ...toast2.getGhostBeforeProps() }),
5183
+ props.children,
5184
+ /* @__PURE__ */ jsx("div", { ...toast2.getGhostAfterProps() })
5185
+ ] });
5186
+ });
5187
+ ToastRoot.displayName = "ToastRoot";
5188
+ const Toaster = forwardRef((props, ref) => {
5189
+ const { toaster, children, ...localProps } = props;
5190
+ const locale = useLocaleContext();
5191
+ const env = useEnvironmentContext();
5192
+ const service = useMachine(group.machine, {
5193
+ store: toaster,
5194
+ id: useId(),
5195
+ dir: locale == null ? void 0 : locale.dir,
5196
+ getRootNode: () => env == null ? void 0 : env.getDocument()
5197
+ });
5198
+ const api = group.connect(service, normalizeProps);
5199
+ const mergedProps = mergeProps(api.getGroupProps(), localProps);
5200
+ return /* @__PURE__ */ jsx(ark.div, { ...mergedProps, ref, children: api.getToasts().map((toast2, index2) => /* @__PURE__ */ jsx(ToastActor, { value: toast2, parent: service, index: index2, children: (ctx2) => children(ctx2) }, toast2.id)) });
5201
+ });
5202
+ Toaster.displayName = "Toaster";
5203
+ const ToastActor = (props) => {
5204
+ const localProps = {
5205
+ ...props.value,
5206
+ parent: props.parent,
5207
+ index: props.index
5208
+ };
5209
+ const service = useMachine(machine, { ...localProps });
5210
+ const api = connect(service, normalizeProps);
5211
+ return /* @__PURE__ */ jsx(ToastProvider$1, { value: api, children: props.children(props.value) });
5212
+ };
5213
+ ToastActor.displayName = "ToastActor";
4077
5214
  const spinnerRecipe = cva({
4078
5215
  base: {
4079
5216
  display: "inline-block",
@@ -4690,7 +5827,7 @@ const createStyleContext = (recipe) => {
4690
5827
  };
4691
5828
  return StyledComponent;
4692
5829
  };
4693
- const withProvider = (Component, slot, options) => {
5830
+ const withProvider2 = (Component, slot, options) => {
4694
5831
  const StyledComponent = styled(
4695
5832
  Component,
4696
5833
  {},
@@ -4717,13 +5854,13 @@ const createStyleContext = (recipe) => {
4717
5854
  };
4718
5855
  return {
4719
5856
  withRootProvider: withRootProvider2,
4720
- withProvider,
5857
+ withProvider: withProvider2,
4721
5858
  withContext: withContext2
4722
5859
  };
4723
5860
  };
4724
5861
  const dialogRecipe = sva({
4725
5862
  className: "dialog",
4726
- slots: [...anatomy$1.keys(), "header", "footer", "body"],
5863
+ slots: [...anatomy$2.keys(), "header", "footer", "body"],
4727
5864
  base: {
4728
5865
  backdrop: {
4729
5866
  backdropFilter: "blur(3px)",
@@ -4805,16 +5942,16 @@ const dialogRecipe = sva({
4805
5942
  }
4806
5943
  }
4807
5944
  });
4808
- const { withRootProvider: withRootProvider$1, withContext: withContext$1 } = createStyleContext(dialogRecipe);
4809
- const Root$1 = withRootProvider$1(DialogRoot);
4810
- const Backdrop$1 = withContext$1(DialogBackdrop, "backdrop");
4811
- const Trigger$1 = withContext$1(DialogTrigger, "trigger");
4812
- const Content = withContext$1(DialogContent, "content");
4813
- const Title = withContext$1(DialogTitle, "title");
4814
- const Description = withContext$1(DialogDescription, "description");
4815
- const Positioner = withContext$1(DialogPositioner, "positioner");
4816
- const Header = withContext$1(ark.header, "header");
4817
- const Footer = withContext$1(
5945
+ const { withRootProvider: withRootProvider$1, withContext: withContext$2 } = createStyleContext(dialogRecipe);
5946
+ const Root$2 = withRootProvider$1(DialogRoot);
5947
+ const Backdrop$1 = withContext$2(DialogBackdrop, "backdrop");
5948
+ const Trigger$1 = withContext$2(DialogTrigger, "trigger");
5949
+ const Content$1 = withContext$2(DialogContent, "content");
5950
+ const Title = withContext$2(DialogTitle, "title");
5951
+ const Description$1 = withContext$2(DialogDescription, "description");
5952
+ const Positioner = withContext$2(DialogPositioner, "positioner");
5953
+ const Header = withContext$2(ark.header, "header");
5954
+ const Footer = withContext$2(
4818
5955
  ({ orientation = "horizontal", className, ...props }) => {
4819
5956
  return /* @__PURE__ */ jsx(
4820
5957
  ark.footer,
@@ -4832,15 +5969,15 @@ const Footer = withContext$1(
4832
5969
  },
4833
5970
  "footer"
4834
5971
  );
4835
- const Body = withContext$1(ark.main, "body");
4836
- const CloseTrigger = withContext$1(DialogCloseTrigger, "closeTrigger");
5972
+ const Body = withContext$2(ark.main, "body");
5973
+ const CloseTrigger = withContext$2(DialogCloseTrigger, "closeTrigger");
4837
5974
  const Dialog = {
4838
- Root: Root$1,
5975
+ Root: Root$2,
4839
5976
  Backdrop: Backdrop$1,
4840
5977
  Trigger: Trigger$1,
4841
- Content,
5978
+ Content: Content$1,
4842
5979
  Title,
4843
- Description,
5980
+ Description: Description$1,
4844
5981
  Positioner,
4845
5982
  Header,
4846
5983
  Footer,
@@ -8403,7 +9540,8 @@ const useBottomSheet = (props) => {
8403
9540
  initTransformValue: 0,
8404
9541
  canDragRef: true,
8405
9542
  maxTransformValue: 0,
8406
- initialOpenHeightPx: 0
9543
+ initialOpenHeightPx: 0,
9544
+ isBottomSheetOpen: false
8407
9545
  });
8408
9546
  const [springs, api] = useSpring(() => ({
8409
9547
  transform: "translateY(0px)",
@@ -8411,22 +9549,25 @@ const useBottomSheet = (props) => {
8411
9549
  }));
8412
9550
  const snapToMax = () => {
8413
9551
  const { maxTransformValue } = metrics.current;
9552
+ console.log("maxTransformValue", maxTransformValue);
8414
9553
  api.start({
8415
9554
  transform: `translateY(${maxTransformValue}px)`,
8416
9555
  config: SPRING_CONFIG.up
8417
9556
  });
8418
- if (onOpen) onOpen();
9557
+ if (onOpen && !metrics.current.isBottomSheetOpen) onOpen();
9558
+ metrics.current.isBottomSheetOpen = true;
8419
9559
  };
8420
9560
  const snapToMin = () => {
8421
9561
  api.start({
8422
9562
  transform: "translateY(0px)",
8423
9563
  config: SPRING_CONFIG.down
8424
9564
  });
8425
- if (onClose) onClose();
9565
+ if (onClose && metrics.current.isBottomSheetOpen) onClose();
9566
+ metrics.current.isBottomSheetOpen = false;
8426
9567
  };
8427
9568
  const handleContentTouch = (e) => {
8428
9569
  const target = e.target;
8429
- if (!target.matches(INTERACTIVE_ELEMENTS) && expendOnContentDrag) {
9570
+ if (!target.matches(INTERACTIVE_ELEMENTS) && expendOnContentDrag || !metrics.current.isBottomSheetOpen) {
8430
9571
  metrics.current.canDragRef = true;
8431
9572
  } else {
8432
9573
  metrics.current.canDragRef = false;
@@ -8442,9 +9583,7 @@ const useBottomSheet = (props) => {
8442
9583
  return;
8443
9584
  }
8444
9585
  const currentTransform = springs.transform.get();
8445
- const initTransformValue = Number(
8446
- currentTransform.replace("translateY(", "").replace("px)", "") || 0
8447
- );
9586
+ const initTransformValue = Number(currentTransform.replace("translateY(", "").replace("px)", "") || 0);
8448
9587
  metrics.current.initTransformValue = initTransformValue;
8449
9588
  metrics.current.initTouchPosition = clientY;
8450
9589
  };
@@ -8470,9 +9609,7 @@ const useBottomSheet = (props) => {
8470
9609
  return;
8471
9610
  }
8472
9611
  const currentTransform = springs.transform.get();
8473
- const finalTransformValue = Number(
8474
- currentTransform.replace("translateY(", "").replace("px)", "") || 0
8475
- );
9612
+ const finalTransformValue = Number(currentTransform.replace("translateY(", "").replace("px)", "") || 0);
8476
9613
  const transformedDistance = initTransformValue - finalTransformValue;
8477
9614
  if (transformedDistance < 0 && SNAP_TO_MIN_THRESHOLD < Math.abs(transformedDistance)) {
8478
9615
  snapToMin();
@@ -8499,21 +9636,55 @@ const useBottomSheet = (props) => {
8499
9636
  up: handleEnd,
8500
9637
  leave: handleEnd
8501
9638
  };
9639
+ const preventScrollOnBackdrop = (e) => {
9640
+ if (bottomSheetRef.current && (bottomSheetRef.current.contains(e.target) || // 최소 높이로 떠 있는 바텀시트의 핸들 영역을 클릭하는 경우 특별 처리
9641
+ e instanceof TouchEvent && isBottomSheetHandleArea(e.touches[0].clientY))) {
9642
+ return;
9643
+ }
9644
+ e.preventDefault();
9645
+ e.stopPropagation();
9646
+ };
9647
+ const isBottomSheetHandleArea = (clientY) => {
9648
+ if (!bottomSheetRef.current) return false;
9649
+ const { initialOpenHeightPx } = metrics.current;
9650
+ const bottomSheetTop = window.innerHeight - initialOpenHeightPx;
9651
+ const handleAreaTop = bottomSheetTop;
9652
+ const handleAreaBottom = bottomSheetTop + BOTTOM_SHEET_HANDLE_HEIGHT;
9653
+ return clientY >= handleAreaTop && clientY <= handleAreaBottom;
9654
+ };
9655
+ const handleTouchStart = (e) => {
9656
+ const clientY = e.touches[0].clientY;
9657
+ if (isBottomSheetHandleArea(clientY)) {
9658
+ e.preventDefault();
9659
+ e.stopPropagation();
9660
+ handleTouch.start(e);
9661
+ }
9662
+ };
8502
9663
  useEffect(() => {
8503
9664
  if (isOpen) snapToMax();
8504
9665
  else snapToMin();
8505
- const handleTouchMove = (e) => {
8506
- if (bottomSheetRef.current && !bottomSheetRef.current.contains(e.target)) {
8507
- e.preventDefault();
8508
- }
8509
- };
8510
9666
  if (isOpen) {
8511
- document.addEventListener("touchmove", handleTouchMove, { passive: false });
9667
+ document.addEventListener("touchmove", preventScrollOnBackdrop, { passive: false });
9668
+ document.addEventListener("wheel", preventScrollOnBackdrop, { passive: false });
9669
+ document.addEventListener("mousewheel", preventScrollOnBackdrop, { passive: false });
9670
+ document.addEventListener("touchstart", handleTouchStart, { passive: false });
9671
+ document.body.style.overflow = "hidden";
9672
+ document.body.style.touchAction = "none";
8512
9673
  } else {
8513
- document.removeEventListener("touchmove", handleTouchMove);
9674
+ document.removeEventListener("touchmove", preventScrollOnBackdrop);
9675
+ document.removeEventListener("wheel", preventScrollOnBackdrop);
9676
+ document.removeEventListener("mousewheel", preventScrollOnBackdrop);
9677
+ document.removeEventListener("touchstart", handleTouchStart);
9678
+ document.body.style.overflow = "";
9679
+ document.body.style.touchAction = "";
8514
9680
  }
8515
9681
  return () => {
8516
- document.removeEventListener("touchmove", handleTouchMove);
9682
+ document.removeEventListener("touchmove", preventScrollOnBackdrop);
9683
+ document.removeEventListener("wheel", preventScrollOnBackdrop);
9684
+ document.removeEventListener("mousewheel", preventScrollOnBackdrop);
9685
+ document.removeEventListener("touchstart", handleTouchStart);
9686
+ document.body.style.overflow = "";
9687
+ document.body.style.touchAction = "";
8517
9688
  };
8518
9689
  }, [isOpen]);
8519
9690
  useEffect(() => {
@@ -8521,7 +9692,7 @@ const useBottomSheet = (props) => {
8521
9692
  const contentElement = contentRef.current;
8522
9693
  metrics.current.initialOpenHeightPx = window.innerHeight * (snapPercent.min > 1 ? 1 : snapPercent.min);
8523
9694
  if (snapPercent.max === "INNER_HEIGHT" && contentElement) {
8524
- metrics.current.maxTransformValue = (contentElement.clientHeight - BOTTOM_SHEET_HANDLE_HEIGHT) * -1;
9695
+ metrics.current.maxTransformValue = (contentElement.clientHeight + BOTTOM_SHEET_HANDLE_HEIGHT) * -1;
8525
9696
  } else if (typeof snapPercent.max === "number") {
8526
9697
  metrics.current.maxTransformValue = (window.innerHeight - metrics.current.initialOpenHeightPx) * (snapPercent.max > 1 ? 1 : snapPercent.max) * -1;
8527
9698
  }
@@ -8684,7 +9855,7 @@ BottomSheetFrame.displayName = "BottomSheetFrame";
8684
9855
  Backdrop.displayName = "Backdrop";
8685
9856
  const navigationRecipe = sva({
8686
9857
  className: "navigation",
8687
- slots: anatomy.keys(),
9858
+ slots: anatomy$1.keys(),
8688
9859
  base: {
8689
9860
  root: {
8690
9861
  bg: "surface.layer_1",
@@ -8725,18 +9896,18 @@ const navigationRecipe = sva({
8725
9896
  }
8726
9897
  }
8727
9898
  });
8728
- const { withRootProvider, withContext } = createStyleContext(navigationRecipe);
8729
- const Root = withRootProvider(TabsRoot);
8730
- const Trigger = withContext(
9899
+ const { withRootProvider, withContext: withContext$1 } = createStyleContext(navigationRecipe);
9900
+ const Root$1 = withRootProvider(TabsRoot);
9901
+ const Trigger = withContext$1(
8731
9902
  ({ icon, label, ...props }) => /* @__PURE__ */ jsxs(TabTrigger, { ...props, children: [
8732
9903
  icon,
8733
9904
  label
8734
9905
  ] }),
8735
9906
  "trigger"
8736
9907
  );
8737
- const List = withContext(TabList, "list");
9908
+ const List = withContext$1(TabList, "list");
8738
9909
  const Navigation = {
8739
- Root,
9910
+ Root: Root$1,
8740
9911
  Item: Trigger,
8741
9912
  List
8742
9913
  };
@@ -9547,6 +10718,261 @@ const preset = definePreset({
9547
10718
  }
9548
10719
  }
9549
10720
  });
10721
+ const toastRecipe = sva({
10722
+ className: "toast",
10723
+ slots: [...anatomy.keys(), "content", "icon"],
10724
+ base: {
10725
+ root: {
10726
+ display: "flex",
10727
+ alignItems: "center",
10728
+ justifyContent: "center",
10729
+ backgroundColor: "background.neutralInverse.default",
10730
+ borderRadius: 16,
10731
+ height: "fit-content",
10732
+ minHeight: "48px",
10733
+ width: "fit-content",
10734
+ maxWidth: "328px",
10735
+ overflowWrap: "anywhere",
10736
+ zIndex: "overlay",
10737
+ fontStyle: "body.md",
10738
+ color: "content.neutralInverse.bold",
10739
+ pr: 4,
10740
+ pl: 3,
10741
+ py: 2,
10742
+ boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
10743
+ animation: "fadeIn 0.25s ease-out",
10744
+ transform: "translateY(20px)",
10745
+ shadow: "overlay",
10746
+ transition: "transform 0.25s ease-out",
10747
+ '&[data-state="open"]': {
10748
+ animation: "slide-in 0.4s cubic-bezier(0.05, 0.7, 0.1, 1.0)",
10749
+ transform: "translateY(0px)"
10750
+ },
10751
+ '&[data-state="closed"]': {
10752
+ animation: "slide-out 0.2s cubic-bezier(0.3, 0.0, 0.8, 0.15)",
10753
+ transform: "translateY(64px)"
10754
+ }
10755
+ },
10756
+ content: {
10757
+ display: "inline-flex",
10758
+ alignItems: "center"
10759
+ },
10760
+ description: {
10761
+ textStyle: "body.md",
10762
+ marginLeft: 2
10763
+ },
10764
+ actionTrigger: {
10765
+ height: "100%",
10766
+ width: "fit-content",
10767
+ display: "flex",
10768
+ alignItems: "center",
10769
+ justifyContent: "center",
10770
+ textStyle: "title.sm",
10771
+ cursor: "pointer",
10772
+ px: 4,
10773
+ pr: 1,
10774
+ whiteSpace: "nowrap",
10775
+ transition: "opacity 0.2s ease",
10776
+ color: "content.neutralInverse.bold",
10777
+ "&:hover": {
10778
+ opacity: 0.8
10779
+ }
10780
+ },
10781
+ icon: {
10782
+ width: 6,
10783
+ height: 6,
10784
+ minWidth: 6,
10785
+ minHeight: 6,
10786
+ display: "flex",
10787
+ alignItems: "center",
10788
+ justifyContent: "center"
10789
+ }
10790
+ },
10791
+ variants: {
10792
+ width: {
10793
+ full: {
10794
+ root: {
10795
+ width: "100%",
10796
+ justifyContent: "space-between"
10797
+ }
10798
+ },
10799
+ fit: {
10800
+ root: {
10801
+ width: "fit-content"
10802
+ }
10803
+ }
10804
+ },
10805
+ asLink: {
10806
+ true: {
10807
+ actionTrigger: {
10808
+ textDecoration: "underline",
10809
+ cursor: "pointer"
10810
+ }
10811
+ }
10812
+ }
10813
+ }
10814
+ });
10815
+ const { withProvider, withContext } = createStyleContext(toastRecipe);
10816
+ const OriginalRoot = withProvider(ToastRoot, "root");
10817
+ const Root = React__default.forwardRef((props, ref) => {
10818
+ const { children, width, ...rest } = props;
10819
+ const hasActionTrigger = React__default.Children.toArray(children).some((child) => {
10820
+ if (React__default.isValidElement(child)) {
10821
+ if (child.type === ActionTrigger) {
10822
+ return true;
10823
+ }
10824
+ if (child.type === React__default.Fragment && child.props.children) {
10825
+ return React__default.Children.toArray(child.props.children).some(
10826
+ (fragmentChild) => React__default.isValidElement(fragmentChild) && fragmentChild.type === ActionTrigger
10827
+ );
10828
+ }
10829
+ }
10830
+ return false;
10831
+ });
10832
+ const widthValue = width !== void 0 ? width : hasActionTrigger ? "full" : "fit";
10833
+ return /* @__PURE__ */ jsx(OriginalRoot, { ref, width: widthValue, ...rest, children });
10834
+ });
10835
+ Root.displayName = "Toast.Root";
10836
+ const OriginalActionTrigger = withContext(
10837
+ ToastActionTrigger,
10838
+ "actionTrigger"
10839
+ );
10840
+ const OriginalActionTriggerAsLink = withContext(ark.a, "actionTrigger");
10841
+ const ActionTrigger = React__default.forwardRef((props, ref) => {
10842
+ const { asLink, ...rest } = props;
10843
+ return asLink ? /* @__PURE__ */ jsx(OriginalActionTriggerAsLink, { ref, ...rest }) : /* @__PURE__ */ jsx(OriginalActionTrigger, { ref, ...rest });
10844
+ });
10845
+ ActionTrigger.displayName = "Toast.ActionTrigger";
10846
+ const Description = withContext(
10847
+ ToastDescription,
10848
+ "description"
10849
+ );
10850
+ const Content = withContext(ark.div, "content");
10851
+ const Icon = withContext(ark.div, "icon");
10852
+ const Toast = {
10853
+ Root,
10854
+ ActionTrigger,
10855
+ Content,
10856
+ Description,
10857
+ Icon
10858
+ };
10859
+ const toast = {
10860
+ queue: [],
10861
+ // ToastProvider에서 호출
10862
+ _getQueue: () => {
10863
+ const queue = [...toast.queue];
10864
+ toast.queue = [];
10865
+ return queue;
10866
+ },
10867
+ // render toast
10868
+ show: (message, options) => {
10869
+ const toastData = {
10870
+ description: message,
10871
+ action: (options == null ? void 0 : options.actionLabel) ? {
10872
+ label: options.actionLabel,
10873
+ onClick: options.onActionClick
10874
+ } : void 0,
10875
+ icon: options == null ? void 0 : options.icon,
10876
+ asLink: options == null ? void 0 : options.asLink,
10877
+ duration: options == null ? void 0 : options.duration
10878
+ };
10879
+ toast.queue.push(toastData);
10880
+ if (typeof window !== "undefined") {
10881
+ window.dispatchEvent(new CustomEvent("toast-queue-updated"));
10882
+ }
10883
+ },
10884
+ success: (message, options) => {
10885
+ toast.show(message, { ...options });
10886
+ },
10887
+ error: (message, options) => {
10888
+ toast.show(message, { ...options });
10889
+ },
10890
+ warning: (message, options) => {
10891
+ toast.show(message, { ...options });
10892
+ },
10893
+ info: (message, options) => {
10894
+ toast.show(message, { ...options });
10895
+ }
10896
+ };
10897
+ const DURATION = {
10898
+ DEFAULT: 2500,
10899
+ HAS_ACTION: 5500
10900
+ };
10901
+ const ToastProvider = ({ children }) => {
10902
+ const toaster = createToaster({
10903
+ placement: "bottom",
10904
+ duration: DURATION.DEFAULT,
10905
+ offsets: {
10906
+ bottom: "55px",
10907
+ top: "0px",
10908
+ left: "0px",
10909
+ right: "0px"
10910
+ },
10911
+ overlap: true
10912
+ });
10913
+ useEffect(() => {
10914
+ let currentZIndexCounter = 1300;
10915
+ const showToasts = () => {
10916
+ const queuedToasts = toast._getQueue();
10917
+ queuedToasts.forEach((toastData) => {
10918
+ try {
10919
+ const options = {
10920
+ description: toastData.description,
10921
+ zIndex: currentZIndexCounter++
10922
+ // 증가된 zIndex 값 사용
10923
+ };
10924
+ options.data = {
10925
+ icon: toastData.icon ? toastData.icon : null,
10926
+ asLink: toastData.asLink,
10927
+ zIndex: options.zIndex
10928
+ // zIndex를 data에도 저장
10929
+ };
10930
+ if (toastData.action) {
10931
+ options.action = {
10932
+ label: toastData.action.label,
10933
+ onClick: toastData.action.onClick ?? (() => {
10934
+ }),
10935
+ duration: DURATION.HAS_ACTION
10936
+ };
10937
+ }
10938
+ if (toastData.duration) {
10939
+ options.duration = toastData.duration;
10940
+ }
10941
+ toaster.create(options);
10942
+ } catch (error) {
10943
+ console.error("Error creating toast:", error);
10944
+ }
10945
+ });
10946
+ };
10947
+ showToasts();
10948
+ const handleToastQueue = () => showToasts();
10949
+ window.addEventListener("toast-queue-updated", handleToastQueue);
10950
+ return () => {
10951
+ window.removeEventListener("toast-queue-updated", handleToastQueue);
10952
+ };
10953
+ }, [toaster]);
10954
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
10955
+ children,
10956
+ /* @__PURE__ */ jsx(Toaster, { toaster, children: (toast2) => {
10957
+ var _a, _b, _c, _d, _e;
10958
+ return /* @__PURE__ */ jsxs(
10959
+ Toast.Root,
10960
+ {
10961
+ asLink: (_a = toast2.data) == null ? void 0 : _a.asLink,
10962
+ style: { zIndex: ((_b = toast2.data) == null ? void 0 : _b.zIndex) || 1e3 },
10963
+ children: [
10964
+ /* @__PURE__ */ jsxs(Toast.Content, { children: [
10965
+ ((_c = toast2.data) == null ? void 0 : _c.icon) && /* @__PURE__ */ jsx(Toast.Icon, { children: toast2.data.icon }),
10966
+ toast2.description && /* @__PURE__ */ jsx(Toast.Description, { children: toast2.description })
10967
+ ] }),
10968
+ toast2.action && /* @__PURE__ */ jsx(Toast.ActionTrigger, { onClick: (_d = toast2.action) == null ? void 0 : _d.onClick, children: (_e = toast2.action) == null ? void 0 : _e.label })
10969
+ ]
10970
+ },
10971
+ toast2.id
10972
+ );
10973
+ } })
10974
+ ] });
10975
+ };
9550
10976
  export {
9551
10977
  BottomSheet,
9552
10978
  Box2 as Box,
@@ -9566,7 +10992,9 @@ export {
9566
10992
  Tag,
9567
10993
  Text,
9568
10994
  Textarea as TextArea,
10995
+ ToastProvider,
9569
10996
  VStack2 as VStack,
9570
- preset
10997
+ preset,
10998
+ toast
9571
10999
  };
9572
11000
  //# sourceMappingURL=index.js.map