@pelatform/starter.shared 0.2.15 → 0.2.16

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.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { ReactNode, CSSProperties, ComponentProps, PropsWithChildren, ComponentType } from 'react';
3
+ import { ReactNode, ComponentProps, CSSProperties, PropsWithChildren, ComponentType } from 'react';
4
4
  import { MenuItem } from 'pelatform-ui';
5
5
  import { NavItem, LanguageSwitcherProps } from 'pelatform-ui/components';
6
6
  export { Logo as LogoDefault } from 'pelatform-ui/components';
@@ -35,6 +35,14 @@ declare function LayoutLoader({ children }: {
35
35
  children: ReactNode;
36
36
  }): string | number | bigint | boolean | react_jsx_runtime.JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
37
37
 
38
+ declare function UserMenu({ homeUrl, hiddenSwitcher, side, align, sideOffset, }: {
39
+ homeUrl?: string;
40
+ hiddenSwitcher?: boolean;
41
+ side?: "bottom" | "top" | "right" | "left";
42
+ align?: "center" | "end" | "start";
43
+ sideOffset?: number;
44
+ }): react_jsx_runtime.JSX.Element;
45
+
38
46
  declare function Sidebar({ children }: {
39
47
  children: ReactNode;
40
48
  }): react_jsx_runtime.JSX.Element | null;
@@ -50,6 +58,10 @@ declare function SidebarContentMenu({ menu, type, }: {
50
58
  menu: MenuItem[];
51
59
  type?: "default" | "toggle";
52
60
  }): react_jsx_runtime.JSX.Element;
61
+ declare function SidebarFooter({ children, className, side, align, sideOffset, ...props }: ComponentProps<typeof UserMenu> & {
62
+ children?: ReactNode;
63
+ className?: string;
64
+ }): react_jsx_runtime.JSX.Element;
53
65
 
54
66
  declare function SiteFooter({ disableProjectBy }: {
55
67
  disableProjectBy?: boolean;
@@ -77,11 +89,13 @@ interface LayoutWrapperProps {
77
89
  children: ReactNode;
78
90
  sidebarHeader: ReactNode;
79
91
  sidebarMenu: ReactNode;
92
+ sidebarFooter?: ReactNode;
80
93
  logoHeader?: ReactNode;
94
+ version?: "v1" | "v2";
81
95
  homeUrl?: string;
82
96
  studioUrl?: string;
83
97
  }
84
- declare function LayoutWrapper({ children, sidebarHeader, sidebarMenu, logoHeader, homeUrl, studioUrl, }: LayoutWrapperProps): react_jsx_runtime.JSX.Element;
98
+ declare function LayoutWrapper({ children, logoHeader, version, ...props }: LayoutWrapperProps): react_jsx_runtime.JSX.Element;
85
99
 
86
100
  /**
87
101
  * Props for the ConfigProvider component
@@ -135,8 +149,9 @@ interface LayoutProviderProps {
135
149
  bodyClassName?: string;
136
150
  className?: string;
137
151
  logoHeader?: ReactNode;
152
+ version?: "v1" | "v2";
138
153
  }
139
- declare function LayoutProvider({ children, style: customStyle, bodyClassName, className, logoHeader, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
154
+ declare function LayoutProvider({ children, style: customStyle, bodyClassName, className, logoHeader, version, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
140
155
 
141
156
  interface SharedProvidersProps {
142
157
  children: ReactNode;
@@ -278,11 +293,6 @@ declare function SignedInHint({ linkHref }: {
278
293
  linkHref?: string;
279
294
  }): react_jsx_runtime.JSX.Element;
280
295
 
281
- declare function UserMenu({ homeUrl, hiddenSwitcher, }: {
282
- homeUrl?: string;
283
- hiddenSwitcher?: boolean;
284
- }): react_jsx_runtime.JSX.Element;
285
-
286
296
  type ViewClassNames = {
287
297
  base?: string;
288
298
  content?: string;
@@ -406,4 +416,4 @@ type Provider = {
406
416
  icon?: ProviderIcon;
407
417
  };
408
418
 
409
- export { ApiKeyView, AuthLayout, type AvatarClassNames, type AvatarProps, CardActionComponent, type CardClassNames, CardComponent, type CardComponentProps, CardFooterComponent, CardHeaderComponent, ConfigProvider, type ConfigProviderProps, type DialogClassNames, DialogComponent, type DialogComponentProps, DialogFooterComponent, DisplayIdCard, EmptyState, type EmptyStateProps, Header, HeaderLeft, HeaderRight, HeaderSidebarMobile, LanguageSwitcher, LayoutLoader, LayoutProvider, type LayoutProviderProps, LayoutWrapper, LogoWithHref, LogoWithName, OTPInputGroup, PasswordInput, type Provider, type ProviderIcon, SharedProviders, type SharedProvidersProps, Sidebar, SidebarContent, SidebarContentMenu, SidebarHeaderBack, SignedInHint, SiteFooter, SiteHeader, SiteHeaderSecondary, SkeletonInputComponent, SkeletonViewComponent, Toolbar, UserAvatar, UserMenu, UserView, type ViewClassNames, type ViewProps, WorkspaceLogo, WorkspaceView, socialProviders };
419
+ export { ApiKeyView, AuthLayout, type AvatarClassNames, type AvatarProps, CardActionComponent, type CardClassNames, CardComponent, type CardComponentProps, CardFooterComponent, CardHeaderComponent, ConfigProvider, type ConfigProviderProps, type DialogClassNames, DialogComponent, type DialogComponentProps, DialogFooterComponent, DisplayIdCard, EmptyState, type EmptyStateProps, Header, HeaderLeft, HeaderRight, HeaderSidebarMobile, LanguageSwitcher, LayoutLoader, LayoutProvider, type LayoutProviderProps, LayoutWrapper, LogoWithHref, LogoWithName, OTPInputGroup, PasswordInput, type Provider, type ProviderIcon, SharedProviders, type SharedProvidersProps, Sidebar, SidebarContent, SidebarContentMenu, SidebarFooter, SidebarHeaderBack, SignedInHint, SiteFooter, SiteHeader, SiteHeaderSecondary, SkeletonInputComponent, SkeletonViewComponent, Toolbar, UserAvatar, UserMenu, UserView, type ViewClassNames, type ViewProps, WorkspaceLogo, WorkspaceView, socialProviders };
package/dist/index.js CHANGED
@@ -512,7 +512,10 @@ function WorkspaceView({ className, classNames, isPending, size, workspace }) {
512
512
  import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
513
513
  function UserMenu({
514
514
  homeUrl,
515
- hiddenSwitcher = false
515
+ hiddenSwitcher = false,
516
+ side = "bottom",
517
+ align = "end",
518
+ sideOffset = 11
516
519
  }) {
517
520
  const { auth, features, path } = useConfig4();
518
521
  const router = useRouter2();
@@ -553,7 +556,7 @@ function UserMenu({
553
556
  const userRole = user?.role || "user";
554
557
  return /* @__PURE__ */ jsxs7(DropdownMenu, { children: [
555
558
  /* @__PURE__ */ jsx9(DropdownMenuTrigger, { className: "focus:outline-none focus:ring-0", children: isPending ? /* @__PURE__ */ jsx9(Skeleton3, { className: "size-8 shrink-0 rounded-full" }) : /* @__PURE__ */ jsx9(UserAvatar2, { className: "size-8", indicator: true, src: userAvatar, alt: userName }) }),
556
- /* @__PURE__ */ jsxs7(DropdownMenuContent, { className: "w-56", side: "bottom", align: "end", sideOffset: 11, children: [
559
+ /* @__PURE__ */ jsxs7(DropdownMenuContent, { className: "w-56", side, align, sideOffset, children: [
557
560
  /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3 px-3 py-2", children: [
558
561
  /* @__PURE__ */ jsx9(UserAvatar2, { src: userAvatar, alt: userName }),
559
562
  /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 flex-col items-start", children: [
@@ -628,6 +631,10 @@ function UserMenu({
628
631
  // src/components/layouts/header.tsx
629
632
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
630
633
  function Header({ children }) {
634
+ const { version } = useLayout();
635
+ if (version === "v2") {
636
+ return /* @__PURE__ */ jsx10("header", { className: "fixed start-0 end-0 top-0 z-50 flex h-(--header-height-mobile) shrink-0 items-center bg-background/95 pe-[var(--removed-body-scroll-bar-size,0px)] backdrop-blur-sm transition-[start,end] duration-300 supports-backdrop-filter:bg-muted", children: /* @__PURE__ */ jsx10("div", { className: "@container flex grow items-stretch justify-between gap-2.5 pe-5", children }) });
637
+ }
631
638
  return /* @__PURE__ */ jsx10("header", { className: "fixed start-0 end-0 top-0 z-10 flex h-(--header-height-mobile) shrink-0 items-stretch border-border border-b bg-background/95 pe-(--removed-body-scroll-bar-size,0px) backdrop-blur-sm supports-backdrop-filter:bg-background/60 lg:h-(--header-height)", children: /* @__PURE__ */ jsx10("div", { className: "@container flex grow items-stretch justify-between gap-2.5 pe-5", children }) });
632
639
  }
633
640
  function HeaderLeft() {
@@ -682,6 +689,7 @@ import Link5 from "next/link";
682
689
  import { usePathname as usePathname3 } from "next/navigation";
683
690
  import { useLocale as useLocale3, useTranslations as useTranslations8 } from "next-intl";
684
691
  import { useLayout as useLayout2 } from "@pelatform/starter.hook";
692
+ import { cn as cn5 } from "pelatform-ui";
685
693
  import { BackLink } from "pelatform-ui/components";
686
694
  import {
687
695
  AccordionMenu,
@@ -697,10 +705,16 @@ import {
697
705
  } from "pelatform-ui/default";
698
706
  import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
699
707
  function Sidebar({ children }) {
700
- const { isMobile } = useLayout2();
708
+ const { isMobile, logoHeader, version } = useLayout2();
701
709
  if (isMobile) {
702
710
  return null;
703
711
  }
712
+ if (version === "v2") {
713
+ return /* @__PURE__ */ jsx11("aside", { className: "fixed start-2.5 top-2.5 bottom-2.5 z-20 flex in-data-[sidebar-open=false]:w-(--sidebar-width-collapsed) w-(--sidebar-width) shrink-0 items-stretch overflow-hidden rounded-xl border border-input bg-background transition-all duration-300", children: /* @__PURE__ */ jsxs9("div", { className: "w-(--sidebar-width) shrink-0 grow transition-all duration-300", children: [
714
+ /* @__PURE__ */ jsx11("div", { className: "flex h-14 shrink-0 items-center justify-center px-2.5 lg:h-15", children: logoHeader }),
715
+ children
716
+ ] }) });
717
+ }
704
718
  return /* @__PURE__ */ jsxs9("aside", { className: "fixed in-data-[sidebar-open=false]:-start-full start-0 top-(--header-height) bottom-0 flex w-(--sidebar-width) shrink-0 flex-col items-stretch border-border border-e transition-all duration-300", children: [
705
719
  children,
706
720
  /* @__PURE__ */ jsx11("div", {})
@@ -715,7 +729,19 @@ function SidebarHeaderBack({
715
729
  return /* @__PURE__ */ jsx11("div", { className: "flex h-14 shrink-0 items-center gap-2 border-border border-b px-2.5 lg:h-15", children: /* @__PURE__ */ jsx11(BackLink, { Link: Link5, href: linkHref, children: text ?? (admin ? t("common.actions.back") : t("ui.navigation.settings")) }) });
716
730
  }
717
731
  function SidebarContent({ children }) {
718
- return /* @__PURE__ */ jsx11(ScrollArea, { className: "mt-2 mb-2.5 h-[calc(100vh-5.5rem)] grow lg:mt-4 lg:mb-7.5 lg:h-[calc(100vh-4rem)]", children });
732
+ const { isMobile, version } = useLayout2();
733
+ if (version === "v2") {
734
+ return /* @__PURE__ */ jsx11(
735
+ ScrollArea,
736
+ {
737
+ className: cn5(
738
+ isMobile ? "my-2 h-[calc(100vh-5.5rem)] grow" : "my-2 h-[calc(100vh-1rem)] w-full shrink-0 lg:my-4 lg:h-[calc(100vh-14.7rem)]"
739
+ ),
740
+ children
741
+ }
742
+ );
743
+ }
744
+ return /* @__PURE__ */ jsx11(ScrollArea, { className: "my-2 h-[calc(100vh-5.5rem)] grow lg:my-4 lg:h-[calc(100vh-4rem)]", children });
719
745
  }
720
746
  function SidebarContentMenu({
721
747
  menu,
@@ -860,19 +886,41 @@ function SidebarContentMenu({
860
886
  }
861
887
  );
862
888
  }
889
+ function SidebarFooter({
890
+ children,
891
+ className,
892
+ side = "top",
893
+ align = "start",
894
+ sideOffset = 10,
895
+ ...props
896
+ }) {
897
+ return /* @__PURE__ */ jsxs9(
898
+ "div",
899
+ {
900
+ className: cn5(
901
+ "flex h-14 shrink-0 items-center gap-2 border-border border-t px-2.5 lg:h-15",
902
+ className
903
+ ),
904
+ children: [
905
+ /* @__PURE__ */ jsx11(UserMenu, { side, align, sideOffset, ...props }),
906
+ children
907
+ ]
908
+ }
909
+ );
910
+ }
863
911
 
864
912
  // src/components/layouts/site-footer.tsx
865
913
  import Link6 from "next/link";
866
914
  import { useTranslations as useTranslations9 } from "next-intl";
867
915
  import { useConfig as useConfig5 } from "@pelatform/starter.hook";
868
- import { cn as cn5 } from "pelatform-ui";
916
+ import { cn as cn6 } from "pelatform-ui";
869
917
  import { SiteFooter as UISiteFooter } from "pelatform-ui/components";
870
918
  import { Button as Button3 } from "pelatform-ui/default";
871
919
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
872
920
  function SiteFooter({ disableProjectBy = false }) {
873
921
  const { app } = useConfig5();
874
922
  const t = useTranslations9();
875
- return /* @__PURE__ */ jsxs10(UISiteFooter, { className: cn5("*:gap-2! *:py-0!", disableProjectBy ? "*:justify-center!" : ""), children: [
923
+ return /* @__PURE__ */ jsxs10(UISiteFooter, { className: cn6("*:gap-2! *:py-0!", disableProjectBy ? "*:justify-center!" : ""), children: [
876
924
  /* @__PURE__ */ jsxs10("div", { className: "text-balance text-center text-muted-foreground text-sm leading-loose md:text-left", children: [
877
925
  "\xA9 ",
878
926
  (/* @__PURE__ */ new Date()).getFullYear(),
@@ -1003,51 +1051,73 @@ function SiteHeaderSecondary({
1003
1051
  }
1004
1052
 
1005
1053
  // src/components/layouts/wrapper.tsx
1054
+ import { useEffect as useEffect4, useState as useState5 } from "react";
1006
1055
  import Link8 from "next/link";
1007
1056
  import { RocketIcon } from "lucide-react";
1008
- import { useSession as useSession5 } from "@pelatform/starter.hook";
1057
+ import { useLayout as useLayout3, useSession as useSession5 } from "@pelatform/starter.hook";
1058
+ import { cn as cn8 } from "pelatform-ui";
1009
1059
  import { Button as Button5 } from "pelatform-ui/default";
1010
1060
 
1011
1061
  // src/components/providers/layout.tsx
1012
- import { useEffect as useEffect3, useState as useState4 } from "react";
1062
+ import { useEffect as useEffect3, useMemo as useMemo2, useState as useState4 } from "react";
1013
1063
  import { LayoutContext } from "@pelatform/starter.hook";
1014
- import { cn as cn6 } from "pelatform-ui";
1064
+ import { cn as cn7 } from "pelatform-ui";
1065
+ import { TooltipProvider } from "pelatform-ui/default";
1015
1066
  import { useIsMobile } from "pelatform-ui/hooks";
1016
1067
  import { jsx as jsx14 } from "react/jsx-runtime";
1017
1068
  var SIDEBAR_WIDTH = "240px";
1018
1069
  var HEADER_HEIGHT = "54px";
1019
1070
  var SIDEBAR_WIDTH_MOBILE = "240px";
1020
1071
  var HEADER_HEIGHT_MOBILE = "54px";
1072
+ var SIDEBAR_WIDTH_V2 = "255px";
1073
+ var HEADER_HEIGHT_V2 = "60px";
1074
+ var SIDEBAR_WIDTH_MOBILE_V2 = "60px";
1075
+ var HEADER_HEIGHT_MOBILE_V2 = "60px";
1021
1076
  function LayoutProvider({
1022
1077
  children,
1023
1078
  style: customStyle,
1024
1079
  bodyClassName = "",
1025
1080
  className = "",
1026
- logoHeader = /* @__PURE__ */ jsx14(LogoWithHref, {})
1081
+ logoHeader = /* @__PURE__ */ jsx14(LogoWithHref, {}),
1082
+ version = "v1"
1027
1083
  }) {
1028
1084
  const isMobile = useIsMobile();
1029
1085
  const [isSidebarOpen, setIsSidebarOpen] = useState4(true);
1030
- const defaultStyle = {
1031
- "--sidebar-width": SIDEBAR_WIDTH,
1032
- "--header-height": HEADER_HEIGHT,
1033
- "--sidebar-width-mobile": SIDEBAR_WIDTH_MOBILE,
1034
- "--header-height-mobile": HEADER_HEIGHT_MOBILE
1035
- };
1036
- const style = {
1037
- ...defaultStyle,
1038
- ...customStyle
1039
- };
1086
+ const cssVariables = useMemo2(
1087
+ () => ({
1088
+ "--sidebar-width": version === "v1" ? SIDEBAR_WIDTH : SIDEBAR_WIDTH_V2,
1089
+ "--header-height": version === "v1" ? HEADER_HEIGHT : HEADER_HEIGHT_V2,
1090
+ "--sidebar-width-mobile": version === "v1" ? SIDEBAR_WIDTH_MOBILE : SIDEBAR_WIDTH_MOBILE_V2,
1091
+ "--header-height-mobile": version === "v1" ? HEADER_HEIGHT_MOBILE : HEADER_HEIGHT_MOBILE_V2,
1092
+ ...customStyle || {}
1093
+ }),
1094
+ [version, customStyle]
1095
+ );
1096
+ const style = useMemo2(
1097
+ () => ({
1098
+ ...cssVariables
1099
+ }),
1100
+ [cssVariables]
1101
+ );
1040
1102
  const sidebarToggle = () => setIsSidebarOpen((open) => !open);
1041
1103
  useEffect3(() => {
1104
+ const html = document.documentElement;
1105
+ const body = document.body;
1106
+ const originalHtmlStyle = html.style.cssText;
1107
+ const originalBodyClasses = body.className;
1108
+ Object.entries(cssVariables).forEach(([prop, val]) => {
1109
+ html.style.setProperty(prop, val);
1110
+ });
1042
1111
  if (bodyClassName) {
1043
- const body = document.body;
1044
- const existingClasses = body.className;
1045
- body.className = `${existingClasses} ${bodyClassName}`.trim();
1046
- return () => {
1047
- body.className = existingClasses;
1048
- };
1112
+ body.className = `${originalBodyClasses} ${bodyClassName}`.trim();
1049
1113
  }
1050
- }, [bodyClassName]);
1114
+ body.setAttribute("data-sidebar-open", isSidebarOpen.toString());
1115
+ return () => {
1116
+ html.style.cssText = originalHtmlStyle;
1117
+ body.className = originalBodyClasses;
1118
+ body.removeAttribute("data-sidebar-open");
1119
+ };
1120
+ }, [cssVariables, bodyClassName, isSidebarOpen]);
1051
1121
  return /* @__PURE__ */ jsx14(
1052
1122
  LayoutContext.Provider,
1053
1123
  {
@@ -1057,16 +1127,17 @@ function LayoutProvider({
1057
1127
  isMobile,
1058
1128
  isSidebarOpen,
1059
1129
  sidebarToggle,
1060
- logoHeader
1130
+ logoHeader,
1131
+ version
1061
1132
  },
1062
1133
  children: /* @__PURE__ */ jsx14(
1063
1134
  "div",
1064
1135
  {
1065
1136
  "data-slot": "layout-wrapper",
1066
- className: cn6("flex grow", className),
1137
+ className: cn7("flex grow", className),
1067
1138
  "data-sidebar-open": isSidebarOpen,
1068
1139
  style,
1069
- children
1140
+ children: /* @__PURE__ */ jsx14(TooltipProvider, { delayDuration: 0, children })
1070
1141
  }
1071
1142
  )
1072
1143
  }
@@ -1076,10 +1147,26 @@ function LayoutProvider({
1076
1147
  // src/components/layouts/wrapper.tsx
1077
1148
  import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1078
1149
  function LayoutWrapper({
1150
+ children,
1151
+ logoHeader,
1152
+ version = "v1",
1153
+ ...props
1154
+ }) {
1155
+ const isVersionV1 = version === "v1";
1156
+ return /* @__PURE__ */ jsx15(
1157
+ LayoutProvider,
1158
+ {
1159
+ logoHeader,
1160
+ version,
1161
+ bodyClassName: isVersionV1 ? "" : "bg-muted!",
1162
+ children: isVersionV1 ? /* @__PURE__ */ jsx15(ContentWrapper, { ...props, children }) : /* @__PURE__ */ jsx15(ContentWrapperV2, { ...props, children })
1163
+ }
1164
+ );
1165
+ }
1166
+ function ContentWrapper({
1079
1167
  children,
1080
1168
  sidebarHeader,
1081
1169
  sidebarMenu,
1082
- logoHeader,
1083
1170
  homeUrl,
1084
1171
  studioUrl
1085
1172
  }) {
@@ -1092,7 +1179,7 @@ function LayoutWrapper({
1092
1179
  /* @__PURE__ */ jsx15(RocketIcon, {}),
1093
1180
  " Studio"
1094
1181
  ] }) });
1095
- return /* @__PURE__ */ jsxs12(LayoutProvider, { logoHeader, children: [
1182
+ return /* @__PURE__ */ jsxs12(Fragment6, { children: [
1096
1183
  /* @__PURE__ */ jsxs12(Header, { children: [
1097
1184
  /* @__PURE__ */ jsx15(HeaderLeft, {}),
1098
1185
  /* @__PURE__ */ jsx15(
@@ -1110,9 +1197,60 @@ function LayoutWrapper({
1110
1197
  ] })
1111
1198
  ] });
1112
1199
  }
1200
+ function ContentWrapperV2({
1201
+ children,
1202
+ sidebarHeader,
1203
+ sidebarMenu,
1204
+ sidebarFooter,
1205
+ homeUrl,
1206
+ studioUrl
1207
+ }) {
1208
+ const { isMobile } = useLayout3();
1209
+ const { user } = useSession5();
1210
+ const [enableTransitions, setEnableTransitions] = useState5(false);
1211
+ useEffect4(() => {
1212
+ const id = requestAnimationFrame(() => setEnableTransitions(true));
1213
+ return () => cancelAnimationFrame(id);
1214
+ }, []);
1215
+ const sidebarContent = /* @__PURE__ */ jsxs12(Fragment6, { children: [
1216
+ sidebarHeader,
1217
+ /* @__PURE__ */ jsx15(SidebarContent, { children: sidebarMenu }),
1218
+ !isMobile && sidebarFooter
1219
+ ] });
1220
+ const studioButton = /* @__PURE__ */ jsx15(Button5, { variant: "mono", size: "sm", className: "rounded-full", asChild: true, children: /* @__PURE__ */ jsxs12(Link8, { href: studioUrl || "#", target: "_blank", children: [
1221
+ /* @__PURE__ */ jsx15(RocketIcon, {}),
1222
+ " Studio"
1223
+ ] }) });
1224
+ return /* @__PURE__ */ jsxs12("div", { className: "flex h-screen w-full [&_.container-fluid]:px-5", children: [
1225
+ /* @__PURE__ */ jsx15(Sidebar, { children: sidebarContent }),
1226
+ /* @__PURE__ */ jsxs12("div", { className: "flex w-full min-w-0 flex-1 flex-col pt-(--header-height-mobile) lg:pt-0", children: [
1227
+ isMobile && /* @__PURE__ */ jsxs12(Header, { children: [
1228
+ /* @__PURE__ */ jsx15(HeaderLeft, {}),
1229
+ /* @__PURE__ */ jsx15(
1230
+ HeaderRight,
1231
+ {
1232
+ sidebar: /* @__PURE__ */ jsx15(HeaderSidebarMobile, { children: sidebarContent }),
1233
+ button: studioUrl && user?.role === "admin" ? studioButton : null,
1234
+ homeUrl
1235
+ }
1236
+ )
1237
+ ] }),
1238
+ /* @__PURE__ */ jsx15("div", { className: "mx-5 flex grow py-2.5 lg:mx-2.5", children: /* @__PURE__ */ jsx15(
1239
+ "div",
1240
+ {
1241
+ className: cn8(
1242
+ "grow overflow-y-auto rounded-xl border border-input bg-background shadow-xs duration-300 lg:in-data-[sidebar-open=true]:ms-[calc(var(--sidebar-width)+0.6rem)] lg:ms-[calc(var(--sidebar-width-collapsed)+0.6rem)]",
1243
+ enableTransitions ? "transition-all duration-300" : "transition-none"
1244
+ ),
1245
+ children: /* @__PURE__ */ jsx15("main", { className: "grow", children })
1246
+ }
1247
+ ) })
1248
+ ] })
1249
+ ] });
1250
+ }
1113
1251
 
1114
1252
  // src/components/providers/config.tsx
1115
- import { useMemo as useMemo2 } from "react";
1253
+ import { useMemo as useMemo3 } from "react";
1116
1254
  import { defaultConfig, mergeConfig } from "@pelatform/starter.config";
1117
1255
  import {
1118
1256
  ConfigContext,
@@ -1128,7 +1266,7 @@ function ConfigProvider({
1128
1266
  workspaceLogo: workspaceLogoProp,
1129
1267
  ...props
1130
1268
  }) {
1131
- const mergedConfig = useMemo2(() => {
1269
+ const mergedConfig = useMemo3(() => {
1132
1270
  return mergeConfig(defaultConfig, configProp);
1133
1271
  }, [configProp]);
1134
1272
  const config = mergedConfig;
@@ -1137,7 +1275,7 @@ function ConfigProvider({
1137
1275
  extension: "png",
1138
1276
  size: 128
1139
1277
  };
1140
- const userAvatar = useMemo2(() => {
1278
+ const userAvatar = useMemo3(() => {
1141
1279
  if (!userAvatarProp) {
1142
1280
  return {
1143
1281
  extension: DEFAULT_IMAGE_OPTIONS.extension,
@@ -1151,7 +1289,7 @@ function ConfigProvider({
1151
1289
  size: userAvatarProp.size || (userAvatarProp.upload ? 256 : DEFAULT_IMAGE_OPTIONS.size)
1152
1290
  };
1153
1291
  }, [userAvatarProp]);
1154
- const workspaceLogo = useMemo2(() => {
1292
+ const workspaceLogo = useMemo3(() => {
1155
1293
  if (!workspaceLogoProp) {
1156
1294
  return {
1157
1295
  extension: DEFAULT_IMAGE_OPTIONS.extension,
@@ -1214,7 +1352,7 @@ function SharedProviders({
1214
1352
  }
1215
1353
 
1216
1354
  // src/components/utils/card.tsx
1217
- import { cn as cn7 } from "pelatform-ui";
1355
+ import { cn as cn9 } from "pelatform-ui";
1218
1356
  import { Button as Button6, Card, CardContent, CardFooter, Skeleton as Skeleton4, Spinner } from "pelatform-ui/default";
1219
1357
  import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1220
1358
  function CardComponent({
@@ -1235,7 +1373,7 @@ function CardComponent({
1235
1373
  return /* @__PURE__ */ jsxs14(
1236
1374
  Card,
1237
1375
  {
1238
- className: cn7(
1376
+ className: cn9(
1239
1377
  "w-full overflow-hidden",
1240
1378
  isDestructive && "border-destructive/70",
1241
1379
  className,
@@ -1243,7 +1381,7 @@ function CardComponent({
1243
1381
  ),
1244
1382
  ...props,
1245
1383
  children: [
1246
- /* @__PURE__ */ jsxs14(CardContent, { className: cn7("space-y-6 p-5 sm:p-10", classNames?.content), children: [
1384
+ /* @__PURE__ */ jsxs14(CardContent, { className: cn9("space-y-6 p-5 sm:p-10", classNames?.content), children: [
1247
1385
  /* @__PURE__ */ jsx18(
1248
1386
  CardHeaderComponent,
1249
1387
  {
@@ -1279,12 +1417,12 @@ function CardHeaderComponent({
1279
1417
  description,
1280
1418
  isPending
1281
1419
  }) {
1282
- return /* @__PURE__ */ jsx18("div", { className: cn7("flex flex-col space-y-2", className, classNames?.header), children: isPending ? /* @__PURE__ */ jsxs14(Fragment7, { children: [
1283
- /* @__PURE__ */ jsx18(Skeleton4, { className: cn7("h-7 w-1/3", classNames?.skeleton) }),
1284
- description && /* @__PURE__ */ jsx18(Skeleton4, { className: cn7("h-5 w-2/3", classNames?.skeleton) })
1420
+ return /* @__PURE__ */ jsx18("div", { className: cn9("flex flex-col space-y-2", className, classNames?.header), children: isPending ? /* @__PURE__ */ jsxs14(Fragment7, { children: [
1421
+ /* @__PURE__ */ jsx18(Skeleton4, { className: cn9("h-7 w-1/3", classNames?.skeleton) }),
1422
+ description && /* @__PURE__ */ jsx18(Skeleton4, { className: cn9("h-5 w-2/3", classNames?.skeleton) })
1285
1423
  ] }) : /* @__PURE__ */ jsxs14(Fragment7, { children: [
1286
- /* @__PURE__ */ jsx18("h2", { className: cn7("font-medium text-xl", classNames?.title), children: title }),
1287
- description && /* @__PURE__ */ jsx18("p", { className: cn7("text-muted-foreground text-sm", classNames?.description), children: description })
1424
+ /* @__PURE__ */ jsx18("h2", { className: cn9("font-medium text-xl", classNames?.title), children: title }),
1425
+ description && /* @__PURE__ */ jsx18("p", { className: cn9("text-muted-foreground text-sm", classNames?.description), children: description })
1288
1426
  ] }) });
1289
1427
  }
1290
1428
  function CardFooterComponent({
@@ -1301,7 +1439,7 @@ function CardFooterComponent({
1301
1439
  return /* @__PURE__ */ jsx18(
1302
1440
  CardFooter,
1303
1441
  {
1304
- className: cn7(
1442
+ className: cn9(
1305
1443
  "flex items-center justify-between space-x-4 bg-muted p-3 sm:px-10",
1306
1444
  isDestructive && "border-destructive/70",
1307
1445
  className,
@@ -1311,7 +1449,7 @@ function CardFooterComponent({
1311
1449
  instructions && /* @__PURE__ */ jsx18(
1312
1450
  Skeleton4,
1313
1451
  {
1314
- className: cn7(
1452
+ className: cn9(
1315
1453
  "h-4 w-48 max-w-full bg-muted-foreground/10 md:h-5 md:w-60",
1316
1454
  classNames?.skeleton
1317
1455
  )
@@ -1320,14 +1458,14 @@ function CardFooterComponent({
1320
1458
  actionLabel && /* @__PURE__ */ jsx18(
1321
1459
  Skeleton4,
1322
1460
  {
1323
- className: cn7("h-8 w-20 bg-muted-foreground/10 md:ms-auto", classNames?.skeleton)
1461
+ className: cn9("h-8 w-20 bg-muted-foreground/10 md:ms-auto", classNames?.skeleton)
1324
1462
  }
1325
1463
  )
1326
1464
  ] }) : /* @__PURE__ */ jsxs14(Fragment7, { children: [
1327
1465
  instructions && /* @__PURE__ */ jsx18(
1328
1466
  "div",
1329
1467
  {
1330
- className: cn7("text-muted-foreground text-xs md:text-sm", classNames?.instructions),
1468
+ className: cn9("text-muted-foreground text-xs md:text-sm", classNames?.instructions),
1331
1469
  children: instructions
1332
1470
  }
1333
1471
  ),
@@ -1361,7 +1499,7 @@ function CardActionComponent({
1361
1499
  type: onClick ? "button" : "submit",
1362
1500
  variant: isDestructive ? "destructive" : "primary",
1363
1501
  size: "sm",
1364
- className: cn7(
1502
+ className: cn9(
1365
1503
  "ms-auto",
1366
1504
  isSubmitting || disabled ? "pointer-events-auto! cursor-not-allowed" : "",
1367
1505
  classNames?.button,
@@ -1380,7 +1518,7 @@ function CardActionComponent({
1380
1518
 
1381
1519
  // src/components/utils/dialog.tsx
1382
1520
  import { useTranslations as useTranslations11 } from "next-intl";
1383
- import { cn as cn8 } from "pelatform-ui";
1521
+ import { cn as cn10 } from "pelatform-ui";
1384
1522
  import {
1385
1523
  Button as Button7,
1386
1524
  Dialog,
@@ -1408,13 +1546,13 @@ function DialogComponent({
1408
1546
  DialogContent,
1409
1547
  {
1410
1548
  onOpenAutoFocus: (e) => e.preventDefault(),
1411
- className: cn8("bg-muted sm:max-w-md", classNames?.dialog?.content),
1549
+ className: cn10("bg-muted sm:max-w-md", classNames?.dialog?.content),
1412
1550
  showCloseButton,
1413
1551
  children: [
1414
1552
  /* @__PURE__ */ jsxs15(
1415
1553
  DialogHeader,
1416
1554
  {
1417
- className: cn8(
1555
+ className: cn10(
1418
1556
  "-ms-6 -me-6 -mt-6 space-y-2 rounded-t-lg bg-background p-6",
1419
1557
  classNames?.header
1420
1558
  ),
@@ -1448,13 +1586,13 @@ function DialogFooterComponent({
1448
1586
  button
1449
1587
  }) {
1450
1588
  const t = useTranslations11();
1451
- return /* @__PURE__ */ jsxs15(DialogFooter, { className: cn8(className, classNames?.dialog?.footer), children: [
1589
+ return /* @__PURE__ */ jsxs15(DialogFooter, { className: cn10(className, classNames?.dialog?.footer), children: [
1452
1590
  cancelButton && /* @__PURE__ */ jsx19(
1453
1591
  Button7,
1454
1592
  {
1455
1593
  type: "button",
1456
1594
  variant: "ghost",
1457
- className: cn8(classNames?.button),
1595
+ className: cn10(classNames?.button),
1458
1596
  onClick: () => onOpenChange?.(false),
1459
1597
  disabled: cancelButtonDisabled,
1460
1598
  children: t("common.actions.cancel")
@@ -1465,22 +1603,22 @@ function DialogFooterComponent({
1465
1603
  }
1466
1604
 
1467
1605
  // src/components/utils/skeleton.tsx
1468
- import { cn as cn9 } from "pelatform-ui";
1606
+ import { cn as cn11 } from "pelatform-ui";
1469
1607
  import { Card as Card2, Skeleton as Skeleton5 } from "pelatform-ui/default";
1470
1608
  import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1471
1609
  function SkeletonViewComponent({ classNames }) {
1472
- return /* @__PURE__ */ jsxs16(Card2, { className: cn9("flex-row items-center gap-3 px-4 py-3", classNames?.cell), children: [
1610
+ return /* @__PURE__ */ jsxs16(Card2, { className: cn11("flex-row items-center gap-3 px-4 py-3", classNames?.cell), children: [
1473
1611
  /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
1474
- /* @__PURE__ */ jsx20(Skeleton5, { className: cn9("size-5 rounded-full", classNames?.skeleton) }),
1475
- /* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(Skeleton5, { className: cn9("h-4 w-32", classNames?.skeleton) }) })
1612
+ /* @__PURE__ */ jsx20(Skeleton5, { className: cn11("size-5 rounded-full", classNames?.skeleton) }),
1613
+ /* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(Skeleton5, { className: cn11("h-4 w-32", classNames?.skeleton) }) })
1476
1614
  ] }),
1477
- /* @__PURE__ */ jsx20(Skeleton5, { className: cn9("ms-auto size-8 w-16", classNames?.skeleton) })
1615
+ /* @__PURE__ */ jsx20(Skeleton5, { className: cn11("ms-auto size-8 w-16", classNames?.skeleton) })
1478
1616
  ] });
1479
1617
  }
1480
1618
  function SkeletonInputComponent({ classNames }) {
1481
1619
  return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
1482
- /* @__PURE__ */ jsx20(Skeleton5, { className: cn9("h-4 w-32", classNames?.skeleton) }),
1483
- /* @__PURE__ */ jsx20(Skeleton5, { className: cn9("h-9 w-full", classNames?.skeleton) })
1620
+ /* @__PURE__ */ jsx20(Skeleton5, { className: cn11("h-4 w-32", classNames?.skeleton) }),
1621
+ /* @__PURE__ */ jsx20(Skeleton5, { className: cn11("h-9 w-full", classNames?.skeleton) })
1484
1622
  ] });
1485
1623
  }
1486
1624
 
@@ -1488,14 +1626,14 @@ function SkeletonInputComponent({ classNames }) {
1488
1626
  import { useRef } from "react";
1489
1627
  import { CheckIcon, CopyIcon } from "lucide-react";
1490
1628
  import { useTranslations as useTranslations12 } from "next-intl";
1491
- import { cn as cn10 } from "pelatform-ui";
1629
+ import { cn as cn12 } from "pelatform-ui";
1492
1630
  import {
1493
1631
  Button as Button8,
1494
1632
  Input,
1495
1633
  Skeleton as Skeleton6,
1496
1634
  Tooltip,
1497
1635
  TooltipContent,
1498
- TooltipProvider,
1636
+ TooltipProvider as TooltipProvider2,
1499
1637
  TooltipTrigger
1500
1638
  } from "pelatform-ui/default";
1501
1639
  import { useCopyToClipboard } from "pelatform-ui/hooks";
@@ -1526,17 +1664,17 @@ function DisplayIdCard({
1526
1664
  description,
1527
1665
  isPending,
1528
1666
  ...props,
1529
- children: isPending ? /* @__PURE__ */ jsx21(Skeleton6, { className: cn10("h-11.5 w-full max-w-md", classNames?.skeleton) }) : /* @__PURE__ */ jsxs17(
1667
+ children: isPending ? /* @__PURE__ */ jsx21(Skeleton6, { className: cn12("h-11.5 w-full max-w-md", classNames?.skeleton) }) : /* @__PURE__ */ jsxs17(
1530
1668
  "div",
1531
1669
  {
1532
- className: cn10(
1670
+ className: cn12(
1533
1671
  "flex w-full max-w-md items-center justify-between rounded-md border p-2",
1534
1672
  classNames?.grid
1535
1673
  ),
1536
1674
  children: [
1537
1675
  /* @__PURE__ */ jsx21(Input, { value: id, ref: inputRef, disabled: true, className: "border-none! bg-transparent!" }),
1538
- /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs17(Tooltip, { children: [
1539
- /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(Button8, { variant: "dim", onClick: handleCopy, disabled: copied, children: copied ? /* @__PURE__ */ jsx21(CheckIcon, { className: cn10("stroke-green-600", classNames?.icon) }) : /* @__PURE__ */ jsx21(CopyIcon, { className: classNames?.icon }) }) }),
1676
+ /* @__PURE__ */ jsx21(TooltipProvider2, { delayDuration: 0, children: /* @__PURE__ */ jsxs17(Tooltip, { children: [
1677
+ /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(Button8, { variant: "dim", onClick: handleCopy, disabled: copied, children: copied ? /* @__PURE__ */ jsx21(CheckIcon, { className: cn12("stroke-green-600", classNames?.icon) }) : /* @__PURE__ */ jsx21(CopyIcon, { className: classNames?.icon }) }) }),
1540
1678
  /* @__PURE__ */ jsx21(TooltipContent, { className: "px-2 py-1 text-xs", children: t("common.actions.copy") })
1541
1679
  ] }) })
1542
1680
  ]
@@ -1549,7 +1687,7 @@ function DisplayIdCard({
1549
1687
  // src/components/empty-state.tsx
1550
1688
  import Link9 from "next/link";
1551
1689
  import { useTranslations as useTranslations13 } from "next-intl";
1552
- import { cn as cn11 } from "pelatform-ui";
1690
+ import { cn as cn13 } from "pelatform-ui";
1553
1691
  import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1554
1692
  function EmptyState({
1555
1693
  className,
@@ -1561,7 +1699,7 @@ function EmptyState({
1561
1699
  children
1562
1700
  }) {
1563
1701
  const t = useTranslations13();
1564
- return /* @__PURE__ */ jsxs18("div", { className: cn11("flex flex-col items-center justify-center gap-y-4", className), children: [
1702
+ return /* @__PURE__ */ jsxs18("div", { className: cn13("flex flex-col items-center justify-center gap-y-4", className), children: [
1565
1703
  Icon && /* @__PURE__ */ jsx22("div", { className: "flex size-14 items-center justify-center rounded-2xl border bg-muted", children: /* @__PURE__ */ jsx22(Icon, { className: "size-6 text-foreground" }) }),
1566
1704
  /* @__PURE__ */ jsx22("p", { className: "text-center font-medium text-base text-foreground", children: title }),
1567
1705
  description && /* @__PURE__ */ jsxs18("p", { className: "max-w-sm text-balance text-center text-muted-foreground text-sm", children: [
@@ -1631,9 +1769,9 @@ function OTPInputGroup({ otpSeparators = 0 }) {
1631
1769
  }
1632
1770
 
1633
1771
  // src/components/password-input.tsx
1634
- import { useState as useState5 } from "react";
1772
+ import { useState as useState6 } from "react";
1635
1773
  import { EyeIcon, EyeOffIcon } from "lucide-react";
1636
- import { cn as cn12 } from "pelatform-ui";
1774
+ import { cn as cn14 } from "pelatform-ui";
1637
1775
  import { Button as Button9, Input as Input2 } from "pelatform-ui/default";
1638
1776
  import { Fragment as Fragment9, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
1639
1777
  function PasswordInput({
@@ -1643,15 +1781,15 @@ function PasswordInput({
1643
1781
  onChange,
1644
1782
  ...props
1645
1783
  }) {
1646
- const [disabled, setDisabled] = useState5(true);
1647
- const [isVisible, setIsVisible] = useState5(false);
1784
+ const [disabled, setDisabled] = useState6(true);
1785
+ const [isVisible, setIsVisible] = useState6(false);
1648
1786
  return /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
1649
1787
  /* @__PURE__ */ jsx24(
1650
1788
  Input2,
1651
1789
  {
1652
1790
  type: isVisible && enableToggle ? "text" : "password",
1653
1791
  variant,
1654
- className: cn12(enableToggle && "pe-10", className),
1792
+ className: cn14(enableToggle && "pe-10", className),
1655
1793
  ...props,
1656
1794
  onChange: (event) => {
1657
1795
  setDisabled(!event.target.value);
@@ -1827,6 +1965,7 @@ export {
1827
1965
  Sidebar,
1828
1966
  SidebarContent,
1829
1967
  SidebarContentMenu,
1968
+ SidebarFooter,
1830
1969
  SidebarHeaderBack,
1831
1970
  SignedInHint,
1832
1971
  SiteFooter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pelatform/starter.shared",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "A part of SaaS starter kit for Pelatform applications.",
5
5
  "author": "Pelatform",
6
6
  "license": "MIT",
@@ -36,15 +36,15 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@pelatform/starter.config": "0.2.2",
39
- "@pelatform/starter.hook": "0.2.4",
39
+ "@pelatform/starter.hook": "0.2.5",
40
40
  "@pelatform/starter.utils": "0.2.10",
41
41
  "@pelatform/tsconfig": "^0.1.4",
42
42
  "@types/react": "^19.2.9",
43
43
  "lucide-react": "^0.563.0",
44
- "next": "^16.1.4",
44
+ "next": "^16.1.5",
45
45
  "next-intl": "^4.7.0",
46
46
  "pelatform-ui": "^1.1.19",
47
- "react": "^19.2.3",
47
+ "react": "^19.2.4",
48
48
  "tsup": "^8.5.1"
49
49
  },
50
50
  "peerDependencies": {