@floegence/floe-webapp-core 0.51.0 → 0.52.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.
@@ -15,6 +15,13 @@ export interface DialogProps {
15
15
  children: JSX.Element;
16
16
  footer?: JSX.Element;
17
17
  class?: string;
18
+ /** Bottom drawers retain the same modal and surface-placement contract. */
19
+ presentation?: 'dialog' | 'bottom-drawer';
20
+ /** Undefined uses the default header; null leaves only accessible title/description. */
21
+ header?: JSX.Element;
22
+ contentClass?: string;
23
+ /** Includes the exit animation, so hosts can retain background input isolation. */
24
+ onPresenceChange?: (present: boolean) => void;
18
25
  /** Optional stacking layer for global dialogs. Overrides the placement provider default. */
19
26
  globalZIndex?: number;
20
27
  }
@@ -1,105 +1,112 @@
1
- import { createComponent as o, use as E, setAttribute as f, style as Y, Portal as X, spread as P, mergeProps as R, memo as B, insert as a, effect as N, template as s } from "solid-js/web";
2
- import { createUniqueId as J, createSignal as S, createMemo as H, createEffect as Q, onCleanup as ee, Show as b, untrack as te } from "solid-js";
3
- import { cn as O } from "../../utils/cn.js";
4
- import { Button as D } from "./Button.js";
5
- import { X as ne } from "../icons/index.js";
6
- import { useResolvedFloeConfig as re } from "../../context/FloeConfigContext.js";
7
- import { useOverlayMask as oe } from "../../hooks/useOverlayMask.js";
8
- import { resolveSurfacePortalHost as ie, DIALOG_SURFACE_BOUNDARY_ATTR as k, isSurfacePortalMode as j, projectSurfacePortalRect as le, resolveSurfacePortalBoundaryRect as ae, resolveSurfacePortalMount as ce } from "./dialogSurfaceScope.js";
9
- import { LOCAL_INTERACTION_SURFACE_ATTR as de } from "./localInteractionSurface.js";
10
- import { createFloatingPresence as se } from "./floatingPresence.js";
11
- import { useDialogPlacement as ue } from "./DialogPlacementContext.js";
12
- var fe = /* @__PURE__ */ s("<span aria-hidden=true>"), ge = /* @__PURE__ */ s('<h2 class="text-sm font-semibold">'), me = /* @__PURE__ */ s('<p class="mt-0.5 text-xs text-muted-foreground">'), he = /* @__PURE__ */ s('<div class="flex items-start justify-between p-3 border-b border-border"><div>'), be = /* @__PURE__ */ s('<div class="flex items-center justify-end gap-2 p-3 border-t border-border">'), we = /* @__PURE__ */ s('<div><div></div><div class="pointer-events-none relative z-[1] flex h-full w-full items-center justify-center"><div data-floe-surface=floating><div class="flex-1 overflow-auto overscroll-contain p-3">'), ye = /* @__PURE__ */ s("<div>");
13
- const ve = {
1
+ import { createComponent as r, use as L, setAttribute as s, style as ee, Portal as te, spread as B, mergeProps as F, memo as C, insert as i, effect as A, className as N, template as c } from "solid-js/web";
2
+ import { createUniqueId as ne, createSignal as I, createEffect as G, onCleanup as j, createMemo as q, Show as f, untrack as re } from "solid-js";
3
+ import { cn as v } from "../../utils/cn.js";
4
+ import { Button as E } from "./Button.js";
5
+ import { X as oe } from "../icons/index.js";
6
+ import { useResolvedFloeConfig as ie } from "../../context/FloeConfigContext.js";
7
+ import { useOverlayMask as le } from "../../hooks/useOverlayMask.js";
8
+ import { resolveSurfacePortalHost as ae, DIALOG_SURFACE_BOUNDARY_ATTR as O, SURFACE_PORTAL_LAYER_ATTR as de, DIALOG_SURFACE_HOST_ATTR as ce, isSurfacePortalMode as K, projectSurfacePortalRect as ue, resolveSurfacePortalBoundaryRect as se, resolveSurfacePortalMount as fe } from "./dialogSurfaceScope.js";
9
+ import { LOCAL_INTERACTION_SURFACE_ATTR as ge } from "./localInteractionSurface.js";
10
+ import { createFloatingPresence as me } from "./floatingPresence.js";
11
+ import { useDialogPlacement as he } from "./DialogPlacementContext.js";
12
+ var be = /* @__PURE__ */ c("<span aria-hidden=true>"), ve = /* @__PURE__ */ c('<h2 class="text-sm font-semibold">'), we = /* @__PURE__ */ c('<p class="mt-0.5 text-xs text-muted-foreground">'), ye = /* @__PURE__ */ c('<div class="flex items-start justify-between p-3 border-b border-border"><div>'), xe = /* @__PURE__ */ c('<div class="flex items-center justify-end gap-2 p-3 border-t border-border">'), $e = /* @__PURE__ */ c("<div><div></div><div><div data-floe-surface=floating><div>"), _e = /* @__PURE__ */ c("<h2 class=sr-only>"), Ce = /* @__PURE__ */ c("<p class=sr-only>"), Ae = /* @__PURE__ */ c("<div>");
13
+ const Oe = {
14
14
  display: "none"
15
15
  };
16
- function xe(e) {
16
+ function Re(e) {
17
17
  if (typeof queueMicrotask == "function") {
18
18
  queueMicrotask(e);
19
19
  return;
20
20
  }
21
21
  Promise.resolve().then(e);
22
22
  }
23
- function q(e) {
23
+ function U(e) {
24
24
  return `${e.left}|${e.top}|${e.right}|${e.bottom}|${e.width}|${e.height}`;
25
25
  }
26
- function pe(e) {
26
+ function ke(e) {
27
27
  return typeof window < "u" && typeof window.requestAnimationFrame == "function" ? window.requestAnimationFrame(e) : window.setTimeout(() => e(Date.now()), 16);
28
28
  }
29
- function $e(e) {
29
+ function Pe(e) {
30
30
  if (typeof window < "u" && typeof window.cancelAnimationFrame == "function") {
31
31
  window.cancelAnimationFrame(e);
32
32
  return;
33
33
  }
34
34
  window.clearTimeout(e);
35
35
  }
36
- function Ce(e) {
37
- const g = ue(), c = J(), I = () => `dialog-${c}-title`, F = () => `dialog-${c}-description`;
38
- let w;
39
- const [y, G] = S(null), [M, K] = S(0), [L, z] = S(0), u = se({
40
- open: () => e.open && !!y() && M() > 0,
41
- exitDurationMs: 120
42
- }), v = () => u.mounted() && !!y() && M() > 0, Z = (t) => {
43
- G(t), xe(() => {
44
- te(y) === t && K((l) => l + 1);
36
+ function pe(e) {
37
+ const w = he(), g = ne(), p = () => `dialog-${g}-title`, S = () => `dialog-${g}-description`;
38
+ let T;
39
+ const [R, z] = I(null), [M, Z] = I(0), [V, W] = I(0), m = () => e.presentation === "bottom-drawer", u = me({
40
+ open: () => e.open && !!R() && M() > 0,
41
+ get exitDurationMs() {
42
+ return m() ? 180 : 120;
43
+ }
44
+ }), y = () => u.mounted() && !!R() && M() > 0;
45
+ G(() => e.onPresenceChange?.(y())), j(() => e.onPresenceChange?.(!1));
46
+ const Y = (n) => {
47
+ z(n), Re(() => {
48
+ re(R) === n && Z((d) => d + 1);
45
49
  });
46
- }, x = H(() => v() ? ie({
47
- owner: y()
50
+ }, k = q(() => y() ? ae({
51
+ owner: R()
48
52
  }) : {
49
53
  host: null,
50
54
  boundaryHost: null,
51
55
  mountHost: null,
52
56
  mode: "global"
53
- }), p = () => `dialog-boundary-${c}`, n = () => g.mode() === "auto" && j(x()), U = () => n() ? ce(x()) : void 0, T = () => e.globalZIndex ?? g.globalZIndex(), A = (t) => le(ae(t), t), V = () => A(x()), $ = H(() => (L(), V())), W = (t) => typeof Element < "u" && t instanceof Element ? !!t.closest(`[${k}="${p()}"]`) : typeof Node < "u" && t instanceof Node ? !!t.parentElement?.closest(`[${k}="${p()}"]`) : !1;
54
- return Q(() => {
55
- const t = x();
56
- if (!v() || !n() || typeof window > "u")
57
+ }), x = () => `dialog-boundary-${g}`, o = () => w.mode() === "auto" && K(k()), X = () => o() ? fe(k()) : void 0, H = () => e.globalZIndex ?? w.globalZIndex(), D = (n) => ue(se(n), n), J = () => D(k()), P = q(() => (V(), J())), Q = (n) => typeof Element < "u" && n instanceof Element ? !!n.closest(`[${O}="${x()}"]`) : typeof Node < "u" && n instanceof Node ? !!n.parentElement?.closest(`[${O}="${x()}"]`) : !1;
58
+ return G(() => {
59
+ const n = k();
60
+ if (!y() || !o() || typeof window > "u")
57
61
  return;
58
- let l = !1, m = null, i = q(A(t));
59
- const C = () => {
60
- if (l || !j(t))
62
+ let d = !1, b = null, l = U(D(n));
63
+ const $ = () => {
64
+ if (d || !K(n))
61
65
  return;
62
- const r = q(A(t));
63
- r !== i && (i = r, z((_) => _ + 1));
64
- }, h = () => {
65
- l || (m = pe(() => {
66
- C(), h();
66
+ const t = U(D(n));
67
+ t !== l && (l = t, W((h) => h + 1));
68
+ }, _ = () => {
69
+ d || (b = ke(() => {
70
+ $(), _();
67
71
  }));
68
72
  };
69
- h(), ee(() => {
70
- l = !0, m !== null && $e(m);
73
+ _(), j(() => {
74
+ d = !0, b !== null && Pe(b);
71
75
  });
72
- }), oe({
73
- open: v,
74
- root: () => w,
75
- containsTarget: (t) => n() ? W(t) : typeof Node < "u" && t instanceof Node ? !!w?.contains(t) : !1,
76
+ }), le({
77
+ open: y,
78
+ root: () => T,
79
+ containsTarget: Q,
76
80
  onClose: () => e.onOpenChange(!1),
77
- lockBodyScroll: () => !n(),
81
+ lockBodyScroll: () => !o(),
78
82
  trapFocus: !0,
79
- closeOnEscape: () => n() ? "inside" : !0,
83
+ closeOnEscape: () => o() ? "inside" : !0,
80
84
  escapeKeyPhase: () => e.escapeKeyPhase ?? "capture",
81
85
  blockHotkeys: !0,
82
86
  // Block scroll bleed outside the dialog while keeping the dialog content scrollable.
83
- blockWheel: () => n() ? "none" : "outside",
84
- blockTouchMove: () => n() ? "none" : "outside",
87
+ blockWheel: () => o() ? "none" : "outside",
88
+ blockTouchMove: () => o() ? "none" : "outside",
85
89
  restoreFocus: !0
86
90
  }), [(() => {
87
- var t = fe();
88
- return E(Z, t), f(t, "data-floe-dialog-owner-anchor", c), Y(t, ve), t;
89
- })(), o(b, {
91
+ var n = be();
92
+ return L(Y, n), s(n, "data-floe-dialog-owner-anchor", g), ee(n, Oe), n;
93
+ })(), r(f, {
90
94
  get when() {
91
- return v();
95
+ return y();
92
96
  },
93
97
  get children() {
94
- return o(X, {
98
+ return r(te, {
95
99
  get mount() {
96
- return U();
100
+ return X();
97
101
  },
98
102
  get children() {
99
- var t = we(), l = t.firstChild, m = l.nextSibling, i = m.firstChild, C = i.firstChild;
100
- f(t, "data-floe-dialog-overlay-root", c), P(t, R({
103
+ var n = $e(), d = n.firstChild, b = d.nextSibling, l = b.firstChild, $ = l.firstChild;
104
+ s(n, "data-floe-dialog-overlay-root", g), B(n, F({
101
105
  get "data-floe-dialog-mode"() {
102
- return n() ? "surface" : "global";
106
+ return o() ? "surface" : "global";
107
+ },
108
+ get "data-floe-dialog-presentation"() {
109
+ return e.presentation ?? "dialog";
103
110
  },
104
111
  get "data-floating-presence"() {
105
112
  return u.state();
@@ -108,110 +115,149 @@ function Ce(e) {
108
115
  return u.exiting() ? "true" : void 0;
109
116
  }
110
117
  }, () => ({
111
- [de]: n() ? "true" : void 0
118
+ [ge]: o() ? "true" : void 0
119
+ }), () => ({
120
+ [de]: "true",
121
+ [O]: x()
112
122
  }), {
113
123
  get class() {
114
- return O(n() ? "absolute z-20 box-border p-3" : O("fixed inset-0 box-border p-4", T() === void 0 && "z-50"), u.exiting() && "pointer-events-none");
124
+ return v(o() ? "absolute z-20 box-border p-3" : v("fixed inset-0 box-border p-4", H() === void 0 && "z-50"), m() && "floe-bottom-drawer-overlay", u.exiting() && !m() && "pointer-events-none");
115
125
  },
116
126
  get style() {
117
- return B(() => !!n())() ? {
118
- left: `${$().left}px`,
119
- top: `${$().top}px`,
120
- width: `${$().width}px`,
121
- height: `${$().height}px`
127
+ return C(() => !!o())() ? {
128
+ left: `${P().left}px`,
129
+ top: `${P().top}px`,
130
+ width: `${P().width}px`,
131
+ height: `${P().height}px`
122
132
  } : {
123
- "z-index": T()
133
+ "z-index": H()
124
134
  };
125
135
  }
126
- }), !1, !0), f(l, "data-floe-dialog-backdrop", c), P(l, R(() => ({
127
- [k]: p()
136
+ }), !1, !0), s(d, "data-floe-dialog-backdrop", g), B(d, F(() => ({
137
+ [O]: x()
128
138
  }), {
129
139
  get "data-floating-presence"() {
130
140
  return u.state();
131
141
  },
132
142
  get class() {
133
- return O("absolute inset-0 floe-floating-presence floe-floating-backdrop", e.closeOnBackdropClick === !1 ? "cursor-default" : "cursor-pointer", n() ? "bg-background/72 backdrop-blur-[2px]" : "bg-background/80 backdrop-blur-sm");
143
+ return v("absolute inset-0 floe-floating-presence floe-floating-backdrop", e.closeOnBackdropClick === !1 ? "cursor-default" : "cursor-pointer", m() ? "floe-bottom-drawer-backdrop" : o() ? "bg-background/72 backdrop-blur-[2px]" : "bg-background/80 backdrop-blur-sm");
134
144
  },
135
145
  onClick: () => {
136
- e.closeOnBackdropClick !== !1 && e.onOpenChange(!1);
146
+ !u.exiting() && e.closeOnBackdropClick !== !1 && e.onOpenChange(!1);
137
147
  }
138
148
  }), !1, !1);
139
- var h = w;
140
- return typeof h == "function" ? E(h, i) : w = i, f(i, "data-floe-dialog-panel", c), P(i, R(() => ({
141
- [k]: p()
149
+ var _ = T;
150
+ return typeof _ == "function" ? L(_, l) : T = l, s(l, "data-floe-dialog-panel", g), B(l, F(() => ({
151
+ [O]: x(),
152
+ [ce]: "true"
142
153
  }), {
143
154
  get class() {
144
- return O(n() ? "flex max-h-[calc(100%-1rem)] w-[min(32rem,calc(100%-1rem))] max-w-[calc(100%-1rem)] flex-col" : "w-full max-w-md max-h-[85vh]", "bg-card text-card-foreground rounded-md shadow-lg", "border border-border", "floe-floating-presence floe-floating-dialog-panel", "pointer-events-auto flex flex-col", e.class);
155
+ return v(o() ? "flex max-h-[calc(100%-1rem)] w-[min(32rem,calc(100%-1rem))] max-w-[calc(100%-1rem)] flex-col" : "w-full max-w-md max-h-[85vh]", "bg-card text-card-foreground rounded-md shadow-lg", "border border-border", "floe-floating-presence", m() ? "floe-bottom-drawer-panel" : "floe-floating-dialog-panel", "pointer-events-auto flex flex-col", e.class);
145
156
  },
146
157
  get "data-floating-presence"() {
147
158
  return u.state();
148
159
  },
160
+ get inert() {
161
+ return C(() => !!m())() && u.exiting();
162
+ },
149
163
  role: "dialog",
150
164
  get "aria-modal"() {
151
- return n() ? void 0 : "true";
165
+ return o() ? void 0 : "true";
152
166
  },
153
167
  get "aria-labelledby"() {
154
- return B(() => !!e.title)() ? I() : void 0;
168
+ return C(() => !!e.title)() ? p() : void 0;
155
169
  },
156
170
  get "aria-describedby"() {
157
- return B(() => !!e.description)() ? F() : void 0;
171
+ return C(() => !!e.description)() ? S() : void 0;
158
172
  },
159
- onKeyDown: (r) => e.onKeyDown?.(r),
173
+ onKeyDown: (t) => e.onKeyDown?.(t),
160
174
  tabIndex: -1
161
- }), !1, !0), a(i, o(b, {
175
+ }), !1, !0), i(l, r(f, {
162
176
  get when() {
163
- return e.title || e.description;
177
+ return e.header === void 0;
164
178
  },
165
- get children() {
166
- var r = he(), _ = r.firstChild;
167
- return a(_, o(b, {
179
+ get fallback() {
180
+ return [r(f, {
168
181
  get when() {
169
182
  return e.title;
170
183
  },
171
184
  get children() {
172
- var d = ge();
173
- return a(d, () => e.title), N(() => f(d, "id", I())), d;
185
+ var t = _e();
186
+ return i(t, () => e.title), A(() => s(t, "id", p())), t;
174
187
  }
175
- }), null), a(_, o(b, {
188
+ }), r(f, {
176
189
  get when() {
177
190
  return e.description;
178
191
  },
179
192
  get children() {
180
- var d = me();
181
- return a(d, () => e.description), N(() => f(d, "id", F())), d;
193
+ var t = Ce();
194
+ return i(t, () => e.description), A(() => s(t, "id", S())), t;
182
195
  }
183
- }), null), a(r, o(D, {
184
- variant: "ghost-destructive",
185
- size: "icon",
186
- class: "-my-2 -mr-2 h-[46px] w-[46px] shrink-0 sm:my-0 sm:-mr-1 sm:h-6 sm:w-6",
187
- onClick: () => e.onOpenChange(!1),
188
- get "aria-label"() {
189
- return e.closeLabel ?? "Close";
196
+ }), C(() => e.header)];
197
+ },
198
+ get children() {
199
+ return r(f, {
200
+ get when() {
201
+ return e.title || e.description;
190
202
  },
191
203
  get children() {
192
- return o(ne, {
193
- class: "w-3.5 h-3.5"
194
- });
204
+ var t = ye(), h = t.firstChild;
205
+ return i(h, r(f, {
206
+ get when() {
207
+ return e.title;
208
+ },
209
+ get children() {
210
+ var a = ve();
211
+ return i(a, () => e.title), A(() => s(a, "id", p())), a;
212
+ }
213
+ }), null), i(h, r(f, {
214
+ get when() {
215
+ return e.description;
216
+ },
217
+ get children() {
218
+ var a = we();
219
+ return i(a, () => e.description), A(() => s(a, "id", S())), a;
220
+ }
221
+ }), null), i(t, r(E, {
222
+ variant: "ghost-destructive",
223
+ size: "icon",
224
+ class: "-my-2 -mr-2 h-[46px] w-[46px] shrink-0 sm:my-0 sm:-mr-1 sm:h-6 sm:w-6",
225
+ onClick: () => e.onOpenChange(!1),
226
+ get "aria-label"() {
227
+ return e.closeLabel ?? "Close";
228
+ },
229
+ get children() {
230
+ return r(oe, {
231
+ class: "w-3.5 h-3.5"
232
+ });
233
+ }
234
+ }), null), t;
195
235
  }
196
- }), null), r;
236
+ });
197
237
  }
198
- }), C), a(C, () => e.children), a(i, o(b, {
238
+ }), $), i($, () => e.children), i(l, r(f, {
199
239
  get when() {
200
240
  return e.footer;
201
241
  },
202
242
  get children() {
203
- var r = be();
204
- return a(r, () => e.footer), r;
243
+ var t = xe();
244
+ return i(t, () => e.footer), t;
205
245
  }
206
- }), null), t;
246
+ }), null), A((t) => {
247
+ var h = v("pointer-events-none relative z-[1] flex h-full w-full justify-center", m() ? "items-end" : "items-center"), a = v("min-h-0 flex-1 overflow-auto overscroll-contain p-3", e.contentClass);
248
+ return h !== t.e && N(b, t.e = h), a !== t.t && N($, t.t = a), t;
249
+ }, {
250
+ e: void 0,
251
+ t: void 0
252
+ }), n;
207
253
  }
208
254
  });
209
255
  }
210
256
  })];
211
257
  }
212
- function Te(e) {
213
- const g = re();
214
- return o(Ce, {
258
+ function je(e) {
259
+ const w = ie();
260
+ return r(pe, {
215
261
  get open() {
216
262
  return e.open;
217
263
  },
@@ -228,16 +274,16 @@ function Te(e) {
228
274
  return e.globalZIndex;
229
275
  },
230
276
  get footer() {
231
- return [o(D, {
277
+ return [r(E, {
232
278
  variant: "ghost",
233
279
  onClick: () => e.onOpenChange(!1),
234
280
  get disabled() {
235
281
  return e.loading;
236
282
  },
237
283
  get children() {
238
- return e.cancelText ?? g.config.strings.confirmDialog.cancel;
284
+ return e.cancelText ?? w.config.strings.confirmDialog.cancel;
239
285
  }
240
- }), o(D, {
286
+ }), r(E, {
241
287
  get variant() {
242
288
  return e.variant === "destructive" ? "destructive" : "primary";
243
289
  },
@@ -248,16 +294,16 @@ function Te(e) {
248
294
  return e.loading;
249
295
  },
250
296
  get children() {
251
- return e.confirmText ?? g.config.strings.confirmDialog.confirm;
297
+ return e.confirmText ?? w.config.strings.confirmDialog.confirm;
252
298
  }
253
299
  })];
254
300
  },
255
301
  get children() {
256
- return e.children ?? ye();
302
+ return e.children ?? Ae();
257
303
  }
258
304
  });
259
305
  }
260
306
  export {
261
- Te as ConfirmDialog,
262
- Ce as Dialog
307
+ je as ConfirmDialog,
308
+ pe as Dialog
263
309
  };