@floegence/floe-webapp-core 0.39.5 → 0.39.6
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/components/layout/BottomBarCompanion.d.ts +33 -0
- package/dist/components/layout/BottomBarCompanion.js +233 -0
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/floe.css +60 -0
- package/dist/full.js +516 -514
- package/dist/layout.js +33 -31
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
export type BottomBarCompanionPhase = 'collapsed' | 'expanding' | 'expanded' | 'collapsing';
|
|
3
|
+
export type BottomBarCompanionDismissReason = 'outside-pointer' | 'escape';
|
|
4
|
+
export interface BottomBarCompanionProps {
|
|
5
|
+
retained: boolean;
|
|
6
|
+
visible: boolean;
|
|
7
|
+
open: boolean;
|
|
8
|
+
anchor: HTMLElement | null;
|
|
9
|
+
mount: HTMLElement | null;
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
children?: JSX.Element;
|
|
13
|
+
maxWidth?: number;
|
|
14
|
+
maxHeight?: number;
|
|
15
|
+
viewportPadding?: number;
|
|
16
|
+
class?: string;
|
|
17
|
+
contentClass?: string;
|
|
18
|
+
surfaceRef?: (element: HTMLElement | null) => void;
|
|
19
|
+
contentHostRef?: (element: HTMLElement | null) => void;
|
|
20
|
+
isOwnedInteraction?: (event: PointerEvent | KeyboardEvent) => boolean;
|
|
21
|
+
onDismiss?: (reason: BottomBarCompanionDismissReason) => void;
|
|
22
|
+
onPhaseChange?: (phase: BottomBarCompanionPhase) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A non-modal surface that grows upward from a Bottom Bar anchor.
|
|
26
|
+
*
|
|
27
|
+
* This is intentionally distinct from windows, popovers, and modal drawers:
|
|
28
|
+
* it retains one fixed shell and one content host across collapsed and expanded
|
|
29
|
+
* presentation. Products that also have a full-page placement can Portal their
|
|
30
|
+
* stable product tree into `contentHostRef` without giving this component
|
|
31
|
+
* ownership of that tree.
|
|
32
|
+
*/
|
|
33
|
+
export declare function BottomBarCompanion(props: BottomBarCompanionProps): JSX.Element;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { createComponent as Z, Portal as ce, use as $, insert as le, effect as ue, setAttribute as R, className as p, style as de, memo as fe, template as me } from "solid-js/web";
|
|
2
|
+
import { createSignal as N, createEffect as k, untrack as G, onCleanup as U, Show as he } from "solid-js";
|
|
3
|
+
import { cn as ee } from "../../utils/cn.js";
|
|
4
|
+
var ve = /* @__PURE__ */ me("<section role=region data-floe-bottom-bar-companion=true><div data-floe-bottom-bar-companion-content=true>");
|
|
5
|
+
const we = 544, be = 544, ge = 12, z = {
|
|
6
|
+
top: "--floe-bottom-bar-companion-safe-area-top",
|
|
7
|
+
right: "--floe-bottom-bar-companion-safe-area-right",
|
|
8
|
+
bottom: "--floe-bottom-bar-companion-safe-area-bottom",
|
|
9
|
+
left: "--floe-bottom-bar-companion-safe-area-left"
|
|
10
|
+
};
|
|
11
|
+
function te(e, a) {
|
|
12
|
+
const l = Number(e);
|
|
13
|
+
return Number.isFinite(l) && l > 0 ? l : a;
|
|
14
|
+
}
|
|
15
|
+
function Ce(e, a) {
|
|
16
|
+
const l = Number(e);
|
|
17
|
+
return Number.isFinite(l) && l >= 0 ? l : a;
|
|
18
|
+
}
|
|
19
|
+
function ne(e) {
|
|
20
|
+
if (!e?.isConnected) return null;
|
|
21
|
+
const a = e.getBoundingClientRect();
|
|
22
|
+
return !Number.isFinite(a.left) || !Number.isFinite(a.top) || a.width <= 0 || a.height <= 0 ? null : {
|
|
23
|
+
left: a.left,
|
|
24
|
+
top: a.top,
|
|
25
|
+
width: a.width,
|
|
26
|
+
height: a.height
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function B(e, a) {
|
|
30
|
+
const l = e.ownerDocument.defaultView;
|
|
31
|
+
if (!l) return 0;
|
|
32
|
+
const m = Number.parseFloat(l.getComputedStyle(e).getPropertyValue(a));
|
|
33
|
+
return Number.isFinite(m) && m > 0 ? m : 0;
|
|
34
|
+
}
|
|
35
|
+
function Fe(e) {
|
|
36
|
+
return {
|
|
37
|
+
top: B(e, z.top),
|
|
38
|
+
right: B(e, z.right),
|
|
39
|
+
bottom: B(e, z.bottom),
|
|
40
|
+
left: B(e, z.left)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function ye(e, a, l, m, C) {
|
|
44
|
+
const F = a.ownerDocument.defaultView, y = F?.visualViewport, v = y?.offsetLeft ?? 0, D = y?.offsetTop ?? 0, q = y?.width ?? F?.innerWidth ?? e.left + e.width, H = y?.height ?? F?.innerHeight ?? e.top + e.height, E = Fe(a), W = v + E.left + C, w = v + q - E.right - C, b = D + E.top + C, h = D + H - E.bottom - C, g = Math.max(0, w - W), d = Math.min(e.width, l, g), P = e.left + (e.width - d) / 2, M = Math.max(W, Math.min(P, w - d)), L = Math.min(e.top + e.height, h), V = Math.max(e.height, L - b), x = Math.min(m, V);
|
|
45
|
+
return {
|
|
46
|
+
left: M,
|
|
47
|
+
top: L - x,
|
|
48
|
+
width: d,
|
|
49
|
+
height: x
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function Ee(e, a) {
|
|
53
|
+
return !!(e && e.left === a.left && e.top === a.top && e.width === a.width && e.height === a.height);
|
|
54
|
+
}
|
|
55
|
+
function Ae(e) {
|
|
56
|
+
return e ? {
|
|
57
|
+
left: `${e.left}px`,
|
|
58
|
+
top: `${e.top}px`,
|
|
59
|
+
width: `${e.width}px`,
|
|
60
|
+
height: `${e.height}px`
|
|
61
|
+
} : {};
|
|
62
|
+
}
|
|
63
|
+
function Me(e) {
|
|
64
|
+
const [a, l] = N(null), [m, C] = N(!1), [F, y] = N(!1), [v, D] = N(null), [q, H] = N(null), [E, W] = N("collapsed");
|
|
65
|
+
let w = null, b = 0, h = 0, g = null, d = null, P = null, M = !1, L = !1;
|
|
66
|
+
const V = (i) => {
|
|
67
|
+
E() !== i && (W(i), e.onPhaseChange?.(i));
|
|
68
|
+
}, x = () => a()?.ownerDocument.defaultView ?? e.anchor?.ownerDocument.defaultView ?? null, oe = () => x()?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? !1, _ = (i) => {
|
|
69
|
+
const t = e.mount, r = e.anchor, n = !!(t?.isConnected && i && r?.ownerDocument === t.ownerDocument);
|
|
70
|
+
n && l(t);
|
|
71
|
+
const c = a();
|
|
72
|
+
if (c) {
|
|
73
|
+
C(c.isConnected);
|
|
74
|
+
const o = !!(n && c === t);
|
|
75
|
+
return y(o), {
|
|
76
|
+
mount: c,
|
|
77
|
+
ready: o
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return C(!1), y(!1), {
|
|
81
|
+
mount: null,
|
|
82
|
+
ready: !1
|
|
83
|
+
};
|
|
84
|
+
}, ie = (i) => {
|
|
85
|
+
const t = ne(e.anchor);
|
|
86
|
+
t && H(t);
|
|
87
|
+
const {
|
|
88
|
+
mount: r,
|
|
89
|
+
ready: n
|
|
90
|
+
} = _(t), c = t ?? q();
|
|
91
|
+
return !c || !r || !n ? null : i ? ye(c, r, te(e.maxWidth, we), te(e.maxHeight, be), Ce(e.viewportPadding, ge)) : c;
|
|
92
|
+
}, X = () => {
|
|
93
|
+
b && g && g.cancelAnimationFrame(b), h && d && d.cancelAnimationFrame(h), b = 0, h = 0, g = null, d = null, P = null;
|
|
94
|
+
}, K = (i, t) => {
|
|
95
|
+
const r = ie(i);
|
|
96
|
+
if (!r) return;
|
|
97
|
+
const n = v(), c = i ? "expanded" : "collapsed";
|
|
98
|
+
if (!t || oe() || Ee(n, r)) {
|
|
99
|
+
D(r), P = null, V(c);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
P = ["height", "width", "top", "left"].find((u) => n?.[u] !== r[u]) ?? null, V(i ? "expanding" : "collapsing");
|
|
103
|
+
const o = x();
|
|
104
|
+
if (!o) {
|
|
105
|
+
D(r), V(c);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
h = o.requestAnimationFrame(() => {
|
|
109
|
+
h = 0, d = null, D(r);
|
|
110
|
+
}), d = o;
|
|
111
|
+
}, j = (i, t) => {
|
|
112
|
+
const r = x();
|
|
113
|
+
if (!r) {
|
|
114
|
+
K(t, i);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
b && g && g.cancelAnimationFrame(b), h && d && d.cancelAnimationFrame(h), h = 0, d = null, b = r.requestAnimationFrame(() => {
|
|
118
|
+
b = 0, g = null, G(() => K(t, i));
|
|
119
|
+
}), g = r;
|
|
120
|
+
};
|
|
121
|
+
k(() => {
|
|
122
|
+
const i = e.retained, t = e.visible, r = e.open;
|
|
123
|
+
if (e.anchor, e.mount, e.maxWidth, e.maxHeight, e.viewportPadding, !i) {
|
|
124
|
+
X(), l(null), C(!1), y(!1), D(null), H(null), w = null, e.surfaceRef?.(null), e.contentHostRef?.(null), M = !1, L = r;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const n = ne(e.anchor);
|
|
128
|
+
if (n && H(n), _(n), !t) {
|
|
129
|
+
M = !1, L = r;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const c = !M, o = L !== r;
|
|
133
|
+
M = !0, L = r, j(!c && o, r);
|
|
134
|
+
}), k(() => {
|
|
135
|
+
if (!e.retained) return;
|
|
136
|
+
const i = e.anchor, t = a(), r = e.mount, n = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set();
|
|
137
|
+
for (const s of [i, t, r]) {
|
|
138
|
+
if (!s) continue;
|
|
139
|
+
n.add(s.ownerDocument);
|
|
140
|
+
const f = s.ownerDocument.defaultView;
|
|
141
|
+
f && c.add(f);
|
|
142
|
+
}
|
|
143
|
+
if (c.size === 0 || n.size === 0) return;
|
|
144
|
+
const o = () => j(!1, G(() => e.open)), u = [];
|
|
145
|
+
for (const s of /* @__PURE__ */ new Set([i, t, r])) {
|
|
146
|
+
const f = s?.ownerDocument.defaultView;
|
|
147
|
+
if (!s || !f || typeof f.ResizeObserver != "function") continue;
|
|
148
|
+
const A = new f.ResizeObserver(o);
|
|
149
|
+
A.observe(s), u.push(A);
|
|
150
|
+
}
|
|
151
|
+
let S = i?.isConnected ?? !1, T = t?.isConnected ?? !1, I = r?.isConnected ?? !1;
|
|
152
|
+
const O = [];
|
|
153
|
+
for (const s of n) {
|
|
154
|
+
const f = s.defaultView;
|
|
155
|
+
if (!f || typeof f.MutationObserver != "function" || !s.documentElement) continue;
|
|
156
|
+
const A = new f.MutationObserver(() => {
|
|
157
|
+
const J = i?.isConnected ?? !1, Q = t?.isConnected ?? !1, Y = r?.isConnected ?? !1;
|
|
158
|
+
S === J && T === Q && I === Y || (S = J, T = Q, I = Y, G(o));
|
|
159
|
+
});
|
|
160
|
+
A.observe(s.documentElement, {
|
|
161
|
+
childList: !0,
|
|
162
|
+
subtree: !0
|
|
163
|
+
}), O.push(A);
|
|
164
|
+
}
|
|
165
|
+
for (const s of c)
|
|
166
|
+
s.addEventListener("resize", o), s.visualViewport?.addEventListener("resize", o), s.visualViewport?.addEventListener("scroll", o);
|
|
167
|
+
U(() => {
|
|
168
|
+
for (const s of u) s.disconnect();
|
|
169
|
+
for (const s of O) s.disconnect();
|
|
170
|
+
for (const s of c)
|
|
171
|
+
s.removeEventListener("resize", o), s.visualViewport?.removeEventListener("resize", o), s.visualViewport?.removeEventListener("scroll", o);
|
|
172
|
+
});
|
|
173
|
+
}), k(() => {
|
|
174
|
+
if (!e.retained || !e.visible || !e.open || !m() || !F() || !v()) return;
|
|
175
|
+
const t = a()?.ownerDocument;
|
|
176
|
+
if (!t) return;
|
|
177
|
+
const r = (o) => {
|
|
178
|
+
const u = typeof o.composedPath == "function" ? o.composedPath() : [];
|
|
179
|
+
return w && u.includes(w) || e.anchor && u.includes(e.anchor) ? !0 : e.isOwnedInteraction?.(o) ?? !1;
|
|
180
|
+
}, n = (o) => {
|
|
181
|
+
r(o) || e.onDismiss?.("outside-pointer");
|
|
182
|
+
}, c = (o) => {
|
|
183
|
+
if (o.key !== "Escape" || o.defaultPrevented || o.isComposing || o.keyCode === 229) return;
|
|
184
|
+
const u = t.activeElement;
|
|
185
|
+
!w?.contains(u) && !e.isOwnedInteraction?.(o) || (o.preventDefault(), e.onDismiss?.("escape"));
|
|
186
|
+
};
|
|
187
|
+
t.addEventListener("pointerdown", n, !0), t.addEventListener("keydown", c), U(() => {
|
|
188
|
+
t.removeEventListener("pointerdown", n, !0), t.removeEventListener("keydown", c);
|
|
189
|
+
});
|
|
190
|
+
}), U(() => {
|
|
191
|
+
X(), e.surfaceRef?.(null), e.contentHostRef?.(null);
|
|
192
|
+
});
|
|
193
|
+
const re = (i) => {
|
|
194
|
+
w = i, e.surfaceRef?.(i);
|
|
195
|
+
}, ae = (i) => {
|
|
196
|
+
e.contentHostRef?.(i);
|
|
197
|
+
}, se = (i) => {
|
|
198
|
+
if (i.target !== w || i.propertyName !== P) return;
|
|
199
|
+
const t = e.open ? "expanding" : "collapsing";
|
|
200
|
+
E() === t && (P = null, V(e.open ? "expanded" : "collapsed"));
|
|
201
|
+
};
|
|
202
|
+
return Z(he, {
|
|
203
|
+
get when() {
|
|
204
|
+
return fe(() => !!e.retained)() && a();
|
|
205
|
+
},
|
|
206
|
+
children: (i) => Z(ce, {
|
|
207
|
+
get mount() {
|
|
208
|
+
return i();
|
|
209
|
+
},
|
|
210
|
+
get children() {
|
|
211
|
+
var t = ve(), r = t.firstChild;
|
|
212
|
+
return t.addEventListener("transitionend", se), $((n) => re(n), t), $((n) => ae(n), r), le(r, () => e.children), ue((n) => {
|
|
213
|
+
var c = e.id, o = e.label, u = !e.visible || !m() || !F() || !v() ? "true" : void 0, S = !e.visible || !m() || !F() || !v(), T = ee("floe-bottom-bar-companion", e.class), I = E(), O = e.visible && m() && F() ? "visible" : "hidden", s = v() ? "true" : "false", f = Ae(v()), A = ee("floe-bottom-bar-companion__content", e.contentClass);
|
|
214
|
+
return c !== n.e && R(t, "id", n.e = c), o !== n.t && R(t, "aria-label", n.t = o), u !== n.a && R(t, "aria-hidden", n.a = u), S !== n.o && (t.inert = n.o = S), T !== n.i && p(t, n.i = T), I !== n.n && R(t, "data-companion-phase", n.n = I), O !== n.s && R(t, "data-companion-visibility", n.s = O), s !== n.h && R(t, "data-companion-frame-ready", n.h = s), n.r = de(t, f, n.r), A !== n.d && p(r, n.d = A), n;
|
|
215
|
+
}, {
|
|
216
|
+
e: void 0,
|
|
217
|
+
t: void 0,
|
|
218
|
+
a: void 0,
|
|
219
|
+
o: void 0,
|
|
220
|
+
i: void 0,
|
|
221
|
+
n: void 0,
|
|
222
|
+
s: void 0,
|
|
223
|
+
h: void 0,
|
|
224
|
+
r: void 0,
|
|
225
|
+
d: void 0
|
|
226
|
+
}), t;
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
export {
|
|
232
|
+
Me as BottomBarCompanion
|
|
233
|
+
};
|
|
@@ -4,6 +4,7 @@ export { Sidebar, SidebarContent, SidebarItemList, SidebarSection, SidebarItem,
|
|
|
4
4
|
export { TopBar, type TopBarProps } from './TopBar';
|
|
5
5
|
export { TopBarIconButton, type TopBarIconButtonProps } from './TopBarIconButton';
|
|
6
6
|
export { BottomBar, BottomBarItem, StatusIndicator, type BottomBarProps, type BottomBarItemProps, type StatusIndicatorProps } from './BottomBar';
|
|
7
|
+
export { BottomBarCompanion, type BottomBarCompanionDismissReason, type BottomBarCompanionPhase, type BottomBarCompanionProps, } from './BottomBarCompanion';
|
|
7
8
|
export { MobileTabBar, type MobileTabBarItem, type MobileTabBarProps } from './MobileTabBar';
|
|
8
9
|
export { ResizeHandle, type ResizeHandleProps } from './ResizeHandle';
|
|
9
10
|
export { SidebarPane, type SidebarPaneProps } from './SidebarPane';
|
package/dist/floe.css
CHANGED
|
@@ -687,6 +687,66 @@
|
|
|
687
687
|
}
|
|
688
688
|
}
|
|
689
689
|
|
|
690
|
+
.floe-bottom-bar-companion {
|
|
691
|
+
position: fixed;
|
|
692
|
+
z-index: var(--floe-bottom-bar-companion-z-index, 72);
|
|
693
|
+
min-width: 0;
|
|
694
|
+
min-height: 0;
|
|
695
|
+
overflow: hidden;
|
|
696
|
+
border: 1px solid color-mix(in srgb, var(--border) 92%, transparent);
|
|
697
|
+
border-radius: var(--floe-bottom-bar-companion-collapsed-radius, 0.3125rem);
|
|
698
|
+
background: var(--background);
|
|
699
|
+
color: var(--foreground);
|
|
700
|
+
opacity: 1;
|
|
701
|
+
pointer-events: auto;
|
|
702
|
+
transform-origin: bottom center;
|
|
703
|
+
transition:
|
|
704
|
+
left 240ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
705
|
+
top 240ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
706
|
+
width 240ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
707
|
+
height 240ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
708
|
+
border-radius 200ms ease,
|
|
709
|
+
border-color 180ms ease,
|
|
710
|
+
box-shadow 200ms ease,
|
|
711
|
+
opacity 120ms ease;
|
|
712
|
+
will-change: left, top, width, height;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.floe-bottom-bar-companion[data-companion-phase='expanding'],
|
|
716
|
+
.floe-bottom-bar-companion[data-companion-phase='expanded'] {
|
|
717
|
+
border-radius: var(--floe-bottom-bar-companion-expanded-radius, 0.5rem);
|
|
718
|
+
border-color: color-mix(in srgb, var(--border) 96%, transparent);
|
|
719
|
+
box-shadow:
|
|
720
|
+
0 22px 54px -24px color-mix(in srgb, var(--foreground) 34%, transparent),
|
|
721
|
+
0 6px 18px -12px color-mix(in srgb, var(--foreground) 24%, transparent);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
.floe-bottom-bar-companion[data-companion-phase='collapsing'] {
|
|
725
|
+
transition-duration: 180ms, 180ms, 180ms, 180ms, 160ms, 140ms, 160ms, 100ms;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.floe-bottom-bar-companion[data-companion-visibility='hidden'],
|
|
729
|
+
.floe-bottom-bar-companion[data-companion-frame-ready='false'] {
|
|
730
|
+
visibility: hidden;
|
|
731
|
+
opacity: 0;
|
|
732
|
+
pointer-events: none;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
.floe-bottom-bar-companion__content {
|
|
736
|
+
width: 100%;
|
|
737
|
+
height: 100%;
|
|
738
|
+
min-width: 0;
|
|
739
|
+
min-height: 0;
|
|
740
|
+
overflow: hidden;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
@media (prefers-reduced-motion: reduce) {
|
|
744
|
+
.floe-bottom-bar-companion {
|
|
745
|
+
transition: none;
|
|
746
|
+
will-change: auto;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
690
750
|
@keyframes glow-pulse {
|
|
691
751
|
0%, 100% {
|
|
692
752
|
box-shadow: 0 0 5px var(--primary), 0 0 20px var(--primary);
|