@mario_hahn/jumpy-ui 0.10.0 → 0.11.0
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/README.md +5 -1
- package/dist/{chunk-LORNGSIB.js → chunk-V3XYXQPA.js} +46 -2
- package/dist/index.js +91 -28
- package/dist/theme.js +1 -1
- package/index.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -211,7 +211,7 @@ Jumpy Components als ein gemeinsames UI-Paket.
|
|
|
211
211
|
Starting with 0.5.0, Jumpy UI uses the public npmjs registry. No package token is required to install:
|
|
212
212
|
|
|
213
213
|
```bash
|
|
214
|
-
npm install @mario_hahn/jumpy-ui@^0.
|
|
214
|
+
npm install @mario_hahn/jumpy-ui@^0.11.0
|
|
215
215
|
```
|
|
216
216
|
|
|
217
217
|
The public npm package uses the `@mario_hahn` scope. Older GitHub Packages releases
|
|
@@ -324,6 +324,10 @@ import { JumpAppShell, JumpSideMenu, JumpSideMenuItem, JumpTabBar, JumpTabBarIte
|
|
|
324
324
|
- `topBar.leading` defaults to `'menu'` when `navigation` exists; `'back'` calls
|
|
325
325
|
`onBack`. `topBar.title` falls back to `brand`. `topBar.desktop` keeps the bar on
|
|
326
326
|
desktop (without the menu button). `topBar={null}` removes it.
|
|
327
|
+
- `topBar.largeTitle` (0.11.0+) renders `title`/`subtitle` as a large page `h1`; on
|
|
328
|
+
mobile the bar stays empty and blends into the page until that heading scrolls under
|
|
329
|
+
it, then shows a compact centered title. Set `--jumpy-app-shell-gutter` to match your
|
|
330
|
+
content padding. Do not render a second page heading yourself.
|
|
327
331
|
- `JumpTopBar` and `JumpTabBar` also work standalone. Both are sticky and include
|
|
328
332
|
safe-area insets. `JumpTabBarItem` accepts `as` (e.g. Next `Link`), `href`, `icon`,
|
|
329
333
|
numeric or custom `badge` and `selected` (`aria-current="page"`).
|
|
@@ -9945,7 +9945,8 @@ var providerStyles = `
|
|
|
9945
9945
|
}
|
|
9946
9946
|
|
|
9947
9947
|
/* An icon SVG fills the leading slot: otherwise a 20px icon is squeezed to the slot width but keeps its height and drops below the label. */
|
|
9948
|
-
[data-jumpy-theme='true'] :is([data-jumpy-component='list-item'], [data-jumpy-component='menu-item'], [data-jumpy-component='side-menu-item']) > [data-jumpy-slot='leading'] > svg
|
|
9948
|
+
[data-jumpy-theme='true'] :is([data-jumpy-component='list-item'], [data-jumpy-component='menu-item'], [data-jumpy-component='side-menu-item']) > [data-jumpy-slot='leading'] > svg,
|
|
9949
|
+
[data-jumpy-theme='true'] [data-jumpy-component='tab-bar-item'] > [data-jumpy-slot='tab-bar-item-icon'] > svg {
|
|
9949
9950
|
width: 100%;
|
|
9950
9951
|
height: 100%;
|
|
9951
9952
|
flex: none;
|
|
@@ -11869,6 +11870,19 @@ var providerStyles = `
|
|
|
11869
11870
|
box-shadow: var(--jumpy-shadow-positive-small);
|
|
11870
11871
|
}
|
|
11871
11872
|
|
|
11873
|
+
[data-jumpy-theme='true'] [data-jumpy-component='top-bar'] > [data-jumpy-slot='top-bar-title'] {
|
|
11874
|
+
transition: opacity var(--jumpy-animation-duration-xsmall) var(--jumpy-animation-easing-drift);
|
|
11875
|
+
}
|
|
11876
|
+
|
|
11877
|
+
/* Large-title mode: until the page title scrolls under it, the bar blends into the page (iOS). */
|
|
11878
|
+
[data-jumpy-theme='true'] [data-jumpy-component='top-bar'][data-large-title='true'][data-title-hidden='true'] {
|
|
11879
|
+
background-color: var(--jumpy-color-surface-canvas);
|
|
11880
|
+
border-bottom-color: transparent;
|
|
11881
|
+
box-shadow: none;
|
|
11882
|
+
-webkit-backdrop-filter: none;
|
|
11883
|
+
backdrop-filter: none;
|
|
11884
|
+
}
|
|
11885
|
+
|
|
11872
11886
|
[data-jumpy-theme='true'] [data-jumpy-component='tab-bar-item'] {
|
|
11873
11887
|
transition: background-color var(--jumpy-animation-duration-xsmall) var(--jumpy-animation-easing-drift), color var(--jumpy-animation-duration-xsmall) var(--jumpy-animation-easing-drift);
|
|
11874
11888
|
-webkit-tap-highlight-color: transparent;
|
|
@@ -11887,13 +11901,43 @@ var providerStyles = `
|
|
|
11887
11901
|
animation: jumpy-app-shell-drawer-in var(--jumpy-animation-duration-small) var(--jumpy-animation-easing-drift);
|
|
11888
11902
|
}
|
|
11889
11903
|
|
|
11904
|
+
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer'][data-state='closing'] {
|
|
11905
|
+
animation: jumpy-app-shell-drawer-out var(--jumpy-animation-duration-small) var(--jumpy-animation-easing-release) forwards;
|
|
11906
|
+
pointer-events: none;
|
|
11907
|
+
}
|
|
11908
|
+
|
|
11909
|
+
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer-overlay'] {
|
|
11910
|
+
animation: jumpy-app-shell-overlay-in var(--jumpy-animation-duration-small) var(--jumpy-animation-easing-drift);
|
|
11911
|
+
}
|
|
11912
|
+
|
|
11913
|
+
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer-overlay'][data-state='closing'] {
|
|
11914
|
+
animation: jumpy-app-shell-overlay-out var(--jumpy-animation-duration-small) var(--jumpy-animation-easing-release) forwards;
|
|
11915
|
+
pointer-events: none;
|
|
11916
|
+
}
|
|
11917
|
+
|
|
11890
11918
|
@keyframes jumpy-app-shell-drawer-in {
|
|
11891
11919
|
from { transform: translateX(-100%); }
|
|
11892
11920
|
to { transform: translateX(0); }
|
|
11893
11921
|
}
|
|
11894
11922
|
|
|
11923
|
+
@keyframes jumpy-app-shell-drawer-out {
|
|
11924
|
+
from { transform: translateX(0); }
|
|
11925
|
+
to { transform: translateX(-100%); }
|
|
11926
|
+
}
|
|
11927
|
+
|
|
11928
|
+
@keyframes jumpy-app-shell-overlay-in {
|
|
11929
|
+
from { opacity: 0; }
|
|
11930
|
+
to { opacity: 1; }
|
|
11931
|
+
}
|
|
11932
|
+
|
|
11933
|
+
@keyframes jumpy-app-shell-overlay-out {
|
|
11934
|
+
from { opacity: 1; }
|
|
11935
|
+
to { opacity: 0; }
|
|
11936
|
+
}
|
|
11937
|
+
|
|
11895
11938
|
@media (prefers-reduced-motion: reduce) {
|
|
11896
|
-
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer']
|
|
11939
|
+
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer'],
|
|
11940
|
+
[data-jumpy-theme='true'] [data-jumpy-component='app-shell-drawer-overlay'] {
|
|
11897
11941
|
animation: none;
|
|
11898
11942
|
}
|
|
11899
11943
|
}
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
textStyleValue,
|
|
29
29
|
themeToCSSVariables,
|
|
30
30
|
useJumpyTheme
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-V3XYXQPA.js";
|
|
32
32
|
import {
|
|
33
33
|
cn
|
|
34
34
|
} from "./chunk-3DBKYKP2.js";
|
|
@@ -2416,7 +2416,7 @@ function JumpyNavigationIcon({ type }) {
|
|
|
2416
2416
|
};
|
|
2417
2417
|
return /* @__PURE__ */ jsx2("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", focusable: "false", "data-jumpy-stroke-icon": "true", style: { display: "block" }, children: /* @__PURE__ */ jsx2("path", { d: paths[type] }) });
|
|
2418
2418
|
}
|
|
2419
|
-
function JumpTopBar({ leading, onMenu, onBack, menuOpen = false, title, subtitle, trailing, sticky = true, ariaLabels = {}, className = "", ...props }) {
|
|
2419
|
+
function JumpTopBar({ leading, onMenu, onBack, menuOpen = false, title, subtitle, trailing, sticky = true, titleAlign = "start", titleHidden = false, ariaLabels = {}, className = "", ...props }) {
|
|
2420
2420
|
const theme = useJumpyTheme();
|
|
2421
2421
|
const [scrolled, setScrolled] = useState2(false);
|
|
2422
2422
|
const titleStyle = textStyleValue(theme, JumpyTextStyle.bodyLargeEmphasized);
|
|
@@ -2437,6 +2437,8 @@ function JumpTopBar({ leading, onMenu, onBack, menuOpen = false, title, subtitle
|
|
|
2437
2437
|
"data-jumpy-component": "top-bar",
|
|
2438
2438
|
"data-sticky": sticky ? "true" : "false",
|
|
2439
2439
|
"data-scrolled": scrolled ? "true" : "false",
|
|
2440
|
+
"data-title-align": titleAlign,
|
|
2441
|
+
"data-title-hidden": titleHidden ? "true" : "false",
|
|
2440
2442
|
className: cn(className),
|
|
2441
2443
|
style: {
|
|
2442
2444
|
boxSizing: "border-box",
|
|
@@ -2453,11 +2455,25 @@ function JumpTopBar({ leading, onMenu, onBack, menuOpen = false, title, subtitle
|
|
|
2453
2455
|
},
|
|
2454
2456
|
children: [
|
|
2455
2457
|
leadingNode ? /* @__PURE__ */ jsx2("span", { "data-jumpy-slot": "top-bar-leading", "data-leading": leadingType, style: { marginLeft: -spacingValue(theme, JumpySpacing.smallXS) }, children: leadingNode }) : null,
|
|
2456
|
-
/* @__PURE__ */ jsxs2("span", { "data-jumpy-slot": "top-bar-title",
|
|
2457
|
-
|
|
2458
|
-
|
|
2458
|
+
/* @__PURE__ */ jsxs2("span", { "data-jumpy-slot": "top-bar-title", "aria-hidden": titleHidden || void 0, style: titleAlign === "center" ? {
|
|
2459
|
+
position: "absolute",
|
|
2460
|
+
left: `calc(${sizeValue(theme, JumpySize.largeXL) + spacingValue(theme, JumpySpacing.large)}px + env(safe-area-inset-left, 0px))`,
|
|
2461
|
+
right: `calc(${sizeValue(theme, JumpySize.largeXL) + spacingValue(theme, JumpySpacing.large)}px + env(safe-area-inset-right, 0px))`,
|
|
2462
|
+
top: "env(safe-area-inset-top, 0px)",
|
|
2463
|
+
bottom: 0,
|
|
2464
|
+
display: "flex",
|
|
2465
|
+
flexDirection: "column",
|
|
2466
|
+
alignItems: "center",
|
|
2467
|
+
justifyContent: "center",
|
|
2468
|
+
textAlign: "center",
|
|
2469
|
+
minWidth: 0,
|
|
2470
|
+
pointerEvents: "none",
|
|
2471
|
+
opacity: titleHidden ? 0 : 1
|
|
2472
|
+
} : { display: "flex", flexDirection: "column", flex: "1 1 auto", minWidth: 0, opacity: titleHidden ? 0 : 1 }, children: [
|
|
2473
|
+
title ? /* @__PURE__ */ jsx2("span", { style: { maxWidth: "100%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: titleStyle.fontSize, lineHeight: titleStyle.lineHeight, fontWeight: titleStyle.fontWeight }, children: title }) : null,
|
|
2474
|
+
subtitle ? /* @__PURE__ */ jsx2("span", { style: { maxWidth: "100%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: "var(--jumpy-color-text-secondary)", fontSize: subtitleStyle.fontSize, lineHeight: subtitleStyle.lineHeight }, children: subtitle }) : null
|
|
2459
2475
|
] }),
|
|
2460
|
-
trailing ? /* @__PURE__ */ jsx2("span", { "data-jumpy-slot": "top-bar-trailing", style: { display: "inline-flex", flex: "0 0 auto", alignItems: "center", gap: spacingValue(theme, JumpySpacing.smallXS) }, children: trailing }) : null
|
|
2476
|
+
trailing ? /* @__PURE__ */ jsx2("span", { "data-jumpy-slot": "top-bar-trailing", style: { display: "inline-flex", flex: "0 0 auto", marginLeft: "auto", alignItems: "center", gap: spacingValue(theme, JumpySpacing.smallXS) }, children: trailing }) : null
|
|
2461
2477
|
]
|
|
2462
2478
|
}
|
|
2463
2479
|
);
|
|
@@ -2504,7 +2520,7 @@ function JumpTabBar({ children, className = "", "aria-label": ariaLabel = "Main
|
|
|
2504
2520
|
function JumpTabBarItem({ as, icon, badge, selected = false, children, className = "", ...props }) {
|
|
2505
2521
|
const theme = useJumpyTheme();
|
|
2506
2522
|
const Component = as || (props.href ? "a" : "button");
|
|
2507
|
-
const labelStyle = textStyleValue(theme, JumpyTextStyle.
|
|
2523
|
+
const labelStyle = textStyleValue(theme, JumpyTextStyle.labelSmall);
|
|
2508
2524
|
const badgeNode = typeof badge === "number" ? badge > 0 ? /* @__PURE__ */ jsx2(JumpBadge, { size: "small", status: "active", "aria-label": void 0, role: "presentation", "aria-live": "off", children: badge > 99 ? "99+" : badge }) : null : badge;
|
|
2509
2525
|
return /* @__PURE__ */ jsxs2(
|
|
2510
2526
|
Component,
|
|
@@ -2539,7 +2555,7 @@ function JumpTabBarItem({ as, icon, badge, selected = false, children, className
|
|
|
2539
2555
|
...props.style || {}
|
|
2540
2556
|
},
|
|
2541
2557
|
children: [
|
|
2542
|
-
icon ? /* @__PURE__ */ jsxs2("span", { "data-jumpy-slot": "tab-bar-item-icon", "aria-hidden": "true", style: { position: "relative", display: "inline-flex", width: sizeValue(theme, JumpySize.
|
|
2558
|
+
icon ? /* @__PURE__ */ jsxs2("span", { "data-jumpy-slot": "tab-bar-item-icon", "aria-hidden": "true", style: { position: "relative", display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, width: sizeValue(theme, JumpySize.smallXS), height: sizeValue(theme, JumpySize.smallXS) }, children: [
|
|
2543
2559
|
icon,
|
|
2544
2560
|
badgeNode ? /* @__PURE__ */ jsx2("span", { "data-jumpy-slot": "tab-bar-item-badge", style: { position: "absolute", top: -spacingValue(theme, JumpySpacing.smallXS), left: "50%", marginLeft: spacingValue(theme, JumpySpacing.small3XS), display: "inline-flex" }, children: badgeNode }) : null
|
|
2545
2561
|
] }) : null,
|
|
@@ -2555,8 +2571,14 @@ function JumpAppShell({ brand, navigation, sidebarFooter, topBar, tabBar, hideTa
|
|
|
2555
2571
|
const isOpen = Boolean(navigation) && (navigationOpen ?? internalOpen);
|
|
2556
2572
|
const swipeStart = useRef2(null);
|
|
2557
2573
|
const rootRef = useRef2(null);
|
|
2558
|
-
const
|
|
2559
|
-
const
|
|
2574
|
+
const [drawerMounted, setDrawerMounted] = useState2(isOpen);
|
|
2575
|
+
const showDrawer = isOpen || drawerMounted;
|
|
2576
|
+
const closing = drawerMounted && !isOpen;
|
|
2577
|
+
const wasShown = useRef2(showDrawer);
|
|
2578
|
+
const { desktop: topBarOnDesktop = false, leading, largeTitle = false, ...topBarProps } = topBar || {};
|
|
2579
|
+
const showLargeTitle = largeTitle && Boolean(topBarProps.title);
|
|
2580
|
+
const largeTitleRef = useRef2(null);
|
|
2581
|
+
const [largeTitleCovered, setLargeTitleCovered] = useState2(false);
|
|
2560
2582
|
const resolvedLeading = leading ?? (navigation ? "menu" : void 0);
|
|
2561
2583
|
const shell = `[data-jumpy-app-shell="${shellId}"]`;
|
|
2562
2584
|
const width = typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth;
|
|
@@ -2575,15 +2597,37 @@ function JumpAppShell({ brand, navigation, sidebarFooter, topBar, tabBar, hideTa
|
|
|
2575
2597
|
return () => desktop.removeEventListener("change", closeOnDesktop);
|
|
2576
2598
|
});
|
|
2577
2599
|
useEffect2(() => {
|
|
2578
|
-
|
|
2579
|
-
|
|
2600
|
+
if (isOpen) {
|
|
2601
|
+
setDrawerMounted(true);
|
|
2602
|
+
return void 0;
|
|
2603
|
+
}
|
|
2604
|
+
if (!drawerMounted) return void 0;
|
|
2605
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
2606
|
+
setDrawerMounted(false);
|
|
2607
|
+
return void 0;
|
|
2608
|
+
}
|
|
2609
|
+
const timer = window.setTimeout(() => setDrawerMounted(false), animationDurationValue(theme, JumpyAnimationDuration.small) * 1e3 + 100);
|
|
2610
|
+
return () => window.clearTimeout(timer);
|
|
2611
|
+
}, [isOpen, drawerMounted]);
|
|
2612
|
+
useEffect2(() => {
|
|
2613
|
+
const closed = wasShown.current && !showDrawer;
|
|
2614
|
+
wasShown.current = showDrawer;
|
|
2580
2615
|
if (!closed) return void 0;
|
|
2581
2616
|
const frame = window.requestAnimationFrame(() => {
|
|
2582
2617
|
if (document.activeElement && document.activeElement !== document.body) return;
|
|
2583
2618
|
rootRef.current?.querySelector(':scope > [data-jumpy-slot="app-shell-body"] > [data-jumpy-component="top-bar"] > [data-leading="menu"] button')?.focus();
|
|
2584
2619
|
});
|
|
2585
2620
|
return () => window.cancelAnimationFrame(frame);
|
|
2586
|
-
}, [
|
|
2621
|
+
}, [showDrawer]);
|
|
2622
|
+
useEffect2(() => {
|
|
2623
|
+
const element = largeTitleRef.current;
|
|
2624
|
+
if (!showLargeTitle || !element || typeof IntersectionObserver === "undefined") return void 0;
|
|
2625
|
+
const bar = rootRef.current?.querySelector(':scope > [data-jumpy-slot="app-shell-body"] > [data-jumpy-component="top-bar"]');
|
|
2626
|
+
const barHeight = bar && bar.getBoundingClientRect().height > 0 ? bar.getBoundingClientRect().height : 0;
|
|
2627
|
+
const observer = new IntersectionObserver(([entry]) => setLargeTitleCovered(!entry.isIntersecting), { rootMargin: `-${Math.round(barHeight)}px 0px 0px 0px` });
|
|
2628
|
+
observer.observe(element);
|
|
2629
|
+
return () => observer.disconnect();
|
|
2630
|
+
}, [showLargeTitle, topBarProps.title]);
|
|
2587
2631
|
function closeOnNavigate(event) {
|
|
2588
2632
|
const item = event.target.closest?.('a[href], [data-jumpy-component="side-menu-item"]');
|
|
2589
2633
|
if (!item || item.hasAttribute("aria-expanded") || item.getAttribute("aria-disabled") === "true" || item.disabled) return;
|
|
@@ -2608,6 +2652,10 @@ ${shell} > [data-jumpy-slot='app-shell-sidebar'] { display: none; }
|
|
|
2608
2652
|
menuOpen: isOpen,
|
|
2609
2653
|
onMenu: () => setOpen(true),
|
|
2610
2654
|
title: topBarProps.title ?? brand,
|
|
2655
|
+
subtitle: showLargeTitle ? void 0 : topBarProps.subtitle,
|
|
2656
|
+
titleAlign: showLargeTitle ? "center" : topBarProps.titleAlign,
|
|
2657
|
+
titleHidden: showLargeTitle ? !largeTitleCovered : topBarProps.titleHidden,
|
|
2658
|
+
"data-large-title": showLargeTitle ? "true" : void 0,
|
|
2611
2659
|
ariaLabels: { menu: ariaLabels.openNavigation, back: ariaLabels.back, ...topBarProps.ariaLabels || {} }
|
|
2612
2660
|
}
|
|
2613
2661
|
);
|
|
@@ -2641,29 +2689,39 @@ ${shell} > [data-jumpy-slot='app-shell-sidebar'] { display: none; }
|
|
|
2641
2689
|
top: 0,
|
|
2642
2690
|
height: "100dvh",
|
|
2643
2691
|
flexDirection: "column",
|
|
2644
|
-
|
|
2692
|
+
overflow: "hidden",
|
|
2645
2693
|
borderRight: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)`,
|
|
2646
2694
|
backgroundColor: "var(--jumpy-color-surface-card)"
|
|
2647
2695
|
},
|
|
2648
2696
|
children: [
|
|
2649
|
-
brand ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-brand", style: { padding: spacingValue(theme, JumpySpacing.large2XL), borderBottom: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)` }, children: brand }) : null,
|
|
2650
|
-
navigation ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-navigation", style: { flex: 1, padding: spacingValue(theme, JumpySpacing.large) }, children: navigation }) : null,
|
|
2651
|
-
sidebarFooter ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-sidebar-footer", style: { padding: spacingValue(theme, JumpySpacing.large), borderTop: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)` }, children: sidebarFooter }) : null
|
|
2697
|
+
brand ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-brand", style: { flex: "0 0 auto", padding: spacingValue(theme, JumpySpacing.large2XL), borderBottom: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)` }, children: brand }) : null,
|
|
2698
|
+
navigation ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-navigation", style: { flex: "1 1 auto", minHeight: 0, overflowY: "auto", overscrollBehavior: "contain", padding: spacingValue(theme, JumpySpacing.large) }, children: navigation }) : null,
|
|
2699
|
+
sidebarFooter ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-sidebar-footer", style: { flex: "0 0 auto", padding: spacingValue(theme, JumpySpacing.large), borderTop: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)` }, children: sidebarFooter }) : null
|
|
2652
2700
|
]
|
|
2653
2701
|
}
|
|
2654
2702
|
),
|
|
2655
2703
|
/* @__PURE__ */ jsxs2("div", { "data-jumpy-slot": "app-shell-body", style: { display: "flex", flexDirection: "column", minWidth: 0, minHeight: "100dvh" }, children: [
|
|
2656
2704
|
topBar !== null ? topBarNode : null,
|
|
2657
|
-
/* @__PURE__ */
|
|
2705
|
+
/* @__PURE__ */ jsxs2("main", { "data-jumpy-slot": "app-shell-content", style: { flex: 1, minWidth: 0 }, children: [
|
|
2706
|
+
showLargeTitle ? /* @__PURE__ */ jsxs2("div", { "data-jumpy-slot": "app-shell-large-title", style: { padding: `${spacingValue(theme, JumpySpacing.smallXS)}px calc(var(--jumpy-app-shell-gutter, ${spacingValue(theme, JumpySpacing.large)}px) + env(safe-area-inset-right, 0px)) 0 calc(var(--jumpy-app-shell-gutter, ${spacingValue(theme, JumpySpacing.large)}px) + env(safe-area-inset-left, 0px))` }, children: [
|
|
2707
|
+
/* @__PURE__ */ jsx2("h1", { ref: largeTitleRef, style: { margin: 0, ...textStyleValue(theme, JumpyTextStyle.displaySmallEmphasized), overflowWrap: "anywhere" }, children: topBarProps.title }),
|
|
2708
|
+
topBarProps.subtitle ? /* @__PURE__ */ jsx2("p", { style: { margin: `${spacingValue(theme, JumpySpacing.small4XS)}px 0 0`, color: "var(--jumpy-color-text-secondary)", ...textStyleValue(theme, JumpyTextStyle.bodyMedium) }, children: topBarProps.subtitle }) : null
|
|
2709
|
+
] }) : null,
|
|
2710
|
+
children
|
|
2711
|
+
] }),
|
|
2658
2712
|
tabBar && !hideTabBar ? tabBar : null
|
|
2659
2713
|
] }),
|
|
2660
|
-
|
|
2714
|
+
showDrawer ? /* @__PURE__ */ jsx2(JumpyModalLayer, { onVisibleChange: setOpen, "data-jumpy-component": "app-shell-drawer-overlay", "data-state": closing ? "closing" : "open", style: { position: "fixed", inset: 0, zIndex: 60, backgroundColor: "var(--jumpy-color-surface-overlay)" }, children: /* @__PURE__ */ jsxs2(
|
|
2661
2715
|
"div",
|
|
2662
2716
|
{
|
|
2663
2717
|
role: "dialog",
|
|
2664
2718
|
"aria-modal": "true",
|
|
2665
2719
|
"aria-label": ariaLabels.navigation || "Navigation",
|
|
2666
2720
|
"data-jumpy-component": "app-shell-drawer",
|
|
2721
|
+
"data-state": closing ? "closing" : "open",
|
|
2722
|
+
onAnimationEnd: (event) => {
|
|
2723
|
+
if (closing && event.target === event.currentTarget) setDrawerMounted(false);
|
|
2724
|
+
},
|
|
2667
2725
|
onClick: closeOnNavigate,
|
|
2668
2726
|
onTouchStart: (event) => {
|
|
2669
2727
|
const touch = event.touches[0];
|
|
@@ -2686,20 +2744,25 @@ ${shell} > [data-jumpy-slot='app-shell-sidebar'] { display: none; }
|
|
|
2686
2744
|
flexDirection: "column",
|
|
2687
2745
|
width: "100vw",
|
|
2688
2746
|
height: "100dvh",
|
|
2689
|
-
|
|
2747
|
+
overflow: "hidden",
|
|
2690
2748
|
outline: "none",
|
|
2691
2749
|
backgroundColor: "var(--jumpy-color-surface-card)",
|
|
2692
2750
|
color: "var(--jumpy-color-text-primary)",
|
|
2693
|
-
fontFamily: theme.fontFamily.familyBase
|
|
2694
|
-
paddingBottom: "env(safe-area-inset-bottom, 0px)"
|
|
2751
|
+
fontFamily: theme.fontFamily.familyBase
|
|
2695
2752
|
},
|
|
2696
2753
|
children: [
|
|
2697
|
-
/* @__PURE__ */
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2754
|
+
/* @__PURE__ */ jsx2(
|
|
2755
|
+
JumpTopBar,
|
|
2756
|
+
{
|
|
2757
|
+
"data-jumpy-slot": "app-shell-drawer-header",
|
|
2758
|
+
sticky: false,
|
|
2759
|
+
style: { flex: "0 0 auto" },
|
|
2760
|
+
leading: /* @__PURE__ */ jsx2(JumpIconButton, { variant: "borderless", "aria-label": ariaLabels.closeNavigation || "Close navigation", onClick: () => setOpen(false), children: /* @__PURE__ */ jsx2(JumpyNavigationIcon, { type: "close" }) }),
|
|
2761
|
+
title: brand
|
|
2762
|
+
}
|
|
2763
|
+
),
|
|
2764
|
+
/* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-drawer-navigation", style: { flex: "1 1 auto", minHeight: 0, overflowY: "auto", overscrollBehavior: "contain", padding: spacingValue(theme, JumpySpacing.large) }, children: navigation }),
|
|
2765
|
+
sidebarFooter ? /* @__PURE__ */ jsx2("div", { "data-jumpy-slot": "app-shell-drawer-footer", style: { flex: "0 0 auto", padding: `${spacingValue(theme, JumpySpacing.large)}px calc(${spacingValue(theme, JumpySpacing.large)}px + env(safe-area-inset-right, 0px)) calc(${spacingValue(theme, JumpySpacing.large)}px + env(safe-area-inset-bottom, 0px)) calc(${spacingValue(theme, JumpySpacing.large)}px + env(safe-area-inset-left, 0px))`, borderTop: `${borderWidthValue(theme, JumpyBorderWidth.small)}px solid var(--jumpy-color-border-subtle)`, backgroundColor: "var(--jumpy-color-surface-card)" }, children: sidebarFooter }) : null
|
|
2703
2766
|
]
|
|
2704
2767
|
}
|
|
2705
2768
|
) }) : null
|
package/dist/theme.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -111,12 +111,12 @@ export declare function JumpTableCell(props: Omit<TdHTMLAttributes<HTMLTableCell
|
|
|
111
111
|
export declare function JumpTableHeaderCell(props: Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> & { as?: ElementTag; ref?: Ref<HTMLTableCellElement>; selected?: boolean; disabled?: boolean; align?: JumpTableAlign; variant?: 'default' | 'control'; padding?: 'default' | 'none' | 'checkbox'; showHorizontalBorder?: boolean; pinned?: JumpTablePinned; pinnedEdge?: boolean; sortable?: boolean; sortOrder?: JumpTableSortOrder; onSortChange?: (sortOrder: JumpTableSortOrder) => void; ariaLabels?: { sort?: string | ((sortOrder: JumpTableSortOrder) => string) }; leading?: ReactNode; trailing?: ReactNode; slots?: { leading?: ReactNode; trailing?: ReactNode }; innerClasses?: JumpTableCellInnerClasses; children?: ReactNode }): ReactNode
|
|
112
112
|
export declare function JumpSheet(props: HTMLAttributes<HTMLElement> & { visible?: boolean; onVisibleChange?: (visible: boolean) => void; position?: 'top' | 'right' | 'bottom' | 'left'; title?: string; subtitle?: string; footer?: ReactNode; children?: ReactNode }): ReactNode
|
|
113
113
|
export type JumpTopBarLeading = 'menu' | 'back' | ReactNode
|
|
114
|
-
export type JumpTopBarProps = Omit<HTMLAttributes<HTMLElement>, 'title'> & { leading?: JumpTopBarLeading; onMenu?: () => void; onBack?: () => void; menuOpen?: boolean; title?: ReactNode; subtitle?: ReactNode; trailing?: ReactNode; sticky?: boolean; ariaLabels?: { menu?: string; back?: string } }
|
|
114
|
+
export type JumpTopBarProps = Omit<HTMLAttributes<HTMLElement>, 'title'> & { leading?: JumpTopBarLeading; onMenu?: () => void; onBack?: () => void; menuOpen?: boolean; title?: ReactNode; subtitle?: ReactNode; trailing?: ReactNode; sticky?: boolean; titleAlign?: 'start' | 'center'; titleHidden?: boolean; ariaLabels?: { menu?: string; back?: string } }
|
|
115
115
|
export declare function JumpTopBar(props: JumpTopBarProps): ReactNode
|
|
116
116
|
export declare function JumpTabBar(props: HTMLAttributes<HTMLElement> & { children: ReactNode }): ReactNode
|
|
117
117
|
export type JumpTabBarItemProps = { as?: ElementType; href?: string; icon?: ReactNode; badge?: ReactNode | number; selected?: boolean; children: ReactNode; className?: string; style?: CSSProperties } & Record<string, unknown>
|
|
118
118
|
export declare function JumpTabBarItem(props: JumpTabBarItemProps): ReactNode
|
|
119
|
-
export type JumpAppShellTopBar = Omit<JumpTopBarProps, 'onMenu' | 'menuOpen'> & { desktop?: boolean }
|
|
119
|
+
export type JumpAppShellTopBar = Omit<JumpTopBarProps, 'onMenu' | 'menuOpen'> & { desktop?: boolean; largeTitle?: boolean }
|
|
120
120
|
export declare function JumpAppShell(props: HTMLAttributes<HTMLDivElement> & { brand?: ReactNode; navigation?: ReactNode; sidebarFooter?: ReactNode; topBar?: JumpAppShellTopBar | null; tabBar?: ReactNode; hideTabBar?: boolean; breakpoint?: number; sidebarWidth?: number | string; navigationOpen?: boolean; defaultNavigationOpen?: boolean; onNavigationOpenChange?: (open: boolean) => void; ariaLabels?: { navigation?: string; openNavigation?: string; closeNavigation?: string; back?: string }; children?: ReactNode }): ReactNode
|
|
121
121
|
export declare function JumpSectionHeader(props: HTMLAttributes<HTMLElement> & { as?: ElementTag; variant?: 'regular' | 'prominent'; description?: ReactNode; children: ReactNode }): ReactNode
|
|
122
122
|
export declare function JumpSectionFooter(props: HTMLAttributes<HTMLElement> & { as?: ElementTag; children: ReactNode }): ReactNode
|