motile-ui 1.1.1 → 1.1.3

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.
@@ -1 +1 @@
1
- .motile-btn{width:fit-content;border:none;border-radius:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none;display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;min-height:fit-content}.motile-btn:active:not(.motile-btn--disabled){filter:brightness(.95);box-shadow:0 2px 4px #0000001a}.motile-btn--primary{background:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );color:#fff;box-shadow:0 1px 2px #0000000d}@media (hover: hover){.motile-btn--primary:hover:not(.motile-btn--disabled){filter:brightness(.9);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--primary:hover:not(.motile-btn--disabled){filter:brightness(.9);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--secondary{background:#fff;color:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );border:1px solid var(--motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)));box-shadow:none}@media (hover: hover){.motile-btn--secondary:hover:not(.motile-btn--disabled){background:color-mix(in srgb,var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) ) 10%,transparent);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--secondary:hover:not(.motile-btn--disabled){background:color-mix(in srgb,var(--motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6))) 10%,transparent);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--ghost{background:transparent;border:none;color:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );box-shadow:none}@media (hover: hover){.motile-btn--ghost:hover:not(.motile-btn--disabled){box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--ghost:hover:not(.motile-btn--disabled){box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--large{padding:0 24px;font-size:16px;height:56px;min-height:56px;line-height:1.4}.motile-btn--medium{padding:0 20px;font-size:15px;height:48px;min-height:48px;min-width:80px;line-height:1.4}.motile-btn--small{padding:0 16px;font-size:14px;height:40px;min-height:40px;min-width:64px;line-height:1.4}.motile-btn--primary.motile-btn--disabled{opacity:.5;filter:saturate(.9);cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--secondary.motile-btn--disabled{background:#e5e7eb;color:#6b7280;border:none;cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--ghost.motile-btn--disabled{background:#e5e7eb;color:#6b7280;cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--full-width{width:100%}.motile-btn svg{flex-shrink:0;margin-right:8px}.motile-btn svg:last-child{margin-right:0;margin-left:8px}.motile-btn svg:only-child{margin:0}@media (max-width: 1024px){.motile-btn--large{padding:0 20px;font-size:15px;height:52px;min-height:52px}}@media (max-width: 768px){.motile-btn--large{padding:0 18px;font-size:14px;height:48px;min-height:48px}.motile-btn:active:not(.motile-btn--disabled){filter:brightness(.92)}}@supports (-webkit-touch-callout: none){.motile-btn{-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}}.motile-btn__wrapper{display:grid;grid-template-areas:"content";place-items:center;width:100%;height:100%}.motile-btn__content{grid-area:content;display:inline-flex;align-items:center;justify-content:center}.motile-btn__loading{grid-area:content;display:flex;align-items:center;justify-content:center}.motile-btn__dots{display:flex;gap:8px;align-items:center;height:1em}.motile-btn--large .motile-btn__dot{width:8px;height:8px}.motile-btn--medium .motile-btn__dot{width:6px;height:6px}.motile-btn--small .motile-btn__dot{width:5px;height:5px}.motile-btn__dot{border-radius:50%;background-color:#ffffffb3;animation:motile-btn-loading-bounce 1.4s ease-in-out infinite both}.motile-btn__dot:nth-child(1){animation-delay:-.32s}.motile-btn__dot:nth-child(2){animation-delay:-.16s}.motile-btn__dot:nth-child(3){animation-delay:0s}.motile-btn--primary .motile-btn__dot{background-color:#ffffffb3}.motile-btn--secondary .motile-btn__dot,.motile-btn--ghost .motile-btn__dot{background-color:#9ca3afb3}@keyframes motile-btn-loading-bounce{0%,80%,to{transform:scale(1);opacity:.4}40%{transform:scale(1.2);opacity:1}}
1
+ .motile-btn{width:fit-content;border:none;border-radius:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none;display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;min-height:fit-content}.motile-btn:active:not(.motile-btn--disabled){filter:brightness(.95);box-shadow:0 2px 4px #0000001a}.motile-btn--primary{background:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );color:#fff;box-shadow:0 1px 2px #0000000d}@media (hover: hover){.motile-btn--primary:hover:not(.motile-btn--disabled){filter:brightness(.9);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--primary:hover:not(.motile-btn--disabled){filter:brightness(.9);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--secondary{background:#fff;color:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );border:1px solid var(--motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)));box-shadow:none}@media (hover: hover){.motile-btn--secondary:hover:not(.motile-btn--disabled){background:color-mix(in srgb,var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) ) 10%,transparent);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--secondary:hover:not(.motile-btn--disabled){background:color-mix(in srgb,var(--motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6))) 10%,transparent);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--ghost{background:transparent;border:none;color:var( --motile-btn-color, var(--motile-ui-btn, var(--motile-theme, #3b82f6)) );box-shadow:none}@media (hover: hover){.motile-btn--ghost:hover:not(.motile-btn--disabled){box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}}.motile-btn--hover-on-touch.motile-btn--ghost:hover:not(.motile-btn--disabled){box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.motile-btn--large{padding:0 24px;font-size:16px;height:56px;min-height:56px;line-height:1.4}.motile-btn--medium{padding:0 20px;font-size:15px;height:48px;min-height:48px;min-width:80px;line-height:1.4}.motile-btn--small{padding:0 16px;font-size:14px;height:40px;min-height:40px;min-width:64px;line-height:1.4}.motile-btn--primary.motile-btn--disabled{opacity:.5;filter:saturate(.9);cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--secondary.motile-btn--disabled{background:#e5e7eb;color:#6b7280;border:none;cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--ghost.motile-btn--disabled{background:#e5e7eb;color:#6b7280;cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}.motile-btn--full-width{width:100%}.motile-btn svg{flex-shrink:0;margin-right:8px}.motile-btn svg:last-child{margin-right:0;margin-left:8px}.motile-btn svg:only-child{margin:0}@media (max-width: 1024px){.motile-btn--large{padding:0 20px;font-size:15px;height:54px;min-height:54px}}@media (max-width: 768px){.motile-btn--large{padding:0 18px;font-size:15px;height:52px;min-height:52px}.motile-btn:active:not(.motile-btn--disabled){filter:brightness(.92)}}@supports (-webkit-touch-callout: none){.motile-btn{-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}}.motile-btn__wrapper{display:grid;grid-template-areas:"content";place-items:center;width:100%;height:100%}.motile-btn__content{grid-area:content;display:inline-flex;align-items:center;justify-content:center}.motile-btn__loading{grid-area:content;display:flex;align-items:center;justify-content:center}.motile-btn__dots{display:flex;gap:8px;align-items:center;height:1em}.motile-btn--large .motile-btn__dot{width:8px;height:8px}.motile-btn--medium .motile-btn__dot{width:6px;height:6px}.motile-btn--small .motile-btn__dot{width:5px;height:5px}.motile-btn__dot{border-radius:50%;background-color:#ffffffb3;animation:motile-btn-loading-bounce 1.4s ease-in-out infinite both}.motile-btn__dot:nth-child(1){animation-delay:-.32s}.motile-btn__dot:nth-child(2){animation-delay:-.16s}.motile-btn__dot:nth-child(3){animation-delay:0s}.motile-btn--primary .motile-btn__dot{background-color:#ffffffb3}.motile-btn--secondary .motile-btn__dot,.motile-btn--ghost .motile-btn__dot{background-color:#9ca3afb3}@keyframes motile-btn-loading-bounce{0%,80%,to{transform:scale(1);opacity:.4}40%{transform:scale(1.2);opacity:1}}
@@ -26,8 +26,14 @@ interface SheetRootProps {
26
26
  open?: boolean;
27
27
  defaultOpen?: boolean;
28
28
  onOpenChange?: (open: boolean) => void;
29
+ /**
30
+ * 히스토리 기반 뒤로가기 닫기 기능 활성화 여부
31
+ * URL로 Sheet를 제어하는 경우 false로 설정하세요.
32
+ * @default true
33
+ */
34
+ enableHistoryClose?: boolean;
29
35
  }
30
- declare function SheetRoot({ children, position, closeOnBackdrop, maxWidth, zIndex, open: controlledOpen, defaultOpen, onOpenChange, }: SheetRootProps): import("react/jsx-runtime").JSX.Element;
36
+ declare function SheetRoot({ children, position, closeOnBackdrop, maxWidth, zIndex, open: controlledOpen, defaultOpen, onOpenChange, enableHistoryClose, }: SheetRootProps): import("react/jsx-runtime").JSX.Element;
31
37
  interface SheetTriggerProps {
32
38
  children: React.ReactElement;
33
39
  asChild?: boolean;
@@ -1,155 +1,156 @@
1
- import { jsx as u, jsxs as $ } from "react/jsx-runtime";
2
- import { useCallback as b, useState as S, useEffect as v, useId as A, useRef as x, useMemo as F, createContext as N, useContext as T } from "react";
1
+ import { jsx as d, jsxs as $ } from "react/jsx-runtime";
2
+ import { useCallback as k, useState as S, useEffect as b, useId as A, useRef as g, useMemo as F, createContext as N, useContext as T } from "react";
3
3
  import { createPortal as w } from "react-dom";
4
- import { Slot as g } from "../../utils/Slot.js";
4
+ import { Slot as O } from "../../utils/Slot.js";
5
5
  import { useScrollLock as K } from "../../hooks/useScrollLock.js";
6
- import { useClickOutside as H } from "../../hooks/useClickOutside.js";
7
- import { useEscapeKey as V } from "../../hooks/useEscapeKey.js";
8
- import { useHistoryClose as q } from "../../hooks/useHistoryClose.js";
6
+ import { useEscapeKey as H } from "../../hooks/useEscapeKey.js";
7
+ import { useHistoryClose as P } from "../../hooks/useHistoryClose.js";
9
8
  import './Sheet.css';/* empty css */
10
9
  const I = N(null);
11
- function k() {
10
+ function v() {
12
11
  const e = T(I);
13
12
  if (!e)
14
13
  throw new Error("Sheet components must be used within Sheet.Root");
15
14
  return e;
16
15
  }
17
- function z({
16
+ function V({
18
17
  value: e,
19
18
  defaultValue: n = !1,
20
19
  onChange: o
21
20
  }) {
22
- const t = e !== void 0, [i, a] = S(n), s = t ? e : i, l = b(
23
- (r) => {
24
- const f = typeof r == "function" ? r(s) : r;
25
- t || a(f), o == null || o(f);
21
+ const t = e !== void 0, [i, l] = S(n), s = t ? e : i, r = k(
22
+ (a) => {
23
+ const f = typeof a == "function" ? a(s) : a;
24
+ t || l(f), o == null || o(f);
26
25
  },
27
26
  [t, o, s]
28
27
  );
29
- return [s, l];
28
+ return [s, r];
30
29
  }
31
- function B({
30
+ function q({
32
31
  children: e,
33
32
  position: n = "right",
34
33
  closeOnBackdrop: o = !0,
35
34
  maxWidth: t = "600px",
36
35
  zIndex: i = 1e3,
37
- open: a,
36
+ open: l,
38
37
  defaultOpen: s = !1,
39
- onOpenChange: l
38
+ onOpenChange: r,
39
+ enableHistoryClose: a = !0
40
40
  }) {
41
- const r = A().replace(/:/g, ""), f = x(null), h = x(null), [d, c] = z({
42
- value: a,
41
+ const f = A().replace(/:/g, ""), h = g(null), m = g(null), [c, p] = V({
42
+ value: l,
43
43
  defaultValue: s,
44
- onChange: l
45
- }), { isClosingFromHistory: p, navigateAndClose: y } = q({
46
- isOpen: d,
47
- onClose: () => c(!1)
48
- }), m = F(
44
+ onChange: r
45
+ }), { isClosingFromHistory: y, navigateAndClose: u } = P({
46
+ isOpen: c,
47
+ onClose: () => p(!1),
48
+ enabled: a
49
+ }), _ = F(
49
50
  () => ({
50
- open: d,
51
- setOpen: c,
51
+ open: c,
52
+ setOpen: p,
52
53
  position: n,
53
54
  closeOnBackdrop: o,
54
55
  maxWidth: t,
55
56
  zIndex: i,
56
- onOpenChange: l,
57
- triggerId: `${r}-trigger`,
58
- contentId: `${r}-content`,
59
- overlayRef: f,
60
- sheetRef: h,
61
- isClosingFromHistory: p,
62
- navigateAndClose: y
57
+ onOpenChange: r,
58
+ triggerId: `${f}-trigger`,
59
+ contentId: `${f}-content`,
60
+ overlayRef: h,
61
+ sheetRef: m,
62
+ isClosingFromHistory: y,
63
+ navigateAndClose: u
63
64
  }),
64
65
  [
65
- d,
66
66
  c,
67
+ p,
67
68
  n,
68
69
  o,
69
70
  t,
70
71
  i,
71
- l,
72
72
  r,
73
73
  f,
74
74
  h,
75
- p,
76
- y
75
+ m,
76
+ y,
77
+ u
77
78
  ]
78
79
  );
79
- return /* @__PURE__ */ u(I.Provider, { value: m, children: e });
80
+ return /* @__PURE__ */ d(I.Provider, { value: _, children: e });
80
81
  }
81
- function P({ children: e, asChild: n = !1 }) {
82
- const { open: o, setOpen: t, triggerId: i, contentId: a } = k(), s = b(() => {
83
- t((l) => !l);
82
+ function z({ children: e, asChild: n = !1 }) {
83
+ const { open: o, setOpen: t, triggerId: i, contentId: l } = v(), s = k(() => {
84
+ t((r) => !r);
84
85
  }, [t]);
85
- return n ? /* @__PURE__ */ u(
86
- g,
86
+ return n ? /* @__PURE__ */ d(
87
+ O,
87
88
  {
88
89
  id: i,
89
90
  "aria-expanded": o,
90
- "aria-controls": a,
91
+ "aria-controls": l,
91
92
  onClick: s,
92
93
  children: e
93
94
  }
94
- ) : /* @__PURE__ */ u(
95
+ ) : /* @__PURE__ */ d(
95
96
  "button",
96
97
  {
97
98
  id: i,
98
99
  type: "button",
99
100
  "aria-expanded": o,
100
- "aria-controls": a,
101
+ "aria-controls": l,
101
102
  onClick: s,
102
103
  children: e
103
104
  }
104
105
  );
105
106
  }
106
- function j({ children: e, container: n }) {
107
- const { open: o } = k(), [t, i] = S(!1);
108
- return v(() => {
107
+ function B({ children: e, container: n }) {
108
+ const { open: o } = v(), [t, i] = S(!1);
109
+ return b(() => {
109
110
  i(!0);
110
111
  }, []), !t || !o ? null : w(e, n || document.body);
111
112
  }
112
- function E({ className: e = "", style: n }) {
113
- const { open: o, setOpen: t, position: i, closeOnBackdrop: a, zIndex: s, overlayRef: l } = k(), [r, f] = S(!1), [h, d] = S(!1), c = typeof a == "boolean" ? { clickOutside: a } : {
114
- escapeKey: a.escapeKey ?? !1,
115
- clickOutside: a.clickOutside ?? !1
113
+ function j({ className: e = "", style: n }) {
114
+ const { open: o, setOpen: t, position: i, closeOnBackdrop: l, zIndex: s, overlayRef: r } = v(), [a, f] = S(!1), [h, m] = S(!1), c = typeof l == "boolean" ? { clickOutside: l } : {
115
+ escapeKey: l.escapeKey ?? !1,
116
+ clickOutside: l.clickOutside ?? !1
116
117
  };
117
- v(() => {
118
+ b(() => {
118
119
  if (o)
119
120
  f(!0);
120
- else if (r) {
121
- d(!1);
122
- const m = setTimeout(() => {
121
+ else if (a) {
122
+ m(!1);
123
+ const u = setTimeout(() => {
123
124
  f(!1);
124
125
  }, 300);
125
- return () => clearTimeout(m);
126
+ return () => clearTimeout(u);
126
127
  }
127
- }, [o, r]), v(() => {
128
- if (!r || !o) return;
129
- const m = requestAnimationFrame(() => {
128
+ }, [o, a]), b(() => {
129
+ if (!a || !o) return;
130
+ const u = requestAnimationFrame(() => {
130
131
  const _ = requestAnimationFrame(() => {
131
- d(!0);
132
+ m(!0);
132
133
  });
133
134
  return () => cancelAnimationFrame(_);
134
135
  });
135
- return () => cancelAnimationFrame(m);
136
- }, [r, o]);
137
- const p = b(
138
- (m) => {
139
- c.clickOutside && m.target === l.current && t(!1);
136
+ return () => cancelAnimationFrame(u);
137
+ }, [a, o]);
138
+ const p = k(
139
+ (u) => {
140
+ c.clickOutside && u.target === r.current && (u.stopPropagation(), t(!1));
140
141
  },
141
- [c.clickOutside, t, l]
142
+ [c.clickOutside, t, r]
142
143
  );
143
- if (!r)
144
+ if (!a)
144
145
  return null;
145
146
  const y = {
146
147
  zIndex: s,
147
148
  ...n
148
149
  };
149
- return /* @__PURE__ */ u(
150
+ return /* @__PURE__ */ d(
150
151
  "div",
151
152
  {
152
- ref: l,
153
+ ref: r,
153
154
  className: `motile-sheet__overlay ${h ? "motile-sheet__overlay--visible" : ""} motile-sheet__overlay--${i} ${e}`,
154
155
  style: y,
155
156
  onClick: p,
@@ -157,18 +158,18 @@ function E({ className: e = "", style: n }) {
157
158
  }
158
159
  );
159
160
  }
160
- function L({ children: e, className: n = "", style: o }) {
161
+ function E({ children: e, className: n = "", style: o }) {
161
162
  const {
162
163
  open: t,
163
164
  setOpen: i,
164
- position: a,
165
+ position: l,
165
166
  closeOnBackdrop: s,
166
- maxWidth: l,
167
- zIndex: r,
167
+ maxWidth: r,
168
+ zIndex: a,
168
169
  contentId: f,
169
170
  sheetRef: h,
170
- isClosingFromHistory: d
171
- } = k(), [c, p] = S(!1), [y, m] = S(!1), _ = typeof s == "boolean" ? { escapeKey: s, clickOutside: s } : {
171
+ isClosingFromHistory: m
172
+ } = v(), [c, p] = S(!1), [y, u] = S(!1), _ = typeof s == "boolean" ? { escapeKey: s } : {
172
173
  escapeKey: s.escapeKey ?? !1,
173
174
  clickOutside: s.clickOutside ?? !1
174
175
  };
@@ -176,44 +177,40 @@ function L({ children: e, className: n = "", style: o }) {
176
177
  enabled: t,
177
178
  allowedSelectors: [".motile-sheet__body"]
178
179
  }), H({
179
- refs: [h],
180
- handler: () => i(!1),
181
- enabled: t && _.clickOutside
182
- }), V({
183
180
  handler: () => i(!1),
184
181
  enabled: t && _.escapeKey
185
- }), v(() => {
182
+ }), b(() => {
186
183
  if (t)
187
184
  p(!0);
188
185
  else if (c) {
189
- m(!1);
186
+ u(!1);
190
187
  const C = setTimeout(() => {
191
188
  p(!1);
192
- }, d ? 0 : 300);
189
+ }, m ? 0 : 300);
193
190
  return () => clearTimeout(C);
194
191
  }
195
- }, [t, c, d]), v(() => {
196
- if (!c || !t || d) return;
197
- const O = requestAnimationFrame(() => {
192
+ }, [t, c, m]), b(() => {
193
+ if (!c || !t || m) return;
194
+ const x = requestAnimationFrame(() => {
198
195
  const C = requestAnimationFrame(() => {
199
- m(!0);
196
+ u(!0);
200
197
  });
201
198
  return () => cancelAnimationFrame(C);
202
199
  });
203
- return () => cancelAnimationFrame(O);
204
- }, [c, t, d]), !c)
200
+ return () => cancelAnimationFrame(x);
201
+ }, [c, t, m]), !c)
205
202
  return null;
206
203
  const R = {
207
- ...l !== "600px" && { "--sheet-max-width": l },
208
- zIndex: r + 1,
204
+ ...r !== "600px" && { "--sheet-max-width": r },
205
+ zIndex: a + 1,
209
206
  ...o
210
207
  };
211
- return /* @__PURE__ */ u(
208
+ return /* @__PURE__ */ d(
212
209
  "div",
213
210
  {
214
211
  ref: h,
215
212
  id: f,
216
- className: `motile-sheet__content motile-sheet__content--${a} ${y ? "motile-sheet__content--visible" : ""} ${n}`,
213
+ className: `motile-sheet__content motile-sheet__content--${l} ${y ? "motile-sheet__content--visible" : ""} ${n}`,
217
214
  style: R,
218
215
  role: "dialog",
219
216
  "aria-modal": "true",
@@ -221,28 +218,28 @@ function L({ children: e, className: n = "", style: o }) {
221
218
  }
222
219
  );
223
220
  }
221
+ function L({ children: e, className: n = "" }) {
222
+ return /* @__PURE__ */ d("div", { className: `motile-sheet__header ${n}`, children: e });
223
+ }
224
224
  function D({ children: e, className: n = "" }) {
225
- return /* @__PURE__ */ u("div", { className: `motile-sheet__header ${n}`, children: e });
225
+ return /* @__PURE__ */ d("h2", { id: "sheet-title", className: `motile-sheet__title ${n}`, children: e });
226
226
  }
227
227
  function M({ children: e, className: n = "" }) {
228
- return /* @__PURE__ */ u("h2", { id: "sheet-title", className: `motile-sheet__title ${n}`, children: e });
229
- }
230
- function W({ children: e, className: n = "" }) {
231
- return /* @__PURE__ */ u("div", { className: `motile-sheet__body ${n}`, children: e });
228
+ return /* @__PURE__ */ d("div", { className: `motile-sheet__body ${n}`, children: e });
232
229
  }
233
- function G({ children: e, asChild: n = !1 }) {
234
- const { setOpen: o } = k(), t = b(() => {
230
+ function W({ children: e, asChild: n = !1 }) {
231
+ const { setOpen: o } = v(), t = k(() => {
235
232
  o(!1);
236
233
  }, [o]);
237
- return n ? /* @__PURE__ */ u(
238
- g,
234
+ return n ? /* @__PURE__ */ d(
235
+ O,
239
236
  {
240
237
  className: "motile-sheet__close",
241
238
  onClick: t,
242
239
  "aria-label": "닫기",
243
240
  children: e
244
241
  }
245
- ) : /* @__PURE__ */ u(
242
+ ) : /* @__PURE__ */ d(
246
243
  "button",
247
244
  {
248
245
  className: "motile-sheet__close",
@@ -261,30 +258,30 @@ function G({ children: e, asChild: n = !1 }) {
261
258
  strokeLinecap: "round",
262
259
  strokeLinejoin: "round",
263
260
  children: [
264
- /* @__PURE__ */ u("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
265
- /* @__PURE__ */ u("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
261
+ /* @__PURE__ */ d("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
262
+ /* @__PURE__ */ d("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
266
263
  ]
267
264
  }
268
265
  )
269
266
  }
270
267
  );
271
268
  }
272
- function ne() {
273
- const { navigateAndClose: e } = k();
269
+ function te() {
270
+ const { navigateAndClose: e } = v();
274
271
  return e;
275
272
  }
276
- const se = {
277
- Root: B,
278
- Trigger: P,
279
- Portal: j,
280
- Overlay: E,
281
- Content: L,
282
- Header: D,
283
- Title: M,
284
- Body: W,
285
- Close: G
273
+ const oe = {
274
+ Root: q,
275
+ Trigger: z,
276
+ Portal: B,
277
+ Overlay: j,
278
+ Content: E,
279
+ Header: L,
280
+ Title: D,
281
+ Body: M,
282
+ Close: W
286
283
  };
287
284
  export {
288
- se as Sheet,
289
- ne as useSheetNavigation
285
+ oe as Sheet,
286
+ te as useSheetNavigation
290
287
  };
@@ -28,6 +28,12 @@ export interface UseHistoryCloseProps {
28
28
  * 모달/Sheet 닫기 핸들러
29
29
  */
30
30
  onClose: () => void;
31
+ /**
32
+ * 히스토리 기반 닫기 기능 활성화 여부
33
+ * URL로 Sheet를 제어하는 경우 false로 설정
34
+ * @default true
35
+ */
36
+ enabled?: boolean;
31
37
  }
32
38
  export interface UseHistoryCloseReturn {
33
39
  /**
@@ -51,4 +57,4 @@ export interface UseHistoryCloseReturn {
51
57
  */
52
58
  navigateAndClose: (navigationFn: () => void) => void;
53
59
  }
54
- export declare function useHistoryClose({ onClose, isOpen, }: UseHistoryCloseProps): UseHistoryCloseReturn;
60
+ export declare function useHistoryClose({ onClose, isOpen, enabled, }: UseHistoryCloseProps): UseHistoryCloseReturn;
@@ -1,42 +1,47 @@
1
- import { useRef as r, useState as w, useEffect as l } from "react";
2
- function p({
3
- onClose: o,
4
- isOpen: s
1
+ import { useRef as i, useState as h, useEffect as c } from "react";
2
+ function m({
3
+ onClose: s,
4
+ isOpen: n,
5
+ enabled: r = !0
5
6
  }) {
6
- const i = r(o), n = r(!1), [a, c] = w(!1), u = r(0), e = r(null);
7
- return l(() => {
8
- i.current = o;
9
- }, [o]), l(() => {
10
- if (s && !n.current) {
11
- const t = (f) => {
12
- c(!0), i.current();
13
- };
14
- return u.current = window.history.length, window.history.pushState({ modal: !0 }, ""), n.current = !0, window.addEventListener("popstate", t), () => {
15
- window.removeEventListener("popstate", t);
16
- };
7
+ const u = i(s), o = i(!1), [a, l] = h(!1), f = i(0), e = i(null);
8
+ return c(() => {
9
+ u.current = s;
10
+ }, [s]), c(() => {
11
+ if (!r || !n) return;
12
+ const t = (d) => {
13
+ l(!0), u.current();
14
+ };
15
+ return o.current || (f.current = window.history.length, window.history.pushState({ modal: !0 }, ""), o.current = !0), window.addEventListener("popstate", t), () => {
16
+ window.removeEventListener("popstate", t);
17
+ };
18
+ }, [n, r]), c(() => {
19
+ if (!r || n || !o.current) return;
20
+ let t = null;
21
+ if (!a) {
22
+ const d = f.current + 1;
23
+ if (window.history.length !== d)
24
+ e.current = null;
25
+ else if (e.current) {
26
+ const w = e.current;
27
+ e.current = null, t = () => {
28
+ window.removeEventListener("popstate", t), t = null, setTimeout(() => {
29
+ w();
30
+ }, 0);
31
+ }, window.addEventListener("popstate", t), window.history.back();
32
+ } else
33
+ window.history.back();
17
34
  }
18
- if (!s && n.current) {
19
- if (!a) {
20
- const t = u.current + 1;
21
- if (window.history.length !== t)
22
- e.current = null;
23
- else if (e.current) {
24
- const d = () => {
25
- window.removeEventListener("popstate", d), e.current && (e.current(), e.current = null);
26
- };
27
- window.addEventListener("popstate", d), window.history.back();
28
- } else
29
- window.history.back();
30
- }
31
- n.current = !1, c(!1);
32
- }
33
- }, [s, a]), {
35
+ return o.current = !1, l(!1), () => {
36
+ t && window.removeEventListener("popstate", t);
37
+ };
38
+ }, [n, a, r]), {
34
39
  isClosingFromHistory: a,
35
40
  navigateAndClose: (t) => {
36
- e.current = t, i.current();
41
+ e.current = t, u.current();
37
42
  }
38
43
  };
39
44
  }
40
45
  export {
41
- p as useHistoryClose
46
+ m as useHistoryClose
42
47
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "motile-ui",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "description": "A modern React component library for webview applications",
6
6
  "main": "./dist/index.js",