@onnechat/ui 0.2.0 → 0.2.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.mjs CHANGED
@@ -1908,6 +1908,7 @@ var MIN_SIDEBAR_WIDTH = 16 * 16;
1908
1908
  var MAX_SIDEBAR_WIDTH = 20 * 16;
1909
1909
  var COLLAPSE_THRESHOLD = MIN_SIDEBAR_WIDTH / 2;
1910
1910
  var SIDEBAR_COOKIE_TTL_DAYS = 365;
1911
+ var SIDEBAR_ANIMATION_DURATION = "duration-300";
1911
1912
  var SIDEBAR_SIDE_CONFIG = {
1912
1913
  left: {
1913
1914
  defaultWidth: SIDEBAR_WIDTH,
@@ -2231,7 +2232,8 @@ function SidebarSidePanel({
2231
2232
  "aria-hidden": true,
2232
2233
  "data-slot": config.gapSlot,
2233
2234
  className: cn(
2234
- "relative shrink-0 bg-transparent transition-[width] duration-300",
2235
+ "relative shrink-0 bg-transparent transition-[width]",
2236
+ SIDEBAR_ANIMATION_DURATION,
2235
2237
  state === "expanded" ? side === "left" ? "w-(--left-sidebar-width)" : "w-(--right-sidebar-width)" : "w-0"
2236
2238
  )
2237
2239
  }
@@ -2241,7 +2243,8 @@ function SidebarSidePanel({
2241
2243
  {
2242
2244
  "data-slot": config.containerSlot,
2243
2245
  className: cn(
2244
- "fixed z-10 hidden overflow-clip bg-sidebar transition-[width] duration-300 lg:flex",
2246
+ "fixed z-10 hidden overflow-clip bg-sidebar transition-[width] lg:flex",
2247
+ SIDEBAR_ANIMATION_DURATION,
2245
2248
  side === "left" ? "left-0 w-(--left-sidebar-width) group-data-[collapsible=offcanvas]:w-0 justify-end" : "right-0 w-(--right-sidebar-width) group-data-[collapsible=offcanvas]:w-0"
2246
2249
  ),
2247
2250
  style: {
@@ -2281,7 +2284,8 @@ function SidebarSidePanel({
2281
2284
  "after:absolute after:inset-y-0 after:w-1 after:rounded-full after:transition-transform",
2282
2285
  "hover:after:translate-x-0 hover:after:bg-sidebar-border",
2283
2286
  "outline-none focus-visible:ring-ring focus-visible:ring-2 focus-visible:border-ring bg-transparent!",
2284
- side === "left" ? "left-(--left-sidebar-width) group-data-[collapsible=offcanvas]:left-0 -translate-x-1/2 after:left-1/2 after:-translate-x-1/2 transition-[left,transform] duration-300" : "right-(--right-sidebar-width) group-data-[collapsible=offcanvas]:right-0 translate-x-1/2 after:right-1/2 after:translate-x-1/2 transition-[right,transform] duration-300",
2287
+ side === "left" ? "left-(--left-sidebar-width) group-data-[collapsible=offcanvas]:left-0 -translate-x-1/2 after:left-1/2 after:-translate-x-1/2 transition-[left,transform]" : "right-(--right-sidebar-width) group-data-[collapsible=offcanvas]:right-0 translate-x-1/2 after:right-1/2 after:translate-x-1/2 transition-[right,transform]",
2288
+ SIDEBAR_ANIMATION_DURATION,
2285
2289
  isDragging && "after:translate-x-0 after:bg-sidebar-border"
2286
2290
  )
2287
2291
  }
@@ -2741,6 +2745,8 @@ function AppShellHeader({
2741
2745
  title,
2742
2746
  actions,
2743
2747
  user,
2748
+ leftSidebarTrigger,
2749
+ rightSidebarTrigger,
2744
2750
  leftSidebarToggleLabel = "Toggle left sidebar",
2745
2751
  rightSidebarToggleLabel = "Toggle right sidebar",
2746
2752
  mobileActionsClassName,
@@ -2748,8 +2754,10 @@ function AppShellHeader({
2748
2754
  }) {
2749
2755
  const leftSidebar = React9.useContext(AppShellLeftSidebarContext);
2750
2756
  const rightSidebar = React9.useContext(AppShellRightSidebarContext);
2757
+ const resolvedLeftTrigger = leftSidebarTrigger === void 0 ? leftSidebar && /* @__PURE__ */ jsx24(AppShellLeftSidebarTrigger, { label: leftSidebarToggleLabel }) : leftSidebarTrigger;
2758
+ const resolvedRightTrigger = rightSidebarTrigger === void 0 ? rightSidebar && /* @__PURE__ */ jsx24(AppShellRightSidebarTrigger, { label: rightSidebarToggleLabel }) : rightSidebarTrigger;
2751
2759
  return /* @__PURE__ */ jsxs11("div", { "data-slot": "app-shell-header", className: cn("contents", className), ...props, children: [
2752
- /* @__PURE__ */ jsxs11("div", { className: "lg:hidden flex items-center justify-between gap-2 md:gap-4 p-4 min-h-16 h-full max-h-16 glass-dashboard-header max-lg:sticky top-(--announcement-height,0px) z-50 transition-all max-lg:border-b max-lg:border-border/70", children: [
2760
+ /* @__PURE__ */ jsxs11("div", { className: "lg:hidden flex items-center justify-between gap-2 md:gap-4 p-4 min-h-16 h-full max-h-16 glass-dashboard-header max-lg:sticky top-[calc(var(--announcement-height,0px)_+_var(--inset-top-height,0px))] z-50 transition-colors max-lg:border-b max-lg:border-border/70", children: [
2753
2761
  /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 items-center gap-4", children: [
2754
2762
  logo && /* @__PURE__ */ jsx24("div", { className: "shrink-0 active:scale-99", children: logo }),
2755
2763
  /* @__PURE__ */ jsx24("div", { className: "flex min-h-7 min-w-0 flex-1 items-center overflow-hidden", children: /* @__PURE__ */ jsx24("div", { className: "flex min-w-0 flex-1 items-center", children: title }) })
@@ -2757,11 +2765,11 @@ function AppShellHeader({
2757
2765
  /* @__PURE__ */ jsx24("div", { className: cn("flex gap-2 empty:hidden", mobileActionsClassName), children: actions }),
2758
2766
  user
2759
2767
  ] }),
2760
- /* @__PURE__ */ jsxs11("div", { className: "max-lg:hidden sticky top-(--announcement-height,0px) z-50 w-full flex min-w-0 items-center gap-2 md:gap-4 p-4 min-h-16 h-full max-h-16 border-b glass-dashboard-header border-border/70 transition-colors lg:rounded-t-2xl", children: [
2761
- leftSidebar && /* @__PURE__ */ jsx24(AppShellLeftSidebarTrigger, { label: leftSidebarToggleLabel }),
2768
+ /* @__PURE__ */ jsxs11("div", { className: "max-lg:hidden sticky top-[calc(var(--announcement-height,0px)_+_var(--inset-top-height,0px))] z-50 w-full flex min-w-0 items-center gap-2 md:gap-4 p-4 min-h-16 h-full max-h-16 border-b glass-dashboard-header border-border/70 transition-colors lg:rounded-t-2xl", children: [
2769
+ resolvedLeftTrigger,
2762
2770
  /* @__PURE__ */ jsx24("div", { className: "flex min-h-7 min-w-0 flex-1 items-center overflow-hidden", children: /* @__PURE__ */ jsx24("div", { className: "flex min-w-0 flex-1 items-center", children: title }) }),
2763
2771
  /* @__PURE__ */ jsx24("div", { className: "relative z-1 grid grid-flow-col shrink-0 ml-auto gap-2 md:gap-4", children: /* @__PURE__ */ jsx24("div", { className: "min-w-0 flex items-center gap-2 empty:hidden", children: actions }) }),
2764
- rightSidebar && /* @__PURE__ */ jsx24(AppShellRightSidebarTrigger, { label: rightSidebarToggleLabel })
2772
+ resolvedRightTrigger
2765
2773
  ] })
2766
2774
  ] });
2767
2775
  }
@@ -2823,49 +2831,136 @@ function AppShellInset({
2823
2831
  children,
2824
2832
  loading = false,
2825
2833
  spacing = 24,
2834
+ top,
2835
+ bottom,
2826
2836
  ...props
2827
2837
  }) {
2828
2838
  const leftSidebar = React9.useContext(AppShellLeftSidebarContext);
2829
2839
  const rightSidebar = React9.useContext(AppShellRightSidebarContext);
2830
2840
  const hasSidebar = Boolean(leftSidebar || rightSidebar);
2831
- return /* @__PURE__ */ jsxs11(
2832
- "div",
2833
- {
2834
- "data-slot": "app-shell-inset",
2835
- style: {
2836
- "--sidebar-spacing": spacing,
2837
- ...style
2838
- },
2839
- className: cn(
2840
- "relative flex w-full min-h-full flex-1 flex-col transition-[margin] duration-300",
2841
- // The inset chrome (margins + rounding) only exists when at least one
2842
- // sidebar provider frames the page; each margin collapses against the
2843
- // side whose sidebar is expanded.
2844
- hasSidebar && "lg:m-2 lg:rounded-2xl",
2845
- leftSidebar?.state === "expanded" && "lg:ml-0",
2846
- rightSidebar?.state === "expanded" && "lg:mr-0",
2847
- loading && "min-h-0 overflow-hidden",
2848
- "max-lg:bg-dashboard-background! bg-dashboard-background",
2849
- "[--calculated-spacing:--spacing(var(--sidebar-spacing))]",
2850
- // `isolate` keeps composited children (e.g. the glass header's
2851
- // backdrop-filter) inside the rounded overflow clip on all engines.
2852
- "w-full min-w-0 lg:overflow-clip isolate",
2853
- "max-lg:pb-(--calculated-spacing)",
2854
- className
2855
- ),
2856
- ...props,
2857
- children: [
2858
- loading && /* @__PURE__ */ jsx24(AppShellLoading, {}),
2859
- /* @__PURE__ */ jsx24(
2860
- "div",
2861
- {
2862
- "aria-hidden": loading || void 0,
2863
- className: cn(loading ? "hidden" : "contents"),
2864
- children
2865
- }
2866
- )
2867
- ]
2841
+ const columnRef = React9.useRef(null);
2842
+ const topRef = React9.useRef(null);
2843
+ React9.useLayoutEffect(() => {
2844
+ const column = columnRef.current;
2845
+ if (!column) return;
2846
+ const el = topRef.current;
2847
+ if (!top || !el) {
2848
+ column.style.setProperty("--inset-top-height", "0px");
2849
+ return;
2868
2850
  }
2851
+ const update = () => {
2852
+ column.style.setProperty(
2853
+ "--inset-top-height",
2854
+ `${el.getBoundingClientRect().height}px`
2855
+ );
2856
+ };
2857
+ update();
2858
+ if (typeof ResizeObserver === "undefined") return;
2859
+ const ro = new ResizeObserver(update);
2860
+ ro.observe(el);
2861
+ return () => {
2862
+ ro.disconnect();
2863
+ column.style.setProperty("--inset-top-height", "0px");
2864
+ };
2865
+ }, [top]);
2866
+ const pinnedRowBackground = cn(
2867
+ "bg-dashboard-background",
2868
+ hasSidebar && "lg:bg-sidebar"
2869
+ );
2870
+ return (
2871
+ // Transparent column that owns the inset's flex cell so pinned rows can
2872
+ // live outside the rounded panel, over the shell background. The page
2873
+ // keeps its document scroll: the sticky rows hold their screen position
2874
+ // while the panel in between slides normally.
2875
+ /* @__PURE__ */ jsxs11(
2876
+ "div",
2877
+ {
2878
+ ref: columnRef,
2879
+ "data-slot": "app-shell-inset-column",
2880
+ className: "relative flex w-full min-w-0 min-h-full flex-1 flex-col",
2881
+ children: [
2882
+ top ? /* @__PURE__ */ jsx24(
2883
+ "div",
2884
+ {
2885
+ ref: topRef,
2886
+ "data-slot": "app-shell-inset-top",
2887
+ className: cn(
2888
+ "sticky top-(--announcement-height,0px) z-40 shrink-0",
2889
+ // On mobile the row and the panel share the same background —
2890
+ // without a divider, scrolling content is chopped at an
2891
+ // invisible line. Desktop gets a tonal boundary from bg-sidebar.
2892
+ "max-lg:border-b max-lg:border-border/70",
2893
+ pinnedRowBackground
2894
+ ),
2895
+ children: top
2896
+ }
2897
+ ) : null,
2898
+ /* @__PURE__ */ jsxs11(
2899
+ "div",
2900
+ {
2901
+ "data-slot": "app-shell-inset",
2902
+ style: {
2903
+ "--sidebar-spacing": spacing,
2904
+ ...style
2905
+ },
2906
+ className: cn(
2907
+ // No `w-full` here: the column's cross-axis stretch sizes the panel
2908
+ // to its width MINUS the side margins below — `w-full` + `mr-2`
2909
+ // would overflow the column by the margin, gluing the panel to the
2910
+ // viewport edge (and clipping its rounded corner) whenever the
2911
+ // right sidebar is collapsed.
2912
+ "relative flex flex-1 flex-col transition-[margin]",
2913
+ SIDEBAR_ANIMATION_DURATION,
2914
+ // The inset chrome (margins + rounding) only exists when at least one
2915
+ // sidebar provider frames the page; each margin collapses against the
2916
+ // side whose sidebar is expanded.
2917
+ hasSidebar && "lg:m-2 lg:rounded-2xl",
2918
+ leftSidebar?.state === "expanded" && "lg:ml-0",
2919
+ rightSidebar?.state === "expanded" && "lg:mr-0",
2920
+ loading && "min-h-0 overflow-hidden",
2921
+ "max-lg:bg-dashboard-background! bg-dashboard-background",
2922
+ "[--calculated-spacing:--spacing(var(--sidebar-spacing))]",
2923
+ // `isolate` keeps composited children (e.g. the glass header's
2924
+ // backdrop-filter) inside the rounded overflow clip on all engines.
2925
+ "min-w-0 isolate lg:overflow-clip",
2926
+ "max-lg:pb-(--calculated-spacing)",
2927
+ className
2928
+ ),
2929
+ ...props,
2930
+ children: [
2931
+ loading && /* @__PURE__ */ jsx24(AppShellLoading, {}),
2932
+ /* @__PURE__ */ jsx24(
2933
+ "div",
2934
+ {
2935
+ "aria-hidden": loading || void 0,
2936
+ className: cn(loading ? "hidden" : "contents"),
2937
+ children
2938
+ }
2939
+ )
2940
+ ]
2941
+ }
2942
+ ),
2943
+ bottom ? /* @__PURE__ */ jsx24(
2944
+ "div",
2945
+ {
2946
+ "data-slot": "app-shell-inset-bottom",
2947
+ className: cn(
2948
+ "sticky bottom-0 z-40 shrink-0",
2949
+ // Divider against the same-background panel on mobile (mirrors
2950
+ // the mobile Header's border-b).
2951
+ "max-lg:border-t max-lg:border-border/70",
2952
+ // The floating mobile Navbar (fixed bottom, z-50, ~100px tall)
2953
+ // would bury and cover this row — when a Navbar is mounted in
2954
+ // the shell, the row yields to it below `lg`.
2955
+ "max-lg:[[data-slot=app-shell]:has([data-slot=app-shell-navbar])_&]:hidden",
2956
+ pinnedRowBackground
2957
+ ),
2958
+ children: bottom
2959
+ }
2960
+ ) : null
2961
+ ]
2962
+ }
2963
+ )
2869
2964
  );
2870
2965
  }
2871
2966
  function AppShellLoading({ className, ...props }) {
@@ -15027,6 +15122,7 @@ export {
15027
15122
  TextShimmer,
15028
15123
  Textarea,
15029
15124
  Toaster,
15125
+ Tooltip,
15030
15126
  TrackerChart,
15031
15127
  VideoPlayer,
15032
15128
  VideoPlayerContent,