@shipfox/client-shell 0.2.0
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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/dist/components/main-layout.d.ts +11 -0
- package/dist/components/main-layout.d.ts.map +1 -0
- package/dist/components/main-layout.js +39 -0
- package/dist/components/main-layout.js.map +1 -0
- package/dist/components/nav-bar.d.ts +4 -0
- package/dist/components/nav-bar.d.ts.map +1 -0
- package/dist/components/nav-bar.js +62 -0
- package/dist/components/nav-bar.js.map +1 -0
- package/dist/components/nav-tabs.d.ts +6 -0
- package/dist/components/nav-tabs.d.ts.map +1 -0
- package/dist/components/nav-tabs.js +38 -0
- package/dist/components/nav-tabs.js.map +1 -0
- package/dist/components/not-found-page.d.ts +2 -0
- package/dist/components/not-found-page.d.ts.map +1 -0
- package/dist/components/not-found-page.js +25 -0
- package/dist/components/not-found-page.js.map +1 -0
- package/dist/components/settings-nav.d.ts +5 -0
- package/dist/components/settings-nav.d.ts.map +1 -0
- package/dist/components/settings-nav.js +45 -0
- package/dist/components/settings-nav.js.map +1 -0
- package/dist/components/user-menu.d.ts +2 -0
- package/dist/components/user-menu.d.ts.map +1 -0
- package/dist/components/user-menu.js +76 -0
- package/dist/components/user-menu.js.map +1 -0
- package/dist/components/workspace-crumb.d.ts +7 -0
- package/dist/components/workspace-crumb.d.ts.map +1 -0
- package/dist/components/workspace-crumb.js +54 -0
- package/dist/components/workspace-crumb.js.map +1 -0
- package/dist/components/workspace-switcher.d.ts +5 -0
- package/dist/components/workspace-switcher.d.ts.map +1 -0
- package/dist/components/workspace-switcher.js +90 -0
- package/dist/components/workspace-switcher.js.map +1 -0
- package/dist/compose/compose-routes.d.ts +6 -0
- package/dist/compose/compose-routes.d.ts.map +1 -0
- package/dist/compose/compose-routes.js +53 -0
- package/dist/compose/compose-routes.js.map +1 -0
- package/dist/compose/errors.d.ts +26 -0
- package/dist/compose/errors.d.ts.map +1 -0
- package/dist/compose/errors.js +39 -0
- package/dist/compose/errors.js.map +1 -0
- package/dist/compose/merge-config.d.ts +4 -0
- package/dist/compose/merge-config.d.ts.map +1 -0
- package/dist/compose/merge-config.js +28 -0
- package/dist/compose/merge-config.js.map +1 -0
- package/dist/compose/normalize-route-path.d.ts +2 -0
- package/dist/compose/normalize-route-path.d.ts.map +1 -0
- package/dist/compose/normalize-route-path.js +7 -0
- package/dist/compose/normalize-route-path.js.map +1 -0
- package/dist/compose/validate-providers.d.ts +3 -0
- package/dist/compose/validate-providers.d.ts.map +1 -0
- package/dist/compose/validate-providers.js +32 -0
- package/dist/compose/validate-providers.js.map +1 -0
- package/dist/compose/validate-registries.d.ts +4 -0
- package/dist/compose/validate-registries.d.ts.map +1 -0
- package/dist/compose/validate-registries.js +50 -0
- package/dist/compose/validate-registries.js.map +1 -0
- package/dist/config/shell-config.d.ts +10 -0
- package/dist/config/shell-config.d.ts.map +1 -0
- package/dist/config/shell-config.js +12 -0
- package/dist/config/shell-config.js.map +1 -0
- package/dist/contract.d.ts +39 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +5 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/active-workspace.d.ts +4 -0
- package/dist/runtime/active-workspace.d.ts.map +1 -0
- package/dist/runtime/active-workspace.js +15 -0
- package/dist/runtime/active-workspace.js.map +1 -0
- package/dist/runtime/anchor-paths.d.ts +9 -0
- package/dist/runtime/anchor-paths.d.ts.map +1 -0
- package/dist/runtime/anchor-paths.js +18 -0
- package/dist/runtime/anchor-paths.js.map +1 -0
- package/dist/runtime/anchors.d.ts +19 -0
- package/dist/runtime/anchors.d.ts.map +1 -0
- package/dist/runtime/anchors.js +125 -0
- package/dist/runtime/anchors.js.map +1 -0
- package/dist/runtime/assemble-route-tree.d.ts +10 -0
- package/dist/runtime/assemble-route-tree.d.ts.map +1 -0
- package/dist/runtime/assemble-route-tree.js +30 -0
- package/dist/runtime/assemble-route-tree.js.map +1 -0
- package/dist/runtime/auth.d.ts +50 -0
- package/dist/runtime/auth.d.ts.map +1 -0
- package/dist/runtime/auth.js +194 -0
- package/dist/runtime/auth.js.map +1 -0
- package/dist/runtime/chrome-context.d.ts +10 -0
- package/dist/runtime/chrome-context.d.ts.map +1 -0
- package/dist/runtime/chrome-context.js +16 -0
- package/dist/runtime/chrome-context.js.map +1 -0
- package/dist/runtime/compose-client-app.d.ts +13 -0
- package/dist/runtime/compose-client-app.d.ts.map +1 -0
- package/dist/runtime/compose-client-app.js +93 -0
- package/dist/runtime/compose-client-app.js.map +1 -0
- package/dist/runtime/define-route.d.ts +19 -0
- package/dist/runtime/define-route.d.ts.map +1 -0
- package/dist/runtime/define-route.js +12 -0
- package/dist/runtime/define-route.js.map +1 -0
- package/dist/runtime/index.d.ts +20 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +21 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/last-workspace.d.ts +4 -0
- package/dist/runtime/last-workspace.d.ts.map +1 -0
- package/dist/runtime/last-workspace.js +20 -0
- package/dist/runtime/last-workspace.js.map +1 -0
- package/dist/runtime/nav-order.d.ts +7 -0
- package/dist/runtime/nav-order.d.ts.map +1 -0
- package/dist/runtime/nav-order.js +8 -0
- package/dist/runtime/nav-order.js.map +1 -0
- package/dist/runtime/provider-stack.d.ts +14 -0
- package/dist/runtime/provider-stack.d.ts.map +1 -0
- package/dist/runtime/provider-stack.js +28 -0
- package/dist/runtime/provider-stack.js.map +1 -0
- package/dist/runtime/registries.d.ts +4 -0
- package/dist/runtime/registries.d.ts.map +1 -0
- package/dist/runtime/registries.js +23 -0
- package/dist/runtime/registries.js.map +1 -0
- package/dist/runtime/router-context.d.ts +9 -0
- package/dist/runtime/router-context.d.ts.map +1 -0
- package/dist/runtime/router-context.js +3 -0
- package/dist/runtime/router-context.js.map +1 -0
- package/dist/runtime/workspace-setup.d.ts +18 -0
- package/dist/runtime/workspace-setup.d.ts.map +1 -0
- package/dist/runtime/workspace-setup.js +64 -0
- package/dist/runtime/workspace-setup.js.map +1 -0
- package/dist/testing/index.d.ts +17 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +35 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/dist/vite/evaluate-features.d.ts +8 -0
- package/dist/vite/evaluate-features.d.ts.map +1 -0
- package/dist/vite/evaluate-features.js +80 -0
- package/dist/vite/evaluate-features.js.map +1 -0
- package/dist/vite/generate.d.ts +9 -0
- package/dist/vite/generate.d.ts.map +1 -0
- package/dist/vite/generate.js +80 -0
- package/dist/vite/generate.js.map +1 -0
- package/dist/vite/index.d.ts +2 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +3 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/plugin.d.ts +7 -0
- package/dist/vite/plugin.d.ts.map +1 -0
- package/dist/vite/plugin.js +77 -0
- package/dist/vite/plugin.js.map +1 -0
- package/package.json +113 -0
- package/src/components/main-layout.tsx +45 -0
- package/src/components/nav-bar.tsx +41 -0
- package/src/components/nav-tabs.test.tsx +60 -0
- package/src/components/nav-tabs.tsx +47 -0
- package/src/components/not-found-page.tsx +14 -0
- package/src/components/settings-nav.tsx +35 -0
- package/src/components/user-menu.tsx +59 -0
- package/src/components/workspace-crumb.tsx +43 -0
- package/src/components/workspace-switcher.tsx +75 -0
- package/src/compose/compose-routes.test.ts +112 -0
- package/src/compose/compose-routes.ts +60 -0
- package/src/compose/errors.ts +54 -0
- package/src/compose/merge-config.test.ts +26 -0
- package/src/compose/merge-config.ts +27 -0
- package/src/compose/normalize-route-path.ts +6 -0
- package/src/compose/validate-providers.test.ts +31 -0
- package/src/compose/validate-providers.ts +36 -0
- package/src/compose/validate-registries.test.ts +92 -0
- package/src/compose/validate-registries.ts +61 -0
- package/src/config/config-screen.test.tsx +37 -0
- package/src/config/shell-config.ts +10 -0
- package/src/contract.ts +47 -0
- package/src/index.ts +1 -0
- package/src/runtime/active-workspace.ts +13 -0
- package/src/runtime/anchor-paths.ts +18 -0
- package/src/runtime/anchors.tsx +106 -0
- package/src/runtime/assemble-route-tree.ts +42 -0
- package/src/runtime/auth.tsx +213 -0
- package/src/runtime/chrome-context.tsx +22 -0
- package/src/runtime/compose-client-app.tsx +122 -0
- package/src/runtime/define-route.test.ts +15 -0
- package/src/runtime/define-route.ts +33 -0
- package/src/runtime/index.ts +19 -0
- package/src/runtime/last-workspace.ts +22 -0
- package/src/runtime/nav-order.ts +1 -0
- package/src/runtime/provider-stack.tsx +39 -0
- package/src/runtime/providers.test.tsx +51 -0
- package/src/runtime/registries.test.tsx +100 -0
- package/src/runtime/registries.ts +42 -0
- package/src/runtime/router-context.ts +9 -0
- package/src/runtime/routes.test.tsx +48 -0
- package/src/runtime/workspace-setup.tsx +61 -0
- package/src/testing/index.test.tsx +57 -0
- package/src/testing/index.tsx +51 -0
- package/src/vite/evaluate-features.test.ts +34 -0
- package/src/vite/evaluate-features.ts +93 -0
- package/src/vite/generate.test.ts +22 -0
- package/src/vite/generate.ts +99 -0
- package/src/vite/generated-router.test.tsx +58 -0
- package/src/vite/index.ts +1 -0
- package/src/vite/plugin.test.ts +181 -0
- package/src/vite/plugin.ts +114 -0
- package/src/vite/validate.test.ts +166 -0
- package/test/default-route-impl.tsx +3 -0
- package/test/external/FINDINGS.md +53 -0
- package/test/external/README.md +39 -0
- package/test/external/fixture/index.html +12 -0
- package/test/external/fixture/package.json +32 -0
- package/test/external/fixture/src/app.fixture.tsx +72 -0
- package/test/external/fixture/src/features/override-impl.tsx +12 -0
- package/test/external/fixture/src/features/override.tsx +20 -0
- package/test/external/fixture/src/features.collision.ts +15 -0
- package/test/external/fixture/src/features.ts +4 -0
- package/test/external/fixture/src/link-typecheck.tsx +10 -0
- package/test/external/fixture/src/main.tsx +4 -0
- package/test/external/fixture/tsconfig.json +15 -0
- package/test/external/fixture/vite.config.ts +10 -0
- package/test/external/fixture/vitest.config.ts +15 -0
- package/test/external/toy-feature/CHANGELOG.md +15 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-biome-check +43 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-biome-format +43 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-biome-lint +43 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-swc +43 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-tsc-check +43 -0
- package/test/external/toy-feature/node_modules/.bin/shipfox-tsc-emit +43 -0
- package/test/external/toy-feature/package.json +57 -0
- package/test/external/toy-feature/src/config.ts +5 -0
- package/test/external/toy-feature/src/index.ts +64 -0
- package/test/external/toy-feature/src/provider.tsx +33 -0
- package/test/external/toy-feature/src/routes/insights.tsx +7 -0
- package/test/external/toy-feature/src/routes/settings.tsx +7 -0
- package/test/external/toy-feature/tsconfig.build.json +5 -0
- package/test/external/toy-feature/tsconfig.json +1 -0
- package/test/external/verify.mjs +318 -0
- package/test/fixtures/features.ts +56 -0
- package/test/named-route-impl.tsx +3 -0
- package/test/not-route-impl.ts +1 -0
- package/test/render.tsx +67 -0
- package/test/search-route-impl.tsx +7 -0
- package/test/setup.ts +3 -0
- package/test/typecheck/shipfox-app.gen.ts +85 -0
- package/test/typecheck/types.tsx +18 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +1 -0
- package/tsconfig.test.json +12 -0
- package/vitest.config.ts +22 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ shipfox-tsc-emit
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ shipfox-tsc-check
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3d064b8: Publishes the client runtime closure with shell, feature, route, Vite, and testing contracts.
|
|
8
|
+
- 6bc2e45: Adds the composable upstream client shell, feature catalog, and route manifests for every client feature.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [3d064b8]
|
|
13
|
+
- @shipfox/client-api@0.2.0
|
|
14
|
+
- @shipfox/client-config@0.2.0
|
|
15
|
+
|
|
16
|
+
## 0.0.2
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [c18d624]
|
|
21
|
+
- @shipfox/react-ui@0.3.1
|
|
22
|
+
- @shipfox/client-config@0.0.2
|
|
23
|
+
|
|
24
|
+
## 0.0.1
|
|
25
|
+
|
|
26
|
+
- Add the private candidate client composition shell.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shipfox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NavTabEntry } from '#contract.js';
|
|
2
|
+
declare module '@tanstack/react-router' {
|
|
3
|
+
interface StaticDataRouteOption {
|
|
4
|
+
layout?: 'full-bleed';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export declare function MainLayout({ navigation, hideProjectNavigation, }: {
|
|
8
|
+
navigation: readonly NavTabEntry[];
|
|
9
|
+
hideProjectNavigation?: boolean;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=main-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-layout.d.ts","sourceRoot":"","sources":["../../src/components/main-layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAK9C,OAAO,QAAQ,wBAAwB,CAAC;IACtC,UAAU,qBAAqB;QAC7B,MAAM,CAAC,EAAE,YAAY,CAAC;KACvB;CACF;AAED,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,qBAA6B,GAC9B,EAAE;IACD,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,+BAyBA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FullPageLoader } from '@shipfox/react-ui/loader';
|
|
3
|
+
import { Outlet, useMatches, useParams } from '@tanstack/react-router';
|
|
4
|
+
import { useMaybeActiveWorkspace } from '#runtime/active-workspace.js';
|
|
5
|
+
import { NavBar } from './nav-bar.js';
|
|
6
|
+
import { NavTabs } from './nav-tabs.js';
|
|
7
|
+
export function MainLayout({ navigation, hideProjectNavigation = false }) {
|
|
8
|
+
const workspace = useMaybeActiveWorkspace();
|
|
9
|
+
const { pid } = useParams({
|
|
10
|
+
strict: false
|
|
11
|
+
});
|
|
12
|
+
const matches = useMatches();
|
|
13
|
+
if (!workspace) return /*#__PURE__*/ _jsx(FullPageLoader, {});
|
|
14
|
+
const fullBleed = matches.some((match)=>match.staticData.layout === 'full-bleed');
|
|
15
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
16
|
+
className: "h-screen w-full flex flex-col bg-background-subtle-base",
|
|
17
|
+
children: [
|
|
18
|
+
/*#__PURE__*/ _jsx(NavBar, {
|
|
19
|
+
hideProjectNavigation: hideProjectNavigation
|
|
20
|
+
}),
|
|
21
|
+
hideProjectNavigation ? undefined : /*#__PURE__*/ _jsx(NavTabs, {
|
|
22
|
+
entries: navigation,
|
|
23
|
+
scope: pid ? 'project' : 'workspace'
|
|
24
|
+
}),
|
|
25
|
+
fullBleed ? /*#__PURE__*/ _jsx("main", {
|
|
26
|
+
className: "flex-1 min-h-0 flex flex-col overflow-hidden",
|
|
27
|
+
children: /*#__PURE__*/ _jsx(Outlet, {})
|
|
28
|
+
}) : /*#__PURE__*/ _jsx("main", {
|
|
29
|
+
className: "flex-1 overflow-auto",
|
|
30
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
31
|
+
className: "max-w-[1120px] mx-auto px-24 py-32",
|
|
32
|
+
children: /*#__PURE__*/ _jsx(Outlet, {})
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=main-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/main-layout.tsx"],"sourcesContent":["import {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Outlet, useMatches, useParams} from '@tanstack/react-router';\nimport type {NavTabEntry} from '#contract.js';\nimport {useMaybeActiveWorkspace} from '#runtime/active-workspace.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 {pid} = useParams({strict: false}) as {pid?: string};\n const matches = useMatches();\n if (!workspace) return <FullPageLoader />;\n const fullBleed = matches.some((match) => match.staticData.layout === 'full-bleed');\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={pid ? '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\">\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","useParams","useMaybeActiveWorkspace","NavBar","NavTabs","MainLayout","navigation","hideProjectNavigation","workspace","pid","strict","matches","fullBleed","some","match","staticData","layout","div","className","undefined","entries","scope","main"],"mappings":";AAAA,SAAQA,cAAc,QAAO,2BAA2B;AACxD,SAAQC,MAAM,EAAEC,UAAU,EAAEC,SAAS,QAAO,yBAAyB;AAErE,SAAQC,uBAAuB,QAAO,+BAA+B;AACrE,SAAQC,MAAM,QAAO,eAAe;AACpC,SAAQC,OAAO,QAAO,gBAAgB;AAQtC,OAAO,SAASC,WAAW,EACzBC,UAAU,EACVC,wBAAwB,KAAK,EAI9B;IACC,MAAMC,YAAYN;IAClB,MAAM,EAACO,GAAG,EAAC,GAAGR,UAAU;QAACS,QAAQ;IAAK;IACtC,MAAMC,UAAUX;IAChB,IAAI,CAACQ,WAAW,qBAAO,KAACV;IACxB,MAAMc,YAAYD,QAAQE,IAAI,CAAC,CAACC,QAAUA,MAAMC,UAAU,CAACC,MAAM,KAAK;IACtE,qBACE,MAACC;QAAIC,WAAU;;0BACb,KAACf;gBAAOI,uBAAuBA;;YAC9BA,wBAAwBY,0BACvB,KAACf;gBAAQgB,SAASd;gBAAYe,OAAOZ,MAAM,YAAY;;YAExDG,0BACC,KAACU;gBAAKJ,WAAU;0BACd,cAAA,KAACnB;+BAGH,KAACuB;gBAAKJ,WAAU;0BACd,cAAA,KAACD;oBAAIC,WAAU;8BACb,cAAA,KAACnB;;;;;AAMb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-bar.d.ts","sourceRoot":"","sources":["../../src/components/nav-bar.tsx"],"names":[],"mappings":"AAOA,wBAAgB,MAAM,CAAC,EAAC,qBAA6B,EAAC,EAAE;IAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAAC,+BAiCxF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Logo } from '@shipfox/react-ui/logo';
|
|
3
|
+
import { Link } from '@tanstack/react-router';
|
|
4
|
+
import { useActiveWorkspace } from '#runtime/active-workspace.js';
|
|
5
|
+
import { useChrome } from '#runtime/chrome-context.js';
|
|
6
|
+
import { UserMenu } from './user-menu.js';
|
|
7
|
+
import { WorkspaceCrumb } from './workspace-crumb.js';
|
|
8
|
+
export function NavBar({ hideProjectNavigation = false }) {
|
|
9
|
+
const workspace = useActiveWorkspace();
|
|
10
|
+
const { ProjectBreadcrumb } = useChrome();
|
|
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",
|
|
13
|
+
children: [
|
|
14
|
+
/*#__PURE__*/ _jsx(Link, {
|
|
15
|
+
to: "/",
|
|
16
|
+
"aria-label": "Shipfox home",
|
|
17
|
+
className: "rounded-6 focus-visible:outline-none focus-visible:shadow-button-neutral-focus",
|
|
18
|
+
children: hideProjectNavigation ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
19
|
+
children: [
|
|
20
|
+
/*#__PURE__*/ _jsx(Logo, {
|
|
21
|
+
variant: "mark",
|
|
22
|
+
alt: "",
|
|
23
|
+
className: "sm:hidden"
|
|
24
|
+
}),
|
|
25
|
+
/*#__PURE__*/ _jsx(Logo, {
|
|
26
|
+
variant: "wordmark",
|
|
27
|
+
alt: "",
|
|
28
|
+
className: "hidden sm:block"
|
|
29
|
+
})
|
|
30
|
+
]
|
|
31
|
+
}) : /*#__PURE__*/ _jsx(Logo, {
|
|
32
|
+
variant: "wordmark",
|
|
33
|
+
alt: ""
|
|
34
|
+
})
|
|
35
|
+
}),
|
|
36
|
+
/*#__PURE__*/ _jsx("span", {
|
|
37
|
+
className: "h-20 w-px bg-border-neutral-base",
|
|
38
|
+
"aria-hidden": "true"
|
|
39
|
+
}),
|
|
40
|
+
/*#__PURE__*/ _jsx(WorkspaceCrumb, {
|
|
41
|
+
workspace: workspace,
|
|
42
|
+
compact: hideProjectNavigation
|
|
43
|
+
}),
|
|
44
|
+
hideProjectNavigation ? undefined : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
45
|
+
children: [
|
|
46
|
+
/*#__PURE__*/ _jsx("span", {
|
|
47
|
+
className: "text-foreground-neutral-muted",
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
children: "/"
|
|
50
|
+
}),
|
|
51
|
+
/*#__PURE__*/ _jsx(ProjectBreadcrumb, {})
|
|
52
|
+
]
|
|
53
|
+
}),
|
|
54
|
+
/*#__PURE__*/ _jsx("div", {
|
|
55
|
+
className: "flex-1"
|
|
56
|
+
}),
|
|
57
|
+
/*#__PURE__*/ _jsx(UserMenu, {})
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=nav-bar.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-tabs.d.ts","sourceRoot":"","sources":["../../src/components/nav-tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CAC7B,+BAoCA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Link, useParams } from '@tanstack/react-router';
|
|
3
|
+
import { useReducedMotion } from 'framer-motion';
|
|
4
|
+
export function NavTabs({ entries, scope }) {
|
|
5
|
+
const params = useParams({
|
|
6
|
+
strict: false
|
|
7
|
+
});
|
|
8
|
+
const reduced = useReducedMotion();
|
|
9
|
+
const tabs = entries.filter((entry)=>entry.scope === scope);
|
|
10
|
+
const tabClassName = `h-40 inline-flex items-center px-4 text-sm font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;
|
|
11
|
+
const activeProps = {
|
|
12
|
+
className: 'border-b-2 border-border-highlights-interactive text-foreground-neutral-base',
|
|
13
|
+
'aria-selected': 'true'
|
|
14
|
+
};
|
|
15
|
+
const inactiveProps = {
|
|
16
|
+
className: 'border-b-2 border-transparent text-foreground-neutral-muted',
|
|
17
|
+
'aria-selected': 'false'
|
|
18
|
+
};
|
|
19
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
20
|
+
role: "tablist",
|
|
21
|
+
"aria-label": `${scope === 'project' ? 'Project' : 'Workspace'} sections`,
|
|
22
|
+
className: "sticky top-56 z-20 h-40 px-16 flex items-end gap-12 bg-background-subtle-base border-b border-border-neutral-base",
|
|
23
|
+
children: tabs.map((entry)=>/*#__PURE__*/ _jsx(Link, {
|
|
24
|
+
to: entry.to,
|
|
25
|
+
params: params,
|
|
26
|
+
role: "tab",
|
|
27
|
+
activeOptions: {
|
|
28
|
+
exact: entry.exact ?? false
|
|
29
|
+
},
|
|
30
|
+
activeProps: activeProps,
|
|
31
|
+
inactiveProps: inactiveProps,
|
|
32
|
+
className: tabClassName,
|
|
33
|
+
children: entry.label
|
|
34
|
+
}, entry.id))
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=nav-tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/nav-tabs.tsx"],"sourcesContent":["import {Link, useParams} from '@tanstack/react-router';\nimport {useReducedMotion} from 'framer-motion';\nimport type {NavTabEntry} from '#contract.js';\n\nexport function NavTabs({\n entries,\n scope,\n}: {\n entries: readonly NavTabEntry[];\n scope: NavTabEntry['scope'];\n}) {\n const params = useParams({strict: false}) as {wid?: string; pid?: string};\n const reduced = useReducedMotion();\n const tabs = entries.filter((entry) => entry.scope === scope);\n const tabClassName = `h-40 inline-flex items-center px-4 text-sm font-medium transition-colors ${reduced ? '' : 'transition-[border-color]'}`;\n const activeProps = {\n className: 'border-b-2 border-border-highlights-interactive text-foreground-neutral-base',\n 'aria-selected': 'true' as const,\n };\n const inactiveProps = {\n className: 'border-b-2 border-transparent text-foreground-neutral-muted',\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 h-40 px-16 flex items-end gap-12 bg-background-subtle-base border-b border-border-neutral-base\"\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","useParams","useReducedMotion","NavTabs","entries","scope","params","strict","reduced","tabs","filter","entry","tabClassName","activeProps","className","inactiveProps","div","role","aria-label","map","to","activeOptions","exact","label","id"],"mappings":";AAAA,SAAQA,IAAI,EAAEC,SAAS,QAAO,yBAAyB;AACvD,SAAQC,gBAAgB,QAAO,gBAAgB;AAG/C,OAAO,SAASC,QAAQ,EACtBC,OAAO,EACPC,KAAK,EAIN;IACC,MAAMC,SAASL,UAAU;QAACM,QAAQ;IAAK;IACvC,MAAMC,UAAUN;IAChB,MAAMO,OAAOL,QAAQM,MAAM,CAAC,CAACC,QAAUA,MAAMN,KAAK,KAAKA;IACvD,MAAMO,eAAe,CAAC,yEAAyE,EAAEJ,UAAU,KAAK,6BAA6B;IAC7I,MAAMK,cAAc;QAClBC,WAAW;QACX,iBAAiB;IACnB;IACA,MAAMC,gBAAgB;QACpBD,WAAW;QACX,iBAAiB;IACnB;IAEA,qBACE,KAACE;QACCC,MAAK;QACLC,cAAY,GAAGb,UAAU,YAAY,YAAY,YAAY,SAAS,CAAC;QACvES,WAAU;kBAETL,KAAKU,GAAG,CAAC,CAACR,sBACT,KAACX;gBAECoB,IAAIT,MAAMS,EAAE;gBACZd,QAAQA;gBACRW,MAAK;gBACLI,eAAe;oBAACC,OAAOX,MAAMW,KAAK,IAAI;gBAAK;gBAC3CT,aAAaA;gBACbE,eAAeA;gBACfD,WAAWF;0BAEVD,MAAMY,KAAK;eATPZ,MAAMa,EAAE;;AAcvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found-page.d.ts","sourceRoot":"","sources":["../../src/components/not-found-page.tsx"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,gCAU3B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Header, Text } from '@shipfox/react-ui/typography';
|
|
3
|
+
import { Link } from '@tanstack/react-router';
|
|
4
|
+
export function NotFoundPage() {
|
|
5
|
+
return /*#__PURE__*/ _jsxs("main", {
|
|
6
|
+
className: "mx-auto max-w-[960px] px-24 py-48",
|
|
7
|
+
children: [
|
|
8
|
+
/*#__PURE__*/ _jsx(Header, {
|
|
9
|
+
variant: "h1",
|
|
10
|
+
children: "Page not found"
|
|
11
|
+
}),
|
|
12
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
13
|
+
size: "md",
|
|
14
|
+
className: "text-foreground-neutral-muted",
|
|
15
|
+
children: "This Shipfox page does not exist."
|
|
16
|
+
}),
|
|
17
|
+
/*#__PURE__*/ _jsx(Link, {
|
|
18
|
+
to: "/",
|
|
19
|
+
children: "Go home"
|
|
20
|
+
})
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=not-found-page.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-nav.d.ts","sourceRoot":"","sources":["../../src/components/settings-nav.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAEvD,wBAAgB,WAAW,CAAC,EAAC,OAAO,EAAC,EAAE;IAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAAC,sCA6BhF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@shipfox/react-ui/button';
|
|
3
|
+
import { Icon } from '@shipfox/react-ui/icon';
|
|
4
|
+
import { Link, useMatchRoute, useParams } from '@tanstack/react-router';
|
|
5
|
+
export function SettingsNav({ entries }) {
|
|
6
|
+
const params = useParams({
|
|
7
|
+
strict: false
|
|
8
|
+
});
|
|
9
|
+
const matchRoute = useMatchRoute();
|
|
10
|
+
if (!params.wid) return null;
|
|
11
|
+
return /*#__PURE__*/ _jsx("nav", {
|
|
12
|
+
"aria-label": "Workspace settings",
|
|
13
|
+
className: "flex flex-col gap-4",
|
|
14
|
+
children: entries.map((entry)=>{
|
|
15
|
+
const to = `/workspaces/$wid/settings/${entry.pathSegment}`;
|
|
16
|
+
const active = Boolean(matchRoute({
|
|
17
|
+
to: to,
|
|
18
|
+
params: {
|
|
19
|
+
wid: params.wid
|
|
20
|
+
}
|
|
21
|
+
}));
|
|
22
|
+
return /*#__PURE__*/ _jsx(Button, {
|
|
23
|
+
asChild: true,
|
|
24
|
+
variant: active ? 'secondary' : 'transparent',
|
|
25
|
+
className: "w-full justify-start",
|
|
26
|
+
children: /*#__PURE__*/ _jsxs(Link, {
|
|
27
|
+
to: to,
|
|
28
|
+
params: {
|
|
29
|
+
wid: params.wid
|
|
30
|
+
},
|
|
31
|
+
"aria-current": active ? 'page' : undefined,
|
|
32
|
+
children: [
|
|
33
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
34
|
+
name: entry.icon,
|
|
35
|
+
className: "size-16"
|
|
36
|
+
}),
|
|
37
|
+
entry.label
|
|
38
|
+
]
|
|
39
|
+
})
|
|
40
|
+
}, entry.id);
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=settings-nav.js.map
|
|
@@ -0,0 +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, useParams} from '@tanstack/react-router';\nimport type {SettingsSectionEntry} from '#contract.js';\n\nexport function SettingsNav({entries}: {entries: readonly SettingsSectionEntry[]}) {\n const params = useParams({strict: false}) as {wid?: string};\n const matchRoute = useMatchRoute();\n if (!params.wid) return null;\n return (\n <nav aria-label=\"Workspace settings\" className=\"flex flex-col gap-4\">\n {entries.map((entry) => {\n const to = `/workspaces/$wid/settings/${entry.pathSegment}`;\n const active = Boolean(matchRoute({to: to as never, params: {wid: params.wid} 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={{wid: params.wid} 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","useParams","SettingsNav","entries","params","strict","matchRoute","wid","nav","aria-label","className","map","entry","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,EAAEC,SAAS,QAAO,yBAAyB;AAGtE,OAAO,SAASC,YAAY,EAACC,OAAO,EAA6C;IAC/E,MAAMC,SAASH,UAAU;QAACI,QAAQ;IAAK;IACvC,MAAMC,aAAaN;IACnB,IAAI,CAACI,OAAOG,GAAG,EAAE,OAAO;IACxB,qBACE,KAACC;QAAIC,cAAW;QAAqBC,WAAU;kBAC5CP,QAAQQ,GAAG,CAAC,CAACC;YACZ,MAAMC,KAAK,CAAC,0BAA0B,EAAED,MAAME,WAAW,EAAE;YAC3D,MAAMC,SAASC,QAAQV,WAAW;gBAACO,IAAIA;gBAAaT,QAAQ;oBAACG,KAAKH,OAAOG,GAAG;gBAAA;YAAU;YACtF,qBACE,KAACV;gBAECoB,OAAO;gBACPC,SAASH,SAAS,cAAc;gBAChCL,WAAU;0BAEV,cAAA,MAACX;oBACCc,IAAIA;oBACJT,QAAQ;wBAACG,KAAKH,OAAOG,GAAG;oBAAA;oBACxBY,gBAAcJ,SAAS,SAASK;;sCAEhC,KAACtB;4BAAKuB,MAAMT,MAAMU,IAAI;4BAAEZ,WAAU;;wBACjCE,MAAMW,KAAK;;;eAXTX,MAAMY,EAAE;QAenB;;AAGN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-menu.d.ts","sourceRoot":"","sources":["../../src/components/user-menu.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,QAAQ,gCAqCvB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Avatar } from '@shipfox/react-ui/avatar';
|
|
3
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@shipfox/react-ui/dropdown-menu';
|
|
4
|
+
import { useTheme } from '@shipfox/react-ui/hooks';
|
|
5
|
+
import { Link } from '@tanstack/react-router';
|
|
6
|
+
import { useAuthState } from '#runtime/auth.js';
|
|
7
|
+
const themeOptions = [
|
|
8
|
+
{
|
|
9
|
+
value: 'light',
|
|
10
|
+
label: 'Light'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
value: 'dark',
|
|
14
|
+
label: 'Dark'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
value: 'system',
|
|
18
|
+
label: 'System'
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
export function UserMenu() {
|
|
22
|
+
const { user } = useAuthState();
|
|
23
|
+
const { theme, setTheme } = useTheme();
|
|
24
|
+
const email = user?.email ?? '';
|
|
25
|
+
return /*#__PURE__*/ _jsxs(DropdownMenu, {
|
|
26
|
+
children: [
|
|
27
|
+
/*#__PURE__*/ _jsx(DropdownMenuTrigger, {
|
|
28
|
+
asChild: true,
|
|
29
|
+
children: /*#__PURE__*/ _jsx("button", {
|
|
30
|
+
type: "button",
|
|
31
|
+
"aria-label": "User menu",
|
|
32
|
+
className: "rounded-full focus-visible:outline-none focus-visible:shadow-button-neutral-focus",
|
|
33
|
+
children: /*#__PURE__*/ _jsx(Avatar, {
|
|
34
|
+
size: "sm",
|
|
35
|
+
content: "letters",
|
|
36
|
+
fallback: email
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
}),
|
|
40
|
+
/*#__PURE__*/ _jsxs(DropdownMenuContent, {
|
|
41
|
+
align: "end",
|
|
42
|
+
sideOffset: 8,
|
|
43
|
+
className: "min-w-[220px]",
|
|
44
|
+
children: [
|
|
45
|
+
/*#__PURE__*/ _jsx(DropdownMenuLabel, {
|
|
46
|
+
className: "text-xs text-foreground-neutral-muted truncate",
|
|
47
|
+
children: email
|
|
48
|
+
}),
|
|
49
|
+
/*#__PURE__*/ _jsx(DropdownMenuSeparator, {}),
|
|
50
|
+
/*#__PURE__*/ _jsx(DropdownMenuLabel, {
|
|
51
|
+
className: "text-xs text-foreground-neutral-muted",
|
|
52
|
+
children: "Theme"
|
|
53
|
+
}),
|
|
54
|
+
/*#__PURE__*/ _jsx(DropdownMenuRadioGroup, {
|
|
55
|
+
value: theme,
|
|
56
|
+
onValueChange: (value)=>setTheme(value),
|
|
57
|
+
children: themeOptions.map((option)=>/*#__PURE__*/ _jsx(DropdownMenuRadioItem, {
|
|
58
|
+
value: option.value,
|
|
59
|
+
children: option.label
|
|
60
|
+
}, option.value))
|
|
61
|
+
}),
|
|
62
|
+
/*#__PURE__*/ _jsx(DropdownMenuSeparator, {}),
|
|
63
|
+
/*#__PURE__*/ _jsx(DropdownMenuItem, {
|
|
64
|
+
asChild: true,
|
|
65
|
+
children: /*#__PURE__*/ _jsx(Link, {
|
|
66
|
+
to: '/auth/logout',
|
|
67
|
+
children: "Logout"
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
})
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=user-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/user-menu.tsx"],"sourcesContent":["import {Avatar} from '@shipfox/react-ui/avatar';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {useTheme} from '@shipfox/react-ui/hooks';\nimport type {Theme} from '@shipfox/react-ui/theme';\nimport {Link} from '@tanstack/react-router';\nimport {useAuthState} from '#runtime/auth.js';\n\nconst themeOptions: Array<{value: Theme; label: string}> = [\n {value: 'light', label: 'Light'},\n {value: 'dark', label: 'Dark'},\n {value: 'system', label: 'System'},\n];\nexport function UserMenu() {\n const {user} = useAuthState();\n const {theme, setTheme} = useTheme();\n const email = user?.email ?? '';\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"User menu\"\n className=\"rounded-full focus-visible:outline-none focus-visible:shadow-button-neutral-focus\"\n >\n <Avatar size=\"sm\" content=\"letters\" fallback={email} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" sideOffset={8} className=\"min-w-[220px]\">\n <DropdownMenuLabel className=\"text-xs text-foreground-neutral-muted truncate\">\n {email}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuLabel className=\"text-xs text-foreground-neutral-muted\">\n Theme\n </DropdownMenuLabel>\n <DropdownMenuRadioGroup value={theme} onValueChange={(value) => setTheme(value as Theme)}>\n {themeOptions.map((option) => (\n <DropdownMenuRadioItem key={option.value} value={option.value}>\n {option.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem asChild>\n <Link to={'/auth/logout' as never}>Logout</Link>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"names":["Avatar","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuLabel","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuSeparator","DropdownMenuTrigger","useTheme","Link","useAuthState","themeOptions","value","label","UserMenu","user","theme","setTheme","email","asChild","button","type","aria-label","className","size","content","fallback","align","sideOffset","onValueChange","map","option","to"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SACEC,YAAY,EACZC,mBAAmB,EACnBC,gBAAgB,EAChBC,iBAAiB,EACjBC,sBAAsB,EACtBC,qBAAqB,EACrBC,qBAAqB,EACrBC,mBAAmB,QACd,kCAAkC;AACzC,SAAQC,QAAQ,QAAO,0BAA0B;AAEjD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,YAAY,QAAO,mBAAmB;AAE9C,MAAMC,eAAqD;IACzD;QAACC,OAAO;QAASC,OAAO;IAAO;IAC/B;QAACD,OAAO;QAAQC,OAAO;IAAM;IAC7B;QAACD,OAAO;QAAUC,OAAO;IAAQ;CAClC;AACD,OAAO,SAASC;IACd,MAAM,EAACC,IAAI,EAAC,GAAGL;IACf,MAAM,EAACM,KAAK,EAAEC,QAAQ,EAAC,GAAGT;IAC1B,MAAMU,QAAQH,MAAMG,SAAS;IAC7B,qBACE,MAAClB;;0BACC,KAACO;gBAAoBY,OAAO;0BAC1B,cAAA,KAACC;oBACCC,MAAK;oBACLC,cAAW;oBACXC,WAAU;8BAEV,cAAA,KAACxB;wBAAOyB,MAAK;wBAAKC,SAAQ;wBAAUC,UAAUR;;;;0BAGlD,MAACjB;gBAAoB0B,OAAM;gBAAMC,YAAY;gBAAGL,WAAU;;kCACxD,KAACpB;wBAAkBoB,WAAU;kCAC1BL;;kCAEH,KAACZ;kCACD,KAACH;wBAAkBoB,WAAU;kCAAwC;;kCAGrE,KAACnB;wBAAuBQ,OAAOI;wBAAOa,eAAe,CAACjB,QAAUK,SAASL;kCACtED,aAAamB,GAAG,CAAC,CAACC,uBACjB,KAAC1B;gCAAyCO,OAAOmB,OAAOnB,KAAK;0CAC1DmB,OAAOlB,KAAK;+BADakB,OAAOnB,KAAK;;kCAK5C,KAACN;kCACD,KAACJ;wBAAiBiB,OAAO;kCACvB,cAAA,KAACV;4BAAKuB,IAAI;sCAAyB;;;;;;;AAK7C"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Workspace } from '#runtime/auth.js';
|
|
2
|
+
export interface WorkspaceCrumbProps {
|
|
3
|
+
workspace: Workspace;
|
|
4
|
+
compact?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function WorkspaceCrumb({ workspace, compact }: WorkspaceCrumbProps): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=workspace-crumb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-crumb.d.ts","sourceRoot":"","sources":["../../src/components/workspace-crumb.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAGhD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,EAAC,SAAS,EAAE,OAAe,EAAC,EAAE,mBAAmB,+BA8B/E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@shipfox/react-ui/icon';
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger } from '@shipfox/react-ui/popover';
|
|
4
|
+
import { Link } from '@tanstack/react-router';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { WorkspaceSwitcher } from './workspace-switcher.js';
|
|
7
|
+
export function WorkspaceCrumb({ workspace, compact = false }) {
|
|
8
|
+
const [open, setOpen] = useState(false);
|
|
9
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
10
|
+
className: "flex items-center",
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ _jsx(Link, {
|
|
13
|
+
to: "/workspaces/$wid",
|
|
14
|
+
params: {
|
|
15
|
+
wid: workspace.id
|
|
16
|
+
},
|
|
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]'}`,
|
|
19
|
+
children: workspace.name
|
|
20
|
+
}),
|
|
21
|
+
/*#__PURE__*/ _jsxs(Popover, {
|
|
22
|
+
open: open,
|
|
23
|
+
onOpenChange: setOpen,
|
|
24
|
+
children: [
|
|
25
|
+
/*#__PURE__*/ _jsx(PopoverTrigger, {
|
|
26
|
+
asChild: true,
|
|
27
|
+
children: /*#__PURE__*/ _jsx("button", {
|
|
28
|
+
type: "button",
|
|
29
|
+
"aria-label": "Switch workspace",
|
|
30
|
+
"aria-haspopup": "listbox",
|
|
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",
|
|
33
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
34
|
+
name: "arrowDownSLine",
|
|
35
|
+
className: "size-16"
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
/*#__PURE__*/ _jsx(PopoverContent, {
|
|
40
|
+
className: "w-[280px] p-0",
|
|
41
|
+
align: "start",
|
|
42
|
+
sideOffset: 8,
|
|
43
|
+
children: /*#__PURE__*/ _jsx(WorkspaceSwitcher, {
|
|
44
|
+
activeWorkspaceId: workspace.id,
|
|
45
|
+
onSelect: ()=>setOpen(false)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
]
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=workspace-crumb.js.map
|
|
@@ -0,0 +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=\"/workspaces/$wid\"\n params={{wid: workspace.id}}\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","wid","id","aria-current","name","onOpenChange","asChild","button","type","aria-label","aria-haspopup","aria-expanded","align","sideOffset","activeWorkspaceId","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,KAAKR,UAAUS,EAAE;gBAAA;gBAC1BC,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,UAAUS,EAAE;4BAAEa,UAAU,IAAMnB,QAAQ;;;;;;;AAKtF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-switcher.d.ts","sourceRoot":"","sources":["../../src/components/workspace-switcher.tsx"],"names":[],"mappings":"AAeA,wBAAgB,iBAAiB,CAAC,EAChC,iBAAiB,EACjB,QAAQ,GACT,EAAE;IACD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,+BAqDA"}
|