polen 0.11.0-next.10 → 0.11.0-next.12
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/build/api/api.d.ts +2 -1
- package/build/api/api.d.ts.map +1 -1
- package/build/api/api.js +5 -1
- package/build/api/api.js.map +1 -1
- package/build/api/iso/$$.d.ts +2 -0
- package/build/api/iso/$$.d.ts.map +1 -0
- package/build/api/iso/$$.js +2 -0
- package/build/api/iso/$$.js.map +1 -0
- package/build/api/iso/$.d.ts +2 -0
- package/build/api/iso/$.d.ts.map +1 -0
- package/build/api/iso/$.js +2 -0
- package/build/api/iso/$.js.map +1 -0
- package/build/api/iso/schema/$$.d.ts +5 -0
- package/build/api/iso/schema/$$.d.ts.map +1 -0
- package/build/api/iso/schema/$$.js +4 -0
- package/build/api/iso/schema/$$.js.map +1 -0
- package/build/api/iso/schema/$.d.ts +2 -0
- package/build/api/iso/schema/$.d.ts.map +1 -0
- package/build/api/iso/schema/$.js +2 -0
- package/build/api/iso/schema/$.js.map +1 -0
- package/build/api/iso/schema/constants.d.ts +25 -0
- package/build/api/iso/schema/constants.d.ts.map +1 -0
- package/build/api/iso/schema/constants.js +42 -0
- package/build/api/iso/schema/constants.js.map +1 -0
- package/build/api/iso/schema/routing.d.ts +56 -0
- package/build/api/iso/schema/routing.d.ts.map +1 -0
- package/build/api/iso/schema/routing.js +97 -0
- package/build/api/iso/schema/routing.js.map +1 -0
- package/build/api/iso/schema/validation.d.ts +32 -0
- package/build/api/iso/schema/validation.d.ts.map +1 -0
- package/build/api/iso/schema/validation.js +101 -0
- package/build/api/iso/schema/validation.js.map +1 -0
- package/build/api/iso.d.ts +2 -0
- package/build/api/iso.d.ts.map +1 -0
- package/build/api/iso.js +2 -0
- package/build/api/iso.js.map +1 -0
- package/build/api/schema/schema.d.ts +3 -25
- package/build/api/schema/schema.d.ts.map +1 -1
- package/build/api/schema/schema.js +5 -42
- package/build/api/schema/schema.js.map +1 -1
- package/build/api/vite/plugins/core.d.ts.map +1 -1
- package/build/api/vite/plugins/core.js +3 -6
- package/build/api/vite/plugins/core.js.map +1 -1
- package/build/template/components/ArgumentList.d.ts +3 -4
- package/build/template/components/ArgumentList.d.ts.map +1 -1
- package/build/template/components/ArgumentList.js.map +1 -1
- package/build/template/components/Changelog.js +2 -2
- package/build/template/components/Changelog.js.map +1 -1
- package/build/template/components/DeprecationReason.d.ts +2 -2
- package/build/template/components/DeprecationReason.d.ts.map +1 -1
- package/build/template/components/DeprecationReason.js.map +1 -1
- package/build/template/components/Description.d.ts +2 -2
- package/build/template/components/Description.d.ts.map +1 -1
- package/build/template/components/Description.js.map +1 -1
- package/build/template/components/Field.d.ts +3 -4
- package/build/template/components/Field.d.ts.map +1 -1
- package/build/template/components/Field.js.map +1 -1
- package/build/template/components/FieldListSection.d.ts +3 -4
- package/build/template/components/FieldListSection.d.ts.map +1 -1
- package/build/template/components/FieldListSection.js.map +1 -1
- package/build/template/components/GraphQLInteractive/lib/parser.d.ts.map +1 -1
- package/build/template/components/GraphQLInteractive/lib/parser.js +32 -10
- package/build/template/components/GraphQLInteractive/lib/parser.js.map +1 -1
- package/build/template/components/HamburgerMenu.d.ts +1 -0
- package/build/template/components/HamburgerMenu.d.ts.map +1 -1
- package/build/template/components/HamburgerMenu.js +2 -2
- package/build/template/components/HamburgerMenu.js.map +1 -1
- package/build/template/components/MissingSchema.d.ts +2 -1
- package/build/template/components/MissingSchema.d.ts.map +1 -1
- package/build/template/components/MissingSchema.js.map +1 -1
- package/build/template/components/ReferenceLink.d.ts +9 -11
- package/build/template/components/ReferenceLink.d.ts.map +1 -1
- package/build/template/components/ReferenceLink.js +2 -4
- package/build/template/components/ReferenceLink.js.map +1 -1
- package/build/template/components/ToastContainer.d.ts +3 -0
- package/build/template/components/ToastContainer.d.ts.map +1 -0
- package/build/template/components/ToastContainer.js +44 -0
- package/build/template/components/ToastContainer.js.map +1 -0
- package/build/template/components/ToastItem.d.ts +7 -0
- package/build/template/components/ToastItem.d.ts.map +1 -0
- package/build/template/components/ToastItem.js +48 -0
- package/build/template/components/ToastItem.js.map +1 -0
- package/build/template/components/TypeAnnotation.d.ts +4 -5
- package/build/template/components/TypeAnnotation.d.ts.map +1 -1
- package/build/template/components/TypeAnnotation.js.map +1 -1
- package/build/template/components/VersionPicker.d.ts +8 -0
- package/build/template/components/VersionPicker.d.ts.map +1 -0
- package/build/template/components/VersionPicker.js +66 -0
- package/build/template/components/VersionPicker.js.map +1 -0
- package/build/template/components/sidebar/Sidebar.d.ts +3 -2
- package/build/template/components/sidebar/Sidebar.d.ts.map +1 -1
- package/build/template/components/sidebar/Sidebar.js +7 -6
- package/build/template/components/sidebar/Sidebar.js.map +1 -1
- package/build/template/components/sidebar/SidebarContext.d.ts +6 -0
- package/build/template/components/sidebar/SidebarContext.d.ts.map +1 -0
- package/build/template/components/sidebar/SidebarContext.js +3 -0
- package/build/template/components/sidebar/SidebarContext.js.map +1 -0
- package/build/template/components/sidebar/SidebarItem.d.ts.map +1 -1
- package/build/template/components/sidebar/SidebarItem.js +11 -4
- package/build/template/components/sidebar/SidebarItem.js.map +1 -1
- package/build/template/hooks/useReferencePath.d.ts +9 -0
- package/build/template/hooks/useReferencePath.d.ts.map +1 -0
- package/build/template/hooks/useReferencePath.js +18 -0
- package/build/template/hooks/useReferencePath.js.map +1 -0
- package/build/template/hooks/useVersionPath.d.ts.map +1 -1
- package/build/template/hooks/useVersionPath.js +3 -1
- package/build/template/hooks/useVersionPath.js.map +1 -1
- package/build/template/layouts/SidebarLayout.d.ts +3 -2
- package/build/template/layouts/SidebarLayout.d.ts.map +1 -1
- package/build/template/layouts/SidebarLayout.js +2 -2
- package/build/template/layouts/SidebarLayout.js.map +1 -1
- package/build/template/routes/reference.d.ts +24 -8
- package/build/template/routes/reference.d.ts.map +1 -1
- package/build/template/routes/reference.js +52 -61
- package/build/template/routes/reference.js.map +1 -1
- package/build/template/routes/root.d.ts +1 -0
- package/build/template/routes/root.d.ts.map +1 -1
- package/build/template/routes/root.js +16 -5
- package/build/template/routes/root.js.map +1 -1
- package/build/template/server/ssg/get-route-paths.d.ts.map +1 -1
- package/build/template/server/ssg/get-route-paths.js +47 -14
- package/build/template/server/ssg/get-route-paths.js.map +1 -1
- package/build/template/stores/$$.d.ts +13 -0
- package/build/template/stores/$$.d.ts.map +1 -0
- package/build/template/stores/$$.js +5 -0
- package/build/template/stores/$$.js.map +1 -0
- package/build/template/stores/$.d.ts +2 -0
- package/build/template/stores/$.d.ts.map +1 -0
- package/build/template/stores/$.js +2 -0
- package/build/template/stores/$.js.map +1 -0
- package/build/template/stores/schema.d.ts +40 -0
- package/build/template/stores/schema.d.ts.map +1 -0
- package/build/template/stores/schema.js +36 -0
- package/build/template/stores/schema.js.map +1 -0
- package/build/template/stores/toast.d.ts +103 -0
- package/build/template/stores/toast.d.ts.map +1 -0
- package/build/template/stores/toast.js +105 -0
- package/build/template/stores/toast.js.map +1 -0
- package/build/template/utils/try-with-toast.d.ts +9 -0
- package/build/template/utils/try-with-toast.d.ts.map +1 -0
- package/build/template/utils/try-with-toast.js +37 -0
- package/build/template/utils/try-with-toast.js.map +1 -0
- package/package.json +5 -1
- package/src/api/api.ts +7 -1
- package/src/api/iso/$$.ts +1 -0
- package/src/api/iso/$.ts +1 -0
- package/src/api/iso/schema/$$.ts +6 -0
- package/src/api/iso/schema/$.ts +1 -0
- package/src/api/iso/schema/constants.ts +49 -0
- package/src/api/iso/schema/routing.ts +142 -0
- package/src/api/iso/schema/validation.ts +136 -0
- package/src/api/iso.ts +1 -0
- package/src/api/schema/schema.ts +6 -53
- package/src/api/vite/plugins/core.ts +3 -6
- package/src/template/components/ArgumentList.tsx +2 -6
- package/src/template/components/Changelog.tsx +2 -2
- package/src/template/components/DeprecationReason.tsx +2 -2
- package/src/template/components/Description.tsx +2 -2
- package/src/template/components/Field.tsx +2 -6
- package/src/template/components/FieldListSection.tsx +2 -6
- package/src/template/components/GraphQLInteractive/lib/parser.ts +32 -16
- package/src/template/components/HamburgerMenu.tsx +3 -1
- package/src/template/components/MissingSchema.tsx +3 -1
- package/src/template/components/ReferenceLink.tsx +16 -15
- package/src/template/components/ToastContainer.tsx +67 -0
- package/src/template/components/ToastItem.tsx +119 -0
- package/src/template/components/TypeAnnotation.tsx +2 -6
- package/src/template/components/VersionPicker.tsx +94 -0
- package/src/template/components/sidebar/Sidebar.tsx +20 -16
- package/src/template/components/sidebar/SidebarContext.tsx +7 -0
- package/src/template/components/sidebar/SidebarItem.tsx +11 -4
- package/src/template/hooks/useReferencePath.ts +20 -0
- package/src/template/hooks/useVersionPath.ts +3 -1
- package/src/template/layouts/SidebarLayout.tsx +5 -3
- package/src/template/routes/reference.tsx +56 -73
- package/src/template/routes/root.tsx +29 -6
- package/src/template/server/ssg/get-route-paths.test.ts +13 -0
- package/src/template/server/ssg/get-route-paths.ts +47 -14
- package/src/template/stores/$$.ts +15 -0
- package/src/template/stores/$.ts +1 -0
- package/src/template/stores/schema.ts +52 -0
- package/src/template/stores/toast.ts +153 -0
- package/src/template/utils/try-with-toast.ts +41 -0
- package/build/template/components/VersionSelector.d.ts +0 -7
- package/build/template/components/VersionSelector.d.ts.map +0 -1
- package/build/template/components/VersionSelector.js +0 -30
- package/build/template/components/VersionSelector.js.map +0 -1
- package/build/template/lib/schema-utils/constants.d.ts +0 -5
- package/build/template/lib/schema-utils/constants.d.ts.map +0 -1
- package/build/template/lib/schema-utils/constants.js +0 -5
- package/build/template/lib/schema-utils/constants.js.map +0 -1
- package/src/template/components/VersionSelector.tsx +0 -50
- package/src/template/lib/schema-utils/constants.ts +0 -4
@@ -0,0 +1,94 @@
|
|
1
|
+
import { Api } from '#api/iso'
|
2
|
+
import type { React } from '#dep/react/index'
|
3
|
+
import { Select } from '@radix-ui/themes'
|
4
|
+
import { useNavigate } from 'react-router'
|
5
|
+
import { useReferencePath } from '../hooks/useReferencePath.js'
|
6
|
+
import { schemaSource } from '../sources/schema-source.js'
|
7
|
+
import { Stores } from '../stores/$.js'
|
8
|
+
import { tryWithToast } from '../utils/try-with-toast.js'
|
9
|
+
|
10
|
+
interface Props {
|
11
|
+
all: string[]
|
12
|
+
current: string
|
13
|
+
}
|
14
|
+
|
15
|
+
export const VersionPicker: React.FC<Props> = ({ all, current }) => {
|
16
|
+
const navigate = useNavigate()
|
17
|
+
const currentPath = useReferencePath()
|
18
|
+
|
19
|
+
// Don't show selector if only one version
|
20
|
+
if (all.length <= 1) {
|
21
|
+
return null
|
22
|
+
}
|
23
|
+
|
24
|
+
const handleVersionChange = async (newVersion: string) => {
|
25
|
+
const error = await tryWithToast(async () => {
|
26
|
+
// Check if current path exists in target version
|
27
|
+
const targetSchema = await schemaSource.get(newVersion)
|
28
|
+
// Find fallback path if needed
|
29
|
+
const fallbackPath = Api.Schema.Validation.findFallbackPath(targetSchema, currentPath)
|
30
|
+
// Get redirect description if path changed
|
31
|
+
const redirectDescription = Api.Schema.Validation.getRedirectDescription(
|
32
|
+
targetSchema,
|
33
|
+
currentPath,
|
34
|
+
fallbackPath,
|
35
|
+
newVersion,
|
36
|
+
)
|
37
|
+
// Create the new path
|
38
|
+
const newPath = Api.Schema.Routing.createReferencePath({
|
39
|
+
version: newVersion,
|
40
|
+
type: fallbackPath.type,
|
41
|
+
field: fallbackPath.field,
|
42
|
+
})
|
43
|
+
// Show toast notification if schema location redirect will occur
|
44
|
+
if (redirectDescription) {
|
45
|
+
Stores.Toast.store.info(redirectDescription, {
|
46
|
+
duration: 160_000,
|
47
|
+
actions: [
|
48
|
+
{
|
49
|
+
label: 'Go back',
|
50
|
+
onClick() {
|
51
|
+
navigate(-1)
|
52
|
+
},
|
53
|
+
},
|
54
|
+
{
|
55
|
+
label: 'View changelog',
|
56
|
+
onClick() {
|
57
|
+
// Navigate to changelog page
|
58
|
+
navigate('/changelog')
|
59
|
+
},
|
60
|
+
},
|
61
|
+
],
|
62
|
+
})
|
63
|
+
}
|
64
|
+
|
65
|
+
navigate(newPath)
|
66
|
+
}, 'Failed to switch version')
|
67
|
+
|
68
|
+
// Fallback logic if error occurred
|
69
|
+
if (error) {
|
70
|
+
// Fallback to simple navigation if schema loading fails
|
71
|
+
const newPath = Api.Schema.Routing.createReferencePath({
|
72
|
+
version: newVersion,
|
73
|
+
type: currentPath.type,
|
74
|
+
field: currentPath.field,
|
75
|
+
})
|
76
|
+
navigate(newPath)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
return (
|
81
|
+
<Select.Root value={current} onValueChange={handleVersionChange}>
|
82
|
+
<Select.Trigger>
|
83
|
+
{current === Api.Schema.VERSION_LATEST ? `Latest` : current}
|
84
|
+
</Select.Trigger>
|
85
|
+
<Select.Content>
|
86
|
+
{all.map(version => (
|
87
|
+
<Select.Item key={version} value={version}>
|
88
|
+
{version === Api.Schema.VERSION_LATEST ? `Latest` : version}
|
89
|
+
</Select.Item>
|
90
|
+
))}
|
91
|
+
</Select.Content>
|
92
|
+
</Select.Root>
|
93
|
+
)
|
94
|
+
}
|
@@ -1,28 +1,32 @@
|
|
1
1
|
import type { Content } from '#api/content/$'
|
2
2
|
import { Box } from '@radix-ui/themes'
|
3
3
|
import type { BoxOwnProps, LayoutProps, MarginProps } from '@radix-ui/themes/props'
|
4
|
+
import { SidebarContext } from './SidebarContext.js'
|
4
5
|
import { Items } from './SidebarItem.js'
|
5
6
|
|
6
|
-
interface
|
7
|
+
interface Props extends LayoutProps, MarginProps, BoxOwnProps {
|
7
8
|
data: Content.Item[]
|
9
|
+
basePath?: string
|
8
10
|
style?: React.CSSProperties
|
9
11
|
}
|
10
12
|
|
11
|
-
export const Sidebar = ({ data, ...props }:
|
13
|
+
export const Sidebar = ({ data, basePath, ...props }: Props) => {
|
12
14
|
return (
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
15
|
+
<SidebarContext.Provider value={{ basePath }}>
|
16
|
+
<Box
|
17
|
+
data-testid='sidebar'
|
18
|
+
role='Sidebar'
|
19
|
+
{...props}
|
20
|
+
>
|
21
|
+
<style>
|
22
|
+
{`
|
23
|
+
div[role="Sidebar"] a:not([data-active]):hover {
|
24
|
+
background-color: var(--iris-2) !important;
|
25
|
+
}
|
26
|
+
`}
|
27
|
+
</style>
|
28
|
+
<Items items={data} />
|
29
|
+
</Box>
|
30
|
+
</SidebarContext.Provider>
|
27
31
|
)
|
28
32
|
}
|
@@ -1,9 +1,12 @@
|
|
1
1
|
import type { Content } from '#api/content/$'
|
2
|
+
import { Api } from '#api/iso'
|
2
3
|
import type { React } from '#dep/react/index'
|
3
4
|
import { Texts } from '#template/components/Texts/index'
|
4
5
|
import { Box, Flex } from '@radix-ui/themes'
|
6
|
+
import { useContext } from 'react'
|
5
7
|
import { useLocation } from 'react-router'
|
6
8
|
import { getPathActiveReport, Link } from '../Link.js'
|
9
|
+
import { SidebarContext } from './SidebarContext.js'
|
7
10
|
|
8
11
|
export const Items: React.FC<{ items: Content.Item[] }> = ({ items }) => {
|
9
12
|
return (
|
@@ -50,15 +53,17 @@ const SBLink: React.FC<{
|
|
50
53
|
link: Content.ItemLink | Content.ItemSection
|
51
54
|
}> = ({ link }) => {
|
52
55
|
const location = useLocation()
|
56
|
+
const { basePath } = useContext(SidebarContext)
|
53
57
|
const currentPathExp = location.pathname
|
54
|
-
const
|
58
|
+
const href = Api.Schema.Routing.joinSegmentsAndPaths(basePath, link.pathExp)
|
59
|
+
const active = getPathActiveReport(href, currentPathExp)
|
55
60
|
|
56
61
|
return (
|
57
62
|
<Link
|
58
63
|
role='Sidebar Link'
|
59
64
|
color={active.is ? `iris` : `gray`}
|
60
65
|
data-testid={`sidebar-link-${link.pathExp}`}
|
61
|
-
to={
|
66
|
+
to={href}
|
62
67
|
style={{
|
63
68
|
display: `block`,
|
64
69
|
textDecoration: `none`,
|
@@ -135,12 +140,14 @@ const LinkedSection: React.FC<{
|
|
135
140
|
|
136
141
|
const SectionLink: React.FC<{ link: Content.ItemLink }> = ({ link }) => {
|
137
142
|
const location = useLocation()
|
138
|
-
const
|
143
|
+
const { basePath } = useContext(SidebarContext)
|
144
|
+
const href = Api.Schema.Routing.joinSegmentsAndPaths(basePath, link.pathExp)
|
145
|
+
const active = getPathActiveReport(href, location.pathname)
|
139
146
|
|
140
147
|
return (
|
141
148
|
<Link
|
142
149
|
role='Sidebar Link'
|
143
|
-
to={
|
150
|
+
to={href}
|
144
151
|
color={active.is ? `iris` : `gray`}
|
145
152
|
style={{
|
146
153
|
textDecoration: `none`,
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Api } from '#api/iso'
|
2
|
+
import { useLocation, useParams } from 'react-router'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Hook that returns parsed reference path parameters
|
6
|
+
*
|
7
|
+
* @throws {Error} If not currently on a reference route
|
8
|
+
* @returns Parsed reference path object
|
9
|
+
*/
|
10
|
+
export const useReferencePath = (): Api.Schema.Validation.PathValidation => {
|
11
|
+
const params = useParams()
|
12
|
+
const location = useLocation()
|
13
|
+
|
14
|
+
Api.Schema.Routing.assertReferenceRoute({
|
15
|
+
pathname: location.pathname,
|
16
|
+
params,
|
17
|
+
})
|
18
|
+
|
19
|
+
return params
|
20
|
+
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { Api } from '#api/iso'
|
1
2
|
import { useParams } from 'react-router'
|
2
3
|
|
3
4
|
/**
|
@@ -6,5 +7,6 @@ import { useParams } from 'react-router'
|
|
6
7
|
*/
|
7
8
|
export const useVersionPath = (): string => {
|
8
9
|
const params = useParams()
|
9
|
-
|
10
|
+
const version = params[`version`] || Api.Schema.VERSION_LATEST
|
11
|
+
return Api.Schema.Routing.createReferenceVersionPath(version)
|
10
12
|
}
|
@@ -6,12 +6,13 @@ import { useLocation } from 'react-router'
|
|
6
6
|
import { HamburgerMenu } from '../components/HamburgerMenu.js'
|
7
7
|
import { Sidebar } from '../components/sidebar/Sidebar.js'
|
8
8
|
|
9
|
-
interface
|
9
|
+
interface Props {
|
10
10
|
children: React.ReactNode
|
11
11
|
sidebar: Content.Item[]
|
12
|
+
basePath?: string
|
12
13
|
}
|
13
14
|
|
14
|
-
export const SidebarLayout: React.FC<
|
15
|
+
export const SidebarLayout: React.FC<Props> = ({ children, sidebar, basePath }) => {
|
15
16
|
const location = useLocation()
|
16
17
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
17
18
|
|
@@ -45,6 +46,7 @@ export const SidebarLayout: React.FC<SidebarLayoutProps> = ({ children, sidebar
|
|
45
46
|
setMobileMenuOpen(false)
|
46
47
|
}}
|
47
48
|
sidebarData={sidebar}
|
49
|
+
basePath={basePath}
|
48
50
|
/>
|
49
51
|
</Box>
|
50
52
|
)}
|
@@ -56,7 +58,7 @@ export const SidebarLayout: React.FC<SidebarLayoutProps> = ({ children, sidebar
|
|
56
58
|
gridColumn='1 / 3'
|
57
59
|
gridRow='1 / auto'
|
58
60
|
>
|
59
|
-
<Sidebar data={sidebar} />
|
61
|
+
<Sidebar data={sidebar} basePath={basePath} />
|
60
62
|
</Box>
|
61
63
|
)}
|
62
64
|
|
@@ -1,23 +1,24 @@
|
|
1
1
|
import type { Content } from '#api/content/$'
|
2
|
+
import { Api } from '#api/iso'
|
3
|
+
import type { React } from '#dep/react/index'
|
2
4
|
import { GrafaidOld } from '#lib/grafaid-old/index'
|
3
|
-
import { Grafaid } from '#lib/grafaid/index'
|
4
5
|
import { route, routeIndex } from '#lib/react-router-aid/react-router-aid'
|
5
6
|
import { createLoader, useLoaderData } from '#lib/react-router-loader/react-router-loader'
|
6
7
|
import { Box } from '@radix-ui/themes'
|
7
|
-
import {
|
8
|
+
import { neverCase } from '@wollybeard/kit/language'
|
9
|
+
import { useParams } from 'react-router'
|
8
10
|
import { Field } from '../components/Field.js'
|
9
11
|
import { MissingSchema } from '../components/MissingSchema.js'
|
10
12
|
import { NamedType } from '../components/NamedType.js'
|
11
|
-
import {
|
13
|
+
import { VersionPicker } from '../components/VersionPicker.js'
|
12
14
|
import { SidebarLayout } from '../layouts/index.js'
|
13
|
-
import { VERSION_LATEST } from '../lib/schema-utils/constants.js'
|
14
15
|
import { schemaSource } from '../sources/schema-source.js'
|
15
16
|
|
16
17
|
export const loader = createLoader(async ({ params }) => {
|
17
18
|
// Handle both versioned and unversioned routes:
|
18
19
|
// - Versioned: /reference/version/:version/:type → params.version exists
|
19
20
|
// - Unversioned: /reference/:type → params.version is undefined, defaults to latest
|
20
|
-
const currentVersion = params.version ?? VERSION_LATEST
|
21
|
+
const currentVersion = params.version ?? Api.Schema.VERSION_LATEST
|
21
22
|
|
22
23
|
const schema = await schemaSource.get(currentVersion)
|
23
24
|
const availableVersions = schemaSource.versions
|
@@ -29,7 +30,9 @@ export const loader = createLoader(async ({ params }) => {
|
|
29
30
|
}
|
30
31
|
})
|
31
32
|
|
32
|
-
|
33
|
+
// Single component that handles all reference route variations
|
34
|
+
const ReferenceView = () => {
|
35
|
+
const params = useParams() as { version?: string; type?: string; field?: string }
|
33
36
|
const data = useLoaderData<typeof loader>()
|
34
37
|
|
35
38
|
if (!data.schema) {
|
@@ -42,12 +45,6 @@ const RouteReferenceComponent = () => {
|
|
42
45
|
const sidebarItems: Content.Item[] = []
|
43
46
|
const kindEntries = Object.entries(kindMap.list).filter(([_, types]) => types.length > 0)
|
44
47
|
|
45
|
-
// Build path prefix based on current version from loader data
|
46
|
-
// This ensures sidebar links always match the current version being viewed
|
47
|
-
const versionPath = data.currentVersion === VERSION_LATEST
|
48
|
-
? ``
|
49
|
-
: `version/${data.currentVersion}/`
|
50
|
-
|
51
48
|
for (const [title, types] of kindEntries) {
|
52
49
|
sidebarItems.push({
|
53
50
|
type: `ItemSection` as const,
|
@@ -57,96 +54,82 @@ const RouteReferenceComponent = () => {
|
|
57
54
|
links: types.map(type => ({
|
58
55
|
type: `ItemLink` as const,
|
59
56
|
title: type.name,
|
60
|
-
pathExp:
|
57
|
+
pathExp: type.name, // Just the type name, basePath will be prepended
|
61
58
|
})),
|
62
59
|
})
|
63
60
|
}
|
64
61
|
|
62
|
+
// Calculate basePath based on current version
|
63
|
+
const basePath = Api.Schema.Routing.createReferenceBasePath(data.currentVersion)
|
64
|
+
|
65
|
+
// Determine view type and render appropriate content
|
66
|
+
const viewType = Api.Schema.Routing.getReferenceViewType({
|
67
|
+
schema: data.schema,
|
68
|
+
type: params.type,
|
69
|
+
field: params.field,
|
70
|
+
})
|
71
|
+
|
72
|
+
const content: React.ReactNode = (() => {
|
73
|
+
if (viewType === 'index') {
|
74
|
+
return <div>Select a type from the sidebar to view its documentation.</div>
|
75
|
+
} else if (viewType === 'type-missing' || viewType === 'field-missing') {
|
76
|
+
return <MissingSchema />
|
77
|
+
} else if (viewType === 'type') {
|
78
|
+
const type = data.schema.getType(params.type!)!
|
79
|
+
return <NamedType data={type} />
|
80
|
+
} else if (viewType === 'field') {
|
81
|
+
const type = data.schema.getType(params.type!)!
|
82
|
+
const fields = (type as any).getFields()
|
83
|
+
const field = fields[params.field!]
|
84
|
+
return <Field data={field} />
|
85
|
+
} else {
|
86
|
+
neverCase(viewType)
|
87
|
+
}
|
88
|
+
})()
|
89
|
+
|
65
90
|
return (
|
66
|
-
<SidebarLayout sidebar={sidebarItems}>
|
91
|
+
<SidebarLayout sidebar={sidebarItems} basePath={basePath}>
|
67
92
|
<Box mb={`4`}>
|
68
|
-
<
|
69
|
-
|
70
|
-
|
93
|
+
<VersionPicker
|
94
|
+
all={[...data.availableVersions]} // Convert readonly to mutable
|
95
|
+
current={data.currentVersion}
|
71
96
|
/>
|
72
97
|
</Box>
|
73
|
-
|
98
|
+
{content}
|
74
99
|
</SidebarLayout>
|
75
100
|
)
|
76
101
|
}
|
77
102
|
|
78
|
-
//
|
79
|
-
const useReferenceSchema = () => {
|
80
|
-
const data = useLoaderData<typeof loader>('reference')
|
81
|
-
if (!data?.schema) {
|
82
|
-
throw new Error('Schema not found')
|
83
|
-
}
|
84
|
-
return data
|
85
|
-
}
|
86
|
-
|
87
|
-
const useSchemaType = (typeName: string) => {
|
88
|
-
const { schema } = useReferenceSchema()
|
89
|
-
const type = schema.getType(typeName)
|
90
|
-
if (!type) {
|
91
|
-
throw new Error(`Could not find type ${typeName}`)
|
92
|
-
}
|
93
|
-
return type
|
94
|
-
}
|
95
|
-
|
96
|
-
const useSchemaField = (typeName: string, fieldName: string) => {
|
97
|
-
const type = useSchemaType(typeName)
|
98
|
-
if (!Grafaid.Schema.TypesLike.isFielded(type)) {
|
99
|
-
throw new Error(`Type ${typeName} does not have fields`)
|
100
|
-
}
|
101
|
-
|
102
|
-
const fields = type.getFields()
|
103
|
-
const field = fields[fieldName]
|
104
|
-
if (!field) {
|
105
|
-
throw new Error(`Could not find field ${fieldName} on type ${typeName}`)
|
106
|
-
}
|
107
|
-
return field
|
108
|
-
}
|
109
|
-
|
110
|
-
const RouteComponentIndex = () => {
|
111
|
-
return <div>Select a type from the sidebar to view its documentation.</div>
|
112
|
-
}
|
113
|
-
|
114
|
-
const RouteComponentType = () => {
|
115
|
-
const params = useParams() as { type: string }
|
116
|
-
const type = useSchemaType(params.type)
|
117
|
-
return <NamedType data={type} />
|
118
|
-
}
|
119
|
-
|
120
|
-
const RouteComponentTypeField = () => {
|
121
|
-
const params = useParams() as { type: string; field: string }
|
122
|
-
const field = useSchemaField(params.type, params.field)
|
123
|
-
return <Field data={field} />
|
124
|
-
}
|
125
|
-
|
103
|
+
// Define routes that handle type and field params
|
126
104
|
const typeAndFieldRoutes = [
|
127
|
-
routeIndex(
|
105
|
+
routeIndex({
|
106
|
+
Component: ReferenceView,
|
107
|
+
loader,
|
108
|
+
}),
|
128
109
|
route({
|
129
110
|
path: `:type`,
|
130
|
-
Component:
|
111
|
+
Component: ReferenceView,
|
131
112
|
errorElement: <MissingSchema />,
|
113
|
+
loader,
|
132
114
|
children: [
|
133
115
|
route({
|
134
116
|
path: `:field`,
|
135
|
-
Component:
|
117
|
+
Component: ReferenceView,
|
136
118
|
errorElement: <MissingSchema />,
|
119
|
+
loader,
|
137
120
|
}),
|
138
121
|
],
|
139
122
|
}),
|
140
123
|
]
|
141
124
|
|
142
125
|
/**
|
143
|
-
* Reference documentation
|
126
|
+
* Reference documentation routes using proper React Router patterns
|
127
|
+
* - Parent routes have no components (automatically render Outlet)
|
128
|
+
* - Leaf routes have components and loaders that always run fresh
|
129
|
+
* - Single ReferenceView component handles all variations
|
144
130
|
*/
|
145
131
|
export const reference = route({
|
146
|
-
id: 'reference',
|
147
132
|
path: `reference`,
|
148
|
-
loader,
|
149
|
-
Component: RouteReferenceComponent,
|
150
133
|
children: [
|
151
134
|
...typeAndFieldRoutes,
|
152
135
|
route({
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import type { ReactRouter } from '#dep/react-router/index'
|
2
2
|
import { route } from '#lib/react-router-aid/react-router-aid'
|
3
|
+
import { createLoader } from '#lib/react-router-loader/react-router-loader'
|
4
|
+
import type { Stores } from '#template/stores/$'
|
3
5
|
import { Box, Flex, Theme } from '@radix-ui/themes'
|
4
6
|
import { Link as LinkReactRouter } from 'react-router'
|
5
7
|
import { Outlet, ScrollRestoration } from 'react-router'
|
@@ -11,6 +13,7 @@ import { Link as PolenLink } from '../components/Link.js'
|
|
11
13
|
import { Logo } from '../components/Logo.js'
|
12
14
|
import { NotFound } from '../components/NotFound.js'
|
13
15
|
import { ThemeToggle } from '../components/ThemeToggle.js'
|
16
|
+
import { ToastContainer } from '../components/ToastContainer.js'
|
14
17
|
import { ThemeProvider, useTheme } from '../contexts/ThemeContext.js'
|
15
18
|
import { changelog } from './changelog.js'
|
16
19
|
import { index } from './index.js'
|
@@ -46,7 +49,12 @@ const Layout = () => {
|
|
46
49
|
style={{ color: `inherit`, textDecoration: `none` }}
|
47
50
|
>
|
48
51
|
<Box display={{ initial: `block`, md: `block` }}>
|
49
|
-
<Logo
|
52
|
+
<Logo
|
53
|
+
src={logoSrc}
|
54
|
+
title={templateVariables.title}
|
55
|
+
height={30}
|
56
|
+
showTitle={true}
|
57
|
+
/>
|
50
58
|
</Box>
|
51
59
|
</LinkReactRouter>
|
52
60
|
<Flex direction='row' gap='4' style={{ flex: 1 }}>
|
@@ -61,7 +69,7 @@ const Layout = () => {
|
|
61
69
|
)
|
62
70
|
|
63
71
|
return (
|
64
|
-
<Theme asChild appearance={appearance}>
|
72
|
+
<Theme asChild appearance={appearance} radius='none'>
|
65
73
|
<Box
|
66
74
|
width={{ initial: `100%`, sm: `100%`, md: `var(--container-4)` }}
|
67
75
|
maxWidth='100vw'
|
@@ -72,15 +80,13 @@ const Layout = () => {
|
|
72
80
|
>
|
73
81
|
{header}
|
74
82
|
<Outlet />
|
83
|
+
<ToastContainer />
|
75
84
|
</Box>
|
76
85
|
</Theme>
|
77
86
|
)
|
78
87
|
}
|
79
88
|
|
80
|
-
const children: ReactRouter.RouteObject[] = [
|
81
|
-
index,
|
82
|
-
pages,
|
83
|
-
]
|
89
|
+
const children: ReactRouter.RouteObject[] = [index, pages]
|
84
90
|
|
85
91
|
//
|
86
92
|
//
|
@@ -122,8 +128,25 @@ children.push(notFoundRoute)
|
|
122
128
|
//
|
123
129
|
//
|
124
130
|
|
131
|
+
const storeModules = import.meta.glob('../stores/!($.*)*.ts', { eager: true }) as Record<
|
132
|
+
string,
|
133
|
+
Stores.StoreModule
|
134
|
+
>
|
135
|
+
|
125
136
|
export const root = route({
|
126
137
|
path: `/`,
|
127
138
|
Component,
|
139
|
+
loader: createLoader(async () => {
|
140
|
+
// Reset all stores on SSR to prevent cross-request pollution
|
141
|
+
if (import.meta.env.SSR) {
|
142
|
+
for (const module of Object.values(storeModules)) {
|
143
|
+
if (module.store?.reset) {
|
144
|
+
module.store.reset()
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
return {}
|
150
|
+
}),
|
128
151
|
children,
|
129
152
|
})
|
@@ -50,6 +50,19 @@ vi.mock('#api/index', () => ({
|
|
50
50
|
Schema: {
|
51
51
|
getMetadata: vi.fn(),
|
52
52
|
VERSION_LATEST: 'latest',
|
53
|
+
Routing: {
|
54
|
+
createReferencePath: vi.fn((parts) => {
|
55
|
+
const version = parts.version || 'latest'
|
56
|
+
const basePath = version === 'latest' ? '/reference' : `/reference/version/${version}`
|
57
|
+
if (parts.type) {
|
58
|
+
return parts.field ? `${basePath}/${parts.type}/${parts.field}` : `${basePath}/${parts.type}`
|
59
|
+
}
|
60
|
+
return basePath
|
61
|
+
}),
|
62
|
+
createReferenceBasePath: vi.fn((version) => {
|
63
|
+
return version === 'latest' ? '/reference' : `/reference/version/${version}`
|
64
|
+
}),
|
65
|
+
},
|
53
66
|
},
|
54
67
|
},
|
55
68
|
}))
|