@withpotter/components 0.13.0-next.67 → 0.13.0-next.68
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MoreHorizontal } from "lucide-react";
|
|
2
2
|
import { universalCoreModules } from "@withpotter/lib/use-platform-modules";
|
|
3
|
-
const MORE_IDS = [
|
|
3
|
+
const MORE_IDS = [];
|
|
4
4
|
function buildMoreGroup(enabledBehaviors, edits = {}) {
|
|
5
5
|
const items = [];
|
|
6
6
|
const hidden = new Set(edits.hiddenModules ?? []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/sidebar/more-group.ts"],"sourcesContent":["import { MoreHorizontal } from 'lucide-react';\nimport { universalCoreModules } from '@withpotter/lib/use-platform-modules';\nimport type { NavGroup, NavItem } from './config';\n\n/**\n * What More holds, in order: the places a business uses now and then that have\n * no row of their own in the rail. Each keeps its behaviour gate from\n * `universalCoreModules
|
|
1
|
+
{"version":3,"sources":["../../src/sidebar/more-group.ts"],"sourcesContent":["import { MoreHorizontal } from 'lucide-react';\nimport { universalCoreModules } from '@withpotter/lib/use-platform-modules';\nimport type { NavGroup, NavItem } from './config';\n\n/**\n * What More holds, in order: the places a business uses now and then that have\n * no row of their own in the rail. Each keeps its behaviour gate from\n * `universalCoreModules`.\n *\n * Empty since Blog moved under Website (it was listed here AND as the last\n * child of Website, so a business with a blog got it twice). The hub is kept,\n * rather than deleted, because the rail's edit list, its row id and its place\n * at the bottom of the rail are all wired to it; with nothing to hold,\n * `buildMoreGroup` returns null and no row is drawn. A place that belongs to\n * no group goes here.\n */\nconst MORE_IDS: readonly string[] = [];\n\n/**\n * MORE — the last row of the general list, as an ordinary hub.\n *\n * It is a `NavGroup` like Marketing or Appointments and is drawn by the same\n * `renderHub`, so it opens in place with the same chevron, the same growing\n * list and the same highlight on the child you are on, and it shares their\n * one-open-at-a-time rule. There is no menu or pop-up of its own to keep in\n * step with them. `alwaysHub` keeps it a dropdown even when a business is left\n * with a single place to show.\n *\n * It honours the same hide, rename and order settings as the rest of the rail\n * (`hiddenModules`, `moduleLabels`, `moduleOrder`), so editing the sidebar\n * reaches it too.\n *\n * Null when none of its places apply, so the row is not drawn empty.\n */\nexport function buildMoreGroup(\n enabledBehaviors: readonly string[] | null | undefined,\n edits: {\n hiddenModules?: readonly string[];\n moduleLabels?: Record<string, string>;\n moduleOrder?: readonly string[];\n } = {},\n): NavGroup | null {\n const items: NavItem[] = [];\n const hidden = new Set(edits.hiddenModules ?? []);\n // The merchant's own order, where they gave one; otherwise ours.\n const order = [...MORE_IDS].sort((a, b) => {\n const at = edits.moduleOrder?.indexOf(a) ?? -1;\n const bt = edits.moduleOrder?.indexOf(b) ?? -1;\n return (at === -1 ? 999 : at) - (bt === -1 ? 999 : bt);\n });\n for (const id of order) {\n if (hidden.has(id)) continue;\n const m = universalCoreModules.find((x) => x.id === id);\n if (!m) continue;\n const need = m.requiredBehavior;\n if (need && enabledBehaviors) {\n const any = Array.isArray(need) ? need : [need];\n if (!any.some((b) => enabledBehaviors.includes(b))) continue;\n }\n items.push({\n id: m.id,\n name: edits.moduleLabels?.[m.id]?.trim() || m.name,\n href: m.href,\n icon: m.icon,\n });\n }\n if (items.length === 0) return null;\n return {\n id: 'more',\n label: 'More',\n icon: MoreHorizontal,\n items,\n alwaysHub: true,\n };\n}\n"],"mappings":"AAAA,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AAerC,MAAM,WAA8B,CAAC;AAkB9B,SAAS,eACd,kBACA,QAII,CAAC,GACY;AACjB,QAAM,QAAmB,CAAC;AAC1B,QAAM,SAAS,IAAI,IAAI,MAAM,iBAAiB,CAAC,CAAC;AAEhD,QAAM,QAAQ,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AACzC,UAAM,KAAK,MAAM,aAAa,QAAQ,CAAC,KAAK;AAC5C,UAAM,KAAK,MAAM,aAAa,QAAQ,CAAC,KAAK;AAC5C,YAAQ,OAAO,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM;AAAA,EACrD,CAAC;AACD,aAAW,MAAM,OAAO;AACtB,QAAI,OAAO,IAAI,EAAE,EAAG;AACpB,UAAM,IAAI,qBAAqB,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACtD,QAAI,CAAC,EAAG;AACR,UAAM,OAAO,EAAE;AACf,QAAI,QAAQ,kBAAkB;AAC5B,YAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAC9C,UAAI,CAAC,IAAI,KAAK,CAAC,MAAM,iBAAiB,SAAS,CAAC,CAAC,EAAG;AAAA,IACtD;AACA,UAAM,KAAK;AAAA,MACT,IAAI,EAAE;AAAA,MACN,MAAM,MAAM,eAAe,EAAE,EAAE,GAAG,KAAK,KAAK,EAAE;AAAA,MAC9C,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,IACV,CAAC;AAAA,EACH;AACA,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,IACN;AAAA,IACA,WAAW;AAAA,EACb;AACF;","names":[]}
|
package/dist/sidebar.js
CHANGED
|
@@ -82,18 +82,18 @@ function Sidebar({
|
|
|
82
82
|
);
|
|
83
83
|
const salesChannel = isSalesChannel(tenantSettings?.salesChannel) ? tenantSettings.salesChannel : null;
|
|
84
84
|
const inPersonOnly = salesChannel === "in_person";
|
|
85
|
+
const enabledBehaviors = useMemo(
|
|
86
|
+
() => resolveEnabledBehaviors(tenantSettings, template),
|
|
87
|
+
[tenantSettings, template]
|
|
88
|
+
);
|
|
85
89
|
const { coreNavigation } = usePlatformModules({
|
|
86
90
|
template,
|
|
87
91
|
dashboardState,
|
|
88
|
-
enabledBehaviors
|
|
92
|
+
enabledBehaviors,
|
|
89
93
|
hiddenModules: tenantSettings?.hiddenModules,
|
|
90
94
|
moduleLabels,
|
|
91
95
|
moduleOrder: tenantSettings?.moduleOrder
|
|
92
96
|
});
|
|
93
|
-
const enabledBehaviors = useMemo(
|
|
94
|
-
() => resolveEnabledBehaviors(tenantSettings, template),
|
|
95
|
-
[tenantSettings, template]
|
|
96
|
-
);
|
|
97
97
|
const intentConfig = useIntentConfig();
|
|
98
98
|
const { can, isOwner, loading: permissionsLoading } = usePermissions();
|
|
99
99
|
const capabilities = useCapabilities();
|
package/dist/sidebar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sidebar.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { PanelLeftClose, PanelLeftOpen } from 'lucide-react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport { usePathname } from '@withpotter/lib/use-pathname';\nimport { ProductSwitcher } from './shell/product-switcher';\nimport { Logo } from '@withpotter/ui-kit/logo';\nimport './shell/shell.css';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { useCapabilities } from '@withpotter/lib/capability-context';\nimport { effectiveModuleLabels } from '@withpotter/lib/effective-module-labels';\nimport { useCurrentTemplate } from '@withpotter/lib/template-context';\nimport { SidebarFooter } from '@withpotter/components/shell/sidebar-footer';\nimport { usePlatformModules } from '@withpotter/lib/use-platform-modules';\nimport { resolveEnabledBehaviors } from '@withpotter/lib/resolve-enabled-behaviors';\nimport { useIntentConfig } from '@withpotter/lib/intents/use-intent-config';\nimport { usePermissions } from '@withpotter/lib/use-permissions';\nimport { isSalesChannel } from '@withpotter/hooks/use-sales-channel';\nimport {\n ACCOUNT_ROUTE_PREFIXES,\n intentKeySet,\n type NavGroup,\n type NavItem,\n} from './sidebar/config';\nimport {\n isActive as isActiveFor,\n resolveActiveHref,\n type SidebarLocation,\n} from './sidebar/active-href';\nimport { buildInboxRow } from './sidebar/inbox-row';\nimport { RailBody } from './sidebar/rail-body';\nimport { EditableRailBody } from './sidebar/rail-editor';\nimport { usableHidden, type SectionId } from './sidebar/rail-edits';\nimport { buildNavGroups } from './sidebar/build-nav-groups';\nimport { buildRailRows } from './sidebar/rail-rows';\nimport {\n buildOrdersPaymentsHub,\n findOrdersRow,\n} from './sidebar/orders-payments-hub';\nimport { splitWorkRows } from './sidebar/work-rows';\nimport { buildMoreGroup } from './sidebar/more-group';\nimport { buildInventoryHub } from './sidebar/inventory-hub';\nimport { SidebarAsk } from './shell/sidebar-ask';\nimport { railContextFor } from './sidebar/route-context';\nimport { useNewNavRows } from './sidebar/use-new-nav-rows';\nimport { useResourceRows } from './sidebar/use-resource-rows';\nimport {\n FIXED_GROUP_IDS,\n flattenWorkGroups,\n groupItems,\n} from './sidebar/flatten-work-groups';\nimport { SettingsNav } from './sidebar/settings-nav';\nimport { createNavRenderers } from './sidebar/nav-renderers';\nimport { useNavBadges } from './sidebar/use-nav-badges';\nimport { useOpenHub } from './sidebar/use-open-hub';\n\nexport function Sidebar({\n collapsed = false,\n onToggleCollapse,\n}: {\n collapsed?: boolean;\n /** Collapses the rail; the button for it sits beside Search in the head. */\n onToggleCollapse?: () => void;\n}) {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n const router = useRouter();\n /** \"Customize sidebar\" is on: the rail itself is editable in place. */\n const [editing, setEditing] = useState<SectionId | null>(null);\n const startEditing = useCallback((s: SectionId) => setEditing(s), []);\n const stopEditing = useCallback(() => setEditing(null), []);\n\n /**\n * Warm a route when the pointer arrives, not when it clicks: every link here\n * is `prefetch={false}`, so a click paid the full cost with nothing ready.\n * Prefetches the URL actually navigated to, query and all, because the\n * adaptive rows are intent-scoped (`/dashboard/catalog?intent=...`).\n */\n const warm = useCallback(\n (href: string) => {\n if (!href || href.startsWith('http')) return;\n router.prefetch(href);\n },\n [router],\n );\n const { tenant } = useAuth();\n const { inSettings, isAccountContext, businessContext } =\n railContextFor(pathname);\n // Editing in place needs the full rail, so it ends when the rail collapses or you\n // go into settings (and does not come back on its own when you return).\n if (editing && (collapsed || inSettings)) setEditing(null);\n // \"Back home\" means home: the dashboard, not wherever you last were.\n const settingsBack = () => router.push('/dashboard');\n const { hubChoice, setHubOpen } = useOpenHub(pathname);\n\n const { template, dashboardState } = useCurrentTemplate(tenant?.templateId);\n\n const tenantSettings = tenant?.settings as\n Record<string, unknown> | undefined;\n const moduleLabels = effectiveModuleLabels(tenantSettings);\n const hiddenModules = tenantSettings?.hiddenModules as string[] | undefined;\n /**\n * What the groups are built without. While editing, nothing is hidden, so a\n * hidden row is still on the rail (dimmed, to be shown again); the rail\n * itself drops hidden rows otherwise. Essential rows are never hidden, so a\n * stale `inbox` entry in the list does not hide the Inbox.\n */\n const navHidden = useMemo(\n () => (editing ? undefined : usableHidden(hiddenModules)),\n [editing, hiddenModules],\n );\n\n // How the tenant takes money (from onboarding). Refines the nav: an\n // in-person-only business doesn't ship, so fulfillment surfaces are hidden.\n // `null` (unset) never hides anything — this only ever removes what genuinely\n // doesn't apply.\n const salesChannel = isSalesChannel(tenantSettings?.salesChannel)\n ? tenantSettings.salesChannel\n : null;\n const inPersonOnly = salesChannel === 'in_person';\n\n // Still use usePlatformModules for behavior resolution and resource sidebar\n const { coreNavigation } = usePlatformModules({\n template,\n dashboardState,\n enabledBehaviors: tenantSettings?.enabledBehaviors as string[] | undefined,\n hiddenModules: tenantSettings?.hiddenModules as string[] | undefined,\n moduleLabels,\n moduleOrder: tenantSettings?.moduleOrder as string[] | undefined,\n });\n\n const enabledBehaviors = useMemo(\n () => resolveEnabledBehaviors(tenantSettings, template),\n [tenantSettings, template],\n );\n\n const intentConfig = useIntentConfig();\n const { can, isOwner, loading: permissionsLoading } = usePermissions();\n const capabilities = useCapabilities();\n\n /**\n * Which archetypes the CURRENT URL is narrowed to, verbatim.\n *\n * Not `intentConfig.primary.key`: that falls back to sessionStorage when the\n * URL carries no `?intent=`, so which row lit up depended on where you had\n * last been rather than where you are. And not a single key either — a\n * collapsed row carries every archetype behind it.\n */\n const currentIntent =\n intentConfig.mode === 'multi'\n ? intentKeySet(searchParams.get('intent'))\n : null;\n\n const location: SidebarLocation = {\n pathname,\n params: searchParams,\n currentIntent,\n };\n const isActive = (href: string) => isActiveFor(href, location);\n\n const getGroupItems = groupItems;\n\n // Build navigation groups. Memoized on its real inputs (NOT pathname) so the\n // whole tree — intent resolution, permission filtering, label overrides —\n // doesn't rebuild on every navigation. Only activeHref/isActive depend on the\n // route, and they're cheap.\n const declaredGroups: NavGroup[] = useMemo(\n () =>\n buildNavGroups({\n hiddenModules: navHidden,\n moduleLabels,\n enabledBehaviors,\n inPersonOnly,\n intentConfig,\n coreNavigation,\n template,\n can,\n isOwner,\n permissionsLoading,\n hasCapability: capabilities.has,\n }),\n [\n navHidden,\n moduleLabels,\n enabledBehaviors,\n inPersonOnly,\n intentConfig,\n coreNavigation,\n template,\n can,\n isOwner,\n permissionsLoading,\n capabilities,\n ],\n );\n\n /**\n * The bookable-things row, told apart: Courts and Coaches rather than one\n * row named after whichever shape the archetype guessed. Only expands when\n * this business actually has groups; see `use-resource-rows.ts`.\n */\n const groups = useResourceRows(declaredGroups);\n\n // Flat render model (console-style): work-surface items sit unlabeled with\n // Home; each fixed spine group is either a single link, or a hub that reveals\n // its children inline (disclosure, no chevron); Settings is pinned in the foot.\n const FIXED_IDS = FIXED_GROUP_IDS;\n /**\n * A flat group is a row, not just a container for rows.\n *\n * This took each non-fixed group's ITEMS and dropped the group itself, which\n * is right for an archetype group — Dine-in and Events are labels, and their\n * children are the destinations. It is wrong for the hoisted shared rows.\n *\n * `Catalog` and `Orders` come out of the collapse as groups carrying their\n * own `href`, because they belong to no archetype: Orders has no children at\n * all, and Catalog has exactly one (Collections). So this rendered **nothing**\n * for Orders and **only Collections** for Catalog — the two most-used\n * destinations in the app were absent from the sidebar of every\n * multi-archetype business, and the archetype rows beside them made it look\n * intentional.\n *\n * Every test in the suite asserts on what `buildNavGroups` returns, which was\n * correct the whole time. Nothing looked at what the sidebar drew.\n */\n // Shared, so the test and `scripts/archetype-shape.mts` see what is drawn\n // here rather than each modelling it. See `flatten-work-groups.ts`.\n const workItems = flattenWorkGroups(groups);\n const spineGroups = groups.filter(\n (g) => FIXED_IDS.has(g.id) && g.id !== 'settings',\n );\n\n // More is built here, ahead of the active-row list, because that list has to\n // include its rows: built after it they are never candidates, so nothing lights\n // on their pages and the hub never opens itself.\n const moduleOrder = tenantSettings?.moduleOrder as string[] | undefined;\n const moreGroup = useMemo(\n () =>\n buildMoreGroup(enabledBehaviors, {\n hiddenModules: navHidden,\n moduleLabels,\n moduleOrder,\n }),\n [enabledBehaviors, navHidden, moduleLabels, moduleOrder],\n );\n\n // Ahead of the active-row list for the same reason as More: its href has to\n // be a candidate or nothing lights on /dashboard/inbox.\n const inboxRow = buildInboxRow({\n hiddenModules: navHidden,\n moduleLabels,\n can,\n isOwner,\n permissionsLoading,\n });\n\n // Exactly one row carries the active highlight. If the path is inside a hub,\n // the hub's landing row lights up (its sub-pages are tabs, not sidebar rows);\n // otherwise the deepest matching flat row wins. Keeping it unique lets the\n // shared motion indicator spring cleanly between rows.\n // The deepest matching row wins — including hub CHILDREN, now that sub-pages\n // render inline in the sidebar rather than only as HubTabs. So the actual\n // current sub-page carries the highlight, not just the hub landing.\n // Exactly one row carries the active highlight — see `active-href.ts` for\n // how it is chosen. The list is every href the sidebar draws, hub children\n // included: Collections is attached as a child of the catalogue row, so when\n // children were missing from this list nothing lit on /dashboard/collections\n // and the hub holding the only row that leads there stayed shut.\n const activeHref = useMemo(\n () =>\n resolveActiveHref(\n [\n '/dashboard',\n ...(inboxRow ? [inboxRow.href] : []),\n ...workItems.flatMap((i) => [\n i.href,\n ...(i.children ?? []).map((c) => c.href),\n ]),\n ...spineGroups.flatMap((g) => [\n g.href,\n ...getGroupItems(g).map((i) => i.href),\n ]),\n ...(moreGroup ? getGroupItems(moreGroup).map((i) => i.href) : []),\n ].filter((h): h is string => !!h),\n location,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [pathname, searchParams, groups, moreGroup, inboxRow?.href],\n );\n\n const { inventoryHub, catalogMatches, collectionsItem, collectionsNested } =\n buildInventoryHub(workItems);\n\n /**\n * When the Inventory hub exists, catalog + collections move inside it; else\n * both still render flat, right where they were.\n *\n * THE ROWS THEMSELVES, not their ids. An id says what a row is called by its\n * archetype, not which screen it opens, and `subscriptions` calls its Plans\n * row `catalog` too — so a business running memberships beside anything with\n * a real catalogue had **Plans deleted from its sidebar**, in all nine\n * two-archetype combinations. Collections is consumed only when the hub took\n * it: dropping it always cost the row to a business with no catalogue row.\n */\n const ordersItem = findOrdersRow(workItems);\n const ordersPaymentsHub = buildOrdersPaymentsHub({\n ordersItem,\n moneyGroup: spineGroups.find((g) => g.id === 'payments') ?? null,\n can,\n });\n\n const consumed = new Set<unknown>([\n ...(inventoryHub\n ? [...catalogMatches, ...(collectionsItem ? [collectionsItem] : [])]\n : []),\n // With no catalogue row to hold it, Collections is drawn as a row of its\n // own by the rail; it must not also be drawn as a work row.\n ...(!inventoryHub && collectionsItem && !collectionsNested\n ? [collectionsItem]\n : []),\n ...(ordersPaymentsHub && ordersItem ? [ordersItem] : []),\n ]);\n /* General (unlabeled) leads; the rest drop into Operations. The rule is in\n `work-rows`. */\n const { primaryWork, extraWork } = splitWorkRows({\n workItems,\n consumed,\n hasInventoryHub: !!inventoryHub,\n });\n\n const hubById = new Map(spineGroups.map((g) => [g.id, g]));\n const operationsHub = hubById.get('operations');\n\n const badges = useNavBadges();\n /* Rows that appeared because the business added something this week — see\n `use-new-nav-rows`. */\n const newRows = useNewNavRows();\n\n // Plain render helpers (NOT inner components) — defining components inside\n // the render remounts them every pass, which breaks motion's shared-layout\n // highlight (it would jump from stale positions). Functions returning JSX\n // keep the elements stable under the parent, so the spring animates cleanly.\n const {\n renderHighlight,\n renderIcon,\n renderRow,\n renderHub,\n renderWorkRow,\n ownsRoute,\n } = createNavRenderers({\n collapsed,\n warm,\n activeHref,\n isActive,\n hubChoice,\n setHubOpen,\n getGroupItems,\n badges,\n isNew: (id: string) => newRows.has(id),\n });\n\n const { moneyRow, manageRows, growRows } = buildRailRows({\n inventoryHub,\n payHub: ordersPaymentsHub ?? hubById.get('payments'),\n primaryWork,\n extraWork,\n collectionsItem,\n collectionsNested,\n customersHub: hubById.get('customers'),\n hardwareHub: hubById.get('hardware'),\n operationsHub,\n growHubs: [\n hubById.get('marketing'),\n hubById.get('analytics'),\n hubById.get('website'),\n ],\n renderHub,\n renderRow,\n renderWorkRow,\n });\n\n /** What the rail is drawn from, in both modes. See `rail-body.tsx`. */\n const railProps = {\n collapsed,\n homeActive: activeHref === '/dashboard',\n toolkitActive: pathname.startsWith('/dashboard/toolkit'),\n highlight: renderHighlight,\n inboxRow,\n renderRow,\n renderHub,\n renderIcon,\n ownsRoute,\n moneyRow,\n manageRows,\n growRows,\n moreGroup,\n };\n\n return (\n <aside\n className={`pv-shell sidebar${collapsed ? ' collapsed' : ''} hidden lg:flex`}\n >\n {/* THE HEAD OF THE RAIL, one flat row (John, 2026-10-04): the business's\n mark and name at the left, the Search and Ask icons at the right. It\n was a bordered card with a second line, and Search a row of its own\n beneath it. */}\n {/* A branded box can put its own logo at the top of the rail\n (NEXT_PUBLIC_BOX_LOGO_IN_SHELL). Left out when the rail is collapsed,\n where there is no room for a wordmark. */}\n {process.env.NEXT_PUBLIC_BOX_LOGO_IN_SHELL === 'true' &&\n process.env.NEXT_PUBLIC_BOX_LOGO &&\n !collapsed && (\n <div className=\"px-3 pb-1 pt-3\">\n <Logo size=\"sm\" theme=\"light\" />\n </div>\n )}\n <div className=\"side-head\">\n {collapsed && onToggleCollapse && (\n /* The way back out of a collapsed rail: laid over the business\n mark, invisible until the pointer is on it, then the expand icon\n (John, 2026-10-11). */\n <button\n type=\"button\"\n onClick={onToggleCollapse}\n className=\"side-head-expand\"\n title=\"Expand sidebar (⌘\\)\"\n aria-label=\"Expand sidebar\"\n >\n <PanelLeftOpen width={18} height={18} />\n </button>\n )}\n {!businessContext ? (\n <ProductSwitcher variant=\"head\" />\n ) : (\n <div className=\"flex-1\" />\n )}\n {/* Search, at the right of the head, after Linear (John, 2026-10-11).\n It was a row under Home; it is an action, not a place, so it leaves\n the list. */}\n <div className=\"side-head-actions\">\n <SidebarAsk collapsed={collapsed} variant=\"icon\" />\n {onToggleCollapse && !collapsed && (\n <button\n type=\"button\"\n onClick={onToggleCollapse}\n className=\"side-head-icon\"\n title=\"Collapse sidebar (⌘\\)\"\n aria-label=\"Collapse sidebar\"\n >\n <PanelLeftClose width={16} height={16} />\n </button>\n )}\n </div>\n </div>\n\n {/* Navigation */}\n <nav className=\"nav\" aria-label=\"Main navigation\">\n {/* No loading skeleton: the general nav renders without the template. */}\n\n {/* General nav ⇄ Settings nav: settings drills in place. The pane is\n keyed on the boundary so it remounts and slides in (from the right\n going into settings, from the left coming back). Enter-only — no\n exit — so the nav never collapses and re-flows from the bottom. */}\n <div\n key={inSettings ? 'settings' : 'main'}\n className={'nav-swap ' + (inSettings ? 'from-right' : 'from-left')}\n >\n {inSettings ? (\n <SettingsNav\n businessContext={businessContext}\n pathname={pathname}\n collapsed={collapsed}\n enabledBehaviors={enabledBehaviors}\n tenant={tenant}\n onBack={settingsBack}\n />\n ) : editing ? (\n <EditableRailBody\n {...railProps}\n onDone={stopEditing}\n editSection={editing}\n savedLabels={moduleLabels}\n storedLabels={\n tenantSettings?.moduleLabels as\n Record<string, string> | undefined\n }\n />\n ) : (\n <RailBody\n {...railProps}\n onConfigure={startEditing}\n edits={{\n hidden: hiddenModules,\n order: moduleOrder,\n labels: moduleLabels,\n sectionLabels: tenantSettings?.sectionLabels as\n Record<string, string> | undefined,\n }}\n />\n )}\n </div>\n </nav>\n\n <SidebarFooter collapsed={collapsed} />\n </aside>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/sidebar.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { PanelLeftClose, PanelLeftOpen } from 'lucide-react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport { usePathname } from '@withpotter/lib/use-pathname';\nimport { ProductSwitcher } from './shell/product-switcher';\nimport { Logo } from '@withpotter/ui-kit/logo';\nimport './shell/shell.css';\nimport { useAuth } from '@withpotter/lib/auth-context';\nimport { useCapabilities } from '@withpotter/lib/capability-context';\nimport { effectiveModuleLabels } from '@withpotter/lib/effective-module-labels';\nimport { useCurrentTemplate } from '@withpotter/lib/template-context';\nimport { SidebarFooter } from '@withpotter/components/shell/sidebar-footer';\nimport { usePlatformModules } from '@withpotter/lib/use-platform-modules';\nimport { resolveEnabledBehaviors } from '@withpotter/lib/resolve-enabled-behaviors';\nimport { useIntentConfig } from '@withpotter/lib/intents/use-intent-config';\nimport { usePermissions } from '@withpotter/lib/use-permissions';\nimport { isSalesChannel } from '@withpotter/hooks/use-sales-channel';\nimport {\n ACCOUNT_ROUTE_PREFIXES,\n intentKeySet,\n type NavGroup,\n type NavItem,\n} from './sidebar/config';\nimport {\n isActive as isActiveFor,\n resolveActiveHref,\n type SidebarLocation,\n} from './sidebar/active-href';\nimport { buildInboxRow } from './sidebar/inbox-row';\nimport { RailBody } from './sidebar/rail-body';\nimport { EditableRailBody } from './sidebar/rail-editor';\nimport { usableHidden, type SectionId } from './sidebar/rail-edits';\nimport { buildNavGroups } from './sidebar/build-nav-groups';\nimport { buildRailRows } from './sidebar/rail-rows';\nimport {\n buildOrdersPaymentsHub,\n findOrdersRow,\n} from './sidebar/orders-payments-hub';\nimport { splitWorkRows } from './sidebar/work-rows';\nimport { buildMoreGroup } from './sidebar/more-group';\nimport { buildInventoryHub } from './sidebar/inventory-hub';\nimport { SidebarAsk } from './shell/sidebar-ask';\nimport { railContextFor } from './sidebar/route-context';\nimport { useNewNavRows } from './sidebar/use-new-nav-rows';\nimport { useResourceRows } from './sidebar/use-resource-rows';\nimport {\n FIXED_GROUP_IDS,\n flattenWorkGroups,\n groupItems,\n} from './sidebar/flatten-work-groups';\nimport { SettingsNav } from './sidebar/settings-nav';\nimport { createNavRenderers } from './sidebar/nav-renderers';\nimport { useNavBadges } from './sidebar/use-nav-badges';\nimport { useOpenHub } from './sidebar/use-open-hub';\n\nexport function Sidebar({\n collapsed = false,\n onToggleCollapse,\n}: {\n collapsed?: boolean;\n /** Collapses the rail; the button for it sits beside Search in the head. */\n onToggleCollapse?: () => void;\n}) {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n const router = useRouter();\n /** \"Customize sidebar\" is on: the rail itself is editable in place. */\n const [editing, setEditing] = useState<SectionId | null>(null);\n const startEditing = useCallback((s: SectionId) => setEditing(s), []);\n const stopEditing = useCallback(() => setEditing(null), []);\n\n /**\n * Warm a route when the pointer arrives, not when it clicks: every link here\n * is `prefetch={false}`, so a click paid the full cost with nothing ready.\n * Prefetches the URL actually navigated to, query and all, because the\n * adaptive rows are intent-scoped (`/dashboard/catalog?intent=...`).\n */\n const warm = useCallback(\n (href: string) => {\n if (!href || href.startsWith('http')) return;\n router.prefetch(href);\n },\n [router],\n );\n const { tenant } = useAuth();\n const { inSettings, isAccountContext, businessContext } =\n railContextFor(pathname);\n // Editing in place needs the full rail, so it ends when the rail collapses or you\n // go into settings (and does not come back on its own when you return).\n if (editing && (collapsed || inSettings)) setEditing(null);\n // \"Back home\" means home: the dashboard, not wherever you last were.\n const settingsBack = () => router.push('/dashboard');\n const { hubChoice, setHubOpen } = useOpenHub(pathname);\n\n const { template, dashboardState } = useCurrentTemplate(tenant?.templateId);\n\n const tenantSettings = tenant?.settings as\n Record<string, unknown> | undefined;\n const moduleLabels = effectiveModuleLabels(tenantSettings);\n const hiddenModules = tenantSettings?.hiddenModules as string[] | undefined;\n /**\n * What the groups are built without. While editing, nothing is hidden, so a\n * hidden row is still on the rail (dimmed, to be shown again); the rail\n * itself drops hidden rows otherwise. Essential rows are never hidden, so a\n * stale `inbox` entry in the list does not hide the Inbox.\n */\n const navHidden = useMemo(\n () => (editing ? undefined : usableHidden(hiddenModules)),\n [editing, hiddenModules],\n );\n\n // How the tenant takes money (from onboarding). Refines the nav: an\n // in-person-only business doesn't ship, so fulfillment surfaces are hidden.\n // `null` (unset) never hides anything — this only ever removes what genuinely\n // doesn't apply.\n const salesChannel = isSalesChannel(tenantSettings?.salesChannel)\n ? tenantSettings.salesChannel\n : null;\n const inPersonOnly = salesChannel === 'in_person';\n\n // The behaviors the business really has: its model, the merchant's own\n // switches (Settings > Features) and the template's defaults. Resolved BEFORE\n // the core list is built, because that list gates its modules on them. It was\n // handed the raw stored `enabledBehaviors` instead, which knows nothing of an\n // override, so a Blog switched on in Features never reached Website's Blog\n // row and showed only in More.\n const enabledBehaviors = useMemo(\n () => resolveEnabledBehaviors(tenantSettings, template),\n [tenantSettings, template],\n );\n\n // Still use usePlatformModules for behavior resolution and resource sidebar\n const { coreNavigation } = usePlatformModules({\n template,\n dashboardState,\n enabledBehaviors,\n hiddenModules: tenantSettings?.hiddenModules as string[] | undefined,\n moduleLabels,\n moduleOrder: tenantSettings?.moduleOrder as string[] | undefined,\n });\n\n const intentConfig = useIntentConfig();\n const { can, isOwner, loading: permissionsLoading } = usePermissions();\n const capabilities = useCapabilities();\n\n /**\n * Which archetypes the CURRENT URL is narrowed to, verbatim.\n *\n * Not `intentConfig.primary.key`: that falls back to sessionStorage when the\n * URL carries no `?intent=`, so which row lit up depended on where you had\n * last been rather than where you are. And not a single key either — a\n * collapsed row carries every archetype behind it.\n */\n const currentIntent =\n intentConfig.mode === 'multi'\n ? intentKeySet(searchParams.get('intent'))\n : null;\n\n const location: SidebarLocation = {\n pathname,\n params: searchParams,\n currentIntent,\n };\n const isActive = (href: string) => isActiveFor(href, location);\n\n const getGroupItems = groupItems;\n\n // Build navigation groups. Memoized on its real inputs (NOT pathname) so the\n // whole tree — intent resolution, permission filtering, label overrides —\n // doesn't rebuild on every navigation. Only activeHref/isActive depend on the\n // route, and they're cheap.\n const declaredGroups: NavGroup[] = useMemo(\n () =>\n buildNavGroups({\n hiddenModules: navHidden,\n moduleLabels,\n enabledBehaviors,\n inPersonOnly,\n intentConfig,\n coreNavigation,\n template,\n can,\n isOwner,\n permissionsLoading,\n hasCapability: capabilities.has,\n }),\n [\n navHidden,\n moduleLabels,\n enabledBehaviors,\n inPersonOnly,\n intentConfig,\n coreNavigation,\n template,\n can,\n isOwner,\n permissionsLoading,\n capabilities,\n ],\n );\n\n /**\n * The bookable-things row, told apart: Courts and Coaches rather than one\n * row named after whichever shape the archetype guessed. Only expands when\n * this business actually has groups; see `use-resource-rows.ts`.\n */\n const groups = useResourceRows(declaredGroups);\n\n // Flat render model (console-style): work-surface items sit unlabeled with\n // Home; each fixed spine group is either a single link, or a hub that reveals\n // its children inline (disclosure, no chevron); Settings is pinned in the foot.\n const FIXED_IDS = FIXED_GROUP_IDS;\n /**\n * A flat group is a row, not just a container for rows.\n *\n * This took each non-fixed group's ITEMS and dropped the group itself, which\n * is right for an archetype group — Dine-in and Events are labels, and their\n * children are the destinations. It is wrong for the hoisted shared rows.\n *\n * `Catalog` and `Orders` come out of the collapse as groups carrying their\n * own `href`, because they belong to no archetype: Orders has no children at\n * all, and Catalog has exactly one (Collections). So this rendered **nothing**\n * for Orders and **only Collections** for Catalog — the two most-used\n * destinations in the app were absent from the sidebar of every\n * multi-archetype business, and the archetype rows beside them made it look\n * intentional.\n *\n * Every test in the suite asserts on what `buildNavGroups` returns, which was\n * correct the whole time. Nothing looked at what the sidebar drew.\n */\n // Shared, so the test and `scripts/archetype-shape.mts` see what is drawn\n // here rather than each modelling it. See `flatten-work-groups.ts`.\n const workItems = flattenWorkGroups(groups);\n const spineGroups = groups.filter(\n (g) => FIXED_IDS.has(g.id) && g.id !== 'settings',\n );\n\n // More is built here, ahead of the active-row list, because that list has to\n // include its rows: built after it they are never candidates, so nothing lights\n // on their pages and the hub never opens itself.\n const moduleOrder = tenantSettings?.moduleOrder as string[] | undefined;\n const moreGroup = useMemo(\n () =>\n buildMoreGroup(enabledBehaviors, {\n hiddenModules: navHidden,\n moduleLabels,\n moduleOrder,\n }),\n [enabledBehaviors, navHidden, moduleLabels, moduleOrder],\n );\n\n // Ahead of the active-row list for the same reason as More: its href has to\n // be a candidate or nothing lights on /dashboard/inbox.\n const inboxRow = buildInboxRow({\n hiddenModules: navHidden,\n moduleLabels,\n can,\n isOwner,\n permissionsLoading,\n });\n\n // Exactly one row carries the active highlight. If the path is inside a hub,\n // the hub's landing row lights up (its sub-pages are tabs, not sidebar rows);\n // otherwise the deepest matching flat row wins. Keeping it unique lets the\n // shared motion indicator spring cleanly between rows.\n // The deepest matching row wins — including hub CHILDREN, now that sub-pages\n // render inline in the sidebar rather than only as HubTabs. So the actual\n // current sub-page carries the highlight, not just the hub landing.\n // Exactly one row carries the active highlight — see `active-href.ts` for\n // how it is chosen. The list is every href the sidebar draws, hub children\n // included: Collections is attached as a child of the catalogue row, so when\n // children were missing from this list nothing lit on /dashboard/collections\n // and the hub holding the only row that leads there stayed shut.\n const activeHref = useMemo(\n () =>\n resolveActiveHref(\n [\n '/dashboard',\n ...(inboxRow ? [inboxRow.href] : []),\n ...workItems.flatMap((i) => [\n i.href,\n ...(i.children ?? []).map((c) => c.href),\n ]),\n ...spineGroups.flatMap((g) => [\n g.href,\n ...getGroupItems(g).map((i) => i.href),\n ]),\n ...(moreGroup ? getGroupItems(moreGroup).map((i) => i.href) : []),\n ].filter((h): h is string => !!h),\n location,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [pathname, searchParams, groups, moreGroup, inboxRow?.href],\n );\n\n const { inventoryHub, catalogMatches, collectionsItem, collectionsNested } =\n buildInventoryHub(workItems);\n\n /**\n * When the Inventory hub exists, catalog + collections move inside it; else\n * both still render flat, right where they were.\n *\n * THE ROWS THEMSELVES, not their ids. An id says what a row is called by its\n * archetype, not which screen it opens, and `subscriptions` calls its Plans\n * row `catalog` too — so a business running memberships beside anything with\n * a real catalogue had **Plans deleted from its sidebar**, in all nine\n * two-archetype combinations. Collections is consumed only when the hub took\n * it: dropping it always cost the row to a business with no catalogue row.\n */\n const ordersItem = findOrdersRow(workItems);\n const ordersPaymentsHub = buildOrdersPaymentsHub({\n ordersItem,\n moneyGroup: spineGroups.find((g) => g.id === 'payments') ?? null,\n can,\n });\n\n const consumed = new Set<unknown>([\n ...(inventoryHub\n ? [...catalogMatches, ...(collectionsItem ? [collectionsItem] : [])]\n : []),\n // With no catalogue row to hold it, Collections is drawn as a row of its\n // own by the rail; it must not also be drawn as a work row.\n ...(!inventoryHub && collectionsItem && !collectionsNested\n ? [collectionsItem]\n : []),\n ...(ordersPaymentsHub && ordersItem ? [ordersItem] : []),\n ]);\n /* General (unlabeled) leads; the rest drop into Operations. The rule is in\n `work-rows`. */\n const { primaryWork, extraWork } = splitWorkRows({\n workItems,\n consumed,\n hasInventoryHub: !!inventoryHub,\n });\n\n const hubById = new Map(spineGroups.map((g) => [g.id, g]));\n const operationsHub = hubById.get('operations');\n\n const badges = useNavBadges();\n /* Rows that appeared because the business added something this week — see\n `use-new-nav-rows`. */\n const newRows = useNewNavRows();\n\n // Plain render helpers (NOT inner components) — defining components inside\n // the render remounts them every pass, which breaks motion's shared-layout\n // highlight (it would jump from stale positions). Functions returning JSX\n // keep the elements stable under the parent, so the spring animates cleanly.\n const {\n renderHighlight,\n renderIcon,\n renderRow,\n renderHub,\n renderWorkRow,\n ownsRoute,\n } = createNavRenderers({\n collapsed,\n warm,\n activeHref,\n isActive,\n hubChoice,\n setHubOpen,\n getGroupItems,\n badges,\n isNew: (id: string) => newRows.has(id),\n });\n\n const { moneyRow, manageRows, growRows } = buildRailRows({\n inventoryHub,\n payHub: ordersPaymentsHub ?? hubById.get('payments'),\n primaryWork,\n extraWork,\n collectionsItem,\n collectionsNested,\n customersHub: hubById.get('customers'),\n hardwareHub: hubById.get('hardware'),\n operationsHub,\n growHubs: [\n hubById.get('marketing'),\n hubById.get('analytics'),\n hubById.get('website'),\n ],\n renderHub,\n renderRow,\n renderWorkRow,\n });\n\n /** What the rail is drawn from, in both modes. See `rail-body.tsx`. */\n const railProps = {\n collapsed,\n homeActive: activeHref === '/dashboard',\n toolkitActive: pathname.startsWith('/dashboard/toolkit'),\n highlight: renderHighlight,\n inboxRow,\n renderRow,\n renderHub,\n renderIcon,\n ownsRoute,\n moneyRow,\n manageRows,\n growRows,\n moreGroup,\n };\n\n return (\n <aside\n className={`pv-shell sidebar${collapsed ? ' collapsed' : ''} hidden lg:flex`}\n >\n {/* THE HEAD OF THE RAIL, one flat row (John, 2026-10-04): the business's\n mark and name at the left, the Search and Ask icons at the right. It\n was a bordered card with a second line, and Search a row of its own\n beneath it. */}\n {/* A branded box can put its own logo at the top of the rail\n (NEXT_PUBLIC_BOX_LOGO_IN_SHELL). Left out when the rail is collapsed,\n where there is no room for a wordmark. */}\n {process.env.NEXT_PUBLIC_BOX_LOGO_IN_SHELL === 'true' &&\n process.env.NEXT_PUBLIC_BOX_LOGO &&\n !collapsed && (\n <div className=\"px-3 pb-1 pt-3\">\n <Logo size=\"sm\" theme=\"light\" />\n </div>\n )}\n <div className=\"side-head\">\n {collapsed && onToggleCollapse && (\n /* The way back out of a collapsed rail: laid over the business\n mark, invisible until the pointer is on it, then the expand icon\n (John, 2026-10-11). */\n <button\n type=\"button\"\n onClick={onToggleCollapse}\n className=\"side-head-expand\"\n title=\"Expand sidebar (⌘\\)\"\n aria-label=\"Expand sidebar\"\n >\n <PanelLeftOpen width={18} height={18} />\n </button>\n )}\n {!businessContext ? (\n <ProductSwitcher variant=\"head\" />\n ) : (\n <div className=\"flex-1\" />\n )}\n {/* Search, at the right of the head, after Linear (John, 2026-10-11).\n It was a row under Home; it is an action, not a place, so it leaves\n the list. */}\n <div className=\"side-head-actions\">\n <SidebarAsk collapsed={collapsed} variant=\"icon\" />\n {onToggleCollapse && !collapsed && (\n <button\n type=\"button\"\n onClick={onToggleCollapse}\n className=\"side-head-icon\"\n title=\"Collapse sidebar (⌘\\)\"\n aria-label=\"Collapse sidebar\"\n >\n <PanelLeftClose width={16} height={16} />\n </button>\n )}\n </div>\n </div>\n\n {/* Navigation */}\n <nav className=\"nav\" aria-label=\"Main navigation\">\n {/* No loading skeleton: the general nav renders without the template. */}\n\n {/* General nav ⇄ Settings nav: settings drills in place. The pane is\n keyed on the boundary so it remounts and slides in (from the right\n going into settings, from the left coming back). Enter-only — no\n exit — so the nav never collapses and re-flows from the bottom. */}\n <div\n key={inSettings ? 'settings' : 'main'}\n className={'nav-swap ' + (inSettings ? 'from-right' : 'from-left')}\n >\n {inSettings ? (\n <SettingsNav\n businessContext={businessContext}\n pathname={pathname}\n collapsed={collapsed}\n enabledBehaviors={enabledBehaviors}\n tenant={tenant}\n onBack={settingsBack}\n />\n ) : editing ? (\n <EditableRailBody\n {...railProps}\n onDone={stopEditing}\n editSection={editing}\n savedLabels={moduleLabels}\n storedLabels={\n tenantSettings?.moduleLabels as\n Record<string, string> | undefined\n }\n />\n ) : (\n <RailBody\n {...railProps}\n onConfigure={startEditing}\n edits={{\n hidden: hiddenModules,\n order: moduleOrder,\n labels: moduleLabels,\n sectionLabels: tenantSettings?.sectionLabels as\n Record<string, string> | undefined,\n }}\n />\n )}\n </div>\n </nav>\n\n <SidebarFooter collapsed={collapsed} />\n </aside>\n );\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@withpotter/components",
|
|
3
|
-
"version": "0.13.0-next.
|
|
3
|
+
"version": "0.13.0-next.68",
|
|
4
4
|
"description": "Box dashboard feature components: editors, mobile screens, pickers, and composite UI built on @withpotter/ui-kit.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"sideEffects": [
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"@tiptap/react": "^3.22.5",
|
|
51
51
|
"@tiptap/starter-kit": "^3.22.5",
|
|
52
52
|
"@tiptap/suggestion": "^3.22.5",
|
|
53
|
-
"@withpotter/hooks": "^0.13.0-next.
|
|
54
|
-
"@withpotter/lib": "^0.13.0-next.
|
|
55
|
-
"@withpotter/ui-kit": "^0.13.0-next.
|
|
53
|
+
"@withpotter/hooks": "^0.13.0-next.68",
|
|
54
|
+
"@withpotter/lib": "^0.13.0-next.68",
|
|
55
|
+
"@withpotter/ui-kit": "^0.13.0-next.68",
|
|
56
56
|
"@xyflow/react": "^12.11.2",
|
|
57
57
|
"dompurify": "^3.3.1",
|
|
58
58
|
"jsqr": "1.4.0",
|