@arbidocs/blocks 0.5.35 → 0.5.37
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/README.md +22 -0
- package/dist/{ConnectedCallDock-V7DPSE6X.cjs → ConnectedCallDock-2LMIR4ID.cjs} +17 -17
- package/dist/{ConnectedCallDock-V7DPSE6X.cjs.map → ConnectedCallDock-2LMIR4ID.cjs.map} +1 -1
- package/dist/{ConnectedCallDock-CT3D6LLI.js → ConnectedCallDock-2NYM46HU.js} +8 -8
- package/dist/{ConnectedCallDock-CT3D6LLI.js.map → ConnectedCallDock-2NYM46HU.js.map} +1 -1
- package/dist/{ConnectedCallRoom-TNOCSTX2.cjs → ConnectedCallRoom-26PBMTCC.cjs} +9 -9
- package/dist/{ConnectedCallRoom-TNOCSTX2.cjs.map → ConnectedCallRoom-26PBMTCC.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-A27AM7IQ.js → ConnectedCallRoom-QJ2UV6GV.js} +8 -8
- package/dist/{ConnectedCallRoom-A27AM7IQ.js.map → ConnectedCallRoom-QJ2UV6GV.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-H2OZMWHT.cjs → ConnectedNativeDocxComparison-5MN7PVRE.cjs} +13 -13
- package/dist/{ConnectedNativeDocxComparison-H2OZMWHT.cjs.map → ConnectedNativeDocxComparison-5MN7PVRE.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-RWKFPJPJ.js → ConnectedNativeDocxComparison-GHOEFJUN.js} +12 -12
- package/dist/{ConnectedNativeDocxComparison-RWKFPJPJ.js.map → ConnectedNativeDocxComparison-GHOEFJUN.js.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-43BI5LN6.js → ConnectedNativeDocxEditor-HWPSWU2A.js} +11 -11
- package/dist/{ConnectedNativeDocxEditor-43BI5LN6.js.map → ConnectedNativeDocxEditor-HWPSWU2A.js.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-6DQEM6SD.cjs → ConnectedNativeDocxEditor-VA7476NF.cjs} +13 -13
- package/dist/{ConnectedNativeDocxEditor-6DQEM6SD.cjs.map → ConnectedNativeDocxEditor-VA7476NF.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-TEB332E3.js → ConnectedStreamedWordArtifact-KZUZB47X.js} +12 -12
- package/dist/ConnectedStreamedWordArtifact-KZUZB47X.js.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-3VKYIG6C.cjs → ConnectedStreamedWordArtifact-UMSTUZBY.cjs} +13 -13
- package/dist/ConnectedStreamedWordArtifact-UMSTUZBY.cjs.map +1 -0
- package/dist/{WorkspaceTableView-ATZHON74.cjs → WorkspaceTableView-DYXHUIRA.cjs} +9 -9
- package/dist/{WorkspaceTableView-ATZHON74.cjs.map → WorkspaceTableView-DYXHUIRA.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-7APDRIPL.js → WorkspaceTableView-HXSBJY42.js} +7 -7
- package/dist/{WorkspaceTableView-7APDRIPL.js.map → WorkspaceTableView-HXSBJY42.js.map} +1 -1
- package/dist/agents/index.cjs +401 -401
- package/dist/agents/index.js +10 -10
- package/dist/calls/index.cjs +131 -131
- package/dist/calls/index.js +9 -9
- package/dist/chat/index.cjs +81 -81
- package/dist/chat/index.js +3 -3
- package/dist/{chunk-NUV5F6MM.js → chunk-2VEBUYEJ.js} +3 -3
- package/dist/{chunk-NUV5F6MM.js.map → chunk-2VEBUYEJ.js.map} +1 -1
- package/dist/{chunk-EGSSLWNZ.cjs → chunk-32ZIHUXE.cjs} +3 -3
- package/dist/{chunk-EGSSLWNZ.cjs.map → chunk-32ZIHUXE.cjs.map} +1 -1
- package/dist/{chunk-24H5WTGM.js → chunk-3ON5DJLR.js} +4 -4
- package/dist/{chunk-24H5WTGM.js.map → chunk-3ON5DJLR.js.map} +1 -1
- package/dist/{chunk-6EQSP77K.cjs → chunk-7P2IL7RX.cjs} +5 -5
- package/dist/{chunk-6EQSP77K.cjs.map → chunk-7P2IL7RX.cjs.map} +1 -1
- package/dist/{chunk-LNYEYR7W.cjs → chunk-7W7TPWSZ.cjs} +3 -3
- package/dist/{chunk-LNYEYR7W.cjs.map → chunk-7W7TPWSZ.cjs.map} +1 -1
- package/dist/{chunk-EFSL4O3B.cjs → chunk-ABKRLMWN.cjs} +5 -5
- package/dist/{chunk-EFSL4O3B.cjs.map → chunk-ABKRLMWN.cjs.map} +1 -1
- package/dist/{chunk-YPR4FSDJ.js → chunk-APPHGHMM.js} +3 -3
- package/dist/{chunk-YPR4FSDJ.js.map → chunk-APPHGHMM.js.map} +1 -1
- package/dist/{chunk-AL7EXOX5.js → chunk-CXY2ELL5.js} +3 -3
- package/dist/{chunk-AL7EXOX5.js.map → chunk-CXY2ELL5.js.map} +1 -1
- package/dist/{chunk-2C3I27VI.js → chunk-EHRT5M5F.js} +3 -3
- package/dist/{chunk-2C3I27VI.js.map → chunk-EHRT5M5F.js.map} +1 -1
- package/dist/{chunk-3ZLNI7ZA.cjs → chunk-EZJOJFY2.cjs} +3 -3
- package/dist/{chunk-3ZLNI7ZA.cjs.map → chunk-EZJOJFY2.cjs.map} +1 -1
- package/dist/{chunk-PRY52BW5.js → chunk-GI5ITZ53.js} +4 -4
- package/dist/{chunk-PRY52BW5.js.map → chunk-GI5ITZ53.js.map} +1 -1
- package/dist/{chunk-RBHVIVWP.js → chunk-GMECFWVT.js} +81 -81
- package/dist/chunk-GMECFWVT.js.map +1 -0
- package/dist/{chunk-S3YRRD54.js → chunk-GMZ2XFQQ.js} +3 -3
- package/dist/{chunk-S3YRRD54.js.map → chunk-GMZ2XFQQ.js.map} +1 -1
- package/dist/{chunk-VMLEISRZ.cjs → chunk-H3JKC55K.cjs} +9 -9
- package/dist/{chunk-VMLEISRZ.cjs.map → chunk-H3JKC55K.cjs.map} +1 -1
- package/dist/{chunk-FHB4G77H.js → chunk-IC2BXIUT.js} +3 -3
- package/dist/{chunk-FHB4G77H.js.map → chunk-IC2BXIUT.js.map} +1 -1
- package/dist/{chunk-PUX4M22Q.cjs → chunk-IYW6Q33D.cjs} +50 -50
- package/dist/{chunk-PUX4M22Q.cjs.map → chunk-IYW6Q33D.cjs.map} +1 -1
- package/dist/{chunk-4DKI37QQ.js → chunk-JYASRZUQ.js} +7 -7
- package/dist/{chunk-4DKI37QQ.js.map → chunk-JYASRZUQ.js.map} +1 -1
- package/dist/{chunk-G4VUVOHZ.cjs → chunk-K7OF4KGP.cjs} +82 -82
- package/dist/chunk-K7OF4KGP.cjs.map +1 -0
- package/dist/{chunk-Q7BS7EOU.cjs → chunk-KFQ6E6LE.cjs} +32 -28
- package/dist/chunk-KFQ6E6LE.cjs.map +1 -0
- package/dist/{chunk-N3HVTMQK.js → chunk-L7IBURSP.js} +3 -3
- package/dist/{chunk-N3HVTMQK.js.map → chunk-L7IBURSP.js.map} +1 -1
- package/dist/{chunk-FEVJA4BP.cjs → chunk-LPGFODB4.cjs} +3 -3
- package/dist/{chunk-FEVJA4BP.cjs.map → chunk-LPGFODB4.cjs.map} +1 -1
- package/dist/{chunk-VKY4SQMH.js → chunk-LXF22VRI.js} +4 -4
- package/dist/{chunk-VKY4SQMH.js.map → chunk-LXF22VRI.js.map} +1 -1
- package/dist/{chunk-XFSEPGF7.cjs → chunk-ME3R44JN.cjs} +4 -4
- package/dist/{chunk-XFSEPGF7.cjs.map → chunk-ME3R44JN.cjs.map} +1 -1
- package/dist/{chunk-P6MVDOCL.js → chunk-MJYGHJ4Y.js} +3 -3
- package/dist/{chunk-P6MVDOCL.js.map → chunk-MJYGHJ4Y.js.map} +1 -1
- package/dist/{chunk-WALADS2S.cjs → chunk-N2SUDWY2.cjs} +3 -3
- package/dist/{chunk-WALADS2S.cjs.map → chunk-N2SUDWY2.cjs.map} +1 -1
- package/dist/{chunk-ICCBNHPU.js → chunk-NNUNS47F.js} +3 -3
- package/dist/{chunk-ICCBNHPU.js.map → chunk-NNUNS47F.js.map} +1 -1
- package/dist/{chunk-NOKTUWTN.cjs → chunk-OJTXFIXU.cjs} +4 -4
- package/dist/{chunk-NOKTUWTN.cjs.map → chunk-OJTXFIXU.cjs.map} +1 -1
- package/dist/{chunk-LTEDORG3.js → chunk-ORBXJ4IT.js} +221 -6
- package/dist/chunk-ORBXJ4IT.js.map +1 -0
- package/dist/{chunk-FSEZEVWZ.cjs → chunk-OXIGJYMO.cjs} +220 -3
- package/dist/chunk-OXIGJYMO.cjs.map +1 -0
- package/dist/{chunk-XHW35TC7.js → chunk-PPHUOWCJ.js} +33 -29
- package/dist/chunk-PPHUOWCJ.js.map +1 -0
- package/dist/{chunk-H5BFOVVL.cjs → chunk-RVCQE66I.cjs} +5 -5
- package/dist/{chunk-H5BFOVVL.cjs.map → chunk-RVCQE66I.cjs.map} +1 -1
- package/dist/{chunk-7CHI36EP.js → chunk-T7O73MX2.js} +5 -5
- package/dist/{chunk-7CHI36EP.js.map → chunk-T7O73MX2.js.map} +1 -1
- package/dist/{chunk-JKMV4QNV.cjs → chunk-U7IEC2EM.cjs} +74 -74
- package/dist/{chunk-JKMV4QNV.cjs.map → chunk-U7IEC2EM.cjs.map} +1 -1
- package/dist/{chunk-FY4C7HU5.cjs → chunk-UCCYCT3R.cjs} +16 -16
- package/dist/{chunk-FY4C7HU5.cjs.map → chunk-UCCYCT3R.cjs.map} +1 -1
- package/dist/{chunk-RH4XIABH.js → chunk-UHYO2E25.js} +3 -3
- package/dist/{chunk-RH4XIABH.js.map → chunk-UHYO2E25.js.map} +1 -1
- package/dist/{chunk-2QDNQM63.cjs → chunk-UKG4DDLI.cjs} +10 -10
- package/dist/{chunk-2QDNQM63.cjs.map → chunk-UKG4DDLI.cjs.map} +1 -1
- package/dist/{chunk-VPWCARVO.js → chunk-VP5TGUBY.js} +5 -5
- package/dist/{chunk-VPWCARVO.js.map → chunk-VP5TGUBY.js.map} +1 -1
- package/dist/{chunk-MLHOG7YH.js → chunk-VWX5UECZ.js} +3 -3
- package/dist/{chunk-MLHOG7YH.js.map → chunk-VWX5UECZ.js.map} +1 -1
- package/dist/{chunk-H6K7EWL2.cjs → chunk-WDMWWBPB.cjs} +7 -7
- package/dist/{chunk-H6K7EWL2.cjs.map → chunk-WDMWWBPB.cjs.map} +1 -1
- package/dist/{chunk-BIWPXSGS.cjs → chunk-YRWMYVHU.cjs} +20 -20
- package/dist/{chunk-BIWPXSGS.cjs.map → chunk-YRWMYVHU.cjs.map} +1 -1
- package/dist/{chunk-EZSYYENN.js → chunk-ZXU2TKUV.js} +6 -6
- package/dist/{chunk-EZSYYENN.js.map → chunk-ZXU2TKUV.js.map} +1 -1
- package/dist/{chunk-BRYRZOS3.cjs → chunk-ZZ76AUGX.cjs} +4 -4
- package/dist/{chunk-BRYRZOS3.cjs.map → chunk-ZZ76AUGX.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/connect/docx.cjs +15 -15
- package/dist/connect/docx.js +11 -11
- package/dist/connect/index.cjs +2866 -2606
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +2090 -1832
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +63 -63
- package/dist/connect/viewer.js +16 -16
- package/dist/connection/workspace-form/ConnectedProjectSelector.d.ts +15 -0
- package/dist/connection/workspace-form/ConnectedWorkspaceFormModal.d.ts +11 -0
- package/dist/connection/workspace-form/WorkspaceCreateForm.d.ts +15 -0
- package/dist/connection/workspace-form/index.d.ts +3 -0
- package/dist/connection/workspace-form/types.d.ts +28 -0
- package/dist/connection/workspace-list/ConnectedWorkspaceList.d.ts +4 -1
- package/dist/connection/workspace-list/useConnectedWorkspaceList.d.ts +12 -36
- package/dist/facts/index.cjs +2 -2
- package/dist/facts/index.js +2 -2
- package/dist/files/index.cjs +223 -223
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +29 -29
- package/dist/home/index.js +4 -4
- package/dist/index.cjs +1660 -1652
- package/dist/index.js +22 -22
- package/dist/settings/index.cjs +156 -156
- package/dist/settings/index.js +3 -3
- package/dist/shell/DockZone.d.ts +27 -0
- package/dist/shell/PanelModeSwitcher.d.ts +30 -0
- package/dist/shell/index.cjs +78 -70
- package/dist/shell/index.d.ts +2 -0
- package/dist/shell/index.js +4 -4
- package/dist/studio/index.cjs +8 -8
- package/dist/studio/index.js +7 -7
- package/dist/workflow-canvas/index.cjs +23 -23
- package/dist/workflow-canvas/index.js +10 -10
- package/dist/workspaces/WorkspaceFormParts.d.ts +3 -2
- package/dist/workspaces/index.cjs +27 -27
- package/dist/workspaces/index.js +2 -2
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ConnectedStreamedWordArtifact-3VKYIG6C.cjs.map +0 -1
- package/dist/ConnectedStreamedWordArtifact-TEB332E3.js.map +0 -1
- package/dist/chunk-FSEZEVWZ.cjs.map +0 -1
- package/dist/chunk-G4VUVOHZ.cjs.map +0 -1
- package/dist/chunk-LTEDORG3.js.map +0 -1
- package/dist/chunk-Q7BS7EOU.cjs.map +0 -1
- package/dist/chunk-RBHVIVWP.js.map +0 -1
- package/dist/chunk-XHW35TC7.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/billing/support.ts","../src/connection/billing/plan-constants.ts","../src/connection/billing/quota-items.ts","../src/connection/billing/reward-balance.ts","../src/connection/billing/addon-pricing.ts","../src/connection/billing/api-error.ts","../src/connection/billing/tax-quote.ts","../src/connection/billing/plan-pricing.ts","../src/connection/billing/plan-badge.ts","../src/connection/workspace-list/projectBilling.tsx"],"names":["useHost","useArbi","PoundSterling","formatGbp","HardDrive","Users","useUserSettings","gbp","jsx","PlanBadge","ProjectReadout","QuotaMeter","ProjectBreakdown","UsageMeter"],"mappings":"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","file":"chunk-G4VUVOHZ.cjs","sourcesContent":["/**\n * What a host adds to the billing kit. Selling plans needs Stripe, which stays the host's: whether\n * this deployment sells plans (a publishable key is configured), and its embedded checkout. It is the\n * host configuration's `billing`; without it nothing is for sale: projects show their limits and\n * usage only.\n */\nimport type { ReactNode } from 'react'\nimport { useArbi } from '@arbidocs/react'\nimport { useHost } from '../../provider/host'\n\nexport interface BillingCheckoutSupport {\n /** Load the host's Stripe (lazily, when a checkout opens); `null` when it cannot. */\n load(): Promise<unknown> | null\n /** Stripe's embedded checkout for a session, on the loaded Stripe. */\n render(stripe: unknown, session: { clientSecret: string; onComplete: () => void }): ReactNode\n}\n\nexport interface BillingSupport {\n /** This deployment sells plans (Stripe is configured). */\n stripeEnabled: boolean\n checkout?: BillingCheckoutSupport\n /**\n * Add-on blocks the user just bought here, so the host does not announce them later as having\n * arrived on their own.\n */\n onAddonBlocksBought?: (projectExtId: string, blocks: { ai: number; storage: number }) => void\n}\n\nconst NOT_FOR_SALE: BillingSupport = { stripeEnabled: false }\n\nexport function useBillingSupport(): BillingSupport {\n return useHost().billing ?? NOT_FOR_SALE\n}\n\n/** The signed-in user's id (`usr-…`), to tell the projects they own from the others. */\nexport function useSelfExtId(): string | undefined {\n const arbi = useArbi()\n return arbi.isLoggedIn ? (arbi.user.identity()?.externalId ?? undefined) : undefined\n}\n","/** Pro's allowance per month (one licence) — must match the backend. Legacy multi-pack plans get it per pack.\n * The live numbers for an existing project come from `project.addons`; these are only for\n * describing the plan before a project exists (new-project dialog, upgrade picker). */\nexport const PRO_AI_GBP = 10\nexport const PRO_STORAGE_GB = 5\n\n/**\n * Add-on block sizes (£25 of AI usage or 25 GB), the same on every plan. Their prices come from the\n * products API (`addon_prices`) before a project exists, and from `project.addons` after.\n */\nexport const ADDON_BLOCK_AI_GBP = 25\nexport const STORAGE_BLOCK_GB = 25\n\n/** Default monthly usage cap for a new Pro project (pence); it limits automatic top-ups only. 0 = no automatic\n * top-ups, null = no limit. */\nexport const DEFAULT_SPEND_CAP_PENCE = 10000\n\n/** The automatic add-on triggers when less than this much AI usage (£) remains; the backend minimum. */\nexport const MIN_AUTO_TOPUP_THRESHOLD_GBP = 1\n\n/** Free-tier quotas — must match backend FREE_* constants in src/constants.py\n * (FREE_AI_GBP=1, FREE_STORAGE_GB=0.05 → 50 MB, FREE_COLLABORATORS=0). */\nexport const FREE_AI_GBP = 1\nexport const FREE_STORAGE_MB = 50\nexport const FREE_COLLABORATORS = 0\n\n/** Collaborator limits at or above this are \"unlimited\" (the backend reports 999 for Pro/dev). */\nexport const UNLIMITED_COLLABORATORS = 999\n\n/**\n * Suggested initial daily per-user AI usage cap (£), pre-filled when creating\n * a new project. The user can clear it to create a project with no cap.\n * Backend treats null as \"no enforcement\" — there is no server-side default.\n */\nexport const SUGGESTED_DAILY_CAP_PER_USER = 10\n","/**\n * Quota display — single source of truth.\n *\n * Builds the icon / label / formatted used-of-limit strings for a project's\n * quotas (AI usage in £, storage, collaborators). Shared by QuotaBadges and the\n * project tooltip so the numbers and units can never disagree (storage in GB on\n * plans of 1 GB or more, MB below).\n */\n\nimport { HardDrive, PoundSterling, Users } from 'lucide-react'\nimport { formatGbp } from '@arbidocs/react'\nimport type { QuotaMeterItem } from '../../settings'\nimport type { components } from '@arbidocs/client'\nimport { UNLIMITED_COLLABORATORS } from './plan-constants'\n\ntype Quotas = components['schemas']['ProjectResponse']['quotas']\n\nconst fmt = (v: number) => Math.round(v).toLocaleString('en-US')\n\n/** \"May 31, 2025\" — the one format every AI-usage-reset mention uses. */\nexport function formatResetDate(unixTimestamp: number | null | undefined): string | null {\n if (!unixTimestamp) return null\n const date = new Date(unixTimestamp * 1000)\n return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })\n}\n\n/**\n * When the project's AI usage allowance next resets, as a unix timestamp.\n * Pro projects report it directly (`addons.ai_usage_reset_at` — monthly, even on an\n * annual plan); monthly subscriptions otherwise reset with the billing period\n * (`current_period_end`); free projects reset on the backend-stamped signup\n * anniversary (`quotas.budget_reset_at`). Only a FUTURE date is returned — a stale\n * past stamp would read as a bug, not a promise.\n */\nexport function aiUsageResetTimestamp(project: {\n quotas?: { budget_reset_at?: number | null } | null\n current_period_end?: number | null\n plan_interval?: string | null\n addons?: { ai_usage_reset_at?: number | null } | null\n}): number | null {\n // An annual period end is a year away — never a monthly AI usage reset.\n const periodEnd = project.plan_interval === 'year' ? null : project.current_period_end\n const ts =\n project.addons?.ai_usage_reset_at ?? periodEnd ?? project.quotas?.budget_reset_at ?? null\n return ts && ts * 1000 > Date.now() ? ts : null\n}\n\n// Defensive: a quota field may be missing on partial/empty payloads — treat it\n// as 0 / 0 rather than crashing the whole row.\nconst quota = (q?: { used?: number; limit?: number }) => ({\n used: q?.used ?? 0,\n limit: q?.limit ?? 0,\n})\n/** GB from 1 GB plans up (\"2.4 GB\", \"5 GB\"), MB below (\"50 MB\"); `unit: false` drops the unit. */\nfunction storageText(gbValue: number, limitGb: number, unit = true): string {\n if (limitGb >= 1) {\n const n = Math.round(gbValue * 10) / 10\n return `${n.toLocaleString('en-US')}${unit ? ' GB' : ''}`\n }\n return `${fmt(gbValue * 1000)}${unit ? ' MB' : ''}`\n}\nconst pctOf = (used: number, limit: number) => (limit > 0 ? (used / limit) * 100 : 0)\n\nexport function getQuotaItems(quotas: Quotas): QuotaMeterItem[] {\n const aiUsage = quota(quotas?.ai_usage)\n const storage = quota(quotas?.storage_gb)\n const collaborators = quota(quotas?.collaborators)\n const unlimitedCollaborators = collaborators.limit >= UNLIMITED_COLLABORATORS\n return [\n {\n key: 'ai-usage',\n icon: PoundSterling,\n label: 'AI usage',\n used: formatGbp(aiUsage.used),\n usedOfLimit: `${formatGbp(aiUsage.used)} / ${formatGbp(aiUsage.limit)}`,\n pct: pctOf(aiUsage.used, aiUsage.limit),\n },\n {\n key: 'storage',\n icon: HardDrive,\n label: 'Storage',\n used: storageText(storage.used, storage.limit),\n usedOfLimit: `${storageText(storage.used, storage.limit, false)} / ${storageText(\n storage.limit,\n storage.limit\n )}`,\n pct: pctOf(storage.used, storage.limit),\n },\n {\n key: 'collaborators',\n icon: Users,\n label: 'Collaborators',\n used: fmt(collaborators.used),\n usedOfLimit: unlimitedCollaborators\n ? `${fmt(collaborators.used)} / Unlimited`\n : `${fmt(collaborators.used)} / ${fmt(collaborators.limit)}`,\n // Zero seats (Free) IS the cap: 0 / 0 shows a full destructive bar,\n // because you can't add anyone — the truth the upgrade door answers.\n // (Only when the quota is actually present; a missing field on a\n // partial payload stays an empty bar, not a false alarm.)\n pct: unlimitedCollaborators\n ? 0\n : quotas?.collaborators && collaborators.limit === 0\n ? 100\n : pctOf(collaborators.used, collaborators.limit),\n },\n ]\n}\n","/**\n * Reward-balance logic (hook + money formatter).\n *\n * A user's reward balance is their available account balance — a single GLOBAL per-user\n * number, the Stripe customer account balance mirrored read-only into\n * `settings.extra_discount`. It auto-applies to the user's NEXT invoice.\n *\n * \"Rewards\" is the broad concept: the balance can be fed by several sources (referral\n * reward is just one). The referral pricing surfaces of the billing kit\n * speak to the referral source specifically; this module owns the balance itself.\n */\n\nimport { useUserSettings } from '@arbidocs/react'\n\nexport interface RewardBalance {\n amount: number // minor units (e.g. pennies) of available account balance\n currency: string\n}\n\n/** The user's available reward balance (all sources), or null if none. */\nexport function useRewardBalance(): RewardBalance | null {\n const { data } = useUserSettings()\n // Backend mirrors this read-only as { amount, currency }; schema types it as a loose object.\n const ed = data?.extra_discount as { amount?: number; currency?: string } | null | undefined\n if (!ed || !ed.amount || ed.amount <= 0) return null\n return { amount: ed.amount, currency: ed.currency || 'gbp' }\n}\n\n/** Format minor units as a localized money string, e.g. `£20` (whole) or `£29.99`. */\nexport function formatMoney(cents: number, currency = 'gbp'): string {\n const value = cents / 100\n const isWhole = Number.isInteger(value)\n const c = currency.toLowerCase()\n const symbol =\n c === 'usd' ? '$' : c === 'gbp' ? '£' : c === 'eur' ? '€' : currency.toUpperCase() + ' '\n return `${symbol}${value.toLocaleString('en-US', {\n minimumFractionDigits: isWhole ? 0 : 2,\n maximumFractionDigits: isWhole ? 0 : 2,\n })}`\n}\n","/** Add-on block price helpers (VAT-inclusive pence from `project.addons`). */\n\nimport { formatGbp } from '@arbidocs/react'\nimport type { components } from '@arbidocs/client'\nimport type { AddonKind } from './useAddonPurchase'\nimport { formatMoney } from './reward-balance'\n\ntype ProjectAddons = components['schemas']['ProjectAddons']\n\nconst gbp = (pence: number) => formatMoney(pence, 'gbp')\n\n/** \"3 Nov 2026\". */\nexport function formatPeriodEnd(unix: number | null | undefined): string | null {\n if (!unix) return null\n return new Date(unix * 1000).toLocaleDateString('en-GB', {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n })\n}\n\n/** What one more block of this kind costs right now, incl. UK VAT. */\nexport function addonPricePence(kind: AddonKind, addons: ProjectAddons): number {\n return kind === 'ai_usage' ? addons.ai_block_price_pence : addons.storage_block_price_pence\n}\n\n/** The same price ex VAT. */\nfunction addonPriceExVatPence(kind: AddonKind, addons: ProjectAddons): number {\n return kind === 'ai_usage'\n ? addons.ai_block_price_ex_vat_pence\n : addons.storage_block_price_ex_vat_pence\n}\n\n/**\n * The PUT /addons/settings body (the monthly usage cap and the automatic add-on trigger) from the current add-on\n * state with the given changes applied.\n */\nexport function addonSettingsBody(\n addons: ProjectAddons,\n change: Partial<{\n spend_cap_pence: number | null\n auto_topup_threshold_gbp: number\n }> = {}\n) {\n return {\n spend_cap_pence: addons.spend_cap_pence ?? null,\n auto_topup_threshold_gbp: addons.auto_topup_threshold_gbp,\n ...change,\n }\n}\n\n/**\n * Of `count` blocks of a kind, how many are on an earlier catalogue's price (legacy, at their old size: £10 of AI\n * usage or 10 GB) and how many on today's. A reduction removes today's blocks first, so the legacy ones are the\n * last kept.\n */\nexport function splitBlocks(\n kind: AddonKind,\n count: number,\n addons: ProjectAddons\n): { legacy: number; current: number } {\n const granted =\n (kind === 'ai_usage' ? addons.legacy_ai_blocks : addons.legacy_storage_blocks) ?? 0\n const legacy = Math.max(0, Math.min(granted, count))\n return { legacy, current: count - legacy }\n}\n\n/** One block's size: \"£25 of AI usage\" / \"25 GB\" (legacy: \"£10\" / \"10 GB\"). */\nfunction blockSize(kind: AddonKind, addons: ProjectAddons, legacy: boolean): string {\n if (kind === 'ai_usage') {\n return formatGbp(legacy ? (addons.legacy_block_ai_gbp ?? 10) : addons.block_ai_gbp)\n }\n return `${legacy ? (addons.legacy_block_storage_gb ?? 10) : addons.block_storage_gb} GB`\n}\n\n/**\n * \"2 × £25 of AI usage\", \"1 × £10 + 1 × £25 of AI usage\", \"1 × 10 GB + 2 × 25 GB\": `count` blocks of a kind, the\n * legacy ones (kept last on a reduction) at their old size.\n */\nexport function blocksLabel(kind: AddonKind, count: number, addons: ProjectAddons): string {\n const { legacy, current } = splitBlocks(kind, count, addons)\n const parts = [\n ...(legacy > 0 ? [`${legacy} × ${blockSize(kind, addons, true)}`] : []),\n ...(current > 0 || legacy === 0 ? [`${current} × ${blockSize(kind, addons, false)}`] : []),\n ]\n return `${parts.join(' + ')}${kind === 'ai_usage' ? ' of AI usage' : ''}`\n}\n\n/**\n * Bounds for \"Reduce from next period\": keep `min`..`current` blocks. `next` is what renews\n * now (a pending reduction, or the current count). Storage can't go below what usage needs.\n */\nexport function reduceBounds(\n kind: AddonKind,\n addons: ProjectAddons\n): { min: number; current: number; next: number } {\n const current = kind === 'ai_usage' ? addons.ai_blocks : addons.storage_blocks\n const pending = kind === 'ai_usage' ? addons.ai_blocks_next : addons.storage_blocks_next\n const min = kind === 'ai_usage' ? 0 : Math.min(addons.storage_blocks_min, current)\n return { min, current, next: pending ?? current }\n}\n\n/** One block's monthly-equivalent price ex VAT: AI usage and storage are priced separately. */\nfunction blockMonthlyExVatPence(kind: AddonKind, addons: ProjectAddons): number {\n return kind === 'ai_usage'\n ? addons.ai_block_monthly_ex_vat_pence\n : addons.storage_block_monthly_ex_vat_pence\n}\n\n/** What one block renews at per billing period, ex VAT (annual: 12 × the monthly price). */\nfunction blockPeriodExVatPence(kind: AddonKind, addons: ProjectAddons): number {\n return kind === 'ai_usage'\n ? addons.ai_block_period_ex_vat_pence\n : addons.storage_block_period_ex_vat_pence\n}\n\n/** What one add-on renews at: \"£25/month + VAT\" or \"£225/year + VAT\". */\nfunction blockRenewalShort(kind: AddonKind, addons: ProjectAddons, isAnnual: boolean): string {\n return `${gbp(blockPeriodExVatPence(kind, addons))}/${isAnnual ? 'year' : 'month'} + VAT`\n}\n\n/** The extra line annual plans show beside an AI usage add-on or upgrade price. */\nexport const ANNUAL_PREMIUM_AI_NOTE = 'No markup on Premium AI on annual plans'\n\n/** The confirm dialog's figures: charged now (incl. / ex VAT), what it covers until, then what renews. */\nexport function addonCharge(\n kind: AddonKind,\n addons: ProjectAddons,\n isAnnual: boolean,\n periodEnd: number | null | undefined\n): { now: string; nowExVat: string; nowVat: string; until: string | null; then: string } {\n return {\n now: gbp(addonPricePence(kind, addons)),\n nowExVat: gbp(addonPriceExVatPence(kind, addons)),\n nowVat: gbp(addonPricePence(kind, addons) - addonPriceExVatPence(kind, addons)),\n until: isAnnual ? formatPeriodEnd(periodEnd) : null,\n then: blockRenewalShort(kind, addons, isAnnual),\n }\n}\n\n/** Why automatic top-ups stopped (one line; the price of a step is on the Add button). */\nexport const CAP_REACHED_MESSAGE = 'Usage cap reached: no more automatic top-ups this month.'\n\n/** The £0 usage cap: no automatic top-ups (adding by hand still works). */\nexport const ZERO_BUDGET_MESSAGE = 'Automatic top-ups are off (£0 usage cap).'\n\n/** The usage cap's heading wherever it is edited or shown. */\nexport const USAGE_CAP_LABEL = 'Usage cap'\n\n/** What the usage cap means (in \"More info\"): £0 and \"No limit\" explained. */\nexport const USAGE_CAP_HELP =\n 'The most automatic top-ups (AI usage added when it runs low, storage added when an upload needs it) may ' +\n 'cost in a month. Adding or removing by hand is never limited by it; the plan and renewals are not counted. ' +\n '£0 = no automatic top-ups: AI usage and uploads stop at your allowance unless you add more. ' +\n 'No limit = no cap.'\n\n/** A £0 cap turns automatic top-ups off (manual adds still work). */\nexport function isAddonBudgetZero(addons: Pick<ProjectAddons, 'spend_cap_pence'>): boolean {\n return addons.spend_cap_pence === 0\n}\n\n/**\n * How much more of a resource automatic top-ups may add this month before the usage cap stops them, in the\n * resource's unit (£ of AI usage / GB): the whole blocks the cap left pays for at today's ex-VAT price. `null` =\n * no limit; 0 with a £0 cap or when not even one block fits.\n */\nexport function autoRoom(kind: AddonKind, addons: ProjectAddons): number | null {\n const left = addons.cap_left_pence\n if (left == null) return addons.spend_cap_pence === 0 ? 0 : null\n const price = addonPriceExVatPence(kind, addons)\n if (price <= 0) return 0\n const blocks = Math.floor(left / price)\n return blocks * (kind === 'ai_usage' ? addons.block_ai_gbp : addons.block_storage_gb)\n}\n\n/** The size of the block a one-step reduction removes from what renews (today's blocks go first). */\nexport function nextRemovedBlockSize(kind: AddonKind, addons: ProjectAddons): number {\n const { next } = reduceBounds(kind, addons)\n const { current } = splitBlocks(kind, next, addons)\n if (kind === 'ai_usage') {\n return current > 0 ? addons.block_ai_gbp : (addons.legacy_block_ai_gbp ?? 10)\n }\n return current > 0 ? addons.block_storage_gb : (addons.legacy_block_storage_gb ?? 10)\n}\n\n/**\n * Pounds typed into a usage cap field → pence. '' → the default (null); invalid → undefined.\n * Equal to the default is also sent as null (\"keep the default\").\n */\nexport function parseBudgetPounds(value: string): number | null | undefined {\n if (value.trim() === '') return null\n const n = Number(value)\n if (!Number.isFinite(n) || n < 0) return undefined\n return Math.round(n * 100)\n}\n\n/** Toast after saving the usage cap. */\nexport function budgetSavedMessage(capPence: number | null): string {\n if (capPence == null) return 'Usage cap: no limit'\n if (capPence === 0) return 'Usage cap: £0 (no automatic top-ups)'\n return `Usage cap: ${gbp(capPence)} a month`\n}\n\nconst gbText = (n: number) => `${Math.round(n * 10) / 10} GB`\n\n/** \"£25 of AI usage\" / \"25 GB\". */\nexport function stepLabel(kind: AddonKind, size: number): string {\n return kind === 'ai_usage' ? `${formatGbp(size)} of AI usage` : gbText(size)\n}\n\n/** The PUT /addons/next-period body that renews `keep` blocks of `kind` (the other kind unchanged). */\nexport function nextPeriodBody(kind: AddonKind, keep: number) {\n return kind === 'ai_usage'\n ? { ai_blocks: keep, storage_blocks: null }\n : { ai_blocks: null, storage_blocks: keep }\n}\n\n/**\n * The \"+\" step's price line, ex VAT: \"£25/month · today £25\" (annual: \"£18.75/month · today £150\");\n * storage, charged for the rest of the period: \"£25/month · prorated today £8.33\".\n */\nexport function addStepCaption(kind: AddonKind, addons: ProjectAddons): string {\n const now = gbp(addonPriceExVatPence(kind, addons))\n const today = kind === 'storage' ? `prorated today ${now}` : `today ${now}`\n return `${gbp(blockMonthlyExVatPence(kind, addons))}/month · ${today}`\n}\n","/**\n * The `detail` of a refused billing call: the response body's `detail` (a string, or the\n * `{code, message}` of a payment refusal), whether the error is an SDK `ArbiApiError` (body in\n * `apiError`) or the body itself.\n */\nexport function apiErrorDetail(error: unknown): unknown {\n const body = (error as { apiError?: unknown } | null)?.apiError ?? error\n return (body as { detail?: unknown } | null)?.detail\n}\n","/**\n * Tax-inclusive totals from the backend's Stripe Tax quotes (`TaxQuoteResponse`, plan-change\n * previews, add-on quotes): \"£48.00 incl. VAT (£40.00 + £8.00 VAT 20%)\", \"£40.00 · no VAT\n * (reverse charge)\", \"£40.00 · no tax\".\n */\n\nimport type { components } from '@arbidocs/client'\nimport { apiErrorDetail } from './api-error'\n\nexport type TaxQuote = components['schemas']['TaxQuoteResponse']\n\n/** Countries whose tax depends on the postcode: the field is shown up front. */\nexport const POSTCODE_COUNTRIES: readonly string[] = ['US', 'CA']\n\n/** The quote error that asks for a ZIP / postal code. */\nexport const TAX_LOCATION_INVALID = 'TAX_LOCATION_INVALID'\n\n/** \"£42.00\" — always pence, so the parts of a total add up on screen. */\nexport function money2(pence: number, currency = 'gbp'): string {\n const symbol = { gbp: '£', usd: '$', eur: '€' }[currency.toLowerCase()] ?? `${currency} `\n return `${symbol}${(pence / 100).toLocaleString('en-GB', {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })}`\n}\n\nexport interface TaxParts {\n subtotal: number\n tax: number\n total: number\n /** \"VAT 20%\"; null when no tax is due. */\n label?: string | null\n reverseCharge?: boolean\n}\n\n/** \"VAT\" for a VAT label, else \"tax\". */\nfunction taxKind(label: string | null | undefined): string {\n return /^vat\\b/i.test(label ?? '') ? 'VAT' : 'tax'\n}\n\n/** What follows the total: \"incl. VAT (£40.00 + £8.00 VAT 20%)\", \"· no VAT (reverse charge)\", \"· no tax\". */\nexport function taxDetail({ subtotal, tax, label, reverseCharge }: TaxParts): string {\n if (reverseCharge) return '· no VAT (reverse charge)'\n if (tax <= 0) return '· no tax'\n return `incl. ${taxKind(label)} (${money2(subtotal)} + ${money2(tax)} ${label ?? 'tax'})`\n}\n\n/** \"£48.00 incl. VAT (£40.00 + £8.00 VAT 20%)\", \"£40.00 · no VAT (reverse charge)\", \"£40.00 · no tax\". */\nexport function taxSummary(parts: TaxParts): string {\n return `${money2(parts.total)} ${taxDetail(parts)}`\n}\n\n/** \"£21.00 incl. VAT\" / \"£17.50\" — a total with only the word for its tax. */\nexport function totalWithTaxWord({ total, tax, label }: TaxParts): string {\n return tax > 0 ? `${money2(total)} incl. ${taxKind(label)}` : money2(total)\n}\n\n/** The parts of a quote response. */\nexport function quoteParts(quote: TaxQuote): TaxParts {\n return {\n subtotal: quote.subtotal_pence,\n tax: quote.tax_pence,\n total: quote.total_pence,\n label: quote.tax_label,\n reverseCharge: quote.reverse_charge,\n }\n}\n\n/** \"Total today £48.00 incl. VAT (£40.00 + £8.00 VAT 20%)\". */\nexport function quoteTotalLine(quote: TaxQuote): string {\n return `Total today ${taxSummary(quoteParts(quote))}`\n}\n\n/** The API error code (`detail.code`) and message, if any. */\nexport function quoteError(error: unknown): { code?: string; message?: string } {\n const detail = apiErrorDetail(error)\n if (detail && typeof detail === 'object') {\n const { code, message } = detail as { code?: unknown; message?: unknown }\n return {\n code: typeof code === 'string' ? code : undefined,\n message: typeof message === 'string' ? message : undefined,\n }\n }\n return { message: typeof detail === 'string' ? detail : undefined }\n}\n","/**\n * Pro plan price helpers. Prices come from Stripe via GET /v1/user/products (source of truth).\n * One plan is sold: Pro, one licence (£10 of AI usage + 5 GB a month). Each price lists\n * `pack_prices` for that one licence — `amount` incl. UK VAT and `amount_ex_vat` — and\n * `addon_prices` (one add-on block on that interval). Display them as-is.\n * Legacy subscriptions with several packs keep working; their name and price come from the project.\n */\n\nimport type { components } from '@arbidocs/client'\nimport { formatGbp } from '@arbidocs/react'\nimport { formatMoney } from './reward-balance'\nimport { formatPeriodEnd } from './addon-pricing'\nimport { taxSummary } from './tax-quote'\nimport { ADDON_BLOCK_AI_GBP, STORAGE_BLOCK_GB } from './plan-constants'\n\ntype PlanChangePreview = components['schemas']['PlanChangePreview']\ntype ProductPrice = components['schemas']['ProductPrice']\ntype ProductResponse = components['schemas']['ProductResponse']\ntype PackPrice = components['schemas']['PackPrice']\ntype AddonPrice = components['schemas']['AddonPrice']\n\nexport type PlanInterval = 'month' | 'year'\n\nconst gbp = (pence: number) => formatMoney(pence, 'gbp')\n\n/** The headline price: \"£40 + VAT\". */\nexport function plusVat(exVatPence: number, currency = 'gbp'): string {\n return `${formatMoney(exVatPence, currency)} + VAT`\n}\n\n/** The one licence Pro sells. Other pack counts exist only on legacy subscriptions (displayed, not sold). */\nexport const PRO_PACKS = 1\n\n/** A plan the pickers offer. */\nexport type PlanChoice = 'free' | 'pro'\n\n/** Packs per plan choice (0 = Free). */\nexport const PLAN_CHOICE_PACKS: Record<PlanChoice, number> = {\n free: 0,\n pro: PRO_PACKS,\n}\n\n/** \"Free\" (0), \"Pro\" (1), otherwise \"Pro ×N\" (a legacy multi-pack plan; the API's own name wins). */\nexport function planNameForPacks(packs: number | null | undefined): string {\n const n = packs ?? 0\n if (n <= 0) return 'Free'\n if (n === PRO_PACKS) return 'Pro'\n return `Pro ×${n}`\n}\n\n/** The plan-change panel's fixed lines, each with a test id. */\nexport interface PlanChangeLine {\n id: 'pay-today' | 'from' | 'current-until' | 'no-change' | 'awaiting-bank'\n text: string\n}\n\n/**\n * What a plan change costs, from the backend's Stripe invoice preview (taxed for the customer's\n * address), as fixed lines:\n * - \"Pay today £42.00 incl. VAT (£35.00 + £7.00 VAT 20%)\" (\"Pay today £0\" for a change that waits)\n * - \"From 16 Nov 2026: £210.00 incl. VAT (£175.00 + £35.00 VAT 20%) a month\"\n * - \"Current plan until 16 Nov 2026\" for a change that waits for the period end.\n * \"No change\" when the selection is what the project already has; \"Waiting for your bank\" while\n * an earlier upgrade payment awaits 3-D Secure.\n */\nexport function planPreviewLines(preview: PlanChangePreview): PlanChangeLine[] {\n if (preview.unchanged) return [{ id: 'no-change', text: 'No change' }]\n const date = formatPeriodEnd(preview.next_renewal_at)\n const cadence = preview.interval === 'year' ? 'year' : 'month'\n const lines: PlanChangeLine[] = [\n preview.awaiting_confirmation\n ? { id: 'awaiting-bank', text: 'Waiting for your bank' }\n : {\n id: 'pay-today',\n text: preview.effective_now\n ? `Pay today ${taxSummary({\n subtotal: preview.due_now_ex_vat_pence,\n tax: preview.due_now_tax_pence,\n total: preview.due_now_pence,\n label: preview.tax_label,\n })}`\n : `Pay today ${gbp(0)}`,\n },\n {\n id: 'from',\n text: `${date ? `From ${date}` : 'From renewal'}: ${taxSummary({\n subtotal: preview.next_renewal_ex_vat_pence,\n tax: preview.next_renewal_tax_pence,\n total: preview.next_renewal_pence,\n label: preview.tax_label,\n })} a ${cadence}`,\n },\n ]\n if (!preview.effective_now) {\n lines.push({ id: 'current-until', text: `Current plan until ${date ?? 'renewal'}` })\n }\n return lines\n}\n\n/** Stand-in for \"Pay today\" when the preview failed for an upgrade. */\nexport const PAY_TODAY_UNPRICED = 'Pay today: the difference for the rest of this period'\n\n/** One add-on block's price on this interval's plan price (`addon_prices`), if listed. */\nexport function addonPrice(\n price: ProductPrice | undefined,\n kind: 'ai_usage' | 'storage' = 'ai_usage'\n): AddonPrice | undefined {\n return price?.addon_prices?.find((p) => p.kind === kind)\n}\n\n/** Per add-on block of `kind` per month, ex VAT (annual plans: the monthly equivalent). */\nexport function addonMonthlyExVat(\n price: ProductPrice | undefined,\n kind: 'ai_usage' | 'storage' = 'ai_usage'\n): number | undefined {\n return addonPrice(price, kind)?.monthly_ex_vat\n}\n\n/** What a checkout buys: \"Pro\", \"Pro + 2 × £25 of AI usage + 1 × 25 GB\". */\nexport function checkoutItemsLabel(aiBlocks: number, storageBlocks: number): string {\n return [\n 'Pro',\n aiBlocks > 0 && `${aiBlocks} × ${formatGbp(ADDON_BLOCK_AI_GBP)} of AI usage`,\n storageBlocks > 0 && `${storageBlocks} × ${STORAGE_BLOCK_GB} GB`,\n ]\n .filter(Boolean)\n .join(' + ')\n}\n\n/** The price of `packs` packs on this interval's price, if Stripe lists it (only one licence is listed). */\nexport function packPrice(\n price: ProductPrice | undefined,\n packs: number = PRO_PACKS\n): PackPrice | undefined {\n return price?.pack_prices?.find((p) => p.packs === packs)\n}\n\nexport interface ProPrices {\n monthly?: ProductPrice\n annual?: ProductPrice\n}\n\n/** The Pro product's monthly and annual prices (default price per interval wins). */\nexport function findProPrices(products: ProductResponse[] | undefined): ProPrices {\n const prices = products?.[0]?.prices ?? []\n const pick = (interval: PlanInterval) =>\n prices.find((p) => p.interval === interval && p.default_price) ??\n prices.find((p) => p.interval === interval)\n return { monthly: pick('month'), annual: pick('year') }\n}\n\n/** Annual savings vs 12 × monthly, as a whole percent (e.g. £360 vs £480 → 25). */\nexport function calcSavingsPercent(\n monthlyPrice: ProductPrice | undefined,\n annualPrice: ProductPrice | undefined\n): number | null {\n const monthly = packPrice(monthlyPrice)?.amount ?? monthlyPrice?.amount\n const annual = packPrice(annualPrice)?.amount ?? annualPrice?.amount\n if (monthly == null || annual == null || monthly === 0) return null\n const savings = Math.round(((monthly * 12 - annual) / (monthly * 12)) * 100)\n return savings > 0 ? savings : null\n}\n\n/** Most add-on blocks of each kind a checkout may include (the backend's limit). */\nexport const MAX_CHECKOUT_BLOCKS = 100\n\n/** \"£25/month + VAT each\", annual: \"£225/year + VAT each\": one block on the chosen interval. */\nexport function checkoutBlockPriceText(\n price: ProductPrice | undefined,\n kind: 'ai_usage' | 'storage'\n): string | null {\n const block = addonPrice(price, kind)\n if (!block) return null\n const currency = price?.currency ?? 'gbp'\n return price?.interval === 'year'\n ? `${formatMoney(block.amount_ex_vat, currency)}/year + VAT each`\n : `${formatMoney(block.amount_ex_vat, currency)}/month + VAT each`\n}\n","import type { PlanBadgeProps } from '../../settings'\nimport type { components } from '@arbidocs/client'\nimport { planNameForPacks } from './plan-pricing'\n\ntype ProjectBillingFields = Pick<\n components['schemas']['ProjectResponse'],\n 'subscription' | 'plan_interval'\n> &\n Partial<Pick<components['schemas']['ProjectResponse'], 'packs' | 'addons'>>\n\n/** A project is on Pro when it has a billing interval (null = Free or checkout pending). */\nexport function isProProject(project: Pick<ProjectBillingFields, 'plan_interval'>): boolean {\n return project.plan_interval != null\n}\n\n/** \"Pro\", or a legacy multi-pack plan's name (\"Pro ×N\") — the API's name when it sends one (owner view). */\nexport function proTierName(project: ProjectBillingFields): string {\n return project.addons?.plan_name || planNameForPacks(Math.max(project.packs ?? 1, 1))\n}\n\n/** \"Free\", \"Pro monthly\", \"Pro annual\", \"Pro ×3 monthly\" (legacy) or \"Dev\" — the full plan name. */\nexport function planName(project: ProjectBillingFields): string {\n if (project.subscription === 'dev') return 'Dev'\n if (!isProProject(project)) return 'Free'\n return `${proTierName(project)} ${project.plan_interval === 'year' ? 'annual' : 'monthly'}`\n}\n\n/**\n * Maps a project's billing state to the `PlanBadge` block's label + tone.\n * Pro reads as accent, Free/dev as neutral, payment trouble or cancelling as pending.\n */\nexport function planBadgeView(\n project: ProjectBillingFields\n): Pick<PlanBadgeProps, 'label' | 'tone'> {\n const { subscription } = project\n const label =\n subscription === 'canceled'\n ? 'Cancelling'\n : subscription === 'dev'\n ? 'Dev'\n : isProProject(project)\n ? proTierName(project)\n : 'Free'\n\n const tone =\n subscription === 'dev'\n ? 'dev'\n : subscription === 'canceled' || subscription === 'past_due'\n ? 'pending'\n : isProProject(project)\n ? 'paid'\n : 'free'\n\n return { label, tone }\n}\n","/**\n * What a project's group in the workspace list says about the project itself: its plan badge (own\n * projects, where plans are sold), the usage readout beside its name, and the plan and limits\n * breakdown behind the name. One source for the cards' bands and the table's headings.\n */\nimport type { ReactNode } from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport type { components } from '@arbidocs/client'\nimport { UsageMeter } from '../../components/UsageMeter'\nimport { PlanBadge, QuotaMeter } from '../../settings'\nimport { ProjectBreakdown, ProjectReadout } from '../../home/ProjectBandParts'\nimport { planBadgeView } from '../billing/plan-badge'\nimport { getQuotaItems } from '../billing/quota-items'\n\ntype Project = components['schemas']['ProjectResponse']\n\nexport interface ProjectGroupBilling {\n /** The plan badge: own projects only, where plans are sold. */\n planBadge?: ReactNode\n /** Plan and usage, right after the name (projects with quotas). */\n readout?: ReactNode\n /** The plan and limits panel behind the name; meters for own projects only. */\n breakdown?: ReactNode\n}\n\nexport function projectGroupBilling(\n project: Project | undefined,\n { isOwned, stripeEnabled }: { isOwned: boolean; stripeEnabled: boolean }\n): ProjectGroupBilling {\n if (!project) return {}\n const planBadge = isOwned && stripeEnabled ? <PlanBadge {...planBadgeView(project)} /> : undefined\n const quotaItems = project.quotas ? getQuotaItems(project.quotas) : []\n const readout = project.quotas ? (\n <ProjectReadout\n plan={\n planBadge ? { badge: planBadge, testId: `project-tier-${project.external_id}` } : undefined\n }\n usage={{\n testId: `project-usage-${project.external_id}`,\n // Bare numbers without plans for sale: a glance beside the name, not the Plan & Usage detail.\n node: (\n <QuotaMeter\n items={quotaItems}\n size=\"sm\"\n showTooltips={false}\n showBars={stripeEnabled}\n showPercent={false}\n />\n ),\n }}\n />\n ) : (\n planBadge\n )\n const breakdown = (\n <ProjectBreakdown\n name={project.name}\n badge={planBadge}\n meters={\n isOwned\n ? quotaItems.map(({ key, icon, label, usedOfLimit, pct }) => (\n <UsageMeter\n key={key}\n icon={icon as LucideIcon}\n label={label}\n value={usedOfLimit}\n pct={pct}\n />\n ))\n : undefined\n }\n dailyCap={{\n label: 'Daily cap',\n value:\n project.daily_cap_per_user == null\n ? 'No limit'\n : project.daily_cap_per_user.toLocaleString('en-US'),\n }}\n />\n )\n return { planBadge, readout, breakdown }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/start-inset.ts","../src/shell/Sidebar.tsx","../src/shell/ShellSidebar.tsx","../src/lib/use-close-on-escape.ts","../src/lib/sidebar-mode.ts","../src/shell/use-sidebar-controller.ts","../src/shell/SidebarRowAction.tsx","../src/shell/AskField.tsx","../src/shell/MobileBars.tsx","../src/shell/install-instructions.ts","../src/shell/use-install-prompt.ts","../src/shell/InstallPrompt.tsx","../src/shell/status-row-styles.ts","../src/shell/StatusRow.tsx","../src/shell/OfflinePill.tsx","../src/shell/RemoteControlPill.tsx","../src/shell/TipCard.tsx","../src/shell/InfoBar.tsx","../src/shell/SplitLayout.tsx"],"names":["jsxs","jsx","useRef","useEffect","useState","cn","Tooltip","TooltipTrigger","TooltipContent","X","Fragment","useCallback","TriangleAlert","Button","Lightbulb"],"mappings":"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","file":"chunk-LTEDORG3.js","sourcesContent":["import { useEffect } from 'react'\n\n/**\n * The CSS custom property that carries how much of the screen's start (left) edge a docked sidebar\n * takes, set on `<html>`. A floating element pinned to the start corner (the install prompt)\n * positions itself `calc(var(--shell-start-inset, 0px) + 0.75rem)` so it never covers the\n * sidebar's footer (the account menu).\n */\nexport const SHELL_START_INSET_VAR = '--shell-start-inset'\n\nconst widths = new Map<symbol, number>()\n\nfunction apply(): void {\n if (typeof document === 'undefined') return\n const inset = Math.max(0, ...widths.values())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_START_INSET_VAR, `${inset}px`)\n else style.removeProperty(SHELL_START_INSET_VAR)\n}\n\n/**\n * Report a sidebar docked at the start edge, `width` px wide (0 while it is collapsed or is an\n * overlay drawer), to {@link SHELL_START_INSET_VAR}. `Sidebar.Root` calls it; call it from your\n * own docked side panel.\n */\nexport function useShellStartInset(width: number): void {\n useEffect(() => {\n const key = Symbol('shell-start-inset')\n widths.set(key, width)\n apply()\n return () => {\n widths.delete(key)\n apply()\n }\n }, [width])\n}\n","import { useMemo, useRef, useState, type CSSProperties, type ReactNode } from 'react'\nimport { PanelLeftClose, PanelLeftOpen, X } from 'lucide-react'\nimport { cn, Tooltip, TooltipContent, TooltipTrigger } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport {\n DEFAULT_SIDEBAR_LABELS,\n SidebarContext,\n SidebarRowHoverContext,\n useSidebarContext,\n type SidebarLabels,\n} from './sidebar-context'\nimport { SidebarBadgeRow } from './SidebarBadgeRow'\nimport { ActionLink } from '../components/ActionLink'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { useShellStartInset } from '../lib/start-inset'\nimport type { SidebarMode } from '../lib/sidebar-mode'\nimport type { NavItem, NavItemIndicator, NavSection } from './types'\n\n/**\n * Sidebar: the one tinted column that carries the app frame. Compound parts:\n * Sidebar.Root positioning shell for the four modes (drawer / collapsed / pinned / rail)\n * Sidebar.Header top block (switcher, ask field, pin toggle)\n * Sidebar.Nav the rows: pass `items` (NavItem[]) or compose Sidebar.NavItem children\n * Sidebar.Group a labelled run of rows (heading when expanded, divider on the rail)\n * Sidebar.Footer pinned to the bottom (offline pill, tips card, action cluster)\n * Sidebar.PinToggle / Sidebar.DrawerHeader the header's two stock controls\n *\n * Presentational and controlled: the app resolves `mode`/`expanded` (see `resolveSidebarLayout`\n * and `useSidebarSettle`) and owns where hover/pin/drawer state lives.\n */\n\nconst noop = () => {}\n\nconst COLLAPSED_PX = 64\nconst EXPANDED_PX = 256\nconst COLLAPSED_WIDTH = `${COLLAPSED_PX}px`\nconst EXPANDED_WIDTH = `${EXPANDED_PX}px`\n\nexport interface SidebarRootProps {\n mode: SidebarMode\n /** Labels visible. Provided to every part through context. */\n expanded: boolean\n /** `rail` mode: floats open to full width. */\n isHovering?: boolean\n onBackdropClick?: () => void\n /** `rail` mode on touch: the floated-open rail dims the content behind it; tapping it closes. */\n hasRailBackdrop?: boolean\n onMouseEnter?: () => void\n onMouseLeave?: () => void\n children: ReactNode\n className?: string\n 'aria-label'?: string\n labels?: Partial<SidebarLabels>\n /** Root id (default `sidebar`). */\n 'data-testid'?: string\n /** Drawer backdrop id (default `sidebar-backdrop`). */\n backdropTestId?: string\n}\n\nfunction SidebarRoot({\n mode,\n expanded,\n isHovering = false,\n onBackdropClick,\n hasRailBackdrop = false,\n onMouseEnter,\n onMouseLeave,\n children,\n className,\n 'aria-label': ariaLabelProp,\n labels,\n 'data-testid': testId,\n backdropTestId,\n}: SidebarRootProps) {\n const mergedLabels = useMemo(() => ({ ...DEFAULT_SIDEBAR_LABELS, ...labels }), [labels])\n // The drawer is a modal: scroll lock, Escape, focus trap and focus return to the opener.\n const drawerRef = useRef<HTMLDivElement>(null)\n const isDrawer = mode === 'drawer'\n useDrawerBehavior(isDrawer, onBackdropClick ?? noop, drawerRef)\n // Floating start-corner elements (the install prompt) sit clear of the docked sidebar; a rail\n // expanding on hover floats over the page, so only its collapsed width counts.\n useShellStartInset(mode === 'pinned' ? EXPANDED_PX : mode === 'rail' ? COLLAPSED_PX : 0)\n const ariaLabel = ariaLabelProp ?? mergedLabels.mainNavigation\n const contextValue = useMemo(() => ({ expanded, labels: mergedLabels }), [expanded, mergedLabels])\n // `navBase` omits horizontal padding so each mode owns its own: the collapsed state must\n // reach a true 0 width, which an `!important` px would block.\n const navBase =\n 'group/sidebar bg-sidebar border-r border-border text-foreground scrollbar-themed flex flex-col h-full overflow-y-auto overflow-x-hidden pb-safe pt-3 transition-all duration-300 ease-in-out'\n const common = {\n 'aria-label': ariaLabel,\n 'data-testid': testIdOr(testId, { testId: 'sidebar' }),\n 'data-slot': 'sidebar',\n 'data-mode': mode,\n } as const\n const fixedWidth: CSSProperties = { width: EXPANDED_WIDTH, minWidth: EXPANDED_WIDTH }\n\n let body: ReactNode\n if (mode === 'drawer') {\n // Small-screen off-canvas panel + dismiss backdrop; bypasses the hover/collapse model. The\n // wrapper is the modal dialog; the nav landmark sits inside it.\n body = (\n <div\n ref={drawerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n data-slot=\"sidebar-drawer\"\n className=\"fixed inset-0 z-50\"\n >\n <div\n className=\"absolute inset-0 bg-black/50\"\n onClick={onBackdropClick}\n aria-hidden=\"true\"\n data-testid={testIdOr(backdropTestId, { testId: 'sidebar-backdrop' })}\n />\n <nav\n {...common}\n className={cn(navBase, '!px-3 absolute left-0 top-0 pt-safe shadow-xl', className)}\n style={fixedWidth}\n >\n {children}\n </nav>\n </div>\n )\n } else if (mode === 'collapsed') {\n // Stays mounted at width 0 so the transition runs on both enter and leave. Horizontal padding\n // is dropped or overflow-hidden would reveal a clipped sliver of the icons.\n body = (\n <nav\n {...common}\n className={cn(navBase, 'absolute left-0 top-0 z-[45]', className)}\n style={{\n width: '0px',\n minWidth: 0,\n paddingLeft: 0,\n paddingRight: 0,\n borderRightWidth: 0,\n pointerEvents: 'none',\n }}\n // Width 0 hides the links visually; inert also takes them out of the tab order and the\n // accessibility tree.\n inert\n >\n {children}\n </nav>\n )\n } else if (mode === 'pinned') {\n body = (\n <nav\n {...common}\n className={cn(navBase, '!px-3 relative flex-shrink-0', className)}\n style={fixedWidth}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </nav>\n )\n } else {\n // Rail: a permanent spacer keeps the flex layout still; the nav is always absolute so only\n // its width animates on hover (no layout jump).\n body = (\n <>\n <div\n className=\"bg-sidebar border-r border-border flex flex-col h-full relative px-0 pb-safe flex-shrink-0\"\n style={{ width: COLLAPSED_WIDTH, minWidth: COLLAPSED_WIDTH }}\n aria-hidden=\"true\"\n />\n {isHovering && hasRailBackdrop && (\n <div\n className=\"fixed inset-0 z-[44] bg-black/40\"\n onClick={onBackdropClick}\n aria-hidden=\"true\"\n data-testid={testIdOr(backdropTestId, { testId: 'sidebar-backdrop' })}\n />\n )}\n <nav\n {...common}\n className={cn(\n navBase,\n isHovering ? '!px-3 shadow-xl' : '!px-2',\n 'absolute left-0 top-0 z-[45]',\n className\n )}\n style={{\n width: isHovering ? EXPANDED_WIDTH : COLLAPSED_WIDTH,\n minWidth: isHovering ? EXPANDED_WIDTH : COLLAPSED_WIDTH,\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </nav>\n </>\n )\n }\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <BlocksTooltipProvider>{body}</BlocksTooltipProvider>\n </SidebarContext.Provider>\n )\n}\n\nexport interface SidebarSectionProps {\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\nfunction SidebarHeader({ children, className, 'data-testid': testId }: SidebarSectionProps) {\n return (\n <div\n data-slot=\"sidebar-header\"\n data-testid={testId}\n className={cn('flex flex-shrink-0 flex-col gap-3 pb-3', className)}\n >\n {children}\n </div>\n )\n}\n\nexport interface SidebarNavProps extends Omit<SidebarSectionProps, 'children'> {\n children?: ReactNode\n /** Rows as data. Children render after them. */\n items?: NavItem[]\n /** Labelled groups of rows as data (each a `Sidebar.Group`), after `items`. */\n sections?: NavSection[]\n}\n\nfunction SidebarNav({\n items,\n sections,\n children,\n className,\n 'data-testid': testId,\n}: SidebarNavProps) {\n const { expanded } = useSidebarContext()\n return (\n <div\n data-slot=\"sidebar-nav\"\n data-testid={testId}\n className={cn('flex flex-shrink-0 flex-col gap-0.5', !expanded && 'items-center', className)}\n >\n {items?.map((item) => (\n <SidebarNavItem key={item.id} {...item} />\n ))}\n {sections?.map((section) => (\n <SidebarGroup\n key={section.id}\n label={section.label}\n ariaLabel={section.ariaLabel}\n data-testid={section.testId}\n >\n {section.items.map((item) => (\n <SidebarNavItem key={item.id} {...item} />\n ))}\n </SidebarGroup>\n ))}\n {children}\n </div>\n )\n}\n\nexport interface SidebarGroupProps extends SidebarSectionProps {\n /** Group heading. Shown above the rows when expanded; a thin divider stands in on the rail. */\n label?: ReactNode\n /** Accessible name when `label` is not plain text. */\n ariaLabel?: string\n}\n\n/** A labelled run of rows inside the nav (for example \"Workspace\", \"Tools\"). */\nfunction SidebarGroup({\n label,\n ariaLabel,\n children,\n className,\n 'data-testid': testId,\n}: SidebarGroupProps) {\n const { expanded } = useSidebarContext()\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel ?? (typeof label === 'string' ? label : undefined)}\n data-slot=\"sidebar-group\"\n data-testid={testId}\n className={cn('flex flex-shrink-0 flex-col gap-0.5', !expanded && 'items-center', className)}\n >\n {label &&\n (expanded ? (\n <SidebarGroupLabel>{label}</SidebarGroupLabel>\n ) : (\n <div\n role=\"separator\"\n data-slot=\"sidebar-group-divider\"\n className=\"my-1 h-px w-6 bg-border\"\n />\n ))}\n {children}\n </div>\n )\n}\n\n/** The heading of a `Sidebar.Group` (exported for custom headings). Hidden by the group on the rail. */\nfunction SidebarGroupLabel({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <div\n data-slot=\"sidebar-group-label\"\n className={cn(\n 'px-2 pb-0.5 pt-2 text-xs font-medium uppercase tracking-wide text-muted-foreground',\n className\n )}\n >\n {children}\n </div>\n )\n}\n\nfunction SidebarFooter({ children, className, 'data-testid': testId }: SidebarSectionProps) {\n const { expanded } = useSidebarContext()\n return (\n <div\n data-slot=\"sidebar-footer\"\n data-testid={testId}\n className={cn(\n 'mt-auto flex flex-shrink-0 flex-col gap-2 pt-3 pb-3',\n !expanded && 'items-center',\n className\n )}\n >\n {children}\n </div>\n )\n}\n\nconst INDICATOR_TONES: Record<NavItemIndicator, string> = {\n progress: 'bg-primary',\n error: 'bg-red-solid',\n attention: 'bg-yellow-solid',\n}\n\nexport type SidebarNavItemProps = Omit<NavItem, 'id'> & {\n id?: string\n className?: string\n /** Tooltip shown on the icon-only rail; defaults to the label. */\n tooltip?: string\n}\n\n/**\n * One row: [icon] [label] [count] [trailing]. 36px (44px on coarse pointers). The active row is\n * the selection tint, never a filled block; counts are quiet numbers, not pills.\n *\n * The expanded row is a div with role=\"button\" (not a native <button>) so an interactive\n * `trailing` control can be nested without producing button-in-button markup.\n */\nfunction SidebarNavItem({\n label,\n icon,\n active = false,\n onSelect,\n href,\n count,\n countIcon,\n testId,\n disabled = false,\n trailing,\n indicator,\n className,\n tooltip,\n}: SidebarNavItemProps) {\n const { expanded } = useSidebarContext()\n // Tracked as state (not CSS :hover) so a trailing control can read it via context.\n const [isRowActive, setIsRowActive] = useState(false)\n const tip = expanded ? undefined : (tooltip ?? label)\n\n if (!expanded) {\n const railButton = (\n <ActionLink\n href={href}\n onSelect={onSelect}\n disabled={disabled}\n aria-label={label}\n aria-current={active ? 'page' : undefined}\n data-slot=\"sidebar-nav-item\"\n data-testid={testId}\n className={cn(\n 'm-0 flex h-9 w-12 items-center justify-center rounded-md transition-colors pointer-coarse:h-11',\n active\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n disabled && 'pointer-events-none cursor-not-allowed opacity-30',\n className\n )}\n >\n <div className=\"flex size-5 items-center justify-center\">\n {indicator ? (\n <div className=\"relative\">\n {icon}\n <div\n data-slot=\"sidebar-nav-indicator\"\n data-tone={indicator}\n className={cn(\n 'absolute -right-1 -top-1 size-2.5 rounded-full border border-sidebar',\n INDICATOR_TONES[indicator]\n )}\n />\n </div>\n ) : (\n icon\n )}\n </div>\n </ActionLink>\n )\n if (!tip) return railButton\n return (\n <Tooltip delayDuration={50}>\n <TooltipTrigger asChild>{railButton}</TooltipTrigger>\n <TooltipContent side=\"right\" sideOffset={8}>\n {tip}\n </TooltipContent>\n </Tooltip>\n )\n }\n\n const rowClass = cn(\n 'group flex h-9 w-full cursor-pointer items-center rounded-md px-3 text-sm transition-colors pointer-coarse:h-11',\n active\n ? 'bg-accent font-semibold text-accent-foreground'\n : 'font-medium text-muted-foreground hover:bg-muted hover:text-foreground',\n disabled && 'pointer-events-none cursor-not-allowed opacity-30',\n className\n )\n const countNode = count !== undefined && (\n <span\n // `ml-auto` lines the counts up on the right edge as one column of numbers.\n className={cn(\n 'ml-auto inline-flex flex-shrink-0 items-center gap-0.5 pl-2 text-xs font-normal tabular-nums',\n active ? 'text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {countIcon}\n {count}\n </span>\n )\n\n // A link row without a nested control is the anchor itself.\n if (href && !disabled && !trailing) {\n return (\n <ActionLink\n href={href}\n onSelect={onSelect}\n aria-current={active ? 'page' : undefined}\n data-slot=\"sidebar-nav-item\"\n data-testid={testId}\n className={rowClass}\n >\n <div className=\"flex size-5 flex-shrink-0 items-center justify-center\">{icon}</div>\n <span className=\"ml-3 min-w-0 truncate text-left\">{label}</span>\n {countNode}\n </ActionLink>\n )\n }\n\n // A link row with a nested control: a stretched anchor sits under the content, and the\n // trailing control rises above it, so there is never an interactive element inside an anchor.\n if (href && !disabled) {\n return (\n <div\n onMouseEnter={() => setIsRowActive(true)}\n onMouseLeave={() => setIsRowActive(false)}\n onFocusCapture={() => setIsRowActive(true)}\n onBlurCapture={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setIsRowActive(false)\n }}\n data-slot=\"sidebar-nav-item\"\n data-testid={testId}\n className={cn(rowClass, 'relative')}\n >\n <ActionLink\n href={href}\n onSelect={onSelect}\n aria-label={label}\n aria-current={active ? 'page' : undefined}\n className=\"absolute inset-0 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <div className=\"pointer-events-none flex min-w-0 flex-1 items-center\">\n <div className=\"flex size-5 flex-shrink-0 items-center justify-center\">{icon}</div>\n <span className=\"ml-3 min-w-0 truncate text-left\">{label}</span>\n {countNode}\n </div>\n <SidebarRowHoverContext.Provider value={isRowActive}>\n <span className=\"relative ml-2 flex flex-shrink-0 items-center\">{trailing}</span>\n </SidebarRowHoverContext.Provider>\n </div>\n )\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-current={active ? 'page' : undefined}\n onClick={disabled ? undefined : onSelect}\n onMouseEnter={() => setIsRowActive(true)}\n onMouseLeave={() => setIsRowActive(false)}\n onFocusCapture={() => setIsRowActive(true)}\n onBlurCapture={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setIsRowActive(false)\n }}\n onKeyDown={\n disabled\n ? undefined\n : (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onSelect()\n }\n }\n }\n data-slot=\"sidebar-nav-item\"\n data-testid={testId}\n className={rowClass}\n >\n <div className=\"flex size-5 flex-shrink-0 items-center justify-center\">{icon}</div>\n <span className=\"ml-3 min-w-0 truncate text-left\">{label}</span>\n {countNode}\n {trailing && (\n <SidebarRowHoverContext.Provider value={isRowActive}>\n <span className=\"ml-auto flex flex-shrink-0 items-center pl-2\">{trailing}</span>\n </SidebarRowHoverContext.Provider>\n )}\n </div>\n )\n}\n\nexport interface SidebarPinToggleProps {\n isPinned: boolean\n onToggle: () => void\n className?: string\n /** Default `sidebar-pin-button`. */\n 'data-testid'?: string\n}\n\n/**\n * Pin/unpin button, revealed while the pointer is over the sidebar. It is always visible on\n * coarse pointers (no hover on touch) and revealed by keyboard focus anywhere in the sidebar. It\n * is hidden with opacity and pointer-events, never display:none, so it keeps its accessible name\n * and stays in the tab order.\n */\nfunction SidebarPinToggle({\n isPinned,\n onToggle,\n className,\n 'data-testid': testId,\n}: SidebarPinToggleProps) {\n const { expanded, labels } = useSidebarContext()\n const label = isPinned ? labels.hideSidebar : labels.showSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n title={label}\n aria-label={label}\n aria-pressed={isPinned}\n data-testid={testIdOr(testId, { testId: 'sidebar-pin-button' })}\n className={cn(\n 'flex flex-shrink-0 items-center justify-center rounded-md text-muted-foreground transition-[opacity,colors] hover:bg-muted hover:text-foreground pointer-coarse:size-11',\n 'pointer-events-none opacity-0 group-hover/sidebar:pointer-events-auto group-hover/sidebar:opacity-100',\n 'group-focus-within/sidebar:pointer-events-auto group-focus-within/sidebar:opacity-100',\n 'pointer-coarse:pointer-events-auto pointer-coarse:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100',\n expanded ? 'size-9' : 'h-9 w-12',\n className\n )}\n >\n {isPinned ? <PanelLeftClose className=\"size-5\" /> : <PanelLeftOpen className=\"size-5\" />}\n </button>\n )\n}\n\nexport interface SidebarDrawerHeaderProps {\n /** Brand mark. */\n logo: ReactNode\n onClose: () => void\n closeLabel?: string\n /** Close button id (default `mobile-nav-close`). */\n 'data-testid'?: string\n}\n\n/** The phone drawer's header: brand mark and a 44px close button. */\nfunction SidebarDrawerHeader({\n logo,\n onClose,\n closeLabel: closeLabelProp,\n 'data-testid': testId,\n}: SidebarDrawerHeaderProps) {\n const { labels } = useSidebarContext()\n const closeLabel = closeLabelProp ?? labels.closeNavigationMenu\n return (\n <div\n data-slot=\"sidebar-drawer-header\"\n className=\"flex flex-shrink-0 items-center justify-between pb-2\"\n >\n {logo}\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={closeLabel}\n data-testid={testIdOr(testId, { testId: 'mobile-nav-close' })}\n className=\"flex size-11 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n )\n}\n\nexport { DEFAULT_SIDEBAR_LABELS, SidebarRowHoverContext, useSidebarContext, type SidebarLabels }\n\nexport const Sidebar = {\n Root: SidebarRoot,\n Header: SidebarHeader,\n Nav: SidebarNav,\n Group: SidebarGroup,\n GroupLabel: SidebarGroupLabel,\n NavItem: SidebarNavItem,\n Footer: SidebarFooter,\n PinToggle: SidebarPinToggle,\n BadgeRow: SidebarBadgeRow,\n DrawerHeader: SidebarDrawerHeader,\n}\n","import type { ReactNode } from 'react'\nimport { Sidebar, type SidebarRootProps } from './Sidebar'\nimport type { SidebarController } from './use-sidebar-controller'\nimport type { NavItem, NavSection } from './types'\n\nexport interface ShellSidebarProps extends Pick<\n SidebarRootProps,\n 'className' | 'aria-label' | 'labels' | 'backdropTestId'\n> {\n /** From `useSidebarController`: layout, hover/pin/drawer behaviour. */\n controller: SidebarController\n /** Brand mark of the phone drawer's header (logo + close). Omit for no drawer header. */\n drawerLogo?: ReactNode\n /** `data-testid` of the drawer's close button. */\n drawerCloseTestId?: string\n /** Top block (workspace switcher, ask field, pin toggle). Read `controller.expanded` for the rail. */\n header?: ReactNode\n /** Rows as data. */\n items?: NavItem[]\n /** Labelled groups of rows as data, after `items`. */\n sections?: NavSection[]\n navClassName?: string\n /**\n * Width-bound cards at the top of the footer (smart tips, notices): shown only once the panel\n * has settled open, and gone the instant it starts to close.\n */\n tips?: ReactNode\n /** The rest of the footer (status rows, account rows). */\n footer?: ReactNode\n /** Root `data-testid` (default `sidebar`). */\n 'data-testid'?: string\n}\n\n/**\n * The whole sidebar from a controller and data: `Sidebar.Root` in the resolved mode, the phone\n * drawer header, the header slot, the nav rows/groups and the footer. Renders nothing while the\n * layout is hidden (a phone with the drawer closed), so no clipped rows carry duplicate test ids.\n *\n * const sidebar = useSidebarController({ isPinned, onPinnedChange: setPinned })\n * <ShellSidebar controller={sidebar} header={…} items={nav} footer={…} />\n */\nexport function ShellSidebar({\n controller,\n drawerLogo,\n drawerCloseTestId,\n header,\n items,\n sections,\n navClassName,\n tips,\n footer,\n ...rootProps\n}: ShellSidebarProps) {\n if (controller.layout.hidden) return null\n return (\n <Sidebar.Root {...controller.rootProps} {...rootProps}>\n {controller.isDrawer && drawerLogo && (\n <Sidebar.DrawerHeader\n logo={drawerLogo}\n onClose={controller.closeDrawer}\n data-testid={drawerCloseTestId}\n />\n )}\n {header && <Sidebar.Header>{header}</Sidebar.Header>}\n <Sidebar.Nav items={items} sections={sections} className={navClassName} />\n {(tips || footer) && (\n <Sidebar.Footer>\n {controller.tipsVisible && tips}\n {footer}\n </Sidebar.Footer>\n )}\n </Sidebar.Root>\n )\n}\n","import { useEffect, useRef } from 'react'\n\n/**\n * While `isActive`, Escape calls `onClose`. For surfaces that float over the page without being a\n * modal (no backdrop, no focus trap), so nothing else closes them from the keyboard. An Escape a\n * dialog already handled (`defaultPrevented`) is left alone so one press closes one layer.\n */\nexport function useCloseOnEscape(isActive: boolean, onClose: () => void): void {\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isActive) return\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !e.defaultPrevented) onCloseRef.current()\n }\n document.addEventListener('keydown', onKeyDown)\n return () => document.removeEventListener('keydown', onKeyDown)\n }, [isActive])\n}\n","import { useEffect, useRef, useState } from 'react'\n\n/**\n * Headless sidebar behaviour (no DOM, no store): how the sidebar lays out for a given set of\n * inputs, and the settle timing that keeps labels/tips from squeezing during the width transition.\n *\n * - `drawer` small-screen off-canvas panel (opened by the app bar's menu button)\n * - `collapsed` hidden (width 0): a phone with the drawer closed, or `isCollapsed`\n * - `pinned` full width, inline, pushes the content\n * - `rail` icon strip that floats open to full width while hovered\n */\nexport type SidebarMode = 'drawer' | 'collapsed' | 'pinned' | 'rail'\n\nexport interface SidebarModeInput {\n isSmallScreen: boolean\n /** The phone drawer was requested open. */\n isDrawerRequested: boolean\n isCollapsed: boolean\n isPinned: boolean\n isHovering: boolean\n /**\n * Tablet-width viewport (above the phone drawer breakpoint but too narrow to give the content a\n * usable column next to a 255px panel): pinning is ignored and the sidebar stays an icon rail.\n */\n isNarrow?: boolean\n}\n\nexport interface SidebarLayout {\n mode: SidebarMode\n /** Labels should be shown (the panel is, or is becoming, full width). */\n expanded: boolean\n /** Phones: nothing is rendered until the drawer opens. */\n hidden: boolean\n /** Hover state that actually applies (never on touch-sized screens). */\n hovering: boolean\n}\n\nexport function resolveSidebarLayout(input: SidebarModeInput): SidebarLayout {\n const { isSmallScreen, isDrawerRequested, isCollapsed, isPinned, isHovering } = input\n const canPin = isPinned && !isSmallScreen && !input.isNarrow\n const drawerOpen = isSmallScreen && isDrawerRequested\n // Small screens are drawer-only: when it is closed the panel is fully off-canvas\n // regardless of pinning (pinning is a desktop concept), and hover never expands.\n const effectiveCollapsed = isCollapsed || (isSmallScreen && !drawerOpen)\n const hovering = isHovering && !isSmallScreen\n\n let mode: SidebarMode\n if (drawerOpen) mode = 'drawer'\n else if (effectiveCollapsed) mode = 'collapsed'\n else if (canPin) mode = 'pinned'\n else mode = 'rail'\n\n // `hovering`, not `isHovering`: a stale hover flag must not report a hidden phone sidebar as expanded.\n const expanded = drawerOpen || (!effectiveCollapsed && (canPin || hovering))\n\n return { mode, expanded, hidden: isSmallScreen && !drawerOpen, hovering }\n}\n\n/**\n * Settle timing around the width transition (default 300ms):\n * - `labelsExpanded` switches on immediately but off only after the transition, so labels do not\n * snap to icon-only while the panel is still wide;\n * - `tipsVisible` is the opposite: width-bound content (a tip card) appears only once the panel\n * has fully opened and disappears the instant collapse starts.\n */\nexport function useSidebarSettle(expanded: boolean, settleMs = 300) {\n const [labelsExpanded, setLabelsExpanded] = useState(expanded)\n const [tipsVisible, setTipsVisible] = useState(expanded)\n const labelsTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const tipsTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n useEffect(() => {\n if (labelsTimer.current) clearTimeout(labelsTimer.current)\n if (expanded) setLabelsExpanded(true)\n else labelsTimer.current = setTimeout(() => setLabelsExpanded(false), settleMs)\n return () => {\n if (labelsTimer.current) clearTimeout(labelsTimer.current)\n }\n }, [expanded, settleMs])\n\n useEffect(() => {\n if (tipsTimer.current) clearTimeout(tipsTimer.current)\n if (expanded) tipsTimer.current = setTimeout(() => setTipsVisible(true), settleMs)\n else setTipsVisible(false)\n return () => {\n if (tipsTimer.current) clearTimeout(tipsTimer.current)\n }\n }, [expanded, settleMs])\n\n return { labelsExpanded, tipsVisible }\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport { useControllableState } from '../lib/useControllableState'\nimport { useCloseOnEscape } from '../lib/use-close-on-escape'\nimport { useIsNarrow, useIsPhone, useIsTouchScreen } from '../lib/use-media-query'\nimport { resolveSidebarLayout, useSidebarSettle, type SidebarLayout } from '../lib/sidebar-mode'\nimport type { SidebarRootProps } from './Sidebar'\n\nexport interface UseSidebarControllerOptions {\n /** Pinned open (desktop). Controlled when set; otherwise kept here, seeded by `defaultPinned`. */\n isPinned?: boolean\n /** Default `true`. */\n defaultPinned?: boolean\n onPinnedChange?: (isPinned: boolean) => void\n /** The rail is floated open (hover, or its toggle at a narrow width). Controlled when set. */\n isHovering?: boolean\n onHoveringChange?: (isHovering: boolean) => void\n /** The phone drawer is open. Controlled when set (the app bar's menu button opens it). */\n isDrawerOpen?: boolean\n onDrawerOpenChange?: (isDrawerOpen: boolean) => void\n /**\n * Keep the sidebar a rail even when pinned, on top of the tablet width (for example while a\n * docked panel squeezes the content). The stored pin is left untouched.\n */\n forceRail?: boolean\n}\n\n/** The `Sidebar.Root` props the controller resolves. */\nexport type SidebarControllerRootProps = Pick<\n SidebarRootProps,\n | 'mode'\n | 'expanded'\n | 'isHovering'\n | 'onBackdropClick'\n | 'hasRailBackdrop'\n | 'onMouseEnter'\n | 'onMouseLeave'\n>\n\nexport interface SidebarController {\n layout: SidebarLayout\n /** Labels shown (settled: they stay on until the closing transition ends). */\n expanded: boolean\n /** Width-bound content (tips, notices) may show: on once fully open, off as closing starts. */\n tipsVisible: boolean\n /** The phone drawer is showing. */\n isDrawer: boolean\n isSmallScreen: boolean\n /** Tablet width (or `forceRail`): pinning is ignored and the sidebar stays a rail. */\n isNarrow: boolean\n /** The pin as it applies (always off while narrow). */\n isPinned: boolean\n /** Spread onto `Sidebar.Root` (or pass the controller to `ShellSidebar`). */\n rootProps: SidebarControllerRootProps\n openDrawer: () => void\n closeDrawer: () => void\n /** The pin toggle: pins/unpins, or floats the rail open/closed while narrow. */\n togglePin: () => void\n /** Open from the rail (its ask button): pins, or floats the rail open while narrow. */\n expand: () => void\n /** After a nav row is chosen: closes the drawer, and a floated rail the pointer has left. */\n afterNavigate: () => void\n}\n\n// A menu opened from the rail (the account menu) is positioned against the sidebar's current\n// layout. Hovering that menu from the content would expand the rail, re-anchor the menu under\n// the pointer and move the item being clicked, so hover does not expand the rail while one is open.\nconst isMenuOpen = () =>\n typeof document !== 'undefined' &&\n document.querySelector('[role=\"menu\"][data-state=\"open\"]') !== null\n\n/**\n * Sidebar behaviour as one hook, shared by every shell: resolves the layout (drawer / pinned /\n * rail) for the viewport, settles labels and tips around the width transition, and owns the hover,\n * pin and drawer rules:\n * - touch: the rail opens only through its toggle, never by the emulated mouseenter of a tap;\n * - narrow: a pointer drifting over the rail does not float the labels over the content;\n * - Escape closes a floated rail; the drawer closes itself when the viewport grows past a phone;\n * - choosing a row closes the drawer, and a floated rail unless the pointer is still over it.\n *\n * State is controlled per field (`isPinned`, `isHovering`, `isDrawerOpen`) so an app can keep it\n * in its own store, or uncontrolled for a shell that does not care.\n */\nexport function useSidebarController(options: UseSidebarControllerOptions = {}): SidebarController {\n const [storedPinned, setPinned] = useControllableState(\n options.isPinned,\n options.defaultPinned ?? true,\n options.onPinnedChange\n )\n const [isHovering, setHovering] = useControllableState(\n options.isHovering,\n false,\n options.onHoveringChange\n )\n const [isDrawerOpen, setDrawerOpen] = useControllableState(\n options.isDrawerOpen,\n false,\n options.onDrawerOpenChange\n )\n\n const isSmallScreen = useIsPhone()\n const isNarrow = useIsNarrow() || !!options.forceRail\n const isTouch = useIsTouchScreen()\n\n const layout = resolveSidebarLayout({\n isSmallScreen,\n isDrawerRequested: isDrawerOpen,\n isCollapsed: false,\n isPinned: storedPinned,\n isHovering,\n isNarrow,\n })\n const isDrawer = layout.mode === 'drawer'\n const { labelsExpanded, tipsVisible } = useSidebarSettle(layout.expanded)\n\n // Whether the pointer is physically over the sidebar (decides if navigating closes the rail).\n const isPointerOver = useRef(false)\n\n const closeDrawer = useCallback(() => setDrawerOpen(false), [setDrawerOpen])\n const openDrawer = useCallback(() => setDrawerOpen(true), [setDrawerOpen])\n\n // The floated rail has no modal behaviour (the drawer gets Escape from `Sidebar.Root`).\n useCloseOnEscape(layout.mode === 'rail' && layout.hovering, () => setHovering(false))\n\n // A drawer left open when the viewport grows past a phone (rotate/resize) would be a stuck overlay.\n useEffect(() => {\n if (isDrawerOpen && !isSmallScreen) setDrawerOpen(false)\n }, [isDrawerOpen, isSmallScreen, setDrawerOpen])\n\n const onMouseEnter = () => {\n if (isTouch) return\n isPointerOver.current = true\n if (!isSmallScreen && !isNarrow && !isMenuOpen()) setHovering(true)\n }\n const onMouseLeave = () => {\n if (isTouch) return\n isPointerOver.current = false\n if (!isSmallScreen) setHovering(false)\n }\n\n return {\n layout,\n expanded: labelsExpanded,\n tipsVisible,\n isDrawer,\n isSmallScreen,\n isNarrow,\n isPinned: storedPinned && !isNarrow,\n rootProps: {\n mode: layout.mode,\n expanded: labelsExpanded,\n isHovering: layout.hovering,\n onBackdropClick: isDrawer ? closeDrawer : () => setHovering(false),\n hasRailBackdrop: isTouch,\n onMouseEnter,\n onMouseLeave,\n },\n openDrawer,\n closeDrawer,\n togglePin: () => (isNarrow ? setHovering(!isHovering) : setPinned(!storedPinned)),\n expand: () => (isNarrow ? setHovering(true) : setPinned(true)),\n afterNavigate: () => {\n if (!isPointerOver.current && !storedPinned) setHovering(false)\n if (isDrawer) closeDrawer()\n },\n }\n}\n","import { useContext, type ReactNode } from 'react'\nimport { cn, Tooltip, TooltipContent, TooltipTrigger } from '@arbidocs/react/ui'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\nimport { SidebarRowHoverContext } from './Sidebar'\n\nexport type SidebarRowActionPulse = 'active' | 'success' | 'error'\n\nexport interface SidebarRowActionProps {\n /** The row this control sits on is selected: the glyph takes the selection ink. */\n active?: boolean\n onClick?: () => void\n /** Tooltip text and accessible label. */\n label: string\n /** Reflected as aria-pressed for toggle controls. */\n pressed?: boolean\n /**\n * Demand attention while the row is idle: `active` pulses primary (work in progress),\n * `success` pulses green (just finished), `error` is a steady red alert. A selected row wins.\n */\n pulse?: SidebarRowActionPulse | null\n 'data-testid'?: string\n children: ReactNode\n}\n\nconst PULSE_STYLES: Record<SidebarRowActionPulse, string> = {\n active: 'animate-pulse-attention text-primary',\n success: 'animate-pulse-attention text-green-text',\n // Steady (not animated) so a failure stays put and reads as a standing alert.\n error: 'text-red-text opacity-100',\n}\n\n/**\n * The secondary control at the right edge of a sidebar row: a small muted glyph. Always visible\n * (touch has no hover); hovering or focusing the row only brightens it a tone, through\n * SidebarRowHoverContext. Stops propagation so it never triggers the row's own click.\n */\nexport function SidebarRowAction({\n active = false,\n onClick,\n label,\n pressed,\n pulse = null,\n 'data-testid': testId,\n children,\n}: SidebarRowActionProps) {\n const rowHovered = useContext(SidebarRowHoverContext)\n\n const tone = active\n ? 'text-accent-foreground hover:bg-background/60'\n : pulse\n ? `${PULSE_STYLES[pulse]} hover:bg-muted`\n : cn(\n 'text-muted-foreground hover:bg-muted hover:text-foreground',\n rowHovered ? 'opacity-100' : 'opacity-70'\n )\n\n return (\n <BlocksTooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild onFocusCapture={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onClick?.()\n }}\n aria-label={label}\n aria-pressed={pressed}\n data-slot=\"sidebar-row-action\"\n data-testid={testId}\n className={cn('rounded-md p-1 transition-colors pointer-coarse:p-2.5', tone)}\n >\n {children}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">{label}</TooltipContent>\n </Tooltip>\n </BlocksTooltipProvider>\n )\n}\n","import type { InputHTMLAttributes, KeyboardEvent, ReactNode, Ref } from 'react'\nimport { ArrowUp, Search, Sparkles, X } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\n\n/** Fixed strings of the ask field, its trigger and the expanded row. */\nexport interface AskFieldLabels {\n /** Input placeholder (the `placeholder` prop wins). */\n placeholder: string\n /** The input's accessible name. */\n inputLabel: string\n search: string\n askAi: string\n /** The icon-only trigger. */\n askOrSearch: string\n closeSearch: string\n}\n\nexport const DEFAULT_ASK_FIELD_LABELS: AskFieldLabels = {\n placeholder: 'Ask or search…',\n inputLabel: 'Ask AI or search your documents',\n search: 'Search',\n askAi: 'Ask AI',\n askOrSearch: 'Ask AI or search',\n closeSearch: 'Close search',\n}\n\nexport interface AskFieldProps {\n value: string\n onValueChange: (value: string) => void\n /** Enter / the arrow button: ask AI. */\n onAsk: (text: string) => void\n /** The magnifier button: semantic search. */\n onSearch: (text: string) => void\n /** Intercept keys first (e.g. a slash menu); call `preventDefault` to stop the default Enter-asks. */\n onInputKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void\n /** Rendered just under the field at its width (a slash/autocomplete menu). */\n menu?: ReactNode\n inputRef?: Ref<HTMLInputElement>\n /** Extra attributes for the input, e.g. the combobox props of `useListKeyNav` for a slash menu. */\n inputProps?: InputHTMLAttributes<HTMLInputElement>\n placeholder?: string\n labels?: Partial<AskFieldLabels>\n autoFocus?: boolean\n className?: string\n /** Root id (default `workspace-ask-bar`); the input/search/submit ids are `<root>-input|search|submit`. */\n 'data-testid'?: string\n}\n\n/**\n * The compact one-line ask/search field: sparkle, input, then two icon doors (Search, Ask AI).\n * Text and the menu are controlled by the host, so the same field serves the sidebar, the phone\n * app bar and any custom shell.\n */\nexport function AskField({\n value,\n onValueChange,\n onAsk,\n onSearch,\n onInputKeyDown,\n menu,\n inputRef,\n inputProps,\n placeholder,\n labels,\n autoFocus = false,\n className,\n 'data-testid': testIdProp,\n}: AskFieldProps) {\n const testId = testIdOr(testIdProp, { testId: 'workspace-ask-bar' })\n const l = { ...DEFAULT_ASK_FIELD_LABELS, ...labels }\n const isEmpty = !value.trim()\n const submit = (handler: (text: string) => void) => {\n const text = value.trim()\n if (text) handler(text)\n }\n\n return (\n <div className={cn('relative', className)} data-slot=\"ask-field\" data-testid={testId}>\n {menu && <div className=\"absolute inset-x-0 top-9 z-30\">{menu}</div>}\n <div\n role=\"search\"\n className=\"flex h-9 items-center gap-0.5 rounded-md border border-border bg-background pl-2.5 pr-0.5 transition-colors focus-within:border-primary focus-within:ring-3 focus-within:ring-primary pointer-coarse:h-11\"\n >\n <Sparkles aria-hidden=\"true\" className=\"size-4 shrink-0 text-ai-ink\" />\n <input\n {...inputProps}\n ref={inputRef}\n type=\"text\"\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n onInputKeyDown?.(e)\n // Enter asks (not mid-IME-composition). A plain div, not a <form>.\n if (e.defaultPrevented) return\n if (e.key === 'Enter' && !e.nativeEvent.isComposing) {\n e.preventDefault()\n submit(onAsk)\n }\n }}\n placeholder={placeholder ?? l.placeholder}\n aria-label={l.inputLabel}\n autoFocus={autoFocus}\n className=\"ml-1.5 h-8 min-w-0 flex-1 bg-transparent pointer-coarse:h-11 text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n data-testid={`${testId}-input`}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isEmpty}\n onClick={() => submit(onSearch)}\n title={l.search}\n aria-label={l.search}\n className=\"size-7 shrink-0 text-muted-foreground hover:text-foreground pointer-coarse:size-10\"\n data-testid={`${testId}-search`}\n >\n <Search className=\"size-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={isEmpty}\n onClick={() => submit(onAsk)}\n title={l.askAi}\n aria-label={l.askAi}\n className=\"!inline-flex size-7 shrink-0 text-ai-ink hover:bg-ai-soft hover:text-ai-ink pointer-coarse:size-10\"\n data-testid={`${testId}-submit`}\n >\n <ArrowUp className=\"size-4\" />\n </Button>\n </div>\n </div>\n )\n}\n\nexport interface AskTriggerProps {\n /** Opens the ask field (the single-action variants) or asks AI (`split`). */\n onClick: () => void\n /**\n * `rail`: the icon-only sidebar's bordered tile; `appbar`: the phone app bar's bare icon;\n * `split`: two icon buttons side by side, Search (`onSearch`) and Ask AI (`onClick`).\n */\n variant?: 'rail' | 'appbar' | 'split'\n /** The Search action of the `split` variant. */\n onSearch?: () => void\n labels?: Partial<Pick<AskFieldLabels, 'askOrSearch' | 'search' | 'askAi'>>\n /**\n * `split` only: show the Search and Ask AI texts beside the icons (from `sm` up; phones keep\n * icons, the texts stay as accessible names and tooltips) instead of icon-only buttons.\n */\n showLabels?: boolean\n /** Root id; the split buttons get `<root>-search` and `<root>-ask` unless overridden. */\n 'data-testid'?: string\n searchTestId?: string\n askTestId?: string\n}\n\n/** The icon that stands in for the field where there is no room for it. */\nexport function AskTrigger({\n onClick,\n variant = 'rail',\n onSearch,\n labels,\n showLabels = false,\n 'data-testid': testId,\n searchTestId,\n askTestId,\n}: AskTriggerProps) {\n const text = labels?.askOrSearch ?? DEFAULT_ASK_FIELD_LABELS.askOrSearch\n if (variant === 'split') {\n const searchText = labels?.search ?? DEFAULT_ASK_FIELD_LABELS.search\n const askText = labels?.askAi ?? DEFAULT_ASK_FIELD_LABELS.askAi\n return (\n <div\n role=\"group\"\n aria-label={text}\n data-slot=\"ask-trigger\"\n data-variant=\"split\"\n data-testid={testId}\n className=\"inline-flex items-center rounded-md border border-border bg-background\"\n >\n <button\n type=\"button\"\n onClick={onSearch}\n title={searchText}\n aria-label={searchText}\n data-testid={searchTestId ?? (testId ? `${testId}-search` : undefined)}\n className={cn(\n 'flex h-9 items-center justify-center gap-1.5 rounded-l-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:h-11',\n showLabels\n ? 'min-w-9 px-2.5 text-sm pointer-coarse:min-w-11'\n : 'w-9 pointer-coarse:w-11'\n )}\n >\n <Search className=\"size-4\" />\n {showLabels && <span className=\"hidden sm:inline\">{searchText}</span>}\n </button>\n <button\n type=\"button\"\n onClick={onClick}\n title={askText}\n aria-label={askText}\n data-testid={askTestId ?? (testId ? `${testId}-ask` : undefined)}\n className={cn(\n 'flex h-9 items-center justify-center gap-1.5 rounded-r-md border-l border-border text-ai-ink transition-colors hover:bg-ai-soft pointer-coarse:h-11',\n showLabels\n ? 'min-w-9 px-2.5 text-sm pointer-coarse:min-w-11'\n : 'w-9 pointer-coarse:w-11'\n )}\n >\n <Sparkles className=\"size-4\" />\n {showLabels && <span className=\"hidden sm:inline\">{askText}</span>}\n </button>\n </div>\n )\n }\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={text}\n aria-label={text}\n data-slot=\"ask-trigger\"\n data-testid={testId}\n className={cn(\n 'flex items-center justify-center rounded-md text-ai-ink transition-colors hover:bg-ai-soft',\n variant === 'rail'\n ? 'h-9 w-12 border border-border bg-background pointer-coarse:h-11'\n : 'size-11'\n )}\n >\n <Sparkles className={variant === 'rail' ? 'size-4' : 'size-5'} />\n </button>\n )\n}\n\nexport interface AskRowProps {\n /** The field (an AskField). */\n children: ReactNode\n onClose: () => void\n labels?: Partial<Pick<AskFieldLabels, 'closeSearch'>>\n /** Row id (default `workspace-ask-bar-expanded`). */\n 'data-testid'?: string\n /** Collapse button id (default `workspace-ask-bar-collapse`). */\n collapseTestId?: string\n}\n\n/** The phone's expanded ask row: takes over the app bar so there is room to type; Escape closes. */\nexport function AskRow({\n children,\n onClose,\n labels,\n 'data-testid': testId,\n collapseTestId,\n}: AskRowProps) {\n return (\n <div\n className=\"flex h-14 flex-shrink-0 items-center gap-1 bg-background px-3 pt-safe\"\n data-slot=\"ask-row\"\n data-testid={testIdOr(testId, { testId: 'workspace-ask-bar-expanded' })}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && !e.defaultPrevented) onClose()\n }}\n >\n <div className=\"min-w-0 flex-1\">{children}</div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={labels?.closeSearch ?? DEFAULT_ASK_FIELD_LABELS.closeSearch}\n data-testid={testIdOr(collapseTestId, { testId: 'workspace-ask-bar-collapse' })}\n className=\"flex size-11 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n )\n}\n","import { useRef, type ReactNode } from 'react'\nimport { Menu } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { ActionLink } from '../components/ActionLink'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\nimport { useShellBottomInset } from '../lib/bottom-inset'\nimport type { NavItem } from './types'\n\n/** Fixed strings of the phone bars. */\nexport interface MobileBarsLabels {\n /** The menu button (the `menuLabel` prop wins). */\n openNavigationMenu: string\n /** The tab bar's accessible name (the `label` prop wins). */\n workspaceSections: string\n}\n\nexport const DEFAULT_MOBILE_BARS_LABELS: MobileBarsLabels = {\n openNavigationMenu: 'Open navigation menu',\n workspaceSections: 'Workspace sections',\n}\n\nexport interface MobileAppBarProps {\n /** Show the menu button that opens the drawer (nothing to open on a list page with no sidebar). */\n showMenu?: boolean\n onMenu?: () => void\n /** Replaces the brand mark (e.g. the workspace switcher). */\n title?: ReactNode\n /** Brand mark shown when there is no `title`. */\n logo?: ReactNode\n /** Right-aligned controls that fit (ask, offline pill, bell, account). */\n actions?: ReactNode\n menuLabel?: string\n labels?: Partial<Pick<MobileBarsLabels, 'openNavigationMenu'>>\n className?: string\n 'data-testid'?: string\n /** Menu button id (default `mobile-nav-toggle`). */\n menuTestId?: string\n}\n\n/**\n * The slim phone app bar (56px): menu button, a title slot and an actions slot. The app mounts\n * it only on small screens; the controls that do not fit live in the drawer.\n */\nexport function MobileAppBar({\n showMenu = true,\n onMenu,\n title,\n logo,\n actions,\n menuLabel,\n labels,\n className,\n 'data-testid': testId,\n menuTestId,\n}: MobileAppBarProps) {\n return (\n <div\n data-slot=\"mobile-app-bar\"\n data-testid={testId}\n className={cn(\n 'sm:hidden flex h-14 flex-shrink-0 items-center gap-1 bg-background pl-1 pr-2 pt-safe',\n className\n )}\n >\n {showMenu && (\n <button\n type=\"button\"\n onClick={onMenu}\n className=\"flex size-11 shrink-0 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted\"\n aria-label={\n menuLabel ?? labels?.openNavigationMenu ?? DEFAULT_MOBILE_BARS_LABELS.openNavigationMenu\n }\n data-testid={testIdOr(menuTestId, { testId: 'mobile-nav-toggle' })}\n >\n <Menu className=\"size-5\" />\n </button>\n )}\n <div className={cn('flex min-w-0 flex-1 items-center', !showMenu && 'pl-3')}>\n {title ?? logo}\n </div>\n {actions && <div className=\"flex shrink-0 items-center gap-0.5\">{actions}</div>}\n </div>\n )\n}\n\n/**\n * A tab's label. It wraps at word boundaries and is never clipped or cut with an ellipsis; a tab\n * narrower than 4.5rem sets it one size smaller so a long single word still fits, and an item with\n * a `shortLabel` shows that one while its tab is narrower than 5.5rem.\n */\nfunction TabLabel({ item }: { item: NavItem }) {\n const wrap =\n 'max-w-full text-balance px-0.5 text-center [overflow-wrap:normal] @max-[4.5rem]:text-[10px]'\n if (!item.shortLabel) return <span className={wrap}>{item.label}</span>\n return (\n <>\n <span data-slot=\"tab-short-label\" aria-hidden=\"true\" className={cn(wrap, '@[5.5rem]:hidden')}>\n {item.shortLabel}\n </span>\n <span className={cn(wrap, 'hidden @[5.5rem]:block')}>{item.label}</span>\n <span className=\"sr-only @[5.5rem]:hidden\">{item.label}</span>\n </>\n )\n}\n\nexport interface MobileTabBarProps {\n /** The workspace's main areas; test ids are `{testIdPrefix}-{id}` (prefix default `mobile-tab`). */\n items: NavItem[]\n label?: string\n labels?: Partial<Pick<MobileBarsLabels, 'workspaceSections'>>\n testIdPrefix?: string\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * Phone bottom navigation: a 64px tinted bar of the main areas. The drawer carries the same\n * destinations with counts, so nothing is reachable only here. The app mounts it on small\n * screens only.\n */\nexport function MobileTabBar({\n items,\n label,\n labels,\n testIdPrefix,\n className,\n 'data-testid': testId,\n}: MobileTabBarProps) {\n const navRef = useRef<HTMLElement>(null)\n // Floating elements (install prompt, toasts) read the bar's height from `--shell-bottom-inset`.\n useShellBottomInset(navRef)\n return (\n <nav\n ref={navRef}\n aria-label={\n label ?? labels?.workspaceSections ?? DEFAULT_MOBILE_BARS_LABELS.workspaceSections\n }\n data-slot=\"mobile-tab-bar\"\n data-testid={testIdOr(testId, { testId: 'mobile-tab-bar' })}\n className={cn(\n 'flex min-h-16 flex-shrink-0 items-stretch bg-sidebar px-2 pb-safe sm:hidden',\n className\n )}\n >\n {items.map((item) => (\n <ActionLink\n key={item.id}\n href={item.href}\n onSelect={item.onSelect}\n disabled={item.disabled}\n aria-current={item.active ? 'page' : undefined}\n className={cn(\n // Each tab is a size container: a `shortLabel` replaces the label when it is narrow.\n '@container flex min-h-12 min-w-0 flex-1 flex-col items-center justify-center gap-0.5 rounded-md text-[11px] leading-tight transition-colors',\n item.active\n ? 'font-semibold text-primary'\n : 'font-medium text-muted-foreground hover:text-foreground'\n )}\n data-testid={prefixedTestId(testIdPrefix, item.id, { testId: `mobile-tab-${item.id}` })}\n >\n {item.icon}\n <TabLabel item={item} />\n </ActionLink>\n ))}\n </nav>\n )\n}\n","/**\n * Per-browser PWA install instructions, for when the browser cannot open the install dialog\n * directly (iOS Safari, Safari on macOS, Firefox, or a Chromium browser that never fired\n * `beforeinstallprompt`). Only Chromium exposes a JS trigger, so off that path we tell the user\n * the right gesture for their browser.\n */\n\nexport interface InstallGuide {\n heading: string\n steps: string[]\n note?: string\n}\n\nexport interface InstallInstructionsOptions {\n /** Name shown in the steps. Default `this app`. */\n appName?: string\n}\n\n/** True on iPhone/iPad/iPod, including iPadOS reporting as a Mac. */\nexport function isIosDevice(): boolean {\n if (typeof navigator === 'undefined') return false\n return (\n /iPad|iPhone|iPod/.test(navigator.userAgent) ||\n (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)\n )\n}\n\n/** Pick install steps for the current browser/platform. */\nexport function getInstallInstructions({\n appName = 'this app',\n}: InstallInstructionsOptions = {}): InstallGuide {\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\n return {\n heading: `Install ${appName}`,\n steps: [`Open ${appName} in Chrome, Edge, or Safari to install it.`],\n }\n }\n\n const ua = navigator.userAgent\n const isChromium = 'onbeforeinstallprompt' in window\n const isFirefox = /firefox|fxios/i.test(ua)\n const isMac = /Macintosh|Mac OS X/.test(ua)\n\n if (isIosDevice()) {\n return {\n heading: 'Install on iPhone or iPad',\n steps: [\n `Open ${appName} in Safari, then tap the Share button.`,\n 'Scroll down and tap “Add to Home Screen”.',\n `Tap “Add”: ${appName} appears on your home screen.`,\n ],\n }\n }\n\n if (isChromium) {\n return {\n heading: `Install ${appName}`,\n steps: [\n 'Click the install icon at the right of the address bar (a small monitor with a down arrow).',\n 'Choose “Install” in the dialog that appears.',\n ],\n note: `On a phone, open the browser menu and choose “Install app” / “Add to Home screen”. If you don’t see the option, ${appName} may already be installed.`,\n }\n }\n\n if (isMac && !isFirefox) {\n return {\n heading: 'Install on macOS Safari',\n steps: ['In the menu bar, open the File menu.', 'Choose “Add to Dock”.'],\n note: 'Requires Safari 17 or later (macOS Sonoma). On older Safari, use Chrome or Edge to install.',\n }\n }\n\n if (isFirefox) {\n return {\n heading: 'Firefox can’t install web apps',\n steps: [`Open ${appName} in Chrome, Edge, or Safari to install it as an app.`],\n }\n }\n\n return {\n heading: `Install ${appName}`,\n steps: [\n 'Look for an “Install” or “Add to Home Screen” option in your browser’s menu or address bar.',\n ],\n }\n}\n","import { useCallback, useEffect, useState } from 'react'\nimport { getInstallInstructions, isIosDevice, type InstallGuide } from './install-instructions'\n\n/** Non-standard Chromium event, not in lib.dom types. */\ninterface BeforeInstallPromptEvent extends Event {\n readonly platforms: string[]\n readonly userChoice: Promise<{ outcome: 'accepted' | 'dismissed'; platform: string }>\n prompt(): Promise<void>\n}\n\nlet deferredPrompt: BeforeInstallPromptEvent | null = null\nlet installed = false\nlet initialized = false\nlet autoPromptParam: string | null = null\n\nconst subscribers = new Set<() => void>()\nconst notify = () => subscribers.forEach((fn) => fn())\n\nfunction isStandalone(): boolean {\n if (typeof window === 'undefined') return false\n const iosStandalone = (navigator as Navigator & { standalone?: boolean }).standalone === true\n return window.matchMedia?.('(display-mode: standalone)').matches === true || iosStandalone\n}\n\nfunction wantsAutoPrompt(): boolean {\n if (!autoPromptParam) return false\n return new URLSearchParams(window.location.search).get(autoPromptParam) === 'true'\n}\n\nfunction onBeforeInstallPrompt(event: Event): void {\n event.preventDefault()\n deferredPrompt = event as BeforeInstallPromptEvent\n notify()\n if (wantsAutoPrompt()) void promptAppInstall()\n}\n\nfunction onAppInstalled(): void {\n installed = true\n deferredPrompt = null\n notify()\n}\n\n/**\n * Begin capturing install events. Idempotent. Chromium fires `beforeinstallprompt` once, early,\n * usually before a lazy route has mounted, so call this at app startup (before the first render);\n * `useInstallPrompt` also calls it, which is enough when the hook mounts at the root.\n *\n * `options.autoPromptParam`: a share link `/?{param}=true` opens the native dialog as soon as the\n * browser is ready (Chromium).\n */\nexport function initInstallPrompt(options: { autoPromptParam?: string } = {}): void {\n if (options.autoPromptParam) autoPromptParam = options.autoPromptParam\n if (initialized || typeof window === 'undefined') return\n initialized = true\n installed = isStandalone()\n\n window.addEventListener('beforeinstallprompt', onBeforeInstallPrompt)\n window.addEventListener('appinstalled', onAppInstalled)\n}\n\n/**\n * Open the browser's install dialog if one was captured. Returns false when there is none (the\n * caller then shows {@link getInstallInstructions}). A captured prompt works once.\n */\nexport async function promptAppInstall(): Promise<boolean> {\n if (!deferredPrompt) return false\n const prompt = deferredPrompt\n deferredPrompt = null\n notify()\n try {\n await prompt.prompt()\n } catch {\n // The user dismissed it or the browser rejected it: nothing actionable.\n }\n return true\n}\n\n/** Default storage key of the remembered dismissal. */\nexport const INSTALL_PROMPT_DISMISSED_KEY = 'arbi-blocks:install-prompt-dismissed'\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction readDismissedAt(key: string): number | null {\n try {\n const raw = window.localStorage.getItem(key)\n const at = raw ? Number(raw) : NaN\n return Number.isFinite(at) ? at : null\n } catch {\n return null\n }\n}\n\nexport interface UseInstallPromptOptions {\n /** localStorage key remembering a dismissal. */\n storageKey?: string\n /** Days a dismissal is remembered. Default 30. */\n dismissDays?: number\n /** Query param that turns a share link into a one-click install (`install` for `?install=true`). */\n autoPromptParam?: string\n /** App name used in the manual instructions. */\n appName?: string\n}\n\nexport interface UseInstallPromptResult {\n /** A native install dialog can be opened right now (Chromium, once the event fired). */\n canPrompt: boolean\n /** Running as an installed app, or `appinstalled` fired. */\n isInstalled: boolean\n /** iOS has no install API: offer manual instructions instead. */\n isIos: boolean\n /** The user dismissed the offer (remembered across visits). */\n isDismissed: boolean\n /** Open the native dialog; false when none is available. */\n promptInstall: () => Promise<boolean>\n /** Hide the offer and remember it. */\n dismiss: () => void\n /** Manual steps for this browser. */\n instructions: InstallGuide\n}\n\n/** The install state of the app, framework-neutral logic behind `InstallPrompt`. */\nexport function useInstallPrompt({\n storageKey = INSTALL_PROMPT_DISMISSED_KEY,\n dismissDays = 30,\n autoPromptParam: autoParam,\n appName,\n}: UseInstallPromptOptions = {}): UseInstallPromptResult {\n const [, forceRender] = useState(0)\n const [dismissedAt, setDismissedAt] = useState<number | null>(() =>\n typeof window === 'undefined' ? null : readDismissedAt(storageKey)\n )\n\n useEffect(() => {\n initInstallPrompt({ autoPromptParam: autoParam })\n const onChange = () => forceRender((n) => n + 1)\n subscribers.add(onChange)\n // The singleton may have started before this mount: pick up the current state.\n onChange()\n return () => {\n subscribers.delete(onChange)\n }\n }, [autoParam])\n\n const dismiss = useCallback(() => {\n const now = Date.now()\n setDismissedAt(now)\n try {\n window.localStorage.setItem(storageKey, String(now))\n } catch {\n // Storage blocked: the dismissal lasts for this page view only.\n }\n }, [storageKey])\n\n const isDismissed = dismissedAt !== null && Date.now() - dismissedAt < dismissDays * DAY_MS\n const isInstalled = installed || isStandalone()\n return {\n canPrompt: !isInstalled && deferredPrompt !== null,\n isInstalled,\n isIos: isIosDevice(),\n isDismissed,\n promptInstall: promptAppInstall,\n dismiss,\n instructions: getInstallInstructions({ appName }),\n }\n}\n\n/** Test seam: forget captured state (the singleton lives for the page). */\nexport function resetInstallPromptForTests(): void {\n if (typeof window !== 'undefined') {\n window.removeEventListener('beforeinstallprompt', onBeforeInstallPrompt)\n window.removeEventListener('appinstalled', onAppInstalled)\n }\n deferredPrompt = null\n installed = false\n initialized = false\n autoPromptParam = null\n subscribers.clear()\n}\n","import { useState } from 'react'\nimport { Download, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { useInstallPrompt, type UseInstallPromptOptions } from './use-install-prompt'\n\n/** Fixed strings of the install prompt. */\nexport interface InstallPromptLabels {\n /** The pill's text. */\n install: string\n /** The dismiss button's accessible name. */\n dismiss: string\n /** Accessible name of the pill (`{app}` is replaced by `appName`). */\n installAs: string\n}\n\nexport const DEFAULT_INSTALL_PROMPT_LABELS: InstallPromptLabels = {\n install: 'Install app',\n dismiss: 'Dismiss install prompt',\n installAs: 'Install {app} as an app',\n}\n\nexport interface InstallPromptProps extends UseInstallPromptOptions {\n /** Which bottom corner the pill sits in. Default `start` (clear of a bottom-right toaster). */\n placement?: 'start' | 'end'\n labels?: Partial<InstallPromptLabels>\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A small floating \"Install app\" pill. Renders only while the app can be installed (the browser\n * fired `beforeinstallprompt`, or on iOS where it shows the Add to Home Screen steps), is not\n * already installed, and was not dismissed (the dismissal is remembered for `dismissDays`).\n *\n * It sits above whatever is pinned to the bottom of the screen: it reads `--shell-bottom-inset`\n * (set by `MobileTabBar` and the chat composer, see `useShellBottomInset`) plus the device\n * safe area, so it never covers the tab bar or the composer. In the start corner it also clears a\n * docked `Sidebar` (`--shell-start-inset`). Both controls are 44px tall on a phone.\n */\nexport function InstallPrompt({\n placement = 'start',\n labels,\n className,\n 'data-testid': testId,\n ...options\n}: InstallPromptProps) {\n const l = { ...DEFAULT_INSTALL_PROMPT_LABELS, ...labels }\n const install = useInstallPrompt(options)\n const [showSteps, setShowSteps] = useState(false)\n\n const isOffer = install.canPrompt || install.isIos\n if (install.isInstalled || install.isDismissed || !isOffer) return null\n\n const appName = options.appName ?? 'this app'\n const onInstall = async () => {\n if (install.canPrompt) await install.promptInstall()\n else setShowSteps((open) => !open)\n }\n\n return (\n <div\n data-slot=\"install-prompt\"\n data-testid={testIdOr(testId, { testId: 'install-app-prompt' })}\n className={cn(\n 'fixed z-30 flex max-w-[calc(100vw-1.5rem)] flex-col gap-2',\n // Above the bottom bars (tab bar / composer) and the home indicator on a phone, a plain\n // corner offset from `sm` up where the tab bar is gone.\n 'bottom-[calc(max(var(--shell-bottom-inset,0px),env(safe-area-inset-bottom,0px))+0.75rem)] sm:bottom-[calc(env(safe-area-inset-bottom,0px)+0.75rem)]',\n // From `sm` up, clear of a docked sidebar (its footer holds the account menu).\n placement === 'start'\n ? 'left-3 items-start sm:left-[calc(var(--shell-start-inset,0px)+0.75rem)]'\n : 'right-3 items-end',\n className\n )}\n >\n {showSteps && (\n <div\n data-slot=\"install-prompt-steps\"\n className=\"w-72 max-w-full rounded-lg border border-border bg-card p-3 text-sm text-card-foreground shadow-lg\"\n >\n <p className=\"font-medium\">{install.instructions.heading}</p>\n <ol className=\"mt-2 list-decimal space-y-1 pl-5 text-muted-foreground\">\n {install.instructions.steps.map((step) => (\n <li key={step}>{step}</li>\n ))}\n </ol>\n </div>\n )}\n <div className=\"inline-flex items-center rounded-full border border-border bg-card/95 text-foreground shadow-sm backdrop-blur\">\n <button\n type=\"button\"\n onClick={() => void onInstall()}\n aria-label={l.installAs.replace('{app}', appName)}\n aria-expanded={install.canPrompt ? undefined : showSteps}\n data-slot=\"install-prompt-action\"\n className=\"inline-flex min-h-11 items-center gap-1.5 rounded-full pl-4 pr-2 text-xs font-medium transition-colors hover:bg-accent sm:min-h-9 sm:pl-3\"\n >\n <Download className=\"size-3.5\" aria-hidden=\"true\" />\n {l.install}\n </button>\n <button\n type=\"button\"\n onClick={install.dismiss}\n aria-label={l.dismiss}\n data-slot=\"install-prompt-dismiss\"\n className=\"inline-flex size-11 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground sm:size-9\"\n >\n <X className=\"size-3.5\" aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n )\n}\n","import { CheckCircle2, Loader2, TriangleAlert } from 'lucide-react'\nimport type { StatusRowTone } from './StatusRow'\n\nexport const STATUS_ROW_BASE_CLASS =\n 'flex items-center gap-2 rounded-md text-sm font-medium transition-colors hover:brightness-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11'\n\nexport const STATUS_ROW_TONES: Record<\n StatusRowTone,\n { className: string; Icon: typeof Loader2; spin?: boolean }\n> = {\n progress: { className: 'bg-muted text-foreground', Icon: Loader2, spin: true },\n success: { className: 'bg-green-bg text-green-text', Icon: CheckCircle2 },\n error: { className: 'bg-red-bg text-red-text', Icon: TriangleAlert },\n}\n","import type { ReactNode } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { STATUS_ROW_BASE_CLASS, STATUS_ROW_TONES } from './status-row-styles'\n\nexport type StatusRowTone = 'progress' | 'success' | 'error'\n\nexport interface StatusRowProps {\n tone: StatusRowTone\n /** e.g. \"Processing 3 files…\". Always the accessible name; hidden visually when `compact`. */\n label: string\n /** Opens the thing the status is about (the processing panel). */\n onClick: () => void\n /** Icon-only (the collapsed rail). */\n compact?: boolean\n /** Replaces the tone's default glyph. */\n icon?: ReactNode\n 'data-testid'?: string\n}\n\n/**\n * A live status line for the sidebar footer: a spinner and a short sentence that opens the\n * thing it reports on. The host renders it ONLY while the state is relevant (work running,\n * something failed), so a quiet app shows nothing. Announced politely to screen readers.\n */\nexport function StatusRow({\n tone,\n label,\n onClick,\n compact = false,\n icon,\n 'data-testid': testId,\n}: StatusRowProps) {\n const { className, Icon, spin } = STATUS_ROW_TONES[tone]\n return (\n <div role=\"status\" data-slot=\"status-row\" className={cn(compact && 'flex justify-center')}>\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n title={label}\n data-testid={testId}\n data-tone={tone}\n className={cn(\n STATUS_ROW_BASE_CLASS,\n compact ? 'size-9 justify-center pointer-coarse:size-11' : 'w-full px-2.5 py-1.5',\n className\n )}\n >\n {icon ?? (\n <Icon\n className={cn('size-4 shrink-0', spin && 'animate-spin motion-reduce:animate-none')}\n />\n )}\n {!compact && <span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>}\n </button>\n </div>\n )\n}\n\n/** Short live state at a navigation row's right edge, replacing inventory counts. */\nexport function StatusBadge({\n tone,\n label,\n onClick,\n onDismiss,\n 'data-testid': testId,\n}: {\n tone: StatusRowTone\n label: string\n onClick?: () => void\n onDismiss?: () => void\n 'data-testid'?: string\n}) {\n const className = cn(\n 'rounded-md px-1.5 py-0.5 text-xs font-medium whitespace-nowrap',\n STATUS_ROW_TONES[tone].className\n )\n return (\n <span\n role=\"status\"\n className={cn(\n 'ml-auto inline-flex items-center rounded-md',\n STATUS_ROW_TONES[tone].className\n )}\n data-testid={testId}\n data-tone={tone}\n >\n {onClick ? (\n <button\n type=\"button\"\n title={label}\n className={className}\n onClick={(event) => {\n event.stopPropagation()\n onClick()\n }}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {label}\n </button>\n ) : (\n <span className={className}>{label}</span>\n )}\n {onDismiss && (\n <button\n type=\"button\"\n aria-label={`Dismiss ${label}`}\n title=\"Dismiss\"\n className=\"mr-1 rounded-sm p-0.5 opacity-60 hover:opacity-100 focus-visible:ring-2 focus-visible:ring-ring\"\n onClick={(event) => {\n event.stopPropagation()\n onDismiss()\n }}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <X className=\"size-3\" />\n </button>\n )}\n </span>\n )\n}\n","import { RefreshCw, TriangleAlert, WifiOff } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { SidebarRowHoverContext } from './Sidebar'\nimport { SidebarRowAction } from './SidebarRowAction'\n\nexport type OfflinePillTone = 'offline' | 'failed' | 'syncing'\n\n/** Fixed strings of the offline pill. */\nexport interface OfflinePillLabels {\n reconnect: string\n}\n\nexport const DEFAULT_OFFLINE_PILL_LABELS: OfflinePillLabels = {\n reconnect: 'Reconnect',\n}\n\nexport interface OfflinePillProps {\n tone: OfflinePillTone\n /** e.g. \"Offline · 3 pending\", \"2 failed to sync\", \"Syncing 4…\". */\n label: string\n /** Icon-only (the collapsed rail / app bar). */\n compact?: boolean\n /** Opens the pending-changes list. */\n onOpen: () => void\n /** Offered beside the pill (only when not compact); pass it only while it can do something. */\n onReconnect?: () => void\n labels?: Partial<OfflinePillLabels>\n /** Pill button id (default `offline-sync-status`). */\n 'data-testid'?: string\n /** Reconnect button id (default `offline-reconnect-button`). */\n reconnectTestId?: string\n}\n\nconst TONES: Record<OfflinePillTone, { className: string; Icon: typeof WifiOff }> = {\n offline: { className: 'bg-yellow-bg text-yellow-text', Icon: WifiOff },\n failed: { className: 'bg-red-bg text-red-text', Icon: TriangleAlert },\n syncing: { className: 'bg-blue-bg text-blue-text', Icon: RefreshCw },\n}\n\n/**\n * Connection + sync indicator: a status pill that opens the pending-changes list, plus an\n * optional Reconnect button beside it. The app renders it only when there is something to say\n * (offline, or changes waiting/failing), so online-and-synced stays clean.\n */\nexport function OfflinePill({\n tone,\n label,\n compact = false,\n onOpen,\n onReconnect,\n labels,\n 'data-testid': testId,\n reconnectTestId,\n}: OfflinePillProps) {\n const { className, Icon } = TONES[tone]\n return (\n <div\n className={cn('flex items-center gap-1', compact && 'justify-center')}\n data-slot=\"offline-pill\"\n >\n <button\n type=\"button\"\n data-testid={testIdOr(testId, { testId: 'offline-sync-status' })}\n aria-label={label}\n title={label}\n onClick={onOpen}\n className={cn(\n 'flex min-w-0 flex-1 cursor-pointer items-center gap-2 rounded-md px-2.5 py-1.5 text-sm font-medium transition-colors hover:brightness-95 pointer-coarse:min-h-11',\n compact && 'flex-none justify-center',\n className\n )}\n >\n <Icon className={cn('size-4 shrink-0', tone === 'syncing' && 'animate-spin')} />\n {!compact && <span className=\"truncate\">{label}</span>}\n </button>\n {!compact && onReconnect && (\n // Forced visible (context true): there is no row to hover.\n <SidebarRowHoverContext.Provider value={true}>\n <SidebarRowAction\n label={labels?.reconnect ?? DEFAULT_OFFLINE_PILL_LABELS.reconnect}\n onClick={onReconnect}\n data-testid={testIdOr(reconnectTestId, { testId: 'offline-reconnect-button' })}\n >\n <RefreshCw className=\"size-5\" />\n </SidebarRowAction>\n </SidebarRowHoverContext.Provider>\n )}\n </div>\n )\n}\n","import { MousePointerClick, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\n\n/** Fixed strings of the remote-control pill. */\nexport interface RemoteControlPillLabels {\n /** The disable button (the `disableLabel` prop wins). */\n turnOffRemoteControl: string\n}\n\nexport const DEFAULT_REMOTE_CONTROL_PILL_LABELS: RemoteControlPillLabels = {\n turnOffRemoteControl: 'Turn off remote control',\n}\n\nexport interface RemoteControlPillProps {\n /** A run is actively driving the screen (tinted + pulsing). */\n isActive: boolean\n label: string\n onDisable: () => void\n disableLabel?: string\n labels?: Partial<RemoteControlPillLabels>\n /** Root id (default `remote-control-indicator`). */\n 'data-testid'?: string\n /** Disable button id (default `remote-control-indicator-disable`). */\n disableTestId?: string\n}\n\n/**\n * Persistent, unobtrusive status pill shown while remote control is on or a run is executing,\n * with a one-click disable. The app decides when to mount it.\n */\nexport function RemoteControlPill({\n isActive,\n label,\n onDisable,\n disableLabel: disableLabelProp,\n labels,\n 'data-testid': testId,\n disableTestId,\n}: RemoteControlPillProps) {\n const disableLabel =\n disableLabelProp ??\n labels?.turnOffRemoteControl ??\n DEFAULT_REMOTE_CONTROL_PILL_LABELS.turnOffRemoteControl\n return (\n <div\n data-slot=\"remote-control-pill\"\n data-testid={testIdOr(testId, { testId: 'remote-control-indicator' })}\n className={cn(\n 'flex min-w-0 max-w-full items-center gap-1.5 rounded-full py-1 pl-2.5 pr-1 text-xs font-medium',\n isActive ? 'bg-accent text-accent-foreground' : 'bg-muted text-muted-foreground'\n )}\n >\n <MousePointerClick className={cn('size-3.5 shrink-0', isActive && 'animate-pulse')} />\n <span className=\"min-w-0 max-w-[16rem] truncate\">{label}</span>\n <button\n type=\"button\"\n onClick={onDisable}\n title={disableLabel}\n aria-label={disableLabel}\n data-testid={testIdOr(disableTestId, { testId: 'remote-control-indicator-disable' })}\n className=\"flex size-5 shrink-0 items-center justify-center rounded-full transition-colors hover:bg-foreground/10 hover:text-foreground pointer-coarse:size-8\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { ChevronLeft, ChevronRight, Lightbulb, Pencil, X } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\n\n/** Fixed strings of the tip card. */\nexport interface TipCardLabels {\n /** Default CTA text (the `ctaLabel` prop wins). */\n showMe: string\n previousTip: string\n nextTip: string\n editTip: string\n /** The card's heading and accessible name. */\n tip: string\n /** The dismiss button: it turns tips off (they come back from the account menu). */\n hideTips: string\n /** \"1 of 3\". */\n position: (index: number, count: number) => string\n}\n\nexport const DEFAULT_TIP_CARD_LABELS: TipCardLabels = {\n showMe: 'Show me',\n previousTip: 'Previous tip',\n nextTip: 'Next tip',\n editTip: 'Edit tip',\n tip: 'Tip',\n hideTips: 'Hide tips',\n position: (index, count) => `${index} of ${count}`,\n}\n\nexport interface TipCardProps {\n /** The tip text: one sentence. */\n message: ReactNode\n /** Which tip is showing (0-based) out of `count`; the pager appears when `count` > 1. */\n index?: number\n count?: number\n onPrev?: () => void\n onNext?: () => void\n /** The single primary action; omit when the tip has none. */\n ctaLabel?: string\n onCta?: () => void\n /** Turns tips off. The card is dismissible so it never becomes permanent furniture. */\n onDismiss?: () => void\n /** Dev-only edit affordance: the host passes it only in development builds. */\n onEdit?: () => void\n /** Hover pauses the host's tip rotation (desktop enhancement). */\n onHoverChange?: (hovered: boolean) => void\n labels?: Partial<TipCardLabels>\n className?: string\n /** Card id (default `tip-row`). */\n testId?: string\n /** Control ids; defaults are the current ids. */\n testIds?: Partial<Record<'prev' | 'next' | 'cta' | 'edit' | 'dismiss', string>>\n}\n\nconst ICON_BUTTON =\n 'flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:size-11'\n\n/**\n * The Smart Tips card: a compact muted tile. Header (bulb, \"Tip\", dismiss), one sentence, then\n * ONE primary action with a quiet \"n of m\" pager. It is shown only while tips are on and a tip\n * applies; the host owns which tip is current, rotation and the on/off preference.\n */\nexport function TipCard({\n message,\n index = 0,\n count = 1,\n onPrev,\n onNext,\n ctaLabel,\n onCta,\n onDismiss,\n onEdit,\n onHoverChange,\n labels,\n className,\n testId,\n testIds,\n}: TipCardProps) {\n const l = { ...DEFAULT_TIP_CARD_LABELS, ...labels }\n const hasMany = count > 1\n\n return (\n <section\n data-slot=\"tip-card\"\n aria-label={l.tip}\n className={cn('min-w-0 rounded-lg bg-muted p-3 text-sm', className)}\n onMouseEnter={() => onHoverChange?.(true)}\n onMouseLeave={() => onHoverChange?.(false)}\n data-testid={testIdOr(testId, { testId: 'tip-row' })}\n >\n <div className=\"-my-1 flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n <Lightbulb className=\"size-4 shrink-0 text-primary\" aria-hidden />\n <span>{l.tip}</span>\n <span className=\"-mr-1.5 ml-auto flex items-center\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={onEdit}\n aria-label={l.editTip}\n title={l.editTip}\n className={cn(ICON_BUTTON, 'text-red-text hover:bg-red-bg hover:text-red-text')}\n data-testid={testIdOr(testIds?.edit, { testId: 'tip-edit' })}\n >\n <Pencil className=\"size-3.5\" />\n </button>\n )}\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label={l.hideTips}\n title={l.hideTips}\n className={ICON_BUTTON}\n data-testid={testIdOr(testIds?.dismiss, { testId: 'tip-dismiss' })}\n >\n <X className=\"size-4\" />\n </button>\n )}\n </span>\n </div>\n <p className=\"mt-2 text-foreground\">{message}</p>\n {(onCta || hasMany) && (\n <div className=\"mt-3 flex items-center justify-between gap-2\">\n {onCta ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onCta}\n className=\"font-medium text-primary\"\n data-testid={testIdOr(testIds?.cta, { testId: 'page-header-info-cta' })}\n >\n {ctaLabel ?? l.showMe}\n </Button>\n ) : (\n <span />\n )}\n {hasMany && (\n <span className=\"-mr-1.5 flex items-center text-xs text-muted-foreground\">\n <button\n type=\"button\"\n onClick={onPrev}\n aria-label={l.previousTip}\n title={l.previousTip}\n className={ICON_BUTTON}\n data-testid={testIdOr(testIds?.prev, { testId: 'tip-prev' })}\n >\n <ChevronLeft className=\"size-4\" />\n </button>\n <span className=\"min-w-10 text-center tabular-nums\" aria-live=\"polite\">\n {l.position(index + 1, count)}\n </span>\n <button\n type=\"button\"\n onClick={onNext}\n aria-label={l.nextTip}\n title={l.nextTip}\n className={ICON_BUTTON}\n data-testid={testIdOr(testIds?.next, { testId: 'tip-next' })}\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </span>\n )}\n </div>\n )}\n </section>\n )\n}\n","import type { ReactNode } from 'react'\nimport { Info, Lightbulb, X } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\n\nexport type InfoBarVariant = 'info' | 'warning' | 'success' | 'hint'\n\nconst VARIANT_TONE: Record<InfoBarVariant, string> = {\n info: 'bg-blue-bg text-primary border-blue-border',\n warning: 'bg-yellow-bg text-yellow-text border-yellow-border',\n success: 'bg-green-bg text-green-text border-green-border',\n hint: 'bg-blue-bg text-foreground border-blue-border',\n}\n\nexport interface InfoBarProps {\n message: ReactNode\n variant?: InfoBarVariant\n /** Suppress the leading variant icon (e.g. tips render their own \"Tip:\" label). */\n hideIcon?: boolean\n /** Element pinned to the right of the bar (e.g. a reward balance). */\n rightSlot?: ReactNode\n cta?: { label: string; onClick: () => void; icon?: ReactNode }\n onDismiss?: () => void\n dismissLabel?: string\n className?: string\n}\n\n/** Full-width page banner: icon, message, optional right slot, CTA and dismiss. */\nexport function InfoBar({\n message,\n variant = 'info',\n hideIcon,\n rightSlot,\n cta,\n onDismiss,\n dismissLabel = 'Dismiss',\n className,\n}: InfoBarProps) {\n const VariantIcon = variant === 'hint' ? Lightbulb : Info\n return (\n <div\n className={cn('relative z-10 flex w-full items-center pt-1', className)}\n data-slot=\"info-bar\"\n >\n <div\n className={cn(\n 'flex w-full flex-wrap items-center gap-3 rounded-md border px-3 py-[7px]',\n VARIANT_TONE[variant]\n )}\n data-testid=\"page-header-info-box\"\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n {!hideIcon && <VariantIcon className=\"hidden size-4 shrink-0 sm:block\" />}\n <div className=\"min-w-0 flex-1 text-sm\">{message}</div>\n </div>\n <div className=\"flex w-full items-center gap-2 sm:ml-auto sm:w-auto\">\n {rightSlot}\n {cta && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={cta.onClick}\n className=\"h-8 flex-1 shrink-0 sm:flex-initial pointer-coarse:h-11\"\n data-testid=\"page-header-info-cta\"\n >\n {cta.icon && <span className=\"mr-1\">{cta.icon}</span>}\n {cta.label}\n </Button>\n )}\n {onDismiss && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onDismiss}\n aria-label={dismissLabel}\n className=\"size-8 shrink-0 p-0 hover:bg-foreground/5 pointer-coarse:size-11\"\n data-testid=\"page-header-info-dismiss\"\n >\n <X className=\"size-4\" />\n </Button>\n )}\n </div>\n </div>\n </div>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nconst SECONDARY_WIDTH = {\n sm: '@3xl:w-72',\n md: '@3xl:w-80',\n lg: '@3xl:w-96',\n xl: '@3xl:w-[28rem]',\n} as const\n\nexport interface SplitLayoutProps {\n /** The main pane (the detail, the form, the transcript): takes the remaining width. */\n primary: ReactNode\n /** The side pane (the list, the preview, the launcher): fixed width beside, full width below. */\n secondary: ReactNode\n /** Width of the side pane once beside the main one. Default `md` (20rem). */\n secondarySize?: keyof typeof SECONDARY_WIDTH\n /** Which side the secondary pane sits on once side by side. Default `end`. */\n secondaryPosition?: 'start' | 'end'\n /** When stacked, show the secondary pane first. Default false (primary first). */\n secondaryFirstWhenStacked?: boolean\n className?: string\n primaryClassName?: string\n secondaryClassName?: string\n testId?: string\n}\n\n/**\n * Two panes (list and detail, form and preview) that stack by the width of their CONTAINER,\n * not the viewport: side by side from 48rem of container width, stacked below. Inside\n * `Shell.Content` / `PageContainer` (both are containers) an open dock or a narrow window\n * therefore stacks the panes instead of squeezing the main one to a sliver. Every pane has\n * `min-w-0`, so long words and wide tables shrink instead of stretching the grid.\n */\nexport function SplitLayout({\n primary,\n secondary,\n secondarySize = 'md',\n secondaryPosition = 'end',\n secondaryFirstWhenStacked = false,\n className,\n primaryClassName,\n secondaryClassName,\n testId = 'split-layout',\n}: SplitLayoutProps) {\n const secondaryAtStart = secondaryPosition === 'start'\n return (\n <div\n data-slot=\"split-layout\"\n data-testid={testId}\n className={cn('flex flex-col gap-6 @3xl:flex-row @3xl:items-start', className)}\n >\n <div\n data-slot=\"split-primary\"\n className={cn(\n 'min-w-0 @3xl:flex-1',\n secondaryFirstWhenStacked && 'order-2',\n secondaryAtStart ? '@3xl:order-2' : '@3xl:order-1',\n primaryClassName\n )}\n >\n {primary}\n </div>\n <div\n data-slot=\"split-secondary\"\n className={cn(\n 'min-w-0 @3xl:shrink-0',\n SECONDARY_WIDTH[secondarySize],\n secondaryFirstWhenStacked && 'order-1',\n secondaryAtStart ? '@3xl:order-1' : '@3xl:order-2',\n secondaryClassName\n )}\n >\n {secondary}\n </div>\n </div>\n )\n}\n"]}
|