{"version":3,"file":"use-navigation-parent-BMFPIGdi.cjs","names":["useAppNavigation","useOptionalAppNavigation"],"sources":["../../core/src/navigation/system-navigation-items.ts","../../core/src/navigation/slug-utils.ts","../src/shell/use-navigation-parent.ts"],"sourcesContent":["/**\n * System navigation items for portal apps\n * These are pre-built screens that cannot be edited or deleted in the builder.\n * They are handled by custom code (slugLibrary) rather than builder screens.\n */\n\nimport type { NavigationItem } from \"../types/navigation\";\n\nexport const SYSTEM_NAVIGATION_SLUGS = [\n  \"activity\",\n  \"app-download\",\n  \"contacts\",\n  \"account\",\n  \"messages\",\n  \"my-site\",\n  \"orders\",\n  \"profile\",\n  \"subscriptions\",\n  // \"share/enrollments\",\n  \"share/media\",\n  \"share/pages\",\n  \"share/playlists\",\n  \"share/products\",\n  \"shop\",\n  // \"upgrade\",\n] as const;\n\nexport type SystemNavigationSlug = (typeof SYSTEM_NAVIGATION_SLUGS)[number];\n\nexport type SystemNavigationItem = Omit<NavigationItem, \"children\">;\n\n/**\n * Slugs hidden from the quicklinks/shortcuts menu.\n * These screens still exist and are navigable, but don't appear in the grid.\n */\nexport const QUICKLINKS_HIDDEN_SLUGS: ReadonlySet<string> =\n  new Set<SystemNavigationSlug>([\"app-download\"]);\n\n/**\n * Core navigation slugs that cannot be removed from a portal's navigation in the builder.\n * Subset of system items considered essential to every portal's UX.\n */\nexport const CORE_NAVIGATION_SLUGS: ReadonlySet<string> =\n  new Set<SystemNavigationSlug>([\"profile\", \"orders\", \"subscriptions\"]);\n\n/**\n * Check if a slug refers to a core navigation item that cannot be deleted.\n * Handles a leading slash (e.g. \"/profile\").\n */\nexport function isCoreNavigationSlug(slug: string | undefined | null): boolean {\n  if (!slug) return false;\n  const normalized = slug.startsWith(\"/\") ? slug.slice(1) : slug;\n  return CORE_NAVIGATION_SLUGS.has(normalized);\n}\n\n/**\n * Slugs restricted to rep (non-customer) users.\n * Customers will not see these in navigation and cannot access these routes.\n */\nexport const REP_ONLY_SLUGS: ReadonlySet<string> =\n  new Set<SystemNavigationSlug>([\"messages\", \"my-site\"]);\n\n/**\n * Check if a slug is restricted to rep users only.\n * Handles both exact matches and prefix matches (e.g. \"contacts/123\").\n */\nexport function isRepOnlySlug(slug: string | undefined | null): boolean {\n  if (!slug) return false;\n  const normalized = slug.startsWith(\"/\") ? slug.slice(1) : slug;\n  if (REP_ONLY_SLUGS.has(normalized)) return true;\n  for (const repSlug of REP_ONLY_SLUGS) {\n    if (normalized.startsWith(repSlug + \"/\")) return true;\n  }\n  return false;\n}\n\nexport const SYSTEM_NAVIGATION_ITEMS: Record<\n  SystemNavigationSlug,\n  SystemNavigationItem\n> = {\n  activity: {\n    slug: \"activity\",\n    label: \"Activity\",\n    icon: \"clock\",\n    section: \"User\",\n  },\n  \"app-download\": {\n    slug: \"app-download\",\n    label: \"App Download\",\n    icon: \"mobile\",\n    section: \"User\",\n  },\n  contacts: {\n    slug: \"contacts\",\n    label: \"Contacts\",\n    icon: \"circle-user\",\n    section: \"User\",\n  },\n  messages: {\n    slug: \"messages\",\n    label: \"Messaging\",\n    icon: \"message\",\n    section: \"User\",\n  },\n  \"my-site\": {\n    slug: \"my-site\",\n    label: \"MySite\",\n    icon: \"globe\",\n    section: \"Shareables\",\n  },\n  orders: {\n    slug: \"orders\",\n    label: \"Orders\",\n    icon: \"package-open\",\n    section: \"User\",\n  },\n  profile: {\n    slug: \"profile\",\n    label: \"Profile\",\n    icon: \"user\",\n    section: \"User\",\n  },\n  account: {\n    slug: \"profile\",\n    label: \"Account\",\n    icon: \"user\",\n    section: \"User\",\n  },\n  // \"share/enrollments\": {\n  //   slug: \"share/enrollments\",\n  //   label: \"Enrollments\",\n  //   icon: \"graduation-cap\",\n  //   section: \"Shareables\",\n  // },\n  \"share/media\": {\n    slug: \"share/media\",\n    label: \"Media\",\n    icon: \"file-video\",\n    section: \"Shareables\",\n  },\n  \"share/pages\": {\n    slug: \"share/pages\",\n    label: \"Pages\",\n    icon: \"file-lines\",\n    section: \"Shareables\",\n  },\n  \"share/playlists\": {\n    slug: \"share/playlists\",\n    label: \"Playlists\",\n    icon: \"list-music\",\n    section: \"Shareables\",\n  },\n  \"share/products\": {\n    slug: \"share/products\",\n    label: \"Products\",\n    icon: \"box\",\n    section: \"Shareables\",\n  },\n  shop: {\n    slug: \"shop\",\n    label: \"Shop\",\n    icon: \"store\",\n    section: \"User\",\n  },\n  subscriptions: {\n    slug: \"subscriptions\",\n    label: \"Subscriptions\",\n    icon: \"arrows-repeat\",\n    section: \"User\",\n  },\n  // upgrade: {\n  //   slug: \"upgrade\",\n  //   label: \"Upgrade\",\n  //   icon: \"arrow-up-from-bracket\",\n  //   section: \"User\",\n  // },\n} as const;\n\n/**\n * Get the default system navigation items for a new portal app.\n * These items have no screen_id - they're handled by the slugLibrary.\n */\nexport function getDefaultSystemNavigationItems(): SystemNavigationItem[] {\n  return Object.values(SYSTEM_NAVIGATION_ITEMS);\n}\n\n/**\n * Check if a navigation item is a system item that doesn't require a screen_id.\n * Used by RepApp to skip screen validation for these items.\n */\nexport function isSystemNavigationItem(\n  slug?: string | null,\n): slug is SystemNavigationSlug {\n  if (!slug) return false;\n  return SYSTEM_NAVIGATION_SLUGS.includes(slug as SystemNavigationSlug);\n}\n\n/**\n * Get icon name for a navigation item by slug.\n */\nexport function getNavigationItemIcon(slug?: string): string | undefined {\n  if (!slug) return undefined;\n  const systemItem = SYSTEM_NAVIGATION_ITEMS[slug as SystemNavigationSlug];\n  return systemItem?.icon;\n}\n\n/**\n * Get system navigation items grouped by section.\n */\nexport function getSystemNavigationBySection(): Record<\n  string,\n  SystemNavigationItem[]\n> {\n  const sections: Record<string, SystemNavigationItem[]> = {};\n  const seenSlugs = new Set<string>();\n  for (const item of Object.values(SYSTEM_NAVIGATION_ITEMS)) {\n    if (item.slug && seenSlugs.has(item.slug)) continue;\n    if (item.slug) seenSlugs.add(item.slug);\n    if (item.slug && QUICKLINKS_HIDDEN_SLUGS.has(item.slug)) continue;\n    const section = item.section || \"Other\";\n    if (!sections[section]) {\n      sections[section] = [];\n    }\n    sections[section].push(item);\n  }\n  return sections;\n}\n\n/**\n * Normalize a navigation slug by stripping a leading slash.\n */\nexport function normalizeSlug(slug: string | undefined): string {\n  if (!slug) return \"\";\n  return slug.startsWith(\"/\") ? slug.slice(1) : slug;\n}\n","import type { NavigationItem } from \"../types/navigation\";\nimport { normalizeSlug } from \"./system-navigation-items\";\n\nexport interface SlugMatch {\n  matchedSlug: string;\n  rest: string;\n}\n\n/**\n * Extract all slugs from a navigation tree, sorted by segment count descending.\n * Longest slugs first enables greedy prefix matching (e.g. \"share/playlists\"\n * is checked before \"share\").\n */\nexport function collectNavSlugs(items: NavigationItem[]): string[] {\n  const slugs: string[] = [];\n\n  for (const item of items) {\n    if (item.slug) slugs.push(normalizeSlug(item.slug));\n    for (const child of item.children ?? []) {\n      if (child.slug) slugs.push(normalizeSlug(child.slug));\n    }\n  }\n\n  return slugs.toSorted((a, b) => b.split(\"/\").length - a.split(\"/\").length);\n}\n\n/**\n * Find the longest registered nav slug that is a prefix of `fullSlug`.\n * Uses segment-boundary checking to prevent \"shop\" from matching \"shopping\".\n */\nexport function matchSlugPrefix(\n  fullSlug: string,\n  navSlugs: string[],\n): SlugMatch | undefined {\n  const normalized = normalizeSlug(fullSlug);\n  if (!normalized) return undefined;\n\n  for (const navSlug of navSlugs) {\n    if (normalized === navSlug) {\n      return { matchedSlug: navSlug, rest: \"\" };\n    }\n    if (normalized.startsWith(navSlug + \"/\")) {\n      return {\n        matchedSlug: navSlug,\n        rest: normalized.slice(navSlug.length + 1),\n      };\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Extract the slug portion from a full pathname by stripping the basePath prefix.\n * Returns an empty string when the pathname equals the basePath exactly.\n *\n * Examples:\n *   extractSlugFromPathname(\"/contacts/123\", \"/\")        → \"contacts/123\"\n *   extractSlugFromPathname(\"/portal/contacts\", \"/portal\") → \"contacts\"\n *   extractSlugFromPathname(\"/portal\", \"/portal\")          → \"\"\n *   extractSlugFromPathname(\"/\", \"/\")                      → \"\"\n */\nexport function extractSlugFromPathname(\n  pathname: string,\n  basePath: string,\n): string {\n  // For root basePath, just strip the leading slash\n  if (basePath === \"/\") {\n    return pathname.replace(/^\\//, \"\");\n  }\n\n  // Strip basePath prefix, then strip leading slash from remainder\n  if (pathname.startsWith(basePath)) {\n    return pathname.slice(basePath.length).replace(/^\\//, \"\");\n  }\n\n  // Fallback: return pathname without leading slash\n  return pathname.replace(/^\\//, \"\");\n}\n\n/**\n * Resolve an href that points at a screen inside this portal back to its slug,\n * or undefined when the href leads somewhere else (another origin, a\n * mailto:/tel: link, a path outside `basePath`, or the portal root itself).\n *\n * Widget buttons and links can be authored as plain URLs, and those URLs are\n * allowed to be in-portal paths like \"/profile\". Left as real anchors they\n * reload the document — which throws away the in-session referrer the mobile\n * header's back button is derived from. Resolving them back to a slug lets the\n * shell navigate in-app instead, so the destination keeps a way back.\n *\n * Slugs are pathnames: the shell matches them against registered nav slugs and\n * has nowhere to put a query string or fragment, so an href carrying either is\n * left to the browser rather than resolved into a slug that would match no\n * screen.\n *\n * Examples:\n *   internalSlugFromHref(\"/profile\", \"/\", \"https://acme.fluid.app\")\n *   → \"profile\"\n *\n *   internalSlugFromHref(\"https://acme.fluid.app/orders\", \"/\", \"https://acme.fluid.app\")\n *   → \"orders\"\n *\n *   internalSlugFromHref(\"/orders?tab=open\", \"/\", \"https://acme.fluid.app\")\n *   → undefined\n *\n *   internalSlugFromHref(\"https://shop.example.com/deals\", \"/\", \"https://acme.fluid.app\")\n *   → undefined\n */\nexport function internalSlugFromHref(\n  href: string,\n  basePath: string,\n  origin: string,\n): string | undefined {\n  const trimmed = href.trim();\n  if (!trimmed) return undefined;\n\n  let parsed: URL;\n  try {\n    parsed = new URL(trimmed, origin);\n  } catch {\n    return undefined;\n  }\n\n  // mailto:, tel: and every other scheme leave the portal, as does a\n  // protocol-relative \"//host/path\" pointing at another host.\n  if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n    return undefined;\n  }\n  if (parsed.origin !== origin) return undefined;\n\n  // A query or fragment can't ride along in a slug — the shell routes on\n  // pathnames alone, so \"orders?tab=open\" would match no registered screen.\n  if (parsed.search || parsed.hash) return undefined;\n\n  const normalizedBase = basePath === \"/\" ? \"/\" : basePath.replace(/\\/+$/, \"\");\n  const withinBase =\n    normalizedBase === \"/\" ||\n    parsed.pathname === normalizedBase ||\n    parsed.pathname.startsWith(`${normalizedBase}/`);\n  if (!withinBase) return undefined;\n\n  // The portal root is not a screen slug — leave those links to the browser.\n  return extractSlugFromPathname(parsed.pathname, normalizedBase) || undefined;\n}\n\n/**\n * Generate a URL-safe slug from a human-readable name. Mirrors the admin\n * builder's `generateSlugFromName` so a navigation item authored as\n * `slugifyName(screen.name)` can be matched back to the screen at runtime\n * even when the screen's own `slug` is opaque (e.g. `screen-{uuid}`).\n */\nexport function slugifyName(name: string): string {\n  return name\n    .toLowerCase()\n    .replace(/[^a-z0-9\\s-]/g, \"\")\n    .replace(/\\s+/g, \"-\")\n    .replace(/-+/g, \"-\")\n    .replace(/^-+|-+$/g, \"\");\n}\n\nexport function resolveSlugLabel(\n  slug: string,\n  items: NavigationItem[],\n): string | null {\n  const normalized = normalizeSlug(slug);\n  if (!normalized) return null;\n\n  const match = matchSlugPrefix(normalized, collectNavSlugs(items));\n  const target = match?.matchedSlug ?? normalized;\n\n  for (const item of items) {\n    if (normalizeSlug(item.slug) === target) return item.label;\n    for (const child of item.children ?? []) {\n      if (normalizeSlug(child.slug) === target) return child.label;\n    }\n  }\n  return null;\n}\n\nexport function isSlugInSection(\n  item: NavigationItem,\n  currentSlug: string,\n  navSlugs: string[],\n): boolean {\n  const match = matchSlugPrefix(currentSlug, navSlugs);\n  const baseSlug = match?.matchedSlug ?? normalizeSlug(currentSlug);\n\n  if (normalizeSlug(item.slug) === baseSlug) return true;\n  return (\n    item.children?.some((child) => normalizeSlug(child.slug) === baseSlug) ??\n    false\n  );\n}\n","import { useMemo } from \"react\";\nimport { resolveSlugLabel } from \"@fluid-app/portal-core/navigation/slug-utils\";\nimport {\n  useAppNavigation,\n  useOptionalAppNavigation,\n} from \"./AppNavigationContext\";\n\nexport interface NavigationParent {\n  slug: string;\n  label: string;\n  onClick: () => void;\n}\n\n/**\n * Resolve the previous in-session slug into a labeled back-target. Returns\n * `null` when there's no referrer or the referrer can't be matched to a\n * known nav item — callers should fall back to their structural parent.\n */\nexport function useNavigationParent(): NavigationParent | null {\n  const { previousSlug, navItems, navigate } = useAppNavigation();\n\n  return useMemo(() => {\n    if (!previousSlug) return null;\n    const label = resolveSlugLabel(previousSlug, navItems);\n    if (!label) return null;\n    return { slug: previousSlug, label, onClick: () => navigate(previousSlug) };\n  }, [previousSlug, navItems, navigate]);\n}\n\n/**\n * useNavigationParent for screens that also render without a shell (the\n * builder preview): no provider simply means no back-target.\n */\nexport function useOptionalNavigationParent(): NavigationParent | null {\n  const navigation = useOptionalAppNavigation();\n  const previousSlug = navigation?.previousSlug ?? null;\n  const navItems = navigation?.navItems;\n  const navigate = navigation?.navigate;\n\n  return useMemo(() => {\n    if (!previousSlug || !navItems || !navigate) return null;\n    const label = resolveSlugLabel(previousSlug, navItems);\n    if (!label) return null;\n    return { slug: previousSlug, label, onClick: () => navigate(previousSlug) };\n  }, [previousSlug, navItems, navigate]);\n}\n"],"mappings":"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"}