@fluid-app/rep-sdk 0.1.3 → 0.1.4

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.cts CHANGED
@@ -394,6 +394,12 @@ interface RawManifestResponse {
394
394
  definition_id: number;
395
395
  navigation_items?: RawApiNavigationItem[];
396
396
  };
397
+ mobile_navigation?: {
398
+ id: number;
399
+ name?: string;
400
+ definition_id: number;
401
+ navigation_items?: RawApiNavigationItem[];
402
+ };
397
403
  };
398
404
  };
399
405
  }
@@ -2510,11 +2516,12 @@ declare function SdkNavigation({ navItems, currentSlug, onNavigate, navSlugs, }:
2510
2516
 
2511
2517
  interface SdkHeaderProps {
2512
2518
  tabs: NavigationItem[];
2519
+ mobileTabs?: NavigationItem[];
2513
2520
  currentSlug: string;
2514
2521
  onNavigate: (slug: string) => void;
2515
2522
  navSlugs: string[];
2516
2523
  }
2517
- declare function SdkHeader({ tabs, currentSlug, onNavigate, navSlugs, }: SdkHeaderProps): react_jsx_runtime.JSX.Element;
2524
+ declare function SdkHeader({ tabs, mobileTabs, currentSlug, onNavigate, navSlugs, }: SdkHeaderProps): react_jsx_runtime.JSX.Element;
2518
2525
 
2519
2526
  interface PageRouterProps {
2520
2527
  currentSlug: string;
package/dist/index.d.ts CHANGED
@@ -394,6 +394,12 @@ interface RawManifestResponse {
394
394
  definition_id: number;
395
395
  navigation_items?: RawApiNavigationItem[];
396
396
  };
397
+ mobile_navigation?: {
398
+ id: number;
399
+ name?: string;
400
+ definition_id: number;
401
+ navigation_items?: RawApiNavigationItem[];
402
+ };
397
403
  };
398
404
  };
399
405
  }
@@ -2510,11 +2516,12 @@ declare function SdkNavigation({ navItems, currentSlug, onNavigate, navSlugs, }:
2510
2516
 
2511
2517
  interface SdkHeaderProps {
2512
2518
  tabs: NavigationItem[];
2519
+ mobileTabs?: NavigationItem[];
2513
2520
  currentSlug: string;
2514
2521
  onNavigate: (slug: string) => void;
2515
2522
  navSlugs: string[];
2516
2523
  }
2517
- declare function SdkHeader({ tabs, currentSlug, onNavigate, navSlugs, }: SdkHeaderProps): react_jsx_runtime.JSX.Element;
2524
+ declare function SdkHeader({ tabs, mobileTabs, currentSlug, onNavigate, navSlugs, }: SdkHeaderProps): react_jsx_runtime.JSX.Element;
2518
2525
 
2519
2526
  interface PageRouterProps {
2520
2527
  currentSlug: string;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { themes_exports, useFluidApi, transformManifestToRepAppData, useThemeContext, useFluidAuthContext, MessagingScreen } from './chunk-7JMNKWPN.js';
2
- export { AUTH_CONSTANTS, ApiError, DEFAULT_AUTH_URL, DEFAULT_SDK_WIDGET_REGISTRY, FluidAuthProvider, FluidProvider, FluidThemeProvider, MessagingScreen, STORAGE_KEYS, URL_PARAMS, USER_TYPES, buildThemeDefinition, cleanTokenFromUrl, clearTokens, createDefaultAuthRedirect, createFluidClient, createFluidFileUploader, decodeToken, extractAllTokensFromUrl, extractCompanyTokenFromUrl, extractTokenFromUrl, getActiveThemeId, getStoredToken, getTokenExpiration, getTokenTimeRemaining, hasStoredToken, hasTokenInUrl, isApiError, isTokenExpired, isUserType, isValidToken, messagingScreenPropertySchema, normalizeComponentTree, storeToken, toNavigationItem, toScreenDefinition, transformManifestToRepAppData, transformThemes, useFluidApi, useFluidAuthContext, useFluidContext, useMessagingAuth, useMessagingConfig, useThemeContext, validateToken } from './chunk-7JMNKWPN.js';
1
+ import { themes_exports, useFluidApi, transformManifestToRepAppData, useThemeContext, useFluidAuthContext, MessagingScreen } from './chunk-R4SXB6EV.js';
2
+ export { AUTH_CONSTANTS, ApiError, DEFAULT_AUTH_URL, DEFAULT_SDK_WIDGET_REGISTRY, FluidAuthProvider, FluidProvider, FluidThemeProvider, MessagingScreen, STORAGE_KEYS, URL_PARAMS, USER_TYPES, buildThemeDefinition, cleanTokenFromUrl, clearTokens, createDefaultAuthRedirect, createFluidClient, createFluidFileUploader, decodeToken, extractAllTokensFromUrl, extractCompanyTokenFromUrl, extractTokenFromUrl, getActiveThemeId, getStoredToken, getTokenExpiration, getTokenTimeRemaining, hasStoredToken, hasTokenInUrl, isApiError, isTokenExpired, isUserType, isValidToken, messagingScreenPropertySchema, normalizeComponentTree, storeToken, toNavigationItem, toScreenDefinition, transformManifestToRepAppData, transformThemes, useFluidApi, useFluidAuthContext, useFluidContext, useMessagingAuth, useMessagingConfig, useThemeContext, validateToken } from './chunk-R4SXB6EV.js';
3
3
  import { ContactsScreen } from './chunk-CMF2FYTD.js';
4
4
  export { ContactsScreen, contactsScreenPropertySchema } from './chunk-CMF2FYTD.js';
5
5
  import { OrdersScreen } from './chunk-WFPYEYC7.js';
@@ -10,6 +10,7 @@ import { ProductsScreen } from './chunk-QZMWG7EM.js';
10
10
  export { ProductsScreen, productsScreenPropertySchema } from './chunk-QZMWG7EM.js';
11
11
  import { CoreScreenPlaceholder } from './chunk-RS4OSTES.js';
12
12
  import './chunk-424PT5DM.js';
13
+ import * as React2 from 'react';
13
14
  import { createContext, memo, forwardRef, useContext, useRef, useEffect, useMemo, useState, useCallback } from 'react';
14
15
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
16
  import { useQuery } from '@tanstack/react-query';
@@ -21,10 +22,12 @@ import { AppShellLayout } from '@fluid-app/rep-core/shell/AppShellLayout';
21
22
  import { useThemeMode, ThemeModeProvider } from '@fluid-app/rep-core/shell/ThemeModeContext';
22
23
  export { ThemeModeProvider, getThemeModeAttribute, useThemeMode } from '@fluid-app/rep-core/shell/ThemeModeContext';
23
24
  import { normalizeSlug, getSystemNavigationBySection, isSystemNavigationItem } from '@fluid-app/rep-core/navigation/system-navigation-items';
24
- import { resolveTheme, applyTheme, removeAllThemes } from '@fluid-app/rep-core/theme';
25
- import { SidebarMenu, SidebarGroupLabel, SidebarMenuItem, SidebarMenuButton, useSidebar } from '@fluid-app/rep-core/shell/sidebar';
26
- import { RepIcon } from '@fluid-app/rep-core/components/RepIcon';
27
25
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
26
+ import { faEllipsis } from '@fortawesome/pro-regular-svg-icons/faEllipsis';
27
+ import { faXmark } from '@fortawesome/pro-regular-svg-icons/faXmark';
28
+ import { RepIcon } from '@fluid-app/rep-core/components/RepIcon';
29
+ import { SidebarMenu, SidebarGroupLabel, SidebarMenuItem, SidebarMenuButton, useSidebar } from '@fluid-app/rep-core/shell/sidebar';
30
+ import { resolveTheme, applyTheme, removeAllThemes } from '@fluid-app/rep-core/theme';
28
31
  import { faBars } from '@fortawesome/pro-regular-svg-icons/faBars';
29
32
  import { faSun } from '@fortawesome/pro-regular-svg-icons/faSun';
30
33
  import { faMoon } from '@fortawesome/pro-regular-svg-icons/faMoon';
@@ -1653,7 +1656,7 @@ function RequireAuth({
1653
1656
 
1654
1657
  // src/screens/index.ts
1655
1658
  var screenPropertySchemas = {
1656
- MessagingScreen: () => import('./MessagingScreen-4H7ZBO3V.js').then((m) => m.messagingScreenPropertySchema),
1659
+ MessagingScreen: () => import('./MessagingScreen-5TEWFUX4.js').then((m) => m.messagingScreenPropertySchema),
1657
1660
  ContactsScreen: () => import('./ContactsScreen-33AJ5XUB.js').then((m) => m.contactsScreenPropertySchema),
1658
1661
  OrdersScreen: () => import('./OrdersScreen-IPPZLEYF.js').then((m) => m.ordersScreenPropertySchema),
1659
1662
  CustomersScreen: () => import('./CustomersScreen-E4HXBKV7.js').then((m) => m.customersScreenPropertySchema),
@@ -1759,6 +1762,113 @@ function registerCorePageTemplates() {
1759
1762
  });
1760
1763
  }
1761
1764
  registerCorePageTemplates();
1765
+ function isInSection(item, currentSlug) {
1766
+ const normalized = normalizeSlug(currentSlug);
1767
+ if (normalizeSlug(item.slug) === normalized) return true;
1768
+ return item.children?.some((child) => normalizeSlug(child.slug) === normalized) ?? false;
1769
+ }
1770
+ function getNavTarget(item) {
1771
+ if (item.slug && (!item.children || item.children.length === 0)) {
1772
+ return normalizeSlug(item.slug);
1773
+ }
1774
+ if (item.children && item.children.length > 0) {
1775
+ const firstChild = item.children[0];
1776
+ if (firstChild?.slug) return normalizeSlug(firstChild.slug);
1777
+ }
1778
+ return null;
1779
+ }
1780
+ function SdkBottomNav({
1781
+ navItems,
1782
+ currentSlug,
1783
+ onNavigate,
1784
+ maxVisibleItems = 5
1785
+ }) {
1786
+ const { isMobile, useBottomNav } = useSidebar();
1787
+ const [moreOpen, setMoreOpen] = React2.useState(false);
1788
+ if (!isMobile || !useBottomNav) return null;
1789
+ const navigableItems = navItems.filter((item) => !item.parent_id).filter((item) => item.slug || item.children && item.children.length > 0);
1790
+ const hasOverflow = navigableItems.length > maxVisibleItems;
1791
+ const visibleItems = hasOverflow ? navigableItems.slice(0, maxVisibleItems - 1) : navigableItems;
1792
+ const overflowItems = hasOverflow ? navigableItems.slice(maxVisibleItems - 1) : [];
1793
+ const handleItemClick = (item) => {
1794
+ const target = getNavTarget(item);
1795
+ if (target) onNavigate(target);
1796
+ setMoreOpen(false);
1797
+ };
1798
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1799
+ /* @__PURE__ */ jsxs("nav", { className: "fixed right-0 bottom-0 left-0 z-40 flex h-16 items-end justify-around border-t border-border bg-sidebar pb-[env(safe-area-inset-bottom)]", children: [
1800
+ visibleItems.map((item) => {
1801
+ const isActive = isInSection(item, currentSlug);
1802
+ return /* @__PURE__ */ jsxs(
1803
+ "button",
1804
+ {
1805
+ type: "button",
1806
+ onClick: () => handleItemClick(item),
1807
+ className: `flex flex-1 flex-col items-center justify-center gap-0.5 py-2 text-[10px] font-medium transition-colors ${isActive ? "text-primary" : "text-muted-foreground"}`,
1808
+ children: [
1809
+ item.icon ? /* @__PURE__ */ jsx(RepIcon, { name: item.icon, className: "size-5" }) : /* @__PURE__ */ jsx("span", { className: "size-5" }),
1810
+ /* @__PURE__ */ jsx("span", { className: "max-w-[72px] truncate", children: item.label })
1811
+ ]
1812
+ },
1813
+ item.id ?? item.slug ?? item.label
1814
+ );
1815
+ }),
1816
+ hasOverflow && /* @__PURE__ */ jsxs(
1817
+ "button",
1818
+ {
1819
+ type: "button",
1820
+ onClick: () => setMoreOpen(true),
1821
+ className: `flex flex-1 flex-col items-center justify-center gap-0.5 py-2 text-[10px] font-medium transition-colors ${overflowItems.some((item) => isInSection(item, currentSlug)) ? "text-primary" : "text-muted-foreground"}`,
1822
+ children: [
1823
+ /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faEllipsis, className: "size-5" }),
1824
+ /* @__PURE__ */ jsx("span", { children: "More" })
1825
+ ]
1826
+ }
1827
+ )
1828
+ ] }),
1829
+ moreOpen && /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col", children: [
1830
+ /* @__PURE__ */ jsx(
1831
+ "div",
1832
+ {
1833
+ className: "flex-1 bg-black/50",
1834
+ onClick: () => setMoreOpen(false),
1835
+ "aria-hidden": "true"
1836
+ }
1837
+ ),
1838
+ /* @__PURE__ */ jsxs("div", { className: "rounded-t-2xl bg-sidebar pb-[env(safe-area-inset-bottom)]", children: [
1839
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 pt-4 pb-2", children: [
1840
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: "More" }),
1841
+ /* @__PURE__ */ jsx(
1842
+ "button",
1843
+ {
1844
+ type: "button",
1845
+ onClick: () => setMoreOpen(false),
1846
+ className: "flex items-center justify-center rounded-full p-1 text-muted-foreground hover:bg-sidebar-accent",
1847
+ "aria-label": "Close",
1848
+ children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faXmark, className: "size-5" })
1849
+ }
1850
+ )
1851
+ ] }),
1852
+ /* @__PURE__ */ jsx("div", { className: "px-2 pb-4", children: overflowItems.map((item) => {
1853
+ const isActive = isInSection(item, currentSlug);
1854
+ return /* @__PURE__ */ jsxs(
1855
+ "button",
1856
+ {
1857
+ type: "button",
1858
+ onClick: () => handleItemClick(item),
1859
+ className: `flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors ${isActive ? "bg-sidebar-primary text-sidebar-primary-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent"}`,
1860
+ children: [
1861
+ item.icon && /* @__PURE__ */ jsx(RepIcon, { name: item.icon, className: "size-5" }),
1862
+ /* @__PURE__ */ jsx("span", { children: item.label })
1863
+ ]
1864
+ },
1865
+ item.id ?? item.slug ?? item.label
1866
+ );
1867
+ }) })
1868
+ ] })
1869
+ ] })
1870
+ ] });
1871
+ }
1762
1872
  var SPIN_STYLE_ID2 = "fluid-app-shell-loading-spin";
1763
1873
  function ensureSpinStyle2() {
1764
1874
  if (typeof document === "undefined") return;
@@ -1965,6 +2075,7 @@ function QuickLinksDropdown({ onNavigate }) {
1965
2075
  }
1966
2076
  function SdkHeader({
1967
2077
  tabs,
2078
+ mobileTabs,
1968
2079
  currentSlug,
1969
2080
  onNavigate,
1970
2081
  navSlugs
@@ -1974,8 +2085,9 @@ function SdkHeader({
1974
2085
  const match = matchSlugPrefix(currentSlug, navSlugs);
1975
2086
  const baseSlug = match?.matchedSlug ?? normalizeSlug(currentSlug);
1976
2087
  const themeIcon = themeMode.mode === "dark" ? faMoon : faSun;
2088
+ const activeTabs = sidebar.isMobile && sidebar.useBottomNav && mobileTabs ? mobileTabs : tabs;
1977
2089
  return /* @__PURE__ */ jsxs("header", { className: "flex h-[52px] shrink-0 items-center gap-2 bg-sidebar px-6", children: [
1978
- sidebar.isMobile && /* @__PURE__ */ jsx(
2090
+ sidebar.isMobile && !sidebar.useBottomNav && /* @__PURE__ */ jsx(
1979
2091
  "button",
1980
2092
  {
1981
2093
  type: "button",
@@ -1985,7 +2097,7 @@ function SdkHeader({
1985
2097
  children: /* @__PURE__ */ jsx(FontAwesomeIcon, { icon: faBars, className: "size-5" })
1986
2098
  }
1987
2099
  ),
1988
- /* @__PURE__ */ jsx("nav", { className: "scrollbar-none flex flex-1 items-center gap-1 overflow-x-auto", children: tabs.map((tab) => {
2100
+ /* @__PURE__ */ jsx("nav", { className: "scrollbar-none flex flex-1 items-center gap-1 overflow-x-auto", children: activeTabs.map((tab) => {
1989
2101
  const tabSlug = normalizeSlug(tab.slug);
1990
2102
  if (!tabSlug) return null;
1991
2103
  const isActive = tabSlug === baseSlug;
@@ -2224,6 +2336,11 @@ function AppShell({
2224
2336
  if (profileNav && profileNav.length > 0) return profileNav;
2225
2337
  return DEFAULT_NAVIGATION;
2226
2338
  }, [navigationProp, appData?.profile?.navigation?.navigation_items]);
2339
+ const mobileNavItems = useMemo(() => {
2340
+ const mobileNav = appData?.profile?.mobile_navigation?.navigation_items;
2341
+ if (mobileNav && mobileNav.length > 0) return mobileNav;
2342
+ return navItems;
2343
+ }, [appData?.profile?.mobile_navigation?.navigation_items, navItems]);
2227
2344
  const screens = appData?.screens;
2228
2345
  const navSlugs = useMemo(() => collectNavSlugs(navItems), [navItems]);
2229
2346
  const [themeMode, setThemeMode] = useState(getInitialThemeMode);
@@ -2289,6 +2406,8 @@ function AppShell({
2289
2406
  const restParams = slugMatch?.rest ?? "";
2290
2407
  const currentSection = findCurrentSection(navItems, baseSlug);
2291
2408
  const secondLevelTabs = currentSection?.children ?? [];
2409
+ const mobileCurrentSection = findCurrentSection(mobileNavItems, baseSlug);
2410
+ const mobileSecondLevelTabs = mobileCurrentSection?.children ?? [];
2292
2411
  const currentNavItem = findNavItem(navItems, baseSlug);
2293
2412
  const content = typeof children === "function" ? children({ currentSlug: activeSlug, currentNavItem }) : children ?? /* @__PURE__ */ jsx(
2294
2413
  PageRouter,
@@ -2337,6 +2456,7 @@ function AppShell({
2337
2456
  SdkHeader,
2338
2457
  {
2339
2458
  tabs: secondLevelTabs,
2459
+ mobileTabs: mobileSecondLevelTabs,
2340
2460
  currentSlug: activeSlug,
2341
2461
  onNavigate: handleNavigate,
2342
2462
  navSlugs
@@ -2344,6 +2464,15 @@ function AppShell({
2344
2464
  ),
2345
2465
  sidebarHeader,
2346
2466
  sidebarFooter,
2467
+ useBottomNav: true,
2468
+ afterContent: /* @__PURE__ */ jsx(
2469
+ SdkBottomNav,
2470
+ {
2471
+ navItems: mobileNavItems,
2472
+ currentSlug: activeSlug,
2473
+ onNavigate: handleNavigate
2474
+ }
2475
+ ),
2347
2476
  children: content
2348
2477
  }
2349
2478
  )