@shipfox/client-shell 14.0.0 → 14.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"auth-shell.d.ts","sourceRoot":"","sources":["../../src/components/auth-shell.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,WAAW,EAAO,MAAM,8BAA8B,CAAC;AAC5E,OAAO,KAAK,EAAC,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAC,MAAM,OAAO,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAChE,UAAU,CAAC,EAAE,GAAG,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,UAAU,GACX,EAAE,cAAc,+BA0ChB;AAED,wBAAgB,WAAW,CAAC,EAAC,QAAQ,EAAC,EAAE,iBAAiB,+BAExD"}
1
+ {"version":3,"file":"auth-shell.d.ts","sourceRoot":"","sources":["../../src/components/auth-shell.tsx"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,WAAW,EAAO,MAAM,8BAA8B,CAAC;AAC5E,OAAO,KAAK,EAAC,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAC,MAAM,OAAO,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAChE,UAAU,CAAC,EAAE,GAAG,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,UAAU,GACX,EAAE,cAAc,+BA4ChB;AAED,wBAAgB,WAAW,CAAC,EAAC,QAAQ,EAAC,EAAE,iBAAiB,+BAExD"}
@@ -3,7 +3,7 @@ import { Icon } from '@shipfox/react-ui/icon';
3
3
  import { Header, Text } from '@shipfox/react-ui/typography';
4
4
  export function AuthShell({ title, description, children, className, headingProps, headingRef }) {
5
5
  return /*#__PURE__*/ _jsxs("main", {
6
- className: "relative flex min-h-screen items-center justify-center overflow-hidden bg-background-subtle-base px-24 py-32 max-[520px]:items-start max-[520px]:px-20 max-[520px]:pb-32 max-[520px]:pt-56",
6
+ className: "relative flex min-h-screen items-center justify-center overflow-hidden bg-background-subtle-base px-frame py-frame max-[520px]:items-start max-[520px]:px-row max-[520px]:pt-[56px]",
7
7
  children: [
8
8
  /*#__PURE__*/ _jsx("div", {
9
9
  className: "pointer-events-none absolute left-1/2 top-0 h-[380px] w-full max-w-[880px] -translate-x-1/2 -translate-y-[120px] opacity-55 max-[520px]:-translate-y-[170px] max-[520px]:opacity-35",
@@ -17,21 +17,21 @@ export function AuthShell({ title, description, children, className, headingProp
17
17
  })
18
18
  }),
19
19
  /*#__PURE__*/ _jsxs("section", {
20
- className: className ?? 'relative flex w-full max-w-[384px] flex-col items-stretch gap-28',
20
+ className: className ?? 'relative flex w-full max-w-[384px] flex-col items-stretch gap-region',
21
21
  "aria-labelledby": "auth-title",
22
22
  children: [
23
23
  /*#__PURE__*/ _jsxs("div", {
24
- className: "flex flex-col items-center gap-16",
24
+ className: "flex flex-col items-center gap-group",
25
25
  children: [
26
26
  /*#__PURE__*/ _jsx("div", {
27
- className: "flex size-64 items-center justify-center rounded-12 border border-border-neutral-base bg-background-neutral-base p-10 shadow-button-neutral",
27
+ className: "flex size-64 items-center justify-center rounded-12 border border-border-neutral-base bg-background-neutral-base p-tight shadow-button-neutral",
28
28
  children: /*#__PURE__*/ _jsx(Icon, {
29
29
  name: "shipfox",
30
30
  className: "size-42 text-background-highlight-interactive"
31
31
  })
32
32
  }),
33
33
  /*#__PURE__*/ _jsxs("div", {
34
- className: "flex min-w-[128px] flex-col items-center gap-4 text-center",
34
+ className: "flex min-w-[128px] flex-col items-center gap-tight text-center",
35
35
  children: [
36
36
  /*#__PURE__*/ _jsx(Header, {
37
37
  id: "auth-title",
@@ -60,7 +60,7 @@ export function AuthShell({ title, description, children, className, headingProp
60
60
  }
61
61
  export function AuthActions({ children }) {
62
62
  return /*#__PURE__*/ _jsx("div", {
63
- className: "flex flex-col gap-20",
63
+ className: "flex flex-col gap-section",
64
64
  children: children
65
65
  });
66
66
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/auth-shell.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {Header, type HeaderProps, Text} from '@shipfox/react-ui/typography';\nimport type {PropsWithChildren, ReactNode, Ref} from 'react';\n\nexport interface AuthShellProps {\n title: string;\n description: string;\n children: ReactNode;\n className?: string;\n headingProps?: Omit<HeaderProps, 'children' | 'id'> | undefined;\n headingRef?: Ref<HTMLHeadingElement> | undefined;\n}\n\nexport function AuthShell({\n title,\n description,\n children,\n className,\n headingProps,\n headingRef,\n}: AuthShellProps) {\n return (\n <main className=\"relative flex min-h-screen items-center justify-center overflow-hidden bg-background-subtle-base px-24 py-32 max-[520px]:items-start max-[520px]:px-20 max-[520px]:pb-32 max-[520px]:pt-56\">\n <div\n className=\"pointer-events-none absolute left-1/2 top-0 h-[380px] w-full max-w-[880px] -translate-x-1/2 -translate-y-[120px] opacity-55 max-[520px]:-translate-y-[170px] max-[520px]:opacity-35\"\n aria-hidden=\"true\"\n style={{\n maskImage:\n 'radial-gradient(ellipse 85% 100% at 50% 0%, #000 0%, #000 24%, transparent 78%)',\n WebkitMaskImage:\n 'radial-gradient(ellipse 85% 100% at 50% 0%, #000 0%, #000 24%, transparent 78%)',\n }}\n >\n <div className=\"h-full w-full bg-[radial-gradient(circle,rgba(230,62,0,0.48)_1.6px,transparent_1.8px)] bg-[length:44px_44px]\" />\n </div>\n <section\n className={className ?? 'relative flex w-full max-w-[384px] flex-col items-stretch gap-28'}\n aria-labelledby=\"auth-title\"\n >\n <div className=\"flex flex-col items-center gap-16\">\n <div className=\"flex size-64 items-center justify-center rounded-12 border border-border-neutral-base bg-background-neutral-base p-10 shadow-button-neutral\">\n <Icon name=\"shipfox\" className=\"size-42 text-background-highlight-interactive\" />\n </div>\n <div className=\"flex min-w-[128px] flex-col items-center gap-4 text-center\">\n <Header\n id=\"auth-title\"\n variant=\"h1\"\n tabIndex={-1}\n {...headingProps}\n {...(headingRef ? ({ref: headingRef} as HeaderProps) : {})}\n >\n {title}\n </Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle\">\n {description}\n </Text>\n </div>\n </div>\n {children}\n </section>\n </main>\n );\n}\n\nexport function AuthActions({children}: PropsWithChildren) {\n return <div className=\"flex flex-col gap-20\">{children}</div>;\n}\n"],"names":["Icon","Header","Text","AuthShell","title","description","children","className","headingProps","headingRef","main","div","aria-hidden","style","maskImage","WebkitMaskImage","section","aria-labelledby","name","id","variant","tabIndex","ref","size","AuthActions"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,MAAM,EAAoBC,IAAI,QAAO,+BAA+B;AAY5E,OAAO,SAASC,UAAU,EACxBC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,SAAS,EACTC,YAAY,EACZC,UAAU,EACK;IACf,qBACE,MAACC;QAAKH,WAAU;;0BACd,KAACI;gBACCJ,WAAU;gBACVK,eAAY;gBACZC,OAAO;oBACLC,WACE;oBACFC,iBACE;gBACJ;0BAEA,cAAA,KAACJ;oBAAIJ,WAAU;;;0BAEjB,MAACS;gBACCT,WAAWA,aAAa;gBACxBU,mBAAgB;;kCAEhB,MAACN;wBAAIJ,WAAU;;0CACb,KAACI;gCAAIJ,WAAU;0CACb,cAAA,KAACP;oCAAKkB,MAAK;oCAAUX,WAAU;;;0CAEjC,MAACI;gCAAIJ,WAAU;;kDACb,KAACN;wCACCkB,IAAG;wCACHC,SAAQ;wCACRC,UAAU,CAAC;wCACV,GAAGb,YAAY;wCACf,GAAIC,aAAc;4CAACa,KAAKb;wCAAU,IAAoB,CAAC,CAAC;kDAExDL;;kDAEH,KAACF;wCAAKqB,MAAK;wCAAKhB,WAAU;kDACvBF;;;;;;oBAINC;;;;;AAIT;AAEA,OAAO,SAASkB,YAAY,EAAClB,QAAQ,EAAoB;IACvD,qBAAO,KAACK;QAAIJ,WAAU;kBAAwBD;;AAChD"}
1
+ {"version":3,"sources":["../../src/components/auth-shell.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {Header, type HeaderProps, Text} from '@shipfox/react-ui/typography';\nimport type {PropsWithChildren, ReactNode, Ref} from 'react';\n\nexport interface AuthShellProps {\n title: string;\n description: string;\n children: ReactNode;\n className?: string;\n headingProps?: Omit<HeaderProps, 'children' | 'id'> | undefined;\n headingRef?: Ref<HTMLHeadingElement> | undefined;\n}\n\nexport function AuthShell({\n title,\n description,\n children,\n className,\n headingProps,\n headingRef,\n}: AuthShellProps) {\n return (\n <main className=\"relative flex min-h-screen items-center justify-center overflow-hidden bg-background-subtle-base px-frame py-frame max-[520px]:items-start max-[520px]:px-row max-[520px]:pt-[56px]\">\n <div\n className=\"pointer-events-none absolute left-1/2 top-0 h-[380px] w-full max-w-[880px] -translate-x-1/2 -translate-y-[120px] opacity-55 max-[520px]:-translate-y-[170px] max-[520px]:opacity-35\"\n aria-hidden=\"true\"\n style={{\n maskImage:\n 'radial-gradient(ellipse 85% 100% at 50% 0%, #000 0%, #000 24%, transparent 78%)',\n WebkitMaskImage:\n 'radial-gradient(ellipse 85% 100% at 50% 0%, #000 0%, #000 24%, transparent 78%)',\n }}\n >\n <div className=\"h-full w-full bg-[radial-gradient(circle,rgba(230,62,0,0.48)_1.6px,transparent_1.8px)] bg-[length:44px_44px]\" />\n </div>\n <section\n className={\n className ?? 'relative flex w-full max-w-[384px] flex-col items-stretch gap-region'\n }\n aria-labelledby=\"auth-title\"\n >\n <div className=\"flex flex-col items-center gap-group\">\n <div className=\"flex size-64 items-center justify-center rounded-12 border border-border-neutral-base bg-background-neutral-base p-tight shadow-button-neutral\">\n <Icon name=\"shipfox\" className=\"size-42 text-background-highlight-interactive\" />\n </div>\n <div className=\"flex min-w-[128px] flex-col items-center gap-tight text-center\">\n <Header\n id=\"auth-title\"\n variant=\"h1\"\n tabIndex={-1}\n {...headingProps}\n {...(headingRef ? ({ref: headingRef} as HeaderProps) : {})}\n >\n {title}\n </Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle\">\n {description}\n </Text>\n </div>\n </div>\n {children}\n </section>\n </main>\n );\n}\n\nexport function AuthActions({children}: PropsWithChildren) {\n return <div className=\"flex flex-col gap-section\">{children}</div>;\n}\n"],"names":["Icon","Header","Text","AuthShell","title","description","children","className","headingProps","headingRef","main","div","aria-hidden","style","maskImage","WebkitMaskImage","section","aria-labelledby","name","id","variant","tabIndex","ref","size","AuthActions"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,MAAM,EAAoBC,IAAI,QAAO,+BAA+B;AAY5E,OAAO,SAASC,UAAU,EACxBC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,SAAS,EACTC,YAAY,EACZC,UAAU,EACK;IACf,qBACE,MAACC;QAAKH,WAAU;;0BACd,KAACI;gBACCJ,WAAU;gBACVK,eAAY;gBACZC,OAAO;oBACLC,WACE;oBACFC,iBACE;gBACJ;0BAEA,cAAA,KAACJ;oBAAIJ,WAAU;;;0BAEjB,MAACS;gBACCT,WACEA,aAAa;gBAEfU,mBAAgB;;kCAEhB,MAACN;wBAAIJ,WAAU;;0CACb,KAACI;gCAAIJ,WAAU;0CACb,cAAA,KAACP;oCAAKkB,MAAK;oCAAUX,WAAU;;;0CAEjC,MAACI;gCAAIJ,WAAU;;kDACb,KAACN;wCACCkB,IAAG;wCACHC,SAAQ;wCACRC,UAAU,CAAC;wCACV,GAAGb,YAAY;wCACf,GAAIC,aAAc;4CAACa,KAAKb;wCAAU,IAAoB,CAAC,CAAC;kDAExDL;;kDAEH,KAACF;wCAAKqB,MAAK;wCAAKhB,WAAU;kDACvBF;;;;;;oBAINC;;;;;AAIT;AAEA,OAAO,SAASkB,YAAY,EAAClB,QAAQ,EAAoB;IACvD,qBAAO,KAACK;QAAIJ,WAAU;kBAA6BD;;AACrD"}
@@ -28,7 +28,7 @@ export function MainLayout({ navigation, hideProjectNavigation = false }) {
28
28
  }) : /*#__PURE__*/ _jsx("main", {
29
29
  className: `flex-1 overflow-auto ${appContentHeight}`,
30
30
  children: /*#__PURE__*/ _jsx("div", {
31
- className: "max-w-[1120px] mx-auto px-24 py-32",
31
+ className: "max-w-[1120px] mx-auto px-frame py-frame",
32
32
  children: /*#__PURE__*/ _jsx(Outlet, {})
33
33
  })
34
34
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/main-layout.tsx"],"sourcesContent":["import {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Outlet, useMatches} from '@tanstack/react-router';\nimport type {NavTabEntry} from '#contract.js';\nimport {useMaybeActiveWorkspace} from '#runtime/active-workspace.js';\nimport {parseWorkspaceProjectParams, useRouteParams} from '#runtime/route-inputs.js';\nimport {NavBar} from './nav-bar.js';\nimport {NavTabs} from './nav-tabs.js';\n\ndeclare module '@tanstack/react-router' {\n interface StaticDataRouteOption {\n layout?: 'full-bleed';\n }\n}\n\nexport function MainLayout({\n navigation,\n hideProjectNavigation = false,\n}: {\n navigation: readonly NavTabEntry[];\n hideProjectNavigation?: boolean;\n}) {\n const workspace = useMaybeActiveWorkspace();\n const {projectSlug} = useRouteParams(parseWorkspaceProjectParams);\n const matches = useMatches();\n if (!workspace) return <FullPageLoader />;\n const fullBleed = matches.some((match) => match.staticData.layout === 'full-bleed');\n const appContentHeight = hideProjectNavigation\n ? '[--app-content-h:calc(100dvh_-_56px)]'\n : '[--app-content-h:calc(100dvh_-_96px)]';\n return (\n <div className=\"h-screen w-full flex flex-col bg-background-subtle-base\">\n <NavBar hideProjectNavigation={hideProjectNavigation} />\n {hideProjectNavigation ? undefined : (\n <NavTabs entries={navigation} scope={projectSlug ? 'project' : 'workspace'} />\n )}\n {fullBleed ? (\n <main className=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <Outlet />\n </main>\n ) : (\n <main className={`flex-1 overflow-auto ${appContentHeight}`}>\n <div className=\"max-w-[1120px] mx-auto px-24 py-32\">\n <Outlet />\n </div>\n </main>\n )}\n </div>\n );\n}\n"],"names":["FullPageLoader","Outlet","useMatches","useMaybeActiveWorkspace","parseWorkspaceProjectParams","useRouteParams","NavBar","NavTabs","MainLayout","navigation","hideProjectNavigation","workspace","projectSlug","matches","fullBleed","some","match","staticData","layout","appContentHeight","div","className","undefined","entries","scope","main"],"mappings":";AAAA,SAAQA,cAAc,QAAO,2BAA2B;AACxD,SAAQC,MAAM,EAAEC,UAAU,QAAO,yBAAyB;AAE1D,SAAQC,uBAAuB,QAAO,+BAA+B;AACrE,SAAQC,2BAA2B,EAAEC,cAAc,QAAO,2BAA2B;AACrF,SAAQC,MAAM,QAAO,eAAe;AACpC,SAAQC,OAAO,QAAO,gBAAgB;AAQtC,OAAO,SAASC,WAAW,EACzBC,UAAU,EACVC,wBAAwB,KAAK,EAI9B;IACC,MAAMC,YAAYR;IAClB,MAAM,EAACS,WAAW,EAAC,GAAGP,eAAeD;IACrC,MAAMS,UAAUX;IAChB,IAAI,CAACS,WAAW,qBAAO,KAACX;IACxB,MAAMc,YAAYD,QAAQE,IAAI,CAAC,CAACC,QAAUA,MAAMC,UAAU,CAACC,MAAM,KAAK;IACtE,MAAMC,mBAAmBT,wBACrB,0CACA;IACJ,qBACE,MAACU;QAAIC,WAAU;;0BACb,KAACf;gBAAOI,uBAAuBA;;YAC9BA,wBAAwBY,0BACvB,KAACf;gBAAQgB,SAASd;gBAAYe,OAAOZ,cAAc,YAAY;;YAEhEE,0BACC,KAACW;gBAAKJ,WAAU;0BACd,cAAA,KAACpB;+BAGH,KAACwB;gBAAKJ,WAAW,CAAC,qBAAqB,EAAEF,kBAAkB;0BACzD,cAAA,KAACC;oBAAIC,WAAU;8BACb,cAAA,KAACpB;;;;;AAMb"}
1
+ {"version":3,"sources":["../../src/components/main-layout.tsx"],"sourcesContent":["import {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Outlet, useMatches} from '@tanstack/react-router';\nimport type {NavTabEntry} from '#contract.js';\nimport {useMaybeActiveWorkspace} from '#runtime/active-workspace.js';\nimport {parseWorkspaceProjectParams, useRouteParams} from '#runtime/route-inputs.js';\nimport {NavBar} from './nav-bar.js';\nimport {NavTabs} from './nav-tabs.js';\n\ndeclare module '@tanstack/react-router' {\n interface StaticDataRouteOption {\n layout?: 'full-bleed';\n }\n}\n\nexport function MainLayout({\n navigation,\n hideProjectNavigation = false,\n}: {\n navigation: readonly NavTabEntry[];\n hideProjectNavigation?: boolean;\n}) {\n const workspace = useMaybeActiveWorkspace();\n const {projectSlug} = useRouteParams(parseWorkspaceProjectParams);\n const matches = useMatches();\n if (!workspace) return <FullPageLoader />;\n const fullBleed = matches.some((match) => match.staticData.layout === 'full-bleed');\n const appContentHeight = hideProjectNavigation\n ? '[--app-content-h:calc(100dvh_-_56px)]'\n : '[--app-content-h:calc(100dvh_-_96px)]';\n return (\n <div className=\"h-screen w-full flex flex-col bg-background-subtle-base\">\n <NavBar hideProjectNavigation={hideProjectNavigation} />\n {hideProjectNavigation ? undefined : (\n <NavTabs entries={navigation} scope={projectSlug ? 'project' : 'workspace'} />\n )}\n {fullBleed ? (\n <main className=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <Outlet />\n </main>\n ) : (\n <main className={`flex-1 overflow-auto ${appContentHeight}`}>\n <div className=\"max-w-[1120px] mx-auto px-frame py-frame\">\n <Outlet />\n </div>\n </main>\n )}\n </div>\n );\n}\n"],"names":["FullPageLoader","Outlet","useMatches","useMaybeActiveWorkspace","parseWorkspaceProjectParams","useRouteParams","NavBar","NavTabs","MainLayout","navigation","hideProjectNavigation","workspace","projectSlug","matches","fullBleed","some","match","staticData","layout","appContentHeight","div","className","undefined","entries","scope","main"],"mappings":";AAAA,SAAQA,cAAc,QAAO,2BAA2B;AACxD,SAAQC,MAAM,EAAEC,UAAU,QAAO,yBAAyB;AAE1D,SAAQC,uBAAuB,QAAO,+BAA+B;AACrE,SAAQC,2BAA2B,EAAEC,cAAc,QAAO,2BAA2B;AACrF,SAAQC,MAAM,QAAO,eAAe;AACpC,SAAQC,OAAO,QAAO,gBAAgB;AAQtC,OAAO,SAASC,WAAW,EACzBC,UAAU,EACVC,wBAAwB,KAAK,EAI9B;IACC,MAAMC,YAAYR;IAClB,MAAM,EAACS,WAAW,EAAC,GAAGP,eAAeD;IACrC,MAAMS,UAAUX;IAChB,IAAI,CAACS,WAAW,qBAAO,KAACX;IACxB,MAAMc,YAAYD,QAAQE,IAAI,CAAC,CAACC,QAAUA,MAAMC,UAAU,CAACC,MAAM,KAAK;IACtE,MAAMC,mBAAmBT,wBACrB,0CACA;IACJ,qBACE,MAACU;QAAIC,WAAU;;0BACb,KAACf;gBAAOI,uBAAuBA;;YAC9BA,wBAAwBY,0BACvB,KAACf;gBAAQgB,SAASd;gBAAYe,OAAOZ,cAAc,YAAY;;YAEhEE,0BACC,KAACW;gBAAKJ,WAAU;0BACd,cAAA,KAACpB;+BAGH,KAACwB;gBAAKJ,WAAW,CAAC,qBAAqB,EAAEF,kBAAkB;0BACzD,cAAA,KAACC;oBAAIC,WAAU;8BACb,cAAA,KAACpB;;;;;AAMb"}
@@ -9,7 +9,7 @@ export function NavBar({ hideProjectNavigation = false }) {
9
9
  const workspace = useActiveWorkspace();
10
10
  const { ProjectBreadcrumb } = useChrome();
11
11
  return /*#__PURE__*/ _jsxs("header", {
12
- className: "sticky top-0 z-30 h-56 px-16 flex items-center gap-12 bg-background-subtle-base border-b border-border-neutral-base shrink-0",
12
+ className: "sticky top-0 z-30 h-56 px-row flex items-center gap-cluster bg-background-subtle-base border-b border-border-neutral-base shrink-0",
13
13
  children: [
14
14
  /*#__PURE__*/ _jsx(Link, {
15
15
  to: "/",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/nav-bar.tsx"],"sourcesContent":["import {Logo} from '@shipfox/react-ui/logo';\nimport {Link} from '@tanstack/react-router';\nimport {useActiveWorkspace} from '#runtime/active-workspace.js';\nimport {useChrome} from '#runtime/chrome-context.js';\nimport {UserMenu} from './user-menu.js';\nimport {WorkspaceCrumb} from './workspace-crumb.js';\n\nexport function NavBar({hideProjectNavigation = false}: {hideProjectNavigation?: boolean}) {\n const workspace = useActiveWorkspace();\n const {ProjectBreadcrumb} = useChrome();\n return (\n <header className=\"sticky top-0 z-30 h-56 px-16 flex items-center gap-12 bg-background-subtle-base border-b border-border-neutral-base shrink-0\">\n <Link\n to=\"/\"\n aria-label=\"Shipfox home\"\n className=\"rounded-6 focus-visible:outline-none focus-visible:shadow-button-neutral-focus\"\n >\n {hideProjectNavigation ? (\n <>\n <Logo variant=\"mark\" alt=\"\" className=\"sm:hidden\" />\n <Logo variant=\"wordmark\" alt=\"\" className=\"hidden sm:block\" />\n </>\n ) : (\n <Logo variant=\"wordmark\" alt=\"\" />\n )}\n </Link>\n <span className=\"h-20 w-px bg-border-neutral-base\" aria-hidden=\"true\" />\n <WorkspaceCrumb workspace={workspace} compact={hideProjectNavigation} />\n {hideProjectNavigation ? undefined : (\n <>\n <span className=\"text-foreground-neutral-muted\" aria-hidden=\"true\">\n /\n </span>\n <ProjectBreadcrumb />\n </>\n )}\n <div className=\"flex-1\" />\n <UserMenu />\n </header>\n );\n}\n"],"names":["Logo","Link","useActiveWorkspace","useChrome","UserMenu","WorkspaceCrumb","NavBar","hideProjectNavigation","workspace","ProjectBreadcrumb","header","className","to","aria-label","variant","alt","span","aria-hidden","compact","undefined","div"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,kBAAkB,QAAO,+BAA+B;AAChE,SAAQC,SAAS,QAAO,6BAA6B;AACrD,SAAQC,QAAQ,QAAO,iBAAiB;AACxC,SAAQC,cAAc,QAAO,uBAAuB;AAEpD,OAAO,SAASC,OAAO,EAACC,wBAAwB,KAAK,EAAoC;IACvF,MAAMC,YAAYN;IAClB,MAAM,EAACO,iBAAiB,EAAC,GAAGN;IAC5B,qBACE,MAACO;QAAOC,WAAU;;0BAChB,KAACV;gBACCW,IAAG;gBACHC,cAAW;gBACXF,WAAU;0BAETJ,sCACC;;sCACE,KAACP;4BAAKc,SAAQ;4BAAOC,KAAI;4BAAGJ,WAAU;;sCACtC,KAACX;4BAAKc,SAAQ;4BAAWC,KAAI;4BAAGJ,WAAU;;;mCAG5C,KAACX;oBAAKc,SAAQ;oBAAWC,KAAI;;;0BAGjC,KAACC;gBAAKL,WAAU;gBAAmCM,eAAY;;0BAC/D,KAACZ;gBAAeG,WAAWA;gBAAWU,SAASX;;YAC9CA,wBAAwBY,0BACvB;;kCACE,KAACH;wBAAKL,WAAU;wBAAgCM,eAAY;kCAAO;;kCAGnE,KAACR;;;0BAGL,KAACW;gBAAIT,WAAU;;0BACf,KAACP;;;AAGP"}
1
+ {"version":3,"sources":["../../src/components/nav-bar.tsx"],"sourcesContent":["import {Logo} from '@shipfox/react-ui/logo';\nimport {Link} from '@tanstack/react-router';\nimport {useActiveWorkspace} from '#runtime/active-workspace.js';\nimport {useChrome} from '#runtime/chrome-context.js';\nimport {UserMenu} from './user-menu.js';\nimport {WorkspaceCrumb} from './workspace-crumb.js';\n\nexport function NavBar({hideProjectNavigation = false}: {hideProjectNavigation?: boolean}) {\n const workspace = useActiveWorkspace();\n const {ProjectBreadcrumb} = useChrome();\n return (\n <header className=\"sticky top-0 z-30 h-56 px-row flex items-center gap-cluster bg-background-subtle-base border-b border-border-neutral-base shrink-0\">\n <Link\n to=\"/\"\n aria-label=\"Shipfox home\"\n className=\"rounded-6 focus-visible:outline-none focus-visible:shadow-button-neutral-focus\"\n >\n {hideProjectNavigation ? (\n <>\n <Logo variant=\"mark\" alt=\"\" className=\"sm:hidden\" />\n <Logo variant=\"wordmark\" alt=\"\" className=\"hidden sm:block\" />\n </>\n ) : (\n <Logo variant=\"wordmark\" alt=\"\" />\n )}\n </Link>\n <span className=\"h-20 w-px bg-border-neutral-base\" aria-hidden=\"true\" />\n <WorkspaceCrumb workspace={workspace} compact={hideProjectNavigation} />\n {hideProjectNavigation ? undefined : (\n <>\n <span className=\"text-foreground-neutral-muted\" aria-hidden=\"true\">\n /\n </span>\n <ProjectBreadcrumb />\n </>\n )}\n <div className=\"flex-1\" />\n <UserMenu />\n </header>\n );\n}\n"],"names":["Logo","Link","useActiveWorkspace","useChrome","UserMenu","WorkspaceCrumb","NavBar","hideProjectNavigation","workspace","ProjectBreadcrumb","header","className","to","aria-label","variant","alt","span","aria-hidden","compact","undefined","div"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,kBAAkB,QAAO,+BAA+B;AAChE,SAAQC,SAAS,QAAO,6BAA6B;AACrD,SAAQC,QAAQ,QAAO,iBAAiB;AACxC,SAAQC,cAAc,QAAO,uBAAuB;AAEpD,OAAO,SAASC,OAAO,EAACC,wBAAwB,KAAK,EAAoC;IACvF,MAAMC,YAAYN;IAClB,MAAM,EAACO,iBAAiB,EAAC,GAAGN;IAC5B,qBACE,MAACO;QAAOC,WAAU;;0BAChB,KAACV;gBACCW,IAAG;gBACHC,cAAW;gBACXF,WAAU;0BAETJ,sCACC;;sCACE,KAACP;4BAAKc,SAAQ;4BAAOC,KAAI;4BAAGJ,WAAU;;sCACtC,KAACX;4BAAKc,SAAQ;4BAAWC,KAAI;4BAAGJ,WAAU;;;mCAG5C,KAACX;oBAAKc,SAAQ;oBAAWC,KAAI;;;0BAGjC,KAACC;gBAAKL,WAAU;gBAAmCM,eAAY;;0BAC/D,KAACZ;gBAAeG,WAAWA;gBAAWU,SAASX;;YAC9CA,wBAAwBY,0BACvB;;kCACE,KAACH;wBAAKL,WAAU;wBAAgCM,eAAY;kCAAO;;kCAGnE,KAACR;;;0BAGL,KAACW;gBAAIT,WAAU;;0BACf,KAACP;;;AAGP"}
@@ -7,7 +7,7 @@ export function NavTabs({ entries, scope }) {
7
7
  const reduced = useReducedMotion();
8
8
  const tabs = entries.filter((entry)=>entry.scope === scope);
9
9
  const projectScoped = scope === 'project';
10
- const tabClassName = `h-40 inline-flex shrink-0 items-center whitespace-nowrap px-4 ${projectScoped ? 'text-xs' : 'text-sm'} font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;
10
+ const tabClassName = `h-40 inline-flex shrink-0 items-center whitespace-nowrap px-tight ${projectScoped ? 'text-xs' : 'text-sm'} font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;
11
11
  const activeProps = {
12
12
  className: projectScoped ? 'border-b border-border-highlights-interactive text-foreground-neutral-base' : 'border-b-2 border-border-highlights-interactive text-foreground-neutral-base',
13
13
  'aria-selected': 'true'
@@ -19,7 +19,7 @@ export function NavTabs({ entries, scope }) {
19
19
  return /*#__PURE__*/ _jsx("div", {
20
20
  role: "tablist",
21
21
  "aria-label": `${scope === 'project' ? 'Project' : 'Workspace'} sections`,
22
- className: "sticky top-56 z-20 flex h-40 items-end gap-12 overflow-x-auto whitespace-nowrap border-b border-border-neutral-base bg-background-subtle-base px-16 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
22
+ className: "sticky top-56 z-20 flex h-40 items-end gap-cluster overflow-x-auto whitespace-nowrap border-b border-border-neutral-base bg-background-subtle-base px-row [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
23
23
  children: tabs.map((entry)=>/*#__PURE__*/ _jsx(Link, {
24
24
  to: entry.to,
25
25
  params: params,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/nav-tabs.tsx"],"sourcesContent":["import {Link} from '@tanstack/react-router';\nimport {useReducedMotion} from 'framer-motion';\nimport type {NavTabEntry} from '#contract.js';\nimport {parseWorkspaceProjectParams, useRouteParams} from '#runtime/route-inputs.js';\n\nexport function NavTabs({\n entries,\n scope,\n}: {\n entries: readonly NavTabEntry[];\n scope: NavTabEntry['scope'];\n}) {\n const params = useRouteParams(parseWorkspaceProjectParams);\n const reduced = useReducedMotion();\n const tabs = entries.filter((entry) => entry.scope === scope);\n const projectScoped = scope === 'project';\n const tabClassName = `h-40 inline-flex shrink-0 items-center whitespace-nowrap px-4 ${projectScoped ? 'text-xs' : 'text-sm'} font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;\n const activeProps = {\n className: projectScoped\n ? 'border-b border-border-highlights-interactive text-foreground-neutral-base'\n : 'border-b-2 border-border-highlights-interactive text-foreground-neutral-base',\n 'aria-selected': 'true' as const,\n };\n const inactiveProps = {\n className: `${projectScoped ? 'border-b' : 'border-b-2'} border-transparent text-foreground-neutral-subtle hover:text-foreground-neutral-base`,\n 'aria-selected': 'false' as const,\n };\n\n return (\n <div\n role=\"tablist\"\n aria-label={`${scope === 'project' ? 'Project' : 'Workspace'} sections`}\n className=\"sticky top-56 z-20 flex h-40 items-end gap-12 overflow-x-auto whitespace-nowrap border-b border-border-neutral-base bg-background-subtle-base px-16 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\"\n >\n {tabs.map((entry) => (\n <Link\n key={entry.id}\n to={entry.to as never}\n params={params as never}\n role=\"tab\"\n activeOptions={{exact: entry.exact ?? false}}\n activeProps={activeProps}\n inactiveProps={inactiveProps}\n className={tabClassName}\n >\n {entry.label}\n </Link>\n ))}\n </div>\n );\n}\n"],"names":["Link","useReducedMotion","parseWorkspaceProjectParams","useRouteParams","NavTabs","entries","scope","params","reduced","tabs","filter","entry","projectScoped","tabClassName","activeProps","className","inactiveProps","div","role","aria-label","map","to","activeOptions","exact","label","id"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,gBAAgB,QAAO,gBAAgB;AAE/C,SAAQC,2BAA2B,EAAEC,cAAc,QAAO,2BAA2B;AAErF,OAAO,SAASC,QAAQ,EACtBC,OAAO,EACPC,KAAK,EAIN;IACC,MAAMC,SAASJ,eAAeD;IAC9B,MAAMM,UAAUP;IAChB,MAAMQ,OAAOJ,QAAQK,MAAM,CAAC,CAACC,QAAUA,MAAML,KAAK,KAAKA;IACvD,MAAMM,gBAAgBN,UAAU;IAChC,MAAMO,eAAe,CAAC,8DAA8D,EAAED,gBAAgB,YAAY,UAAU,+BAA+B,EAAEJ,UAAU,KAAK,6BAA6B;IACzM,MAAMM,cAAc;QAClBC,WAAWH,gBACP,+EACA;QACJ,iBAAiB;IACnB;IACA,MAAMI,gBAAgB;QACpBD,WAAW,GAAGH,gBAAgB,aAAa,aAAa,qFAAqF,CAAC;QAC9I,iBAAiB;IACnB;IAEA,qBACE,KAACK;QACCC,MAAK;QACLC,cAAY,GAAGb,UAAU,YAAY,YAAY,YAAY,SAAS,CAAC;QACvES,WAAU;kBAETN,KAAKW,GAAG,CAAC,CAACT,sBACT,KAACX;gBAECqB,IAAIV,MAAMU,EAAE;gBACZd,QAAQA;gBACRW,MAAK;gBACLI,eAAe;oBAACC,OAAOZ,MAAMY,KAAK,IAAI;gBAAK;gBAC3CT,aAAaA;gBACbE,eAAeA;gBACfD,WAAWF;0BAEVF,MAAMa,KAAK;eATPb,MAAMc,EAAE;;AAcvB"}
1
+ {"version":3,"sources":["../../src/components/nav-tabs.tsx"],"sourcesContent":["import {Link} from '@tanstack/react-router';\nimport {useReducedMotion} from 'framer-motion';\nimport type {NavTabEntry} from '#contract.js';\nimport {parseWorkspaceProjectParams, useRouteParams} from '#runtime/route-inputs.js';\n\nexport function NavTabs({\n entries,\n scope,\n}: {\n entries: readonly NavTabEntry[];\n scope: NavTabEntry['scope'];\n}) {\n const params = useRouteParams(parseWorkspaceProjectParams);\n const reduced = useReducedMotion();\n const tabs = entries.filter((entry) => entry.scope === scope);\n const projectScoped = scope === 'project';\n const tabClassName = `h-40 inline-flex shrink-0 items-center whitespace-nowrap px-tight ${projectScoped ? 'text-xs' : 'text-sm'} font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;\n const activeProps = {\n className: projectScoped\n ? 'border-b border-border-highlights-interactive text-foreground-neutral-base'\n : 'border-b-2 border-border-highlights-interactive text-foreground-neutral-base',\n 'aria-selected': 'true' as const,\n };\n const inactiveProps = {\n className: `${projectScoped ? 'border-b' : 'border-b-2'} border-transparent text-foreground-neutral-subtle hover:text-foreground-neutral-base`,\n 'aria-selected': 'false' as const,\n };\n\n return (\n <div\n role=\"tablist\"\n aria-label={`${scope === 'project' ? 'Project' : 'Workspace'} sections`}\n className=\"sticky top-56 z-20 flex h-40 items-end gap-cluster overflow-x-auto whitespace-nowrap border-b border-border-neutral-base bg-background-subtle-base px-row [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\"\n >\n {tabs.map((entry) => (\n <Link\n key={entry.id}\n to={entry.to as never}\n params={params as never}\n role=\"tab\"\n activeOptions={{exact: entry.exact ?? false}}\n activeProps={activeProps}\n inactiveProps={inactiveProps}\n className={tabClassName}\n >\n {entry.label}\n </Link>\n ))}\n </div>\n );\n}\n"],"names":["Link","useReducedMotion","parseWorkspaceProjectParams","useRouteParams","NavTabs","entries","scope","params","reduced","tabs","filter","entry","projectScoped","tabClassName","activeProps","className","inactiveProps","div","role","aria-label","map","to","activeOptions","exact","label","id"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,gBAAgB,QAAO,gBAAgB;AAE/C,SAAQC,2BAA2B,EAAEC,cAAc,QAAO,2BAA2B;AAErF,OAAO,SAASC,QAAQ,EACtBC,OAAO,EACPC,KAAK,EAIN;IACC,MAAMC,SAASJ,eAAeD;IAC9B,MAAMM,UAAUP;IAChB,MAAMQ,OAAOJ,QAAQK,MAAM,CAAC,CAACC,QAAUA,MAAML,KAAK,KAAKA;IACvD,MAAMM,gBAAgBN,UAAU;IAChC,MAAMO,eAAe,CAAC,kEAAkE,EAAED,gBAAgB,YAAY,UAAU,+BAA+B,EAAEJ,UAAU,KAAK,6BAA6B;IAC7M,MAAMM,cAAc;QAClBC,WAAWH,gBACP,+EACA;QACJ,iBAAiB;IACnB;IACA,MAAMI,gBAAgB;QACpBD,WAAW,GAAGH,gBAAgB,aAAa,aAAa,qFAAqF,CAAC;QAC9I,iBAAiB;IACnB;IAEA,qBACE,KAACK;QACCC,MAAK;QACLC,cAAY,GAAGb,UAAU,YAAY,YAAY,YAAY,SAAS,CAAC;QACvES,WAAU;kBAETN,KAAKW,GAAG,CAAC,CAACT,sBACT,KAACX;gBAECqB,IAAIV,MAAMU,EAAE;gBACZd,QAAQA;gBACRW,MAAK;gBACLI,eAAe;oBAACC,OAAOZ,MAAMY,KAAK,IAAI;gBAAK;gBAC3CT,aAAaA;gBACbE,eAAeA;gBACfD,WAAWF;0BAEVF,MAAMa,KAAK;eATPb,MAAMc,EAAE;;AAcvB"}
@@ -3,7 +3,7 @@ import { Header, Text } from '@shipfox/react-ui/typography';
3
3
  import { Link } from '@tanstack/react-router';
4
4
  export function NotFoundPage() {
5
5
  return /*#__PURE__*/ _jsxs("main", {
6
- className: "mx-auto max-w-[960px] px-24 py-48",
6
+ className: "mx-auto max-w-[960px] px-frame py-[48px]",
7
7
  children: [
8
8
  /*#__PURE__*/ _jsx(Header, {
9
9
  variant: "h1",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/not-found-page.tsx"],"sourcesContent":["import {Header, Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\n\nexport function NotFoundPage() {\n return (\n <main className=\"mx-auto max-w-[960px] px-24 py-48\">\n <Header variant=\"h1\">Page not found</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n This Shipfox page does not exist.\n </Text>\n <Link to=\"/\">Go home</Link>\n </main>\n );\n}\n"],"names":["Header","Text","Link","NotFoundPage","main","className","variant","size","to"],"mappings":";AAAA,SAAQA,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,IAAI,QAAO,yBAAyB;AAE5C,OAAO,SAASC;IACd,qBACE,MAACC;QAAKC,WAAU;;0BACd,KAACL;gBAAOM,SAAQ;0BAAK;;0BACrB,KAACL;gBAAKM,MAAK;gBAAKF,WAAU;0BAAgC;;0BAG1D,KAACH;gBAAKM,IAAG;0BAAI;;;;AAGnB"}
1
+ {"version":3,"sources":["../../src/components/not-found-page.tsx"],"sourcesContent":["import {Header, Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\n\nexport function NotFoundPage() {\n return (\n <main className=\"mx-auto max-w-[960px] px-frame py-[48px]\">\n <Header variant=\"h1\">Page not found</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n This Shipfox page does not exist.\n </Text>\n <Link to=\"/\">Go home</Link>\n </main>\n );\n}\n"],"names":["Header","Text","Link","NotFoundPage","main","className","variant","size","to"],"mappings":";AAAA,SAAQA,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,IAAI,QAAO,yBAAyB;AAE5C,OAAO,SAASC;IACd,qBACE,MAACC;QAAKC,WAAU;;0BACd,KAACL;gBAAOM,SAAQ;0BAAK;;0BACrB,KAACL;gBAAKM,MAAK;gBAAKF,WAAU;0BAAgC;;0BAG1D,KAACH;gBAAKM,IAAG;0BAAI;;;;AAGnB"}
@@ -17,7 +17,7 @@ export function SettingsNav({ entries, scope }) {
17
17
  };
18
18
  return /*#__PURE__*/ _jsx("nav", {
19
19
  "aria-label": `${scope === 'workspace' ? 'Workspace' : 'Project'} settings`,
20
- className: "flex flex-col gap-4",
20
+ className: "flex flex-col gap-tight",
21
21
  children: scopedEntries.map((entry)=>{
22
22
  const to = `${settingsPath}/${entry.pathSegment}`;
23
23
  const active = Boolean(matchRoute({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/settings-nav.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Link, useMatchRoute} from '@tanstack/react-router';\nimport type {SettingsSectionEntry} from '#contract.js';\nimport {\n parseWorkspaceParams,\n parseWorkspaceProjectParams,\n useRouteParams,\n} from '#runtime/route-inputs.js';\n\nexport function SettingsNav({\n entries,\n scope,\n}: {\n entries: readonly SettingsSectionEntry[];\n scope: 'workspace' | 'project';\n}) {\n const params = useRouteParams((input): {workspaceSlug?: string; projectSlug?: string} =>\n scope === 'workspace' ? parseWorkspaceParams(input) : parseWorkspaceProjectParams(input),\n );\n const matchRoute = useMatchRoute();\n if (!params.workspaceSlug || (scope === 'project' && !params.projectSlug)) return null;\n const scopedEntries = entries.filter((entry) => (entry.scope ?? 'workspace') === scope);\n const settingsPath =\n scope === 'workspace'\n ? '/w/$workspaceSlug/settings'\n : '/w/$workspaceSlug/p/$projectSlug/settings';\n const paramsForLink =\n scope === 'workspace'\n ? {workspaceSlug: params.workspaceSlug}\n : {workspaceSlug: params.workspaceSlug, projectSlug: params.projectSlug};\n\n return (\n <nav\n aria-label={`${scope === 'workspace' ? 'Workspace' : 'Project'} settings`}\n className=\"flex flex-col gap-4\"\n >\n {scopedEntries.map((entry) => {\n const to = `${settingsPath}/${entry.pathSegment}`;\n const active = Boolean(matchRoute({to: to as never, params: paramsForLink as never}));\n return (\n <Button\n key={entry.id}\n asChild\n variant={active ? 'secondary' : 'transparent'}\n className=\"w-full justify-start\"\n >\n <Link\n to={to as never}\n params={paramsForLink as never}\n aria-current={active ? 'page' : undefined}\n >\n <Icon name={entry.icon} className=\"size-16\" />\n {entry.label}\n </Link>\n </Button>\n );\n })}\n </nav>\n );\n}\n"],"names":["Button","Icon","Link","useMatchRoute","parseWorkspaceParams","parseWorkspaceProjectParams","useRouteParams","SettingsNav","entries","scope","params","input","matchRoute","workspaceSlug","projectSlug","scopedEntries","filter","entry","settingsPath","paramsForLink","nav","aria-label","className","map","to","pathSegment","active","Boolean","asChild","variant","aria-current","undefined","name","icon","label","id"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,EAAEC,aAAa,QAAO,yBAAyB;AAE3D,SACEC,oBAAoB,EACpBC,2BAA2B,EAC3BC,cAAc,QACT,2BAA2B;AAElC,OAAO,SAASC,YAAY,EAC1BC,OAAO,EACPC,KAAK,EAIN;IACC,MAAMC,SAASJ,eAAe,CAACK,QAC7BF,UAAU,cAAcL,qBAAqBO,SAASN,4BAA4BM;IAEpF,MAAMC,aAAaT;IACnB,IAAI,CAACO,OAAOG,aAAa,IAAKJ,UAAU,aAAa,CAACC,OAAOI,WAAW,EAAG,OAAO;IAClF,MAAMC,gBAAgBP,QAAQQ,MAAM,CAAC,CAACC,QAAU,AAACA,CAAAA,MAAMR,KAAK,IAAI,WAAU,MAAOA;IACjF,MAAMS,eACJT,UAAU,cACN,+BACA;IACN,MAAMU,gBACJV,UAAU,cACN;QAACI,eAAeH,OAAOG,aAAa;IAAA,IACpC;QAACA,eAAeH,OAAOG,aAAa;QAAEC,aAAaJ,OAAOI,WAAW;IAAA;IAE3E,qBACE,KAACM;QACCC,cAAY,GAAGZ,UAAU,cAAc,cAAc,UAAU,SAAS,CAAC;QACzEa,WAAU;kBAETP,cAAcQ,GAAG,CAAC,CAACN;YAClB,MAAMO,KAAK,GAAGN,aAAa,CAAC,EAAED,MAAMQ,WAAW,EAAE;YACjD,MAAMC,SAASC,QAAQf,WAAW;gBAACY,IAAIA;gBAAad,QAAQS;YAAsB;YAClF,qBACE,KAACnB;gBAEC4B,OAAO;gBACPC,SAASH,SAAS,cAAc;gBAChCJ,WAAU;0BAEV,cAAA,MAACpB;oBACCsB,IAAIA;oBACJd,QAAQS;oBACRW,gBAAcJ,SAAS,SAASK;;sCAEhC,KAAC9B;4BAAK+B,MAAMf,MAAMgB,IAAI;4BAAEX,WAAU;;wBACjCL,MAAMiB,KAAK;;;eAXTjB,MAAMkB,EAAE;QAenB;;AAGN"}
1
+ {"version":3,"sources":["../../src/components/settings-nav.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Link, useMatchRoute} from '@tanstack/react-router';\nimport type {SettingsSectionEntry} from '#contract.js';\nimport {\n parseWorkspaceParams,\n parseWorkspaceProjectParams,\n useRouteParams,\n} from '#runtime/route-inputs.js';\n\nexport function SettingsNav({\n entries,\n scope,\n}: {\n entries: readonly SettingsSectionEntry[];\n scope: 'workspace' | 'project';\n}) {\n const params = useRouteParams((input): {workspaceSlug?: string; projectSlug?: string} =>\n scope === 'workspace' ? parseWorkspaceParams(input) : parseWorkspaceProjectParams(input),\n );\n const matchRoute = useMatchRoute();\n if (!params.workspaceSlug || (scope === 'project' && !params.projectSlug)) return null;\n const scopedEntries = entries.filter((entry) => (entry.scope ?? 'workspace') === scope);\n const settingsPath =\n scope === 'workspace'\n ? '/w/$workspaceSlug/settings'\n : '/w/$workspaceSlug/p/$projectSlug/settings';\n const paramsForLink =\n scope === 'workspace'\n ? {workspaceSlug: params.workspaceSlug}\n : {workspaceSlug: params.workspaceSlug, projectSlug: params.projectSlug};\n\n return (\n <nav\n aria-label={`${scope === 'workspace' ? 'Workspace' : 'Project'} settings`}\n className=\"flex flex-col gap-tight\"\n >\n {scopedEntries.map((entry) => {\n const to = `${settingsPath}/${entry.pathSegment}`;\n const active = Boolean(matchRoute({to: to as never, params: paramsForLink as never}));\n return (\n <Button\n key={entry.id}\n asChild\n variant={active ? 'secondary' : 'transparent'}\n className=\"w-full justify-start\"\n >\n <Link\n to={to as never}\n params={paramsForLink as never}\n aria-current={active ? 'page' : undefined}\n >\n <Icon name={entry.icon} className=\"size-16\" />\n {entry.label}\n </Link>\n </Button>\n );\n })}\n </nav>\n );\n}\n"],"names":["Button","Icon","Link","useMatchRoute","parseWorkspaceParams","parseWorkspaceProjectParams","useRouteParams","SettingsNav","entries","scope","params","input","matchRoute","workspaceSlug","projectSlug","scopedEntries","filter","entry","settingsPath","paramsForLink","nav","aria-label","className","map","to","pathSegment","active","Boolean","asChild","variant","aria-current","undefined","name","icon","label","id"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,EAAEC,aAAa,QAAO,yBAAyB;AAE3D,SACEC,oBAAoB,EACpBC,2BAA2B,EAC3BC,cAAc,QACT,2BAA2B;AAElC,OAAO,SAASC,YAAY,EAC1BC,OAAO,EACPC,KAAK,EAIN;IACC,MAAMC,SAASJ,eAAe,CAACK,QAC7BF,UAAU,cAAcL,qBAAqBO,SAASN,4BAA4BM;IAEpF,MAAMC,aAAaT;IACnB,IAAI,CAACO,OAAOG,aAAa,IAAKJ,UAAU,aAAa,CAACC,OAAOI,WAAW,EAAG,OAAO;IAClF,MAAMC,gBAAgBP,QAAQQ,MAAM,CAAC,CAACC,QAAU,AAACA,CAAAA,MAAMR,KAAK,IAAI,WAAU,MAAOA;IACjF,MAAMS,eACJT,UAAU,cACN,+BACA;IACN,MAAMU,gBACJV,UAAU,cACN;QAACI,eAAeH,OAAOG,aAAa;IAAA,IACpC;QAACA,eAAeH,OAAOG,aAAa;QAAEC,aAAaJ,OAAOI,WAAW;IAAA;IAE3E,qBACE,KAACM;QACCC,cAAY,GAAGZ,UAAU,cAAc,cAAc,UAAU,SAAS,CAAC;QACzEa,WAAU;kBAETP,cAAcQ,GAAG,CAAC,CAACN;YAClB,MAAMO,KAAK,GAAGN,aAAa,CAAC,EAAED,MAAMQ,WAAW,EAAE;YACjD,MAAMC,SAASC,QAAQf,WAAW;gBAACY,IAAIA;gBAAad,QAAQS;YAAsB;YAClF,qBACE,KAACnB;gBAEC4B,OAAO;gBACPC,SAASH,SAAS,cAAc;gBAChCJ,WAAU;0BAEV,cAAA,MAACpB;oBACCsB,IAAIA;oBACJd,QAAQS;oBACRW,gBAAcJ,SAAS,SAASK;;sCAEhC,KAAC9B;4BAAK+B,MAAMf,MAAMgB,IAAI;4BAAEX,WAAU;;wBACjCL,MAAMiB,KAAK;;;eAXTjB,MAAMkB,EAAE;QAenB;;AAGN"}
@@ -7,7 +7,7 @@ import { WorkspaceSwitcher } from './workspace-switcher.js';
7
7
  export function WorkspaceCrumb({ workspace, compact = false }) {
8
8
  const [open, setOpen] = useState(false);
9
9
  return /*#__PURE__*/ _jsxs("div", {
10
- className: "flex items-center",
10
+ className: "flex items-center gap-tight",
11
11
  children: [
12
12
  /*#__PURE__*/ _jsx(Link, {
13
13
  to: "/w/$workspaceSlug",
@@ -15,7 +15,7 @@ export function WorkspaceCrumb({ workspace, compact = false }) {
15
15
  workspaceSlug: workspace.slug
16
16
  },
17
17
  "aria-current": "page",
18
- className: `inline-block text-md font-medium text-foreground-neutral-base px-6 py-4 rounded-6 hover:bg-background-components-hover transition-colors truncate ${compact ? 'max-w-[120px] sm:max-w-[200px]' : 'max-w-[200px]'}`,
18
+ className: `inline-block text-md font-medium text-foreground-neutral-base p-tight rounded-6 hover:bg-background-components-hover transition-colors truncate ${compact ? 'max-w-[120px] sm:max-w-[200px]' : 'max-w-[200px]'}`,
19
19
  children: workspace.name
20
20
  }),
21
21
  /*#__PURE__*/ _jsxs(Popover, {
@@ -29,7 +29,7 @@ export function WorkspaceCrumb({ workspace, compact = false }) {
29
29
  "aria-label": "Switch workspace",
30
30
  "aria-haspopup": "listbox",
31
31
  "aria-expanded": open,
32
- className: "ml-2 grid place-items-center size-24 rounded-4 text-foreground-neutral-muted hover:bg-background-components-hover hover:text-foreground-neutral-base transition-colors",
32
+ className: "grid place-items-center size-24 rounded-4 text-foreground-neutral-muted hover:bg-background-components-hover hover:text-foreground-neutral-base transition-colors",
33
33
  children: /*#__PURE__*/ _jsx(Icon, {
34
34
  name: "arrowDownSLine",
35
35
  className: "size-16"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/workspace-crumb.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {Popover, PopoverContent, PopoverTrigger} from '@shipfox/react-ui/popover';\nimport {Link} from '@tanstack/react-router';\nimport {useState} from 'react';\nimport type {Workspace} from '#runtime/auth.js';\nimport {WorkspaceSwitcher} from './workspace-switcher.js';\n\nexport interface WorkspaceCrumbProps {\n workspace: Workspace;\n compact?: boolean;\n}\n\nexport function WorkspaceCrumb({workspace, compact = false}: WorkspaceCrumbProps) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"flex items-center\">\n <Link\n to=\"/w/$workspaceSlug\"\n params={{workspaceSlug: workspace.slug}}\n aria-current=\"page\"\n className={`inline-block text-md font-medium text-foreground-neutral-base px-6 py-4 rounded-6 hover:bg-background-components-hover transition-colors truncate ${compact ? 'max-w-[120px] sm:max-w-[200px]' : 'max-w-[200px]'}`}\n >\n {workspace.name}\n </Link>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Switch workspace\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n className=\"ml-2 grid place-items-center size-24 rounded-4 text-foreground-neutral-muted hover:bg-background-components-hover hover:text-foreground-neutral-base transition-colors\"\n >\n <Icon name=\"arrowDownSLine\" className=\"size-16\" />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-[280px] p-0\" align=\"start\" sideOffset={8}>\n <WorkspaceSwitcher activeWorkspaceId={workspace.id} onSelect={() => setOpen(false)} />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"names":["Icon","Popover","PopoverContent","PopoverTrigger","Link","useState","WorkspaceSwitcher","WorkspaceCrumb","workspace","compact","open","setOpen","div","className","to","params","workspaceSlug","slug","aria-current","name","onOpenChange","asChild","button","type","aria-label","aria-haspopup","aria-expanded","align","sideOffset","activeWorkspaceId","id","onSelect"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,QAAQ,QAAO,QAAQ;AAE/B,SAAQC,iBAAiB,QAAO,0BAA0B;AAO1D,OAAO,SAASC,eAAe,EAACC,SAAS,EAAEC,UAAU,KAAK,EAAsB;IAC9E,MAAM,CAACC,MAAMC,QAAQ,GAAGN,SAAS;IACjC,qBACE,MAACO;QAAIC,WAAU;;0BACb,KAACT;gBACCU,IAAG;gBACHC,QAAQ;oBAACC,eAAeR,UAAUS,IAAI;gBAAA;gBACtCC,gBAAa;gBACbL,WAAW,CAAC,kJAAkJ,EAAEJ,UAAU,mCAAmC,iBAAiB;0BAE7ND,UAAUW,IAAI;;0BAEjB,MAAClB;gBAAQS,MAAMA;gBAAMU,cAAcT;;kCACjC,KAACR;wBAAekB,OAAO;kCACrB,cAAA,KAACC;4BACCC,MAAK;4BACLC,cAAW;4BACXC,iBAAc;4BACdC,iBAAehB;4BACfG,WAAU;sCAEV,cAAA,KAACb;gCAAKmB,MAAK;gCAAiBN,WAAU;;;;kCAG1C,KAACX;wBAAeW,WAAU;wBAAgBc,OAAM;wBAAQC,YAAY;kCAClE,cAAA,KAACtB;4BAAkBuB,mBAAmBrB,UAAUsB,EAAE;4BAAEC,UAAU,IAAMpB,QAAQ;;;;;;;AAKtF"}
1
+ {"version":3,"sources":["../../src/components/workspace-crumb.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {Popover, PopoverContent, PopoverTrigger} from '@shipfox/react-ui/popover';\nimport {Link} from '@tanstack/react-router';\nimport {useState} from 'react';\nimport type {Workspace} from '#runtime/auth.js';\nimport {WorkspaceSwitcher} from './workspace-switcher.js';\n\nexport interface WorkspaceCrumbProps {\n workspace: Workspace;\n compact?: boolean;\n}\n\nexport function WorkspaceCrumb({workspace, compact = false}: WorkspaceCrumbProps) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"flex items-center gap-tight\">\n <Link\n to=\"/w/$workspaceSlug\"\n params={{workspaceSlug: workspace.slug}}\n aria-current=\"page\"\n className={`inline-block text-md font-medium text-foreground-neutral-base p-tight rounded-6 hover:bg-background-components-hover transition-colors truncate ${compact ? 'max-w-[120px] sm:max-w-[200px]' : 'max-w-[200px]'}`}\n >\n {workspace.name}\n </Link>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Switch workspace\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n className=\"grid place-items-center size-24 rounded-4 text-foreground-neutral-muted hover:bg-background-components-hover hover:text-foreground-neutral-base transition-colors\"\n >\n <Icon name=\"arrowDownSLine\" className=\"size-16\" />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-[280px] p-0\" align=\"start\" sideOffset={8}>\n <WorkspaceSwitcher activeWorkspaceId={workspace.id} onSelect={() => setOpen(false)} />\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"names":["Icon","Popover","PopoverContent","PopoverTrigger","Link","useState","WorkspaceSwitcher","WorkspaceCrumb","workspace","compact","open","setOpen","div","className","to","params","workspaceSlug","slug","aria-current","name","onOpenChange","asChild","button","type","aria-label","aria-haspopup","aria-expanded","align","sideOffset","activeWorkspaceId","id","onSelect"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,QAAQ,QAAO,QAAQ;AAE/B,SAAQC,iBAAiB,QAAO,0BAA0B;AAO1D,OAAO,SAASC,eAAe,EAACC,SAAS,EAAEC,UAAU,KAAK,EAAsB;IAC9E,MAAM,CAACC,MAAMC,QAAQ,GAAGN,SAAS;IACjC,qBACE,MAACO;QAAIC,WAAU;;0BACb,KAACT;gBACCU,IAAG;gBACHC,QAAQ;oBAACC,eAAeR,UAAUS,IAAI;gBAAA;gBACtCC,gBAAa;gBACbL,WAAW,CAAC,gJAAgJ,EAAEJ,UAAU,mCAAmC,iBAAiB;0BAE3ND,UAAUW,IAAI;;0BAEjB,MAAClB;gBAAQS,MAAMA;gBAAMU,cAAcT;;kCACjC,KAACR;wBAAekB,OAAO;kCACrB,cAAA,KAACC;4BACCC,MAAK;4BACLC,cAAW;4BACXC,iBAAc;4BACdC,iBAAehB;4BACfG,WAAU;sCAEV,cAAA,KAACb;gCAAKmB,MAAK;gCAAiBN,WAAU;;;;kCAG1C,KAACX;wBAAeW,WAAU;wBAAgBc,OAAM;wBAAQC,YAAY;kCAClE,cAAA,KAACtB;4BAAkBuB,mBAAmBrB,UAAUsB,EAAE;4BAAEC,UAAU,IAAMpB,QAAQ;;;;;;;AAKtF"}
@@ -35,7 +35,7 @@ export function WorkspaceSwitcher({ activeWorkspaceId, onSelect }) {
35
35
  className: "max-h-none overflow-visible overflow-y-visible p-0",
36
36
  children: [
37
37
  /*#__PURE__*/ _jsxs("div", {
38
- className: "max-h-300 overflow-y-auto overflow-x-hidden p-4 scrollbar",
38
+ className: "max-h-300 overflow-y-auto overflow-x-hidden p-menu-surface scrollbar",
39
39
  children: [
40
40
  /*#__PURE__*/ _jsx(CommandEmpty, {
41
41
  children: "No workspaces found."
@@ -51,7 +51,7 @@ export function WorkspaceSwitcher({ activeWorkspaceId, onSelect }) {
51
51
  children: [
52
52
  /*#__PURE__*/ _jsx(Icon, {
53
53
  name: "check",
54
- className: `size-16 mr-8 ${activeWorkspaceId === workspace.id ? 'opacity-100' : 'opacity-0'}`
54
+ className: `size-16 ${activeWorkspaceId === workspace.id ? 'opacity-100' : 'opacity-0'}`
55
55
  }),
56
56
  workspace.name
57
57
  ]
@@ -65,7 +65,7 @@ export function WorkspaceSwitcher({ activeWorkspaceId, onSelect }) {
65
65
  }),
66
66
  /*#__PURE__*/ _jsx(CommandGroup, {
67
67
  forceMount: true,
68
- className: "p-4",
68
+ className: "p-menu-surface",
69
69
  children: /*#__PURE__*/ _jsxs(CommandItem, {
70
70
  value: "__create",
71
71
  onSelect: ()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/workspace-switcher.tsx"],"sourcesContent":["import {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from '@shipfox/react-ui/command';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {useNavigate} from '@tanstack/react-router';\nimport {useSetAtom} from 'jotai';\nimport {useAuthState} from '#runtime/auth.js';\nimport {lastWorkspaceIdAtom, rememberLastWorkspaceId} from '#runtime/last-workspace.js';\n\nexport function WorkspaceSwitcher({\n activeWorkspaceId,\n onSelect,\n}: {\n activeWorkspaceId?: string;\n onSelect?: () => void;\n}) {\n const {user, workspaces} = useAuthState();\n const navigate = useNavigate();\n const setLastWorkspaceId = useSetAtom(lastWorkspaceIdAtom);\n const selectWorkspace = (wid: string) => {\n const workspace = workspaces.find((candidate) => candidate.id === wid);\n if (!workspace) return;\n try {\n setLastWorkspaceId(wid);\n if (user?.id) rememberLastWorkspaceId(user.id, wid);\n } catch {\n // Local storage is best effort.\n }\n navigate({to: '/w/$workspaceSlug', params: {workspaceSlug: workspace.slug}});\n onSelect?.();\n };\n return (\n <Command>\n <CommandInput placeholder=\"Search workspaces...\" />\n <CommandList className=\"max-h-none overflow-visible overflow-y-visible p-0\">\n <div className=\"max-h-300 overflow-y-auto overflow-x-hidden p-4 scrollbar\">\n <CommandEmpty>No workspaces found.</CommandEmpty>\n <CommandGroup heading=\"Workspaces\">\n {workspaces.map((workspace) => (\n <CommandItem\n key={workspace.id}\n value={workspace.id}\n keywords={[workspace.name]}\n onSelect={() => selectWorkspace(workspace.id)}\n >\n <Icon\n name=\"check\"\n className={`size-16 mr-8 ${activeWorkspaceId === workspace.id ? 'opacity-100' : 'opacity-0'}`}\n />\n {workspace.name}\n </CommandItem>\n ))}\n </CommandGroup>\n </div>\n <CommandSeparator alwaysRender className=\"mx-0\" />\n <CommandGroup forceMount className=\"p-4\">\n <CommandItem\n value=\"__create\"\n onSelect={() => {\n navigate({to: '/setup/workspaces/new' as never});\n onSelect?.();\n }}\n forceMount\n >\n <Icon name=\"addLine\" className=\"size-16\" />\n Create workspace\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n"],"names":["Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","CommandSeparator","Icon","useNavigate","useSetAtom","useAuthState","lastWorkspaceIdAtom","rememberLastWorkspaceId","WorkspaceSwitcher","activeWorkspaceId","onSelect","user","workspaces","navigate","setLastWorkspaceId","selectWorkspace","wid","workspace","find","candidate","id","to","params","workspaceSlug","slug","placeholder","className","div","heading","map","value","keywords","name","alwaysRender","forceMount"],"mappings":";AAAA,SACEA,OAAO,EACPC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,WAAW,EACXC,WAAW,EACXC,gBAAgB,QACX,4BAA4B;AACnC,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,WAAW,QAAO,yBAAyB;AACnD,SAAQC,UAAU,QAAO,QAAQ;AACjC,SAAQC,YAAY,QAAO,mBAAmB;AAC9C,SAAQC,mBAAmB,EAAEC,uBAAuB,QAAO,6BAA6B;AAExF,OAAO,SAASC,kBAAkB,EAChCC,iBAAiB,EACjBC,QAAQ,EAIT;IACC,MAAM,EAACC,IAAI,EAAEC,UAAU,EAAC,GAAGP;IAC3B,MAAMQ,WAAWV;IACjB,MAAMW,qBAAqBV,WAAWE;IACtC,MAAMS,kBAAkB,CAACC;QACvB,MAAMC,YAAYL,WAAWM,IAAI,CAAC,CAACC,YAAcA,UAAUC,EAAE,KAAKJ;QAClE,IAAI,CAACC,WAAW;QAChB,IAAI;YACFH,mBAAmBE;YACnB,IAAIL,MAAMS,IAAIb,wBAAwBI,KAAKS,EAAE,EAAEJ;QACjD,EAAE,OAAM;QACN,gCAAgC;QAClC;QACAH,SAAS;YAACQ,IAAI;YAAqBC,QAAQ;gBAACC,eAAeN,UAAUO,IAAI;YAAA;QAAC;QAC1Ed;IACF;IACA,qBACE,MAACf;;0BACC,KAACG;gBAAa2B,aAAY;;0BAC1B,MAACzB;gBAAY0B,WAAU;;kCACrB,MAACC;wBAAID,WAAU;;0CACb,KAAC9B;0CAAa;;0CACd,KAACC;gCAAa+B,SAAQ;0CACnBhB,WAAWiB,GAAG,CAAC,CAACZ,0BACf,MAAClB;wCAEC+B,OAAOb,UAAUG,EAAE;wCACnBW,UAAU;4CAACd,UAAUe,IAAI;yCAAC;wCAC1BtB,UAAU,IAAMK,gBAAgBE,UAAUG,EAAE;;0DAE5C,KAAClB;gDACC8B,MAAK;gDACLN,WAAW,CAAC,aAAa,EAAEjB,sBAAsBQ,UAAUG,EAAE,GAAG,gBAAgB,aAAa;;4CAE9FH,UAAUe,IAAI;;uCATVf,UAAUG,EAAE;;;;kCAczB,KAACnB;wBAAiBgC,YAAY;wBAACP,WAAU;;kCACzC,KAAC7B;wBAAaqC,UAAU;wBAACR,WAAU;kCACjC,cAAA,MAAC3B;4BACC+B,OAAM;4BACNpB,UAAU;gCACRG,SAAS;oCAACQ,IAAI;gCAAgC;gCAC9CX;4BACF;4BACAwB,UAAU;;8CAEV,KAAChC;oCAAK8B,MAAK;oCAAUN,WAAU;;gCAAY;;;;;;;;AAOvD"}
1
+ {"version":3,"sources":["../../src/components/workspace-switcher.tsx"],"sourcesContent":["import {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from '@shipfox/react-ui/command';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {useNavigate} from '@tanstack/react-router';\nimport {useSetAtom} from 'jotai';\nimport {useAuthState} from '#runtime/auth.js';\nimport {lastWorkspaceIdAtom, rememberLastWorkspaceId} from '#runtime/last-workspace.js';\n\nexport function WorkspaceSwitcher({\n activeWorkspaceId,\n onSelect,\n}: {\n activeWorkspaceId?: string;\n onSelect?: () => void;\n}) {\n const {user, workspaces} = useAuthState();\n const navigate = useNavigate();\n const setLastWorkspaceId = useSetAtom(lastWorkspaceIdAtom);\n const selectWorkspace = (wid: string) => {\n const workspace = workspaces.find((candidate) => candidate.id === wid);\n if (!workspace) return;\n try {\n setLastWorkspaceId(wid);\n if (user?.id) rememberLastWorkspaceId(user.id, wid);\n } catch {\n // Local storage is best effort.\n }\n navigate({to: '/w/$workspaceSlug', params: {workspaceSlug: workspace.slug}});\n onSelect?.();\n };\n return (\n <Command>\n <CommandInput placeholder=\"Search workspaces...\" />\n <CommandList className=\"max-h-none overflow-visible overflow-y-visible p-0\">\n <div className=\"max-h-300 overflow-y-auto overflow-x-hidden p-menu-surface scrollbar\">\n <CommandEmpty>No workspaces found.</CommandEmpty>\n <CommandGroup heading=\"Workspaces\">\n {workspaces.map((workspace) => (\n <CommandItem\n key={workspace.id}\n value={workspace.id}\n keywords={[workspace.name]}\n onSelect={() => selectWorkspace(workspace.id)}\n >\n <Icon\n name=\"check\"\n className={`size-16 ${activeWorkspaceId === workspace.id ? 'opacity-100' : 'opacity-0'}`}\n />\n {workspace.name}\n </CommandItem>\n ))}\n </CommandGroup>\n </div>\n <CommandSeparator alwaysRender className=\"mx-0\" />\n <CommandGroup forceMount className=\"p-menu-surface\">\n <CommandItem\n value=\"__create\"\n onSelect={() => {\n navigate({to: '/setup/workspaces/new' as never});\n onSelect?.();\n }}\n forceMount\n >\n <Icon name=\"addLine\" className=\"size-16\" />\n Create workspace\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n );\n}\n"],"names":["Command","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","CommandSeparator","Icon","useNavigate","useSetAtom","useAuthState","lastWorkspaceIdAtom","rememberLastWorkspaceId","WorkspaceSwitcher","activeWorkspaceId","onSelect","user","workspaces","navigate","setLastWorkspaceId","selectWorkspace","wid","workspace","find","candidate","id","to","params","workspaceSlug","slug","placeholder","className","div","heading","map","value","keywords","name","alwaysRender","forceMount"],"mappings":";AAAA,SACEA,OAAO,EACPC,YAAY,EACZC,YAAY,EACZC,YAAY,EACZC,WAAW,EACXC,WAAW,EACXC,gBAAgB,QACX,4BAA4B;AACnC,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,WAAW,QAAO,yBAAyB;AACnD,SAAQC,UAAU,QAAO,QAAQ;AACjC,SAAQC,YAAY,QAAO,mBAAmB;AAC9C,SAAQC,mBAAmB,EAAEC,uBAAuB,QAAO,6BAA6B;AAExF,OAAO,SAASC,kBAAkB,EAChCC,iBAAiB,EACjBC,QAAQ,EAIT;IACC,MAAM,EAACC,IAAI,EAAEC,UAAU,EAAC,GAAGP;IAC3B,MAAMQ,WAAWV;IACjB,MAAMW,qBAAqBV,WAAWE;IACtC,MAAMS,kBAAkB,CAACC;QACvB,MAAMC,YAAYL,WAAWM,IAAI,CAAC,CAACC,YAAcA,UAAUC,EAAE,KAAKJ;QAClE,IAAI,CAACC,WAAW;QAChB,IAAI;YACFH,mBAAmBE;YACnB,IAAIL,MAAMS,IAAIb,wBAAwBI,KAAKS,EAAE,EAAEJ;QACjD,EAAE,OAAM;QACN,gCAAgC;QAClC;QACAH,SAAS;YAACQ,IAAI;YAAqBC,QAAQ;gBAACC,eAAeN,UAAUO,IAAI;YAAA;QAAC;QAC1Ed;IACF;IACA,qBACE,MAACf;;0BACC,KAACG;gBAAa2B,aAAY;;0BAC1B,MAACzB;gBAAY0B,WAAU;;kCACrB,MAACC;wBAAID,WAAU;;0CACb,KAAC9B;0CAAa;;0CACd,KAACC;gCAAa+B,SAAQ;0CACnBhB,WAAWiB,GAAG,CAAC,CAACZ,0BACf,MAAClB;wCAEC+B,OAAOb,UAAUG,EAAE;wCACnBW,UAAU;4CAACd,UAAUe,IAAI;yCAAC;wCAC1BtB,UAAU,IAAMK,gBAAgBE,UAAUG,EAAE;;0DAE5C,KAAClB;gDACC8B,MAAK;gDACLN,WAAW,CAAC,QAAQ,EAAEjB,sBAAsBQ,UAAUG,EAAE,GAAG,gBAAgB,aAAa;;4CAEzFH,UAAUe,IAAI;;uCATVf,UAAUG,EAAE;;;;kCAczB,KAACnB;wBAAiBgC,YAAY;wBAACP,WAAU;;kCACzC,KAAC7B;wBAAaqC,UAAU;wBAACR,WAAU;kCACjC,cAAA,MAAC3B;4BACC+B,OAAM;4BACNpB,UAAU;gCACRG,SAAS;oCAACQ,IAAI;gCAAgC;gCAC9CX;4BACF;4BACAwB,UAAU;;8CAEV,KAAChC;oCAAK8B,MAAK;oCAAUN,WAAU;;gCAAY;;;;;;;;AAOvD"}
@@ -138,10 +138,10 @@ function SettingsAnchorLayout({ scope, title, description, settingsSections }) {
138
138
  const params = useRouteParams((input)=>scope === 'workspace' ? parseWorkspaceParams(input) : parseWorkspaceProjectParams(input));
139
139
  if (!params.workspaceSlug || scope === 'project' && !params.projectSlug) return null;
140
140
  return /*#__PURE__*/ _jsxs("div", {
141
- className: "flex w-full flex-col gap-24",
141
+ className: "flex w-full flex-col gap-section",
142
142
  children: [
143
143
  /*#__PURE__*/ _jsxs("header", {
144
- className: "flex flex-col gap-6",
144
+ className: "flex flex-col gap-inline",
145
145
  children: [
146
146
  /*#__PURE__*/ _jsx(Header, {
147
147
  variant: "h2",
@@ -155,7 +155,7 @@ function SettingsAnchorLayout({ scope, title, description, settingsSections }) {
155
155
  ]
156
156
  }),
157
157
  /*#__PURE__*/ _jsxs("div", {
158
- className: "grid grid-cols-[180px_minmax(0,1fr)] gap-32 max-[760px]:grid-cols-1",
158
+ className: "grid grid-cols-[180px_minmax(0,1fr)] gap-region max-[760px]:grid-cols-1",
159
159
  children: [
160
160
  /*#__PURE__*/ _jsx(SettingsNav, {
161
161
  entries: settingsSections,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/anchors.tsx"],"sourcesContent":["import {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {createRootRouteWithContext, createRoute, Outlet, redirect} from '@tanstack/react-router';\nimport {MainLayout} from '#components/main-layout.js';\nimport {NotFoundPage} from '#components/not-found-page.js';\nimport {SettingsNav} from '#components/settings-nav.js';\nimport type {NavTabEntry, SettingsSectionEntry} from '#contract.js';\nimport {useActiveWorkspace, useMaybeActiveWorkspace} from './active-workspace.js';\nimport {anchorPaths} from './anchor-paths.js';\nimport {rememberLastWorkspaceId} from './last-workspace.js';\nimport {parseWorkspaceParams, parseWorkspaceProjectParams, useRouteParams} from './route-inputs.js';\nimport type {RouterContext} from './router-context.js';\nimport type {WorkspaceSetupState} from './workspace-setup.js';\nimport {\n WorkspaceLayoutErrorRoute,\n WorkspaceSetupPending,\n WorkspaceUnavailablePage,\n} from './workspace-setup.js';\n\nexport {routePathForAnchor} from './anchor-paths.js';\n\nexport function buildAnchorSkeleton({\n navigation,\n settingsSections,\n}: {\n navigation: readonly NavTabEntry[];\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const rootRoute = createRootRouteWithContext<RouterContext>()({\n component: Outlet,\n notFoundComponent: NotFoundPage,\n });\n const workspaceLayout = createRoute({\n getParentRoute: () => rootRoute,\n path: anchorPaths.workspaceLayout,\n beforeLoad: async ({context, params, location}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if (!auth.isAuthenticated)\n throw redirect({to: '/auth/login' as never, search: {redirect: location.href} as never});\n const workspace = auth.workspaces.find(\n (candidate) => candidate.slug === params.workspaceSlug,\n );\n if (!workspace) throw redirect({to: '/'});\n try {\n if (auth.user?.id) rememberLastWorkspaceId(auth.user.id, workspace.id);\n } catch {\n // Local storage is best effort.\n }\n if (!context.workspaceSetup)\n throw new Error('Client composition includes workspace routes but no workspaceSetup gate.');\n return await context.workspaceSetup({\n queryClient: context.queryClient,\n workspaceId: workspace.id,\n workspaceSlug: params.workspaceSlug,\n pathname: location.pathname,\n });\n },\n pendingComponent: () => (\n <div className=\"flex h-screen items-center justify-center\">\n <ShipfoxLoader size={64} animation=\"circular\" color=\"orange\" background=\"dark\" />\n </div>\n ),\n errorComponent: WorkspaceLayoutErrorRoute,\n component: () => {\n const setupState = workspaceLayout.useRouteContext() as {\n hideProjectNavigation?: boolean;\n unavailable?: boolean;\n };\n const workspace = useMaybeActiveWorkspace();\n return setupState.hideProjectNavigation === undefined ? (\n <WorkspaceSetupPending />\n ) : setupState.unavailable ? (\n <WorkspaceUnavailablePage workspaceName={workspace?.name} />\n ) : (\n <MainLayout\n navigation={navigation}\n hideProjectNavigation={setupState.hideProjectNavigation}\n />\n );\n },\n });\n const projectLayout = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/p/$projectSlug',\n beforeLoad: async ({context, params}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if ((context as RouterContext & Partial<WorkspaceSetupState>).unavailable) return;\n const workspace = auth.workspaces.find(\n (candidate) => candidate.slug === params.workspaceSlug,\n );\n if (!workspace) throw redirect({to: '/'});\n if (!context.projectSlugResolver) {\n throw new Error('Client composition includes project routes but no project slug resolver.');\n }\n const projectId = await context.projectSlugResolver({\n queryClient: context.queryClient,\n workspaceId: workspace.id,\n projectSlug: params.projectSlug,\n });\n if (!projectId) {\n throw redirect({\n to: '/w/$workspaceSlug',\n params: {workspaceSlug: params.workspaceSlug},\n });\n }\n },\n component: Outlet,\n });\n const projectSettings = createRoute({\n getParentRoute: () => projectLayout,\n path: '/settings',\n component: () => (\n <SettingsAnchorLayout\n scope=\"project\"\n title=\"Project settings\"\n description=\"Configure this project.\"\n settingsSections={settingsSections}\n />\n ),\n });\n const workspaceSettings = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/settings',\n component: () => {\n const workspace = useActiveWorkspace();\n return (\n <SettingsAnchorLayout\n scope=\"workspace\"\n title=\"Workspace settings\"\n description={`Configure ${workspace.name}.`}\n settingsSections={settingsSections}\n />\n );\n },\n });\n return {\n anchors: {root: rootRoute, workspaceLayout, projectLayout, workspaceSettings, projectSettings},\n rootRoute,\n workspaceLayout,\n projectLayout,\n workspaceSettings,\n projectSettings,\n };\n}\n\nfunction SettingsAnchorLayout({\n scope,\n title,\n description,\n settingsSections,\n}: {\n scope: 'workspace' | 'project';\n title: string;\n description: string;\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const params = useRouteParams((input): {workspaceSlug?: string; projectSlug?: string} =>\n scope === 'workspace' ? parseWorkspaceParams(input) : parseWorkspaceProjectParams(input),\n );\n if (!params.workspaceSlug || (scope === 'project' && !params.projectSlug)) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-24\">\n <header className=\"flex flex-col gap-6\">\n <Header variant=\"h2\">{title}</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {description}\n </Text>\n </header>\n\n <div className=\"grid grid-cols-[180px_minmax(0,1fr)] gap-32 max-[760px]:grid-cols-1\">\n <SettingsNav entries={settingsSections} scope={scope} />\n <Outlet />\n </div>\n </div>\n );\n}\n"],"names":["ShipfoxLoader","Header","Text","createRootRouteWithContext","createRoute","Outlet","redirect","MainLayout","NotFoundPage","SettingsNav","useActiveWorkspace","useMaybeActiveWorkspace","anchorPaths","rememberLastWorkspaceId","parseWorkspaceParams","parseWorkspaceProjectParams","useRouteParams","WorkspaceLayoutErrorRoute","WorkspaceSetupPending","WorkspaceUnavailablePage","routePathForAnchor","buildAnchorSkeleton","navigation","settingsSections","rootRoute","component","notFoundComponent","workspaceLayout","getParentRoute","path","beforeLoad","context","params","location","auth","isLoading","queryClient","isAuthenticated","to","search","href","workspace","workspaces","find","candidate","slug","workspaceSlug","user","id","workspaceSetup","Error","workspaceId","pathname","pendingComponent","div","className","size","animation","color","background","errorComponent","setupState","useRouteContext","hideProjectNavigation","undefined","unavailable","workspaceName","name","projectLayout","projectSlugResolver","projectId","projectSlug","projectSettings","SettingsAnchorLayout","scope","title","description","workspaceSettings","anchors","root","input","header","variant","entries"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/runtime/anchors.tsx"],"sourcesContent":["import {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {createRootRouteWithContext, createRoute, Outlet, redirect} from '@tanstack/react-router';\nimport {MainLayout} from '#components/main-layout.js';\nimport {NotFoundPage} from '#components/not-found-page.js';\nimport {SettingsNav} from '#components/settings-nav.js';\nimport type {NavTabEntry, SettingsSectionEntry} from '#contract.js';\nimport {useActiveWorkspace, useMaybeActiveWorkspace} from './active-workspace.js';\nimport {anchorPaths} from './anchor-paths.js';\nimport {rememberLastWorkspaceId} from './last-workspace.js';\nimport {parseWorkspaceParams, parseWorkspaceProjectParams, useRouteParams} from './route-inputs.js';\nimport type {RouterContext} from './router-context.js';\nimport type {WorkspaceSetupState} from './workspace-setup.js';\nimport {\n WorkspaceLayoutErrorRoute,\n WorkspaceSetupPending,\n WorkspaceUnavailablePage,\n} from './workspace-setup.js';\n\nexport {routePathForAnchor} from './anchor-paths.js';\n\nexport function buildAnchorSkeleton({\n navigation,\n settingsSections,\n}: {\n navigation: readonly NavTabEntry[];\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const rootRoute = createRootRouteWithContext<RouterContext>()({\n component: Outlet,\n notFoundComponent: NotFoundPage,\n });\n const workspaceLayout = createRoute({\n getParentRoute: () => rootRoute,\n path: anchorPaths.workspaceLayout,\n beforeLoad: async ({context, params, location}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if (!auth.isAuthenticated)\n throw redirect({to: '/auth/login' as never, search: {redirect: location.href} as never});\n const workspace = auth.workspaces.find(\n (candidate) => candidate.slug === params.workspaceSlug,\n );\n if (!workspace) throw redirect({to: '/'});\n try {\n if (auth.user?.id) rememberLastWorkspaceId(auth.user.id, workspace.id);\n } catch {\n // Local storage is best effort.\n }\n if (!context.workspaceSetup)\n throw new Error('Client composition includes workspace routes but no workspaceSetup gate.');\n return await context.workspaceSetup({\n queryClient: context.queryClient,\n workspaceId: workspace.id,\n workspaceSlug: params.workspaceSlug,\n pathname: location.pathname,\n });\n },\n pendingComponent: () => (\n <div className=\"flex h-screen items-center justify-center\">\n <ShipfoxLoader size={64} animation=\"circular\" color=\"orange\" background=\"dark\" />\n </div>\n ),\n errorComponent: WorkspaceLayoutErrorRoute,\n component: () => {\n const setupState = workspaceLayout.useRouteContext() as {\n hideProjectNavigation?: boolean;\n unavailable?: boolean;\n };\n const workspace = useMaybeActiveWorkspace();\n return setupState.hideProjectNavigation === undefined ? (\n <WorkspaceSetupPending />\n ) : setupState.unavailable ? (\n <WorkspaceUnavailablePage workspaceName={workspace?.name} />\n ) : (\n <MainLayout\n navigation={navigation}\n hideProjectNavigation={setupState.hideProjectNavigation}\n />\n );\n },\n });\n const projectLayout = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/p/$projectSlug',\n beforeLoad: async ({context, params}) => {\n const auth = context.auth;\n if (!auth || auth.isLoading || !context.queryClient) return;\n if ((context as RouterContext & Partial<WorkspaceSetupState>).unavailable) return;\n const workspace = auth.workspaces.find(\n (candidate) => candidate.slug === params.workspaceSlug,\n );\n if (!workspace) throw redirect({to: '/'});\n if (!context.projectSlugResolver) {\n throw new Error('Client composition includes project routes but no project slug resolver.');\n }\n const projectId = await context.projectSlugResolver({\n queryClient: context.queryClient,\n workspaceId: workspace.id,\n projectSlug: params.projectSlug,\n });\n if (!projectId) {\n throw redirect({\n to: '/w/$workspaceSlug',\n params: {workspaceSlug: params.workspaceSlug},\n });\n }\n },\n component: Outlet,\n });\n const projectSettings = createRoute({\n getParentRoute: () => projectLayout,\n path: '/settings',\n component: () => (\n <SettingsAnchorLayout\n scope=\"project\"\n title=\"Project settings\"\n description=\"Configure this project.\"\n settingsSections={settingsSections}\n />\n ),\n });\n const workspaceSettings = createRoute({\n getParentRoute: () => workspaceLayout,\n path: '/settings',\n component: () => {\n const workspace = useActiveWorkspace();\n return (\n <SettingsAnchorLayout\n scope=\"workspace\"\n title=\"Workspace settings\"\n description={`Configure ${workspace.name}.`}\n settingsSections={settingsSections}\n />\n );\n },\n });\n return {\n anchors: {root: rootRoute, workspaceLayout, projectLayout, workspaceSettings, projectSettings},\n rootRoute,\n workspaceLayout,\n projectLayout,\n workspaceSettings,\n projectSettings,\n };\n}\n\nfunction SettingsAnchorLayout({\n scope,\n title,\n description,\n settingsSections,\n}: {\n scope: 'workspace' | 'project';\n title: string;\n description: string;\n settingsSections: readonly SettingsSectionEntry[];\n}) {\n const params = useRouteParams((input): {workspaceSlug?: string; projectSlug?: string} =>\n scope === 'workspace' ? parseWorkspaceParams(input) : parseWorkspaceProjectParams(input),\n );\n if (!params.workspaceSlug || (scope === 'project' && !params.projectSlug)) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-section\">\n <header className=\"flex flex-col gap-inline\">\n <Header variant=\"h2\">{title}</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {description}\n </Text>\n </header>\n\n <div className=\"grid grid-cols-[180px_minmax(0,1fr)] gap-region max-[760px]:grid-cols-1\">\n <SettingsNav entries={settingsSections} scope={scope} />\n <Outlet />\n </div>\n </div>\n );\n}\n"],"names":["ShipfoxLoader","Header","Text","createRootRouteWithContext","createRoute","Outlet","redirect","MainLayout","NotFoundPage","SettingsNav","useActiveWorkspace","useMaybeActiveWorkspace","anchorPaths","rememberLastWorkspaceId","parseWorkspaceParams","parseWorkspaceProjectParams","useRouteParams","WorkspaceLayoutErrorRoute","WorkspaceSetupPending","WorkspaceUnavailablePage","routePathForAnchor","buildAnchorSkeleton","navigation","settingsSections","rootRoute","component","notFoundComponent","workspaceLayout","getParentRoute","path","beforeLoad","context","params","location","auth","isLoading","queryClient","isAuthenticated","to","search","href","workspace","workspaces","find","candidate","slug","workspaceSlug","user","id","workspaceSetup","Error","workspaceId","pathname","pendingComponent","div","className","size","animation","color","background","errorComponent","setupState","useRouteContext","hideProjectNavigation","undefined","unavailable","workspaceName","name","projectLayout","projectSlugResolver","projectId","projectSlug","projectSettings","SettingsAnchorLayout","scope","title","description","workspaceSettings","anchors","root","input","header","variant","entries"],"mappings":";AAAA,SAAQA,aAAa,QAAO,2BAA2B;AACvD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,0BAA0B,EAAEC,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAO,yBAAyB;AACjG,SAAQC,UAAU,QAAO,6BAA6B;AACtD,SAAQC,YAAY,QAAO,gCAAgC;AAC3D,SAAQC,WAAW,QAAO,8BAA8B;AAExD,SAAQC,kBAAkB,EAAEC,uBAAuB,QAAO,wBAAwB;AAClF,SAAQC,WAAW,QAAO,oBAAoB;AAC9C,SAAQC,uBAAuB,QAAO,sBAAsB;AAC5D,SAAQC,oBAAoB,EAAEC,2BAA2B,EAAEC,cAAc,QAAO,oBAAoB;AAGpG,SACEC,yBAAyB,EACzBC,qBAAqB,EACrBC,wBAAwB,QACnB,uBAAuB;AAE9B,SAAQC,kBAAkB,QAAO,oBAAoB;AAErD,OAAO,SAASC,oBAAoB,EAClCC,UAAU,EACVC,gBAAgB,EAIjB;IACC,MAAMC,YAAYrB,6BAA4C;QAC5DsB,WAAWpB;QACXqB,mBAAmBlB;IACrB;IACA,MAAMmB,kBAAkBvB,YAAY;QAClCwB,gBAAgB,IAAMJ;QACtBK,MAAMjB,YAAYe,eAAe;QACjCG,YAAY,OAAO,EAACC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,EAAC;YAC5C,MAAMC,OAAOH,QAAQG,IAAI;YACzB,IAAI,CAACA,QAAQA,KAAKC,SAAS,IAAI,CAACJ,QAAQK,WAAW,EAAE;YACrD,IAAI,CAACF,KAAKG,eAAe,EACvB,MAAM/B,SAAS;gBAACgC,IAAI;gBAAwBC,QAAQ;oBAACjC,UAAU2B,SAASO,IAAI;gBAAA;YAAU;YACxF,MAAMC,YAAYP,KAAKQ,UAAU,CAACC,IAAI,CACpC,CAACC,YAAcA,UAAUC,IAAI,KAAKb,OAAOc,aAAa;YAExD,IAAI,CAACL,WAAW,MAAMnC,SAAS;gBAACgC,IAAI;YAAG;YACvC,IAAI;gBACF,IAAIJ,KAAKa,IAAI,EAAEC,IAAInC,wBAAwBqB,KAAKa,IAAI,CAACC,EAAE,EAAEP,UAAUO,EAAE;YACvE,EAAE,OAAM;YACN,gCAAgC;YAClC;YACA,IAAI,CAACjB,QAAQkB,cAAc,EACzB,MAAM,IAAIC,MAAM;YAClB,OAAO,MAAMnB,QAAQkB,cAAc,CAAC;gBAClCb,aAAaL,QAAQK,WAAW;gBAChCe,aAAaV,UAAUO,EAAE;gBACzBF,eAAed,OAAOc,aAAa;gBACnCM,UAAUnB,SAASmB,QAAQ;YAC7B;QACF;QACAC,kBAAkB,kBAChB,KAACC;gBAAIC,WAAU;0BACb,cAAA,KAACvD;oBAAcwD,MAAM;oBAAIC,WAAU;oBAAWC,OAAM;oBAASC,YAAW;;;QAG5EC,gBAAgB3C;QAChBQ,WAAW;YACT,MAAMoC,aAAalC,gBAAgBmC,eAAe;YAIlD,MAAMrB,YAAY9B;YAClB,OAAOkD,WAAWE,qBAAqB,KAAKC,0BAC1C,KAAC9C,6BACC2C,WAAWI,WAAW,iBACxB,KAAC9C;gBAAyB+C,eAAezB,WAAW0B;+BAEpD,KAAC5D;gBACCe,YAAYA;gBACZyC,uBAAuBF,WAAWE,qBAAqB;;QAG7D;IACF;IACA,MAAMK,gBAAgBhE,YAAY;QAChCwB,gBAAgB,IAAMD;QACtBE,MAAM;QACNC,YAAY,OAAO,EAACC,OAAO,EAAEC,MAAM,EAAC;YAClC,MAAME,OAAOH,QAAQG,IAAI;YACzB,IAAI,CAACA,QAAQA,KAAKC,SAAS,IAAI,CAACJ,QAAQK,WAAW,EAAE;YACrD,IAAI,AAACL,QAAyDkC,WAAW,EAAE;YAC3E,MAAMxB,YAAYP,KAAKQ,UAAU,CAACC,IAAI,CACpC,CAACC,YAAcA,UAAUC,IAAI,KAAKb,OAAOc,aAAa;YAExD,IAAI,CAACL,WAAW,MAAMnC,SAAS;gBAACgC,IAAI;YAAG;YACvC,IAAI,CAACP,QAAQsC,mBAAmB,EAAE;gBAChC,MAAM,IAAInB,MAAM;YAClB;YACA,MAAMoB,YAAY,MAAMvC,QAAQsC,mBAAmB,CAAC;gBAClDjC,aAAaL,QAAQK,WAAW;gBAChCe,aAAaV,UAAUO,EAAE;gBACzBuB,aAAavC,OAAOuC,WAAW;YACjC;YACA,IAAI,CAACD,WAAW;gBACd,MAAMhE,SAAS;oBACbgC,IAAI;oBACJN,QAAQ;wBAACc,eAAed,OAAOc,aAAa;oBAAA;gBAC9C;YACF;QACF;QACArB,WAAWpB;IACb;IACA,MAAMmE,kBAAkBpE,YAAY;QAClCwB,gBAAgB,IAAMwC;QACtBvC,MAAM;QACNJ,WAAW,kBACT,KAACgD;gBACCC,OAAM;gBACNC,OAAM;gBACNC,aAAY;gBACZrD,kBAAkBA;;IAGxB;IACA,MAAMsD,oBAAoBzE,YAAY;QACpCwB,gBAAgB,IAAMD;QACtBE,MAAM;QACNJ,WAAW;YACT,MAAMgB,YAAY/B;YAClB,qBACE,KAAC+D;gBACCC,OAAM;gBACNC,OAAM;gBACNC,aAAa,CAAC,UAAU,EAAEnC,UAAU0B,IAAI,CAAC,CAAC,CAAC;gBAC3C5C,kBAAkBA;;QAGxB;IACF;IACA,OAAO;QACLuD,SAAS;YAACC,MAAMvD;YAAWG;YAAiByC;YAAeS;YAAmBL;QAAe;QAC7FhD;QACAG;QACAyC;QACAS;QACAL;IACF;AACF;AAEA,SAASC,qBAAqB,EAC5BC,KAAK,EACLC,KAAK,EACLC,WAAW,EACXrD,gBAAgB,EAMjB;IACC,MAAMS,SAAShB,eAAe,CAACgE,QAC7BN,UAAU,cAAc5D,qBAAqBkE,SAASjE,4BAA4BiE;IAEpF,IAAI,CAAChD,OAAOc,aAAa,IAAK4B,UAAU,aAAa,CAAC1C,OAAOuC,WAAW,EAAG,OAAO;IAElF,qBACE,MAACjB;QAAIC,WAAU;;0BACb,MAAC0B;gBAAO1B,WAAU;;kCAChB,KAACtD;wBAAOiF,SAAQ;kCAAMP;;kCACtB,KAACzE;wBAAKsD,MAAK;wBAAKD,WAAU;kCACvBqB;;;;0BAIL,MAACtB;gBAAIC,WAAU;;kCACb,KAAC9C;wBAAY0E,SAAS5D;wBAAkBmD,OAAOA;;kCAC/C,KAACrE;;;;;AAIT"}
@@ -16,9 +16,9 @@ export function WorkspaceSetupPending() {
16
16
  }
17
17
  export function WorkspaceUnavailablePage({ workspaceName }) {
18
18
  return /*#__PURE__*/ _jsx("main", {
19
- className: "min-h-screen bg-background-subtle-base px-24 py-32 max-[520px]:px-16",
19
+ className: "min-h-screen bg-background-subtle-base px-frame py-frame max-[520px]:px-row",
20
20
  children: /*#__PURE__*/ _jsxs("div", {
21
- className: "mx-auto flex w-full max-w-[640px] flex-col gap-12",
21
+ className: "mx-auto flex w-full max-w-[640px] flex-col gap-cluster",
22
22
  children: [
23
23
  /*#__PURE__*/ _jsx(Header, {
24
24
  variant: "h1",
@@ -46,9 +46,9 @@ export function WorkspaceLayoutErrorRoute({ error, reset }) {
46
46
  const setupError = error instanceof WorkspaceSetupLoadError;
47
47
  const message = error instanceof ApiError ? error.message : setupError && error.cause instanceof ApiError ? error.cause.message : 'Try again in a moment.';
48
48
  return /*#__PURE__*/ _jsx("main", {
49
- className: "min-h-screen bg-background-subtle-base px-24 py-32 max-[520px]:px-16",
49
+ className: "min-h-screen bg-background-subtle-base px-frame py-frame max-[520px]:px-row",
50
50
  children: /*#__PURE__*/ _jsxs("div", {
51
- className: "mx-auto flex w-full max-w-[640px] flex-col gap-24",
51
+ className: "mx-auto flex w-full max-w-[640px] flex-col gap-section",
52
52
  children: [
53
53
  /*#__PURE__*/ _jsx(Header, {
54
54
  variant: "h1",
@@ -58,7 +58,7 @@ export function WorkspaceLayoutErrorRoute({ error, reset }) {
58
58
  role: "alert",
59
59
  type: "error",
60
60
  children: /*#__PURE__*/ _jsxs("div", {
61
- className: "flex flex-col gap-8",
61
+ className: "flex flex-col gap-inline",
62
62
  children: [
63
63
  /*#__PURE__*/ _jsx(Text, {
64
64
  size: "sm",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/workspace-setup.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport type {QueryClient} from '@tanstack/react-query';\nimport {type ErrorComponentProps, useRouter} from '@tanstack/react-router';\n\nexport interface WorkspaceSetupState {\n hideProjectNavigation: boolean;\n unavailable?: boolean;\n}\nexport interface WorkspaceSetupRouteOptions {\n queryClient: QueryClient;\n workspaceId: string;\n workspaceSlug: string;\n pathname: string;\n}\nexport type WorkspaceSetupGate = (\n options: WorkspaceSetupRouteOptions,\n) => Promise<WorkspaceSetupState>;\n\nexport class WorkspaceSetupLoadError extends Error {\n constructor(public override readonly cause: unknown) {\n super(cause instanceof Error ? cause.message : 'Workspace setup load failed');\n this.name = 'WorkspaceSetupLoadError';\n }\n}\nexport function WorkspaceSetupPending() {\n return <FullPageLoader />;\n}\n\nexport function WorkspaceUnavailablePage({workspaceName}: {workspaceName?: string | undefined}) {\n return (\n <main className=\"min-h-screen bg-background-subtle-base px-24 py-32 max-[520px]:px-16\">\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-12\">\n <Header variant=\"h1\">Workspace unavailable</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n {workspaceName\n ? `${workspaceName} is currently unavailable.`\n : 'This workspace is currently unavailable.'}{' '}\n Please contact your configured support contact if you need help.\n </Text>\n </div>\n </main>\n );\n}\nexport function WorkspaceLayoutErrorRoute({error, reset}: ErrorComponentProps) {\n const router = useRouter();\n const retry = () => {\n reset();\n void router.invalidate();\n };\n const setupError = error instanceof WorkspaceSetupLoadError;\n const message =\n error instanceof ApiError\n ? error.message\n : setupError && error.cause instanceof ApiError\n ? error.cause.message\n : 'Try again in a moment.';\n return (\n <main className=\"min-h-screen bg-background-subtle-base px-24 py-32 max-[520px]:px-16\">\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-24\">\n <Header variant=\"h1\">{setupError ? 'Workspace setup' : 'Workspace'}</Header>\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n {setupError ? 'Could not load workspace setup' : 'Could not load workspace'}\n </Text>\n <Text size=\"sm\">{message}</Text>\n <Button size=\"sm\" variant=\"secondary\" onClick={retry} className=\"w-fit\">\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n </main>\n );\n}\n"],"names":["ApiError","Button","Callout","FullPageLoader","Header","Text","useRouter","WorkspaceSetupLoadError","Error","cause","message","name","WorkspaceSetupPending","WorkspaceUnavailablePage","workspaceName","main","className","div","variant","size","WorkspaceLayoutErrorRoute","error","reset","router","retry","invalidate","setupError","role","type","bold","onClick"],"mappings":";AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAC7C,SAAQC,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,cAAc,QAAO,2BAA2B;AACxD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAE1D,SAAkCC,SAAS,QAAO,yBAAyB;AAgB3E,OAAO,MAAMC,gCAAgCC;IAC3C,YAAY,AAAyBC,KAAc,CAAE;QACnD,KAAK,CAACA,iBAAiBD,QAAQC,MAAMC,OAAO,GAAG,qCADZD,QAAAA;QAEnC,IAAI,CAACE,IAAI,GAAG;IACd;AACF;AACA,OAAO,SAASC;IACd,qBAAO,KAACT;AACV;AAEA,OAAO,SAASU,yBAAyB,EAACC,aAAa,EAAuC;IAC5F,qBACE,KAACC;QAAKC,WAAU;kBACd,cAAA,MAACC;YAAID,WAAU;;8BACb,KAACZ;oBAAOc,SAAQ;8BAAK;;8BACrB,MAACb;oBAAKc,MAAK;oBAAKH,WAAU;;wBACvBF,gBACG,GAAGA,cAAc,0BAA0B,CAAC,GAC5C;wBAA4C;wBAAI;;;;;;AAM9D;AACA,OAAO,SAASM,0BAA0B,EAACC,KAAK,EAAEC,KAAK,EAAsB;IAC3E,MAAMC,SAASjB;IACf,MAAMkB,QAAQ;QACZF;QACA,KAAKC,OAAOE,UAAU;IACxB;IACA,MAAMC,aAAaL,iBAAiBd;IACpC,MAAMG,UACJW,iBAAiBrB,WACbqB,MAAMX,OAAO,GACbgB,cAAcL,MAAMZ,KAAK,YAAYT,WACnCqB,MAAMZ,KAAK,CAACC,OAAO,GACnB;IACR,qBACE,KAACK;QAAKC,WAAU;kBACd,cAAA,MAACC;YAAID,WAAU;;8BACb,KAACZ;oBAAOc,SAAQ;8BAAMQ,aAAa,oBAAoB;;8BACvD,KAACxB;oBAAQyB,MAAK;oBAAQC,MAAK;8BACzB,cAAA,MAACX;wBAAID,WAAU;;0CACb,KAACX;gCAAKc,MAAK;gCAAKU,IAAI;0CACjBH,aAAa,mCAAmC;;0CAEnD,KAACrB;gCAAKc,MAAK;0CAAMT;;0CACjB,KAACT;gCAAOkB,MAAK;gCAAKD,SAAQ;gCAAYY,SAASN;gCAAOR,WAAU;0CAAQ;;;;;;;;AAQpF"}
1
+ {"version":3,"sources":["../../src/runtime/workspace-setup.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport type {QueryClient} from '@tanstack/react-query';\nimport {type ErrorComponentProps, useRouter} from '@tanstack/react-router';\n\nexport interface WorkspaceSetupState {\n hideProjectNavigation: boolean;\n unavailable?: boolean;\n}\nexport interface WorkspaceSetupRouteOptions {\n queryClient: QueryClient;\n workspaceId: string;\n workspaceSlug: string;\n pathname: string;\n}\nexport type WorkspaceSetupGate = (\n options: WorkspaceSetupRouteOptions,\n) => Promise<WorkspaceSetupState>;\n\nexport class WorkspaceSetupLoadError extends Error {\n constructor(public override readonly cause: unknown) {\n super(cause instanceof Error ? cause.message : 'Workspace setup load failed');\n this.name = 'WorkspaceSetupLoadError';\n }\n}\nexport function WorkspaceSetupPending() {\n return <FullPageLoader />;\n}\n\nexport function WorkspaceUnavailablePage({workspaceName}: {workspaceName?: string | undefined}) {\n return (\n <main className=\"min-h-screen bg-background-subtle-base px-frame py-frame max-[520px]:px-row\">\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-cluster\">\n <Header variant=\"h1\">Workspace unavailable</Header>\n <Text size=\"md\" className=\"text-foreground-neutral-muted\">\n {workspaceName\n ? `${workspaceName} is currently unavailable.`\n : 'This workspace is currently unavailable.'}{' '}\n Please contact your configured support contact if you need help.\n </Text>\n </div>\n </main>\n );\n}\nexport function WorkspaceLayoutErrorRoute({error, reset}: ErrorComponentProps) {\n const router = useRouter();\n const retry = () => {\n reset();\n void router.invalidate();\n };\n const setupError = error instanceof WorkspaceSetupLoadError;\n const message =\n error instanceof ApiError\n ? error.message\n : setupError && error.cause instanceof ApiError\n ? error.cause.message\n : 'Try again in a moment.';\n return (\n <main className=\"min-h-screen bg-background-subtle-base px-frame py-frame max-[520px]:px-row\">\n <div className=\"mx-auto flex w-full max-w-[640px] flex-col gap-section\">\n <Header variant=\"h1\">{setupError ? 'Workspace setup' : 'Workspace'}</Header>\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-inline\">\n <Text size=\"sm\" bold>\n {setupError ? 'Could not load workspace setup' : 'Could not load workspace'}\n </Text>\n <Text size=\"sm\">{message}</Text>\n <Button size=\"sm\" variant=\"secondary\" onClick={retry} className=\"w-fit\">\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n </main>\n );\n}\n"],"names":["ApiError","Button","Callout","FullPageLoader","Header","Text","useRouter","WorkspaceSetupLoadError","Error","cause","message","name","WorkspaceSetupPending","WorkspaceUnavailablePage","workspaceName","main","className","div","variant","size","WorkspaceLayoutErrorRoute","error","reset","router","retry","invalidate","setupError","role","type","bold","onClick"],"mappings":";AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAC7C,SAAQC,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,cAAc,QAAO,2BAA2B;AACxD,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAE1D,SAAkCC,SAAS,QAAO,yBAAyB;AAgB3E,OAAO,MAAMC,gCAAgCC;IAC3C,YAAY,AAAyBC,KAAc,CAAE;QACnD,KAAK,CAACA,iBAAiBD,QAAQC,MAAMC,OAAO,GAAG,qCADZD,QAAAA;QAEnC,IAAI,CAACE,IAAI,GAAG;IACd;AACF;AACA,OAAO,SAASC;IACd,qBAAO,KAACT;AACV;AAEA,OAAO,SAASU,yBAAyB,EAACC,aAAa,EAAuC;IAC5F,qBACE,KAACC;QAAKC,WAAU;kBACd,cAAA,MAACC;YAAID,WAAU;;8BACb,KAACZ;oBAAOc,SAAQ;8BAAK;;8BACrB,MAACb;oBAAKc,MAAK;oBAAKH,WAAU;;wBACvBF,gBACG,GAAGA,cAAc,0BAA0B,CAAC,GAC5C;wBAA4C;wBAAI;;;;;;AAM9D;AACA,OAAO,SAASM,0BAA0B,EAACC,KAAK,EAAEC,KAAK,EAAsB;IAC3E,MAAMC,SAASjB;IACf,MAAMkB,QAAQ;QACZF;QACA,KAAKC,OAAOE,UAAU;IACxB;IACA,MAAMC,aAAaL,iBAAiBd;IACpC,MAAMG,UACJW,iBAAiBrB,WACbqB,MAAMX,OAAO,GACbgB,cAAcL,MAAMZ,KAAK,YAAYT,WACnCqB,MAAMZ,KAAK,CAACC,OAAO,GACnB;IACR,qBACE,KAACK;QAAKC,WAAU;kBACd,cAAA,MAACC;YAAID,WAAU;;8BACb,KAACZ;oBAAOc,SAAQ;8BAAMQ,aAAa,oBAAoB;;8BACvD,KAACxB;oBAAQyB,MAAK;oBAAQC,MAAK;8BACzB,cAAA,MAACX;wBAAID,WAAU;;0CACb,KAACX;gCAAKc,MAAK;gCAAKU,IAAI;0CACjBH,aAAa,mCAAmC;;0CAEnD,KAACrB;gCAAKc,MAAK;0CAAMT;;0CACjB,KAACT;gCAAOkB,MAAK;gCAAKD,SAAQ;gCAAYY,SAASN;gCAAOR,WAAU;0CAAQ;;;;;;;;AAQpF"}