@postxl/ui-components 1.5.5 → 1.6.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/dist/index.js CHANGED
@@ -91,6 +91,7 @@ import { DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringStrateg
91
91
  import { SortableContext, arrayMove, defaultAnimateLayoutChanges, horizontalListSortingStrategy, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
92
92
  import { CSS } from "@dnd-kit/utilities";
93
93
  import * as ReactDOM from "react-dom";
94
+ import { createPortal } from "react-dom";
94
95
  import * as MenubarPrimitive from "@radix-ui/react-menubar";
95
96
  import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
96
97
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
@@ -9756,12 +9757,24 @@ function SidebarMenuSubButton({ asChild = false, size = "md", isActive = false,
9756
9757
  const SidebarTabsContext = React$11.createContext(null);
9757
9758
  function SidebarTabsProvider({ children, storageKey }) {
9758
9759
  const [tabsMap, setTabsMap] = React$11.useState({});
9760
+ const [portalTargets, setPortalTargets] = React$11.useState({});
9759
9761
  const fallbackKey = React$11.useId();
9760
9762
  const [storedActiveTabs, setStoredActiveTabs] = useLocalStorageState(storageKey ?? fallbackKey, {
9761
9763
  defaultValue: {},
9762
9764
  storageSync: !!storageKey
9763
9765
  });
9764
9766
  const [activeTab, setActiveTabState] = React$11.useState(storedActiveTabs);
9767
+ const setPortalTarget = React$11.useCallback((side, tabId, element) => {
9768
+ setPortalTargets((prev) => {
9769
+ const next = new Map(prev[side]);
9770
+ if (element) next.set(tabId, element);
9771
+ else next.delete(tabId);
9772
+ return {
9773
+ ...prev,
9774
+ [side]: next
9775
+ };
9776
+ });
9777
+ }, []);
9765
9778
  const register = React$11.useCallback((side, tab) => {
9766
9779
  setTabsMap((prev) => {
9767
9780
  const next = new Map(prev[side]);
@@ -9815,13 +9828,17 @@ function SidebarTabsProvider({ children, storageKey }) {
9815
9828
  activeTab: resolvedActiveTab,
9816
9829
  register,
9817
9830
  unregister,
9818
- setActiveTab
9831
+ setActiveTab,
9832
+ portalTargets,
9833
+ setPortalTarget
9819
9834
  }), [
9820
9835
  sortedTabs,
9821
9836
  resolvedActiveTab,
9822
9837
  register,
9823
9838
  unregister,
9824
- setActiveTab
9839
+ setActiveTab,
9840
+ portalTargets,
9841
+ setPortalTarget
9825
9842
  ]);
9826
9843
  return /* @__PURE__ */ jsx(SidebarTabsContext.Provider, {
9827
9844
  value,
@@ -9850,21 +9867,17 @@ function useSidebarTabs(side) {
9850
9867
 
9851
9868
  //#endregion
9852
9869
  //#region src/sidebar/sidebar-tab.tsx
9853
- function SidebarTab({ side, id, icon, label, render, order, badge }) {
9870
+ function SidebarTab({ side, id, icon, label, order, badge, children }) {
9854
9871
  const ctx = React$10.useContext(SidebarTabsContext);
9855
9872
  if (!ctx) throw new Error("SidebarTab must be used within a SidebarTabsProvider.");
9856
9873
  const { register, unregister } = ctx;
9857
- const renderRef = React$10.useRef(render);
9858
- renderRef.current = render;
9859
9874
  const iconRef = React$10.useRef(icon);
9860
9875
  iconRef.current = icon;
9861
- const stableRender = React$10.useCallback(() => renderRef.current(), []);
9862
9876
  React$10.useEffect(() => {
9863
9877
  register(side, {
9864
9878
  id,
9865
9879
  icon: iconRef.current,
9866
9880
  label,
9867
- render: stableRender,
9868
9881
  order,
9869
9882
  badge
9870
9883
  });
@@ -9876,17 +9889,17 @@ function SidebarTab({ side, id, icon, label, render, order, badge }) {
9876
9889
  order,
9877
9890
  badge,
9878
9891
  register,
9879
- unregister,
9880
- stableRender
9892
+ unregister
9881
9893
  ]);
9882
- return null;
9894
+ const target = ctx.portalTargets[side]?.get(id);
9895
+ if (!target) return null;
9896
+ return createPortal(children, target);
9883
9897
  }
9884
9898
  function DynamicTabbedSidebar({ side, orientation = "horizontal", collapsible = "offcanvas", className,...sidebarProps }) {
9885
9899
  const ctx = React$10.useContext(SidebarTabsContext);
9886
9900
  if (!ctx) throw new Error("DynamicTabbedSidebar must be used within a SidebarTabsProvider.");
9887
9901
  const tabs = ctx.tabs[side] ?? [];
9888
9902
  const activeTabId = ctx.activeTab[side] ?? null;
9889
- const activeTab = tabs.find((t) => t.id === activeTabId);
9890
9903
  const isVertical = orientation === "vertical";
9891
9904
  const effectiveCollapsible = isVertical && collapsible === "offcanvas" ? "icon" : collapsible;
9892
9905
  if (tabs.length === 0) return null;
@@ -9899,23 +9912,49 @@ function DynamicTabbedSidebar({ side, orientation = "horizontal", collapsible =
9899
9912
  side,
9900
9913
  tabs,
9901
9914
  activeTabId,
9902
- activeTab,
9903
9915
  isVertical,
9904
9916
  collapsible: effectiveCollapsible
9905
9917
  }), /* @__PURE__ */ jsx(SidebarRail, {})] })
9906
9918
  });
9907
9919
  }
9908
- function TabbedSidebarContent({ side, tabs, activeTabId, activeTab, isVertical, collapsible }) {
9920
+ function TabPortalTargets({ side, tabs, activeTabId, hidden }) {
9921
+ const ctx = React$10.useContext(SidebarTabsContext);
9922
+ const callbackRefs = React$10.useRef(new Map());
9923
+ const getRef = (tabId) => {
9924
+ let ref = callbackRefs.current.get(tabId);
9925
+ if (!ref) {
9926
+ ref = (el) => {
9927
+ ctx.setPortalTarget(side, tabId, el);
9928
+ };
9929
+ callbackRefs.current.set(tabId, ref);
9930
+ }
9931
+ return ref;
9932
+ };
9933
+ return /* @__PURE__ */ jsx(Fragment, { children: tabs.map((tab) => {
9934
+ const isVisible = !hidden && tab.id === activeTabId;
9935
+ return /* @__PURE__ */ jsx("div", {
9936
+ ref: getRef(tab.id),
9937
+ hidden: !isVisible || void 0,
9938
+ className: isVisible ? "flex flex-col flex-1 min-h-0" : void 0
9939
+ }, tab.id);
9940
+ }) });
9941
+ }
9942
+ function TabbedSidebarContent({ side, tabs, activeTabId, isVertical, collapsible }) {
9909
9943
  const { state } = useSidebar(side);
9910
9944
  const isCollapsed = state === "collapsed";
9911
9945
  const isIconCollapsible = collapsible === "icon";
9912
- if (isCollapsed && isIconCollapsible) return /* @__PURE__ */ jsx("div", {
9946
+ if (isCollapsed && isIconCollapsible) return /* @__PURE__ */ jsxs("div", {
9913
9947
  className: "flex h-full flex-col",
9914
- children: /* @__PURE__ */ jsx(VerticalTabBar, {
9948
+ children: [/* @__PURE__ */ jsx(VerticalTabBar, {
9915
9949
  side,
9916
9950
  tabs,
9917
9951
  activeTabId
9918
- })
9952
+ }), /* @__PURE__ */ jsx(TabPortalTargets, {
9953
+ side,
9954
+ tabs,
9955
+ activeTabId,
9956
+ hidden: true
9957
+ })]
9919
9958
  });
9920
9959
  if (isVertical) return /* @__PURE__ */ jsxs("div", {
9921
9960
  className: "flex h-full flex-row",
@@ -9923,7 +9962,11 @@ function TabbedSidebarContent({ side, tabs, activeTabId, activeTab, isVertical,
9923
9962
  side,
9924
9963
  tabs,
9925
9964
  activeTabId
9926
- }), /* @__PURE__ */ jsx(SidebarContent, { children: activeTab?.render() })]
9965
+ }), /* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsx(TabPortalTargets, {
9966
+ side,
9967
+ tabs,
9968
+ activeTabId
9969
+ }) })]
9927
9970
  });
9928
9971
  return /* @__PURE__ */ jsxs("div", {
9929
9972
  className: "flex h-full flex-col",
@@ -9934,7 +9977,11 @@ function TabbedSidebarContent({ side, tabs, activeTabId, activeTab, isVertical,
9934
9977
  activeTabId
9935
9978
  }),
9936
9979
  tabs.length > 0 && /* @__PURE__ */ jsx(SidebarSeparator, {}),
9937
- /* @__PURE__ */ jsx(SidebarContent, { children: activeTab?.render() })
9980
+ /* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsx(TabPortalTargets, {
9981
+ side,
9982
+ tabs,
9983
+ activeTabId
9984
+ }) })
9938
9985
  ]
9939
9986
  });
9940
9987
  }