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.
Files changed (193) hide show
  1. package/build/api/api.d.ts +2 -1
  2. package/build/api/api.d.ts.map +1 -1
  3. package/build/api/api.js +5 -1
  4. package/build/api/api.js.map +1 -1
  5. package/build/api/iso/$$.d.ts +2 -0
  6. package/build/api/iso/$$.d.ts.map +1 -0
  7. package/build/api/iso/$$.js +2 -0
  8. package/build/api/iso/$$.js.map +1 -0
  9. package/build/api/iso/$.d.ts +2 -0
  10. package/build/api/iso/$.d.ts.map +1 -0
  11. package/build/api/iso/$.js +2 -0
  12. package/build/api/iso/$.js.map +1 -0
  13. package/build/api/iso/schema/$$.d.ts +5 -0
  14. package/build/api/iso/schema/$$.d.ts.map +1 -0
  15. package/build/api/iso/schema/$$.js +4 -0
  16. package/build/api/iso/schema/$$.js.map +1 -0
  17. package/build/api/iso/schema/$.d.ts +2 -0
  18. package/build/api/iso/schema/$.d.ts.map +1 -0
  19. package/build/api/iso/schema/$.js +2 -0
  20. package/build/api/iso/schema/$.js.map +1 -0
  21. package/build/api/iso/schema/constants.d.ts +25 -0
  22. package/build/api/iso/schema/constants.d.ts.map +1 -0
  23. package/build/api/iso/schema/constants.js +42 -0
  24. package/build/api/iso/schema/constants.js.map +1 -0
  25. package/build/api/iso/schema/routing.d.ts +56 -0
  26. package/build/api/iso/schema/routing.d.ts.map +1 -0
  27. package/build/api/iso/schema/routing.js +97 -0
  28. package/build/api/iso/schema/routing.js.map +1 -0
  29. package/build/api/iso/schema/validation.d.ts +32 -0
  30. package/build/api/iso/schema/validation.d.ts.map +1 -0
  31. package/build/api/iso/schema/validation.js +101 -0
  32. package/build/api/iso/schema/validation.js.map +1 -0
  33. package/build/api/iso.d.ts +2 -0
  34. package/build/api/iso.d.ts.map +1 -0
  35. package/build/api/iso.js +2 -0
  36. package/build/api/iso.js.map +1 -0
  37. package/build/api/schema/schema.d.ts +3 -25
  38. package/build/api/schema/schema.d.ts.map +1 -1
  39. package/build/api/schema/schema.js +5 -42
  40. package/build/api/schema/schema.js.map +1 -1
  41. package/build/api/vite/plugins/core.d.ts.map +1 -1
  42. package/build/api/vite/plugins/core.js +3 -6
  43. package/build/api/vite/plugins/core.js.map +1 -1
  44. package/build/template/components/ArgumentList.d.ts +3 -4
  45. package/build/template/components/ArgumentList.d.ts.map +1 -1
  46. package/build/template/components/ArgumentList.js.map +1 -1
  47. package/build/template/components/Changelog.js +2 -2
  48. package/build/template/components/Changelog.js.map +1 -1
  49. package/build/template/components/DeprecationReason.d.ts +2 -2
  50. package/build/template/components/DeprecationReason.d.ts.map +1 -1
  51. package/build/template/components/DeprecationReason.js.map +1 -1
  52. package/build/template/components/Description.d.ts +2 -2
  53. package/build/template/components/Description.d.ts.map +1 -1
  54. package/build/template/components/Description.js.map +1 -1
  55. package/build/template/components/Field.d.ts +3 -4
  56. package/build/template/components/Field.d.ts.map +1 -1
  57. package/build/template/components/Field.js.map +1 -1
  58. package/build/template/components/FieldListSection.d.ts +3 -4
  59. package/build/template/components/FieldListSection.d.ts.map +1 -1
  60. package/build/template/components/FieldListSection.js.map +1 -1
  61. package/build/template/components/GraphQLInteractive/lib/parser.d.ts.map +1 -1
  62. package/build/template/components/GraphQLInteractive/lib/parser.js +32 -10
  63. package/build/template/components/GraphQLInteractive/lib/parser.js.map +1 -1
  64. package/build/template/components/HamburgerMenu.d.ts +1 -0
  65. package/build/template/components/HamburgerMenu.d.ts.map +1 -1
  66. package/build/template/components/HamburgerMenu.js +2 -2
  67. package/build/template/components/HamburgerMenu.js.map +1 -1
  68. package/build/template/components/MissingSchema.d.ts +2 -1
  69. package/build/template/components/MissingSchema.d.ts.map +1 -1
  70. package/build/template/components/MissingSchema.js.map +1 -1
  71. package/build/template/components/ReferenceLink.d.ts +9 -11
  72. package/build/template/components/ReferenceLink.d.ts.map +1 -1
  73. package/build/template/components/ReferenceLink.js +2 -4
  74. package/build/template/components/ReferenceLink.js.map +1 -1
  75. package/build/template/components/ToastContainer.d.ts +3 -0
  76. package/build/template/components/ToastContainer.d.ts.map +1 -0
  77. package/build/template/components/ToastContainer.js +44 -0
  78. package/build/template/components/ToastContainer.js.map +1 -0
  79. package/build/template/components/ToastItem.d.ts +7 -0
  80. package/build/template/components/ToastItem.d.ts.map +1 -0
  81. package/build/template/components/ToastItem.js +48 -0
  82. package/build/template/components/ToastItem.js.map +1 -0
  83. package/build/template/components/TypeAnnotation.d.ts +4 -5
  84. package/build/template/components/TypeAnnotation.d.ts.map +1 -1
  85. package/build/template/components/TypeAnnotation.js.map +1 -1
  86. package/build/template/components/VersionPicker.d.ts +8 -0
  87. package/build/template/components/VersionPicker.d.ts.map +1 -0
  88. package/build/template/components/VersionPicker.js +66 -0
  89. package/build/template/components/VersionPicker.js.map +1 -0
  90. package/build/template/components/sidebar/Sidebar.d.ts +3 -2
  91. package/build/template/components/sidebar/Sidebar.d.ts.map +1 -1
  92. package/build/template/components/sidebar/Sidebar.js +7 -6
  93. package/build/template/components/sidebar/Sidebar.js.map +1 -1
  94. package/build/template/components/sidebar/SidebarContext.d.ts +6 -0
  95. package/build/template/components/sidebar/SidebarContext.d.ts.map +1 -0
  96. package/build/template/components/sidebar/SidebarContext.js +3 -0
  97. package/build/template/components/sidebar/SidebarContext.js.map +1 -0
  98. package/build/template/components/sidebar/SidebarItem.d.ts.map +1 -1
  99. package/build/template/components/sidebar/SidebarItem.js +11 -4
  100. package/build/template/components/sidebar/SidebarItem.js.map +1 -1
  101. package/build/template/hooks/useReferencePath.d.ts +9 -0
  102. package/build/template/hooks/useReferencePath.d.ts.map +1 -0
  103. package/build/template/hooks/useReferencePath.js +18 -0
  104. package/build/template/hooks/useReferencePath.js.map +1 -0
  105. package/build/template/hooks/useVersionPath.d.ts.map +1 -1
  106. package/build/template/hooks/useVersionPath.js +3 -1
  107. package/build/template/hooks/useVersionPath.js.map +1 -1
  108. package/build/template/layouts/SidebarLayout.d.ts +3 -2
  109. package/build/template/layouts/SidebarLayout.d.ts.map +1 -1
  110. package/build/template/layouts/SidebarLayout.js +2 -2
  111. package/build/template/layouts/SidebarLayout.js.map +1 -1
  112. package/build/template/routes/reference.d.ts +24 -8
  113. package/build/template/routes/reference.d.ts.map +1 -1
  114. package/build/template/routes/reference.js +52 -61
  115. package/build/template/routes/reference.js.map +1 -1
  116. package/build/template/routes/root.d.ts +1 -0
  117. package/build/template/routes/root.d.ts.map +1 -1
  118. package/build/template/routes/root.js +16 -5
  119. package/build/template/routes/root.js.map +1 -1
  120. package/build/template/server/ssg/get-route-paths.d.ts.map +1 -1
  121. package/build/template/server/ssg/get-route-paths.js +47 -14
  122. package/build/template/server/ssg/get-route-paths.js.map +1 -1
  123. package/build/template/stores/$$.d.ts +13 -0
  124. package/build/template/stores/$$.d.ts.map +1 -0
  125. package/build/template/stores/$$.js +5 -0
  126. package/build/template/stores/$$.js.map +1 -0
  127. package/build/template/stores/$.d.ts +2 -0
  128. package/build/template/stores/$.d.ts.map +1 -0
  129. package/build/template/stores/$.js +2 -0
  130. package/build/template/stores/$.js.map +1 -0
  131. package/build/template/stores/schema.d.ts +40 -0
  132. package/build/template/stores/schema.d.ts.map +1 -0
  133. package/build/template/stores/schema.js +36 -0
  134. package/build/template/stores/schema.js.map +1 -0
  135. package/build/template/stores/toast.d.ts +103 -0
  136. package/build/template/stores/toast.d.ts.map +1 -0
  137. package/build/template/stores/toast.js +105 -0
  138. package/build/template/stores/toast.js.map +1 -0
  139. package/build/template/utils/try-with-toast.d.ts +9 -0
  140. package/build/template/utils/try-with-toast.d.ts.map +1 -0
  141. package/build/template/utils/try-with-toast.js +37 -0
  142. package/build/template/utils/try-with-toast.js.map +1 -0
  143. package/package.json +5 -1
  144. package/src/api/api.ts +7 -1
  145. package/src/api/iso/$$.ts +1 -0
  146. package/src/api/iso/$.ts +1 -0
  147. package/src/api/iso/schema/$$.ts +6 -0
  148. package/src/api/iso/schema/$.ts +1 -0
  149. package/src/api/iso/schema/constants.ts +49 -0
  150. package/src/api/iso/schema/routing.ts +142 -0
  151. package/src/api/iso/schema/validation.ts +136 -0
  152. package/src/api/iso.ts +1 -0
  153. package/src/api/schema/schema.ts +6 -53
  154. package/src/api/vite/plugins/core.ts +3 -6
  155. package/src/template/components/ArgumentList.tsx +2 -6
  156. package/src/template/components/Changelog.tsx +2 -2
  157. package/src/template/components/DeprecationReason.tsx +2 -2
  158. package/src/template/components/Description.tsx +2 -2
  159. package/src/template/components/Field.tsx +2 -6
  160. package/src/template/components/FieldListSection.tsx +2 -6
  161. package/src/template/components/GraphQLInteractive/lib/parser.ts +32 -16
  162. package/src/template/components/HamburgerMenu.tsx +3 -1
  163. package/src/template/components/MissingSchema.tsx +3 -1
  164. package/src/template/components/ReferenceLink.tsx +16 -15
  165. package/src/template/components/ToastContainer.tsx +67 -0
  166. package/src/template/components/ToastItem.tsx +119 -0
  167. package/src/template/components/TypeAnnotation.tsx +2 -6
  168. package/src/template/components/VersionPicker.tsx +94 -0
  169. package/src/template/components/sidebar/Sidebar.tsx +20 -16
  170. package/src/template/components/sidebar/SidebarContext.tsx +7 -0
  171. package/src/template/components/sidebar/SidebarItem.tsx +11 -4
  172. package/src/template/hooks/useReferencePath.ts +20 -0
  173. package/src/template/hooks/useVersionPath.ts +3 -1
  174. package/src/template/layouts/SidebarLayout.tsx +5 -3
  175. package/src/template/routes/reference.tsx +56 -73
  176. package/src/template/routes/root.tsx +29 -6
  177. package/src/template/server/ssg/get-route-paths.test.ts +13 -0
  178. package/src/template/server/ssg/get-route-paths.ts +47 -14
  179. package/src/template/stores/$$.ts +15 -0
  180. package/src/template/stores/$.ts +1 -0
  181. package/src/template/stores/schema.ts +52 -0
  182. package/src/template/stores/toast.ts +153 -0
  183. package/src/template/utils/try-with-toast.ts +41 -0
  184. package/build/template/components/VersionSelector.d.ts +0 -7
  185. package/build/template/components/VersionSelector.d.ts.map +0 -1
  186. package/build/template/components/VersionSelector.js +0 -30
  187. package/build/template/components/VersionSelector.js.map +0 -1
  188. package/build/template/lib/schema-utils/constants.d.ts +0 -5
  189. package/build/template/lib/schema-utils/constants.d.ts.map +0 -1
  190. package/build/template/lib/schema-utils/constants.js +0 -5
  191. package/build/template/lib/schema-utils/constants.js.map +0 -1
  192. package/src/template/components/VersionSelector.tsx +0 -50
  193. package/src/template/lib/schema-utils/constants.ts +0 -4
@@ -1,10 +1,13 @@
1
1
  import type { GraphqlChangeset } from '#lib/graphql-changeset/index'
2
2
 
3
- export * as DataSources from './data-sources/data-sources.js'
4
-
5
- export * from './read.js'
3
+ // Re-export everything from isomorphic layer
4
+ export * from '../iso/schema/constants.js'
5
+ export * as Routing from '../iso/schema/routing.js'
6
6
 
7
+ // Server-only exports
8
+ export * as DataSources from './data-sources/data-sources.js'
7
9
  export * from './metadata.js'
10
+ export * from './read.js'
8
11
 
9
12
  export type ChangeSets = GraphqlChangeset.ChangeSet[]
10
13
 
@@ -17,53 +20,3 @@ export interface ChangelogData {
17
20
  changes: GraphqlChangeset.ChangeSet['changes']
18
21
  date: string
19
22
  }
20
-
21
- /**
22
- * Constants for schema versioning
23
- */
24
-
25
- /**
26
- * The version identifier for the latest schema
27
- */
28
- export const VERSION_LATEST = `latest`
29
-
30
- /**
31
- * Fallback version name when date parsing fails
32
- */
33
- export const VERSION_UNKNOWN_FALLBACK = `unknown`
34
-
35
- /**
36
- * Convert a date to a version string in YYYY-MM-DD format
37
- */
38
- export const dateToVersionString = (date: Date): string => {
39
- return date.toLocaleDateString('en-CA')
40
- }
41
-
42
- /**
43
- * Determine if a version at the given index should have a changelog file.
44
- * Only non-oldest versions get changelog files.
45
- */
46
- export const shouldVersionHaveChangelog = (versionIndex: number, totalVersions: number): boolean => {
47
- return versionIndex < totalVersions - 1
48
- }
49
-
50
- /**
51
- * Convert a version string back to a Date
52
- */
53
- export const versionStringToDate = (version: string): Date => {
54
- if (version === VERSION_LATEST) {
55
- return new Date()
56
- }
57
-
58
- // Use modern date parsing - the version string should be in YYYY-MM-DD format
59
- // which is ISO 8601 compatible
60
- const parsedDate = new Date(version + 'T00:00:00Z')
61
-
62
- // Check if the date is valid
63
- if (!isNaN(parsedDate.getTime())) {
64
- return parsedDate
65
- }
66
-
67
- // Throw error for invalid dates instead of silently defaulting
68
- throw new Error(`Invalid version string: ${version}`)
69
- }
@@ -1,22 +1,18 @@
1
1
  import type { Config } from '#api/config/index'
2
2
  import { Content } from '#api/content/$'
3
3
  import { createNavbar } from '#api/content/navbar'
4
+ import { Api } from '#api/index'
4
5
  import { VitePluginSelfContainedMode } from '#cli/_/self-contained-mode'
5
- import { Hono } from '#dep/hono/index'
6
6
  import type { ReactRouter } from '#dep/react-router/index'
7
7
  import type { Vite } from '#dep/vite/index'
8
8
  import { VitePluginJson } from '#lib/vite-plugin-json/index'
9
9
  import { ViteVirtual } from '#lib/vite-virtual/index'
10
10
  import { debugPolen } from '#singletons/debug'
11
11
  import { superjson } from '#singletons/superjson'
12
- import * as HonoNodeServer from '@hono/node-server'
13
- import { serveStatic } from '@hono/node-server/serve-static'
14
12
  import { Json, Str } from '@wollybeard/kit'
15
- import * as NodePath from 'node:path'
16
13
  import type { ProjectData } from '../../../project-data.js'
17
14
  import { SchemaAugmentation } from '../../schema-augmentation/index.js'
18
15
  import { Schema } from '../../schema/index.js'
19
- import { createLogger } from '../logger.js'
20
16
  import { polenVirtual } from '../vi.js'
21
17
  import { Pages } from './pages.js'
22
18
  import { SchemaAssets } from './schema-assets.js'
@@ -201,7 +197,8 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
201
197
  // Without the leading slash, React Router treats paths as relative, which causes
202
198
  // hydration mismatches between SSR (where base path is prepended) and client
203
199
  // (where basename is configured). This ensures consistent behavior.
204
- navbar.push({ pathExp: `/reference`, title: `Reference` })
200
+ const referencePath = Api.Schema.Routing.createReferenceBasePath()
201
+ navbar.push({ pathExp: referencePath, title: `Reference` })
205
202
  if (schemaResult.data.length > 1) {
206
203
  navbar.push({ pathExp: `/changelog`, title: `Changelog` })
207
204
  }
@@ -1,13 +1,9 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import { Box, Flex, Heading, Text } from '@radix-ui/themes'
2
3
  import type { GraphQLArgument } from 'graphql'
3
- import type { FC } from 'react'
4
4
  import { TypeAnnotation } from './TypeAnnotation.js'
5
5
 
6
- export interface Props {
7
- args: readonly GraphQLArgument[]
8
- }
9
-
10
- export const ArgumentsList: FC<Props> = ({ args }) => {
6
+ export const ArgumentsList: React.FC<{ args: readonly GraphQLArgument[] }> = ({ args }) => {
11
7
  if (args.length === 0) return null
12
8
 
13
9
  return (
@@ -61,11 +61,11 @@ const Changeset: React.FC<{ changeset: GraphqlChangeset.ChangeSet }> = ({ change
61
61
  </h1>
62
62
  {groupedChanges.map(group => (
63
63
  <CriticalitySection key={group.level} level={group.level} changes={group.changes}>
64
- {group.changes.map(change => {
64
+ {group.changes.map((change, index) => {
65
65
  const type = GraphqlChange.Group.getType(change)
66
66
  return (
67
67
  <ComponentDispatch
68
- key={`${change.type}-${change.path || change.message}`}
68
+ key={`${change.type}-${change.path || change.message}-${index}`}
69
69
  components={Group}
70
70
  name={type}
71
71
  props={{ change }}
@@ -1,9 +1,9 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import type { GrafaidOld } from '#lib/grafaid-old/index'
2
3
  import { Text } from '@radix-ui/themes'
3
- import type { FC } from 'react'
4
4
  import { Markdown } from './Markdown.js'
5
5
 
6
- export const DeprecationReason: FC<{ data: GrafaidOld.GraphQLField }> = ({ data }) => {
6
+ export const DeprecationReason: React.FC<{ data: GrafaidOld.GraphQLField }> = ({ data }) => {
7
7
  if (!data.deprecationReason) return null
8
8
 
9
9
  return (
@@ -1,11 +1,11 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import { Text } from '@radix-ui/themes'
2
- import type { FC } from 'react'
3
3
  import { Markdown } from './Markdown.js'
4
4
  // import type { Grafaid } from '#lib/grafaid'
5
5
  import type { GrafaidOld } from '#lib/grafaid-old/index'
6
6
  import type { GraphQLNamedType } from 'graphql'
7
7
 
8
- export const Description: FC<{ data: GraphQLNamedType | GrafaidOld.GraphQLField }> = ({ data }) => {
8
+ export const Description: React.FC<{ data: GraphQLNamedType | GrafaidOld.GraphQLField }> = ({ data }) => {
9
9
  if (!data.description) return null
10
10
 
11
11
  return (
@@ -1,17 +1,13 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import { GrafaidOld } from '#lib/grafaid-old/index'
2
3
  import type { BoxProps } from '@radix-ui/themes'
3
4
  import { Box, Text } from '@radix-ui/themes'
4
- import type { FC } from 'react'
5
5
  import { ArgumentListAnnotation } from './ArgumentListAnnotation.js'
6
6
  import { DeprecationReason } from './DeprecationReason.js'
7
7
  import { Description } from './Description.js'
8
8
  import { TypeAnnotation } from './TypeAnnotation.js'
9
9
 
10
- export type Props = BoxProps & {
11
- data: GrafaidOld.GraphQLField
12
- }
13
-
14
- export const Field: FC<Props> = ({ data, ...boxProps }) => {
10
+ export const Field: React.FC<BoxProps & { data: GrafaidOld.GraphQLField }> = ({ data, ...boxProps }) => {
15
11
  const argumentList = GrafaidOld.isOutputField(data)
16
12
  ? <ArgumentListAnnotation field={data} />
17
13
  : null
@@ -1,14 +1,10 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import { Grafaid } from '#lib/grafaid/index'
2
3
  import { Box, Heading } from '@radix-ui/themes'
3
4
  import type { GraphQLNamedType } from 'graphql'
4
- import type { FC } from 'react'
5
5
  import { FieldList } from './FieldList.js'
6
6
 
7
- export interface Props {
8
- data: GraphQLNamedType
9
- }
10
-
11
- export const FieldListSection: FC<Props> = ({ data }) => {
7
+ export const FieldListSection: React.FC<{ data: GraphQLNamedType }> = ({ data }) => {
12
8
  if (!Grafaid.Schema.TypesLike.isFielded(data)) return null
13
9
 
14
10
  const fields = Grafaid.Schema.NodesLike.getFields(data)
@@ -5,6 +5,7 @@
5
5
  * analysis to create unified tokens for interactive code blocks.
6
6
  */
7
7
 
8
+ import { Api } from '#api/iso'
8
9
  import type { CodeAnnotation } from 'codehike/code'
9
10
  import {
10
11
  getNamedType,
@@ -14,7 +15,6 @@ import {
14
15
  GraphQLInputObjectType,
15
16
  GraphQLInterfaceType,
16
17
  GraphQLObjectType,
17
- type GraphQLOutputType,
18
18
  GraphQLScalarType,
19
19
  type GraphQLSchema,
20
20
  GraphQLUnionType,
@@ -24,12 +24,7 @@ import {
24
24
  import graphqlWasmUrl from 'tree-sitter-graphql-grammar-wasm/grammar.wasm?url'
25
25
  import * as WebTreeSitter from 'web-tree-sitter'
26
26
  import treeSitterWasmUrl from 'web-tree-sitter/tree-sitter.wasm?url'
27
- import {
28
- isKeywordNodeType,
29
- isLiteralNodeType,
30
- isPunctuationNodeType,
31
- type TreeSitterGraphQLNodeType,
32
- } from './graphql-node-types.js'
27
+ import { isKeywordNodeType, isPunctuationNodeType, type TreeSitterGraphQLNodeType } from './graphql-node-types.js'
33
28
  import type { SemanticNode } from './semantic-nodes.js'
34
29
  import {
35
30
  isArgument,
@@ -263,42 +258,63 @@ class UnifiedToken implements GraphQLToken {
263
258
 
264
259
  // Arguments - use #<field>__<argument> pattern
265
260
  if (isArgument(this.semantic)) {
266
- return `/reference/${this.semantic.parentType.name}#${this.semantic.parentField.name}__${this.semantic.argumentDef.name}`
261
+ const basePath = Api.Schema.Routing.createReferencePath({
262
+ type: this.semantic.parentType.name,
263
+ })
264
+ return `${basePath}#${this.semantic.parentField.name}__${this.semantic.argumentDef.name}`
267
265
  }
268
266
 
269
267
  // Output fields - use hash links since field routes aren't connected yet
270
268
  if (isOutputField(this.semantic)) {
271
- return `/reference/${this.semantic.parentType.name}#${this.semantic.fieldDef.name}`
269
+ const basePath = Api.Schema.Routing.createReferencePath({
270
+ type: this.semantic.parentType.name,
271
+ })
272
+ return `${basePath}#${this.semantic.fieldDef.name}`
272
273
  }
273
274
 
274
275
  // Input fields - use hash links since field routes aren't connected yet
275
276
  if (isInputField(this.semantic)) {
276
- return `/reference/${this.semantic.parentType.name}#${this.semantic.fieldDef.name}`
277
+ const basePath = Api.Schema.Routing.createReferencePath({
278
+ type: this.semantic.parentType.name,
279
+ })
280
+ return `${basePath}#${this.semantic.fieldDef.name}`
277
281
  }
278
282
 
279
283
  // Type references - use :type pattern
280
284
  if (this.semantic instanceof GraphQLObjectType) {
281
- return `/reference/${this.semantic.name}`
285
+ return Api.Schema.Routing.createReferencePath({
286
+ type: this.semantic.name,
287
+ })
282
288
  }
283
289
 
284
290
  if (this.semantic instanceof GraphQLScalarType) {
285
- return `/reference/${this.semantic.name}`
291
+ return Api.Schema.Routing.createReferencePath({
292
+ type: this.semantic.name,
293
+ })
286
294
  }
287
295
 
288
296
  if (this.semantic instanceof GraphQLInterfaceType) {
289
- return `/reference/${this.semantic.name}`
297
+ return Api.Schema.Routing.createReferencePath({
298
+ type: this.semantic.name,
299
+ })
290
300
  }
291
301
 
292
302
  if (this.semantic instanceof GraphQLUnionType) {
293
- return `/reference/${this.semantic.name}`
303
+ return Api.Schema.Routing.createReferencePath({
304
+ type: this.semantic.name,
305
+ })
294
306
  }
295
307
 
296
308
  if (this.semantic instanceof GraphQLEnumType) {
297
- return `/reference/${this.semantic.name}`
309
+ return Api.Schema.Routing.createReferencePath({
310
+ type: this.semantic.name,
311
+ })
298
312
  }
299
313
 
300
314
  if (this.semantic instanceof GraphQLInputObjectType) {
301
- return `/reference/${this.semantic.name}`
315
+ return Api.Schema.Routing.createReferencePath({
316
+ type: this.semantic.name,
317
+ })
302
318
  }
303
319
 
304
320
  return null
@@ -9,6 +9,7 @@ export interface HamburgerMenuProps {
9
9
  onToggle: () => void
10
10
  onClose: () => void
11
11
  sidebarData: Content.Item[]
12
+ basePath?: string
12
13
  }
13
14
 
14
15
  export const HamburgerMenu: React.FC<HamburgerMenuProps> = ({
@@ -16,6 +17,7 @@ export const HamburgerMenu: React.FC<HamburgerMenuProps> = ({
16
17
  onToggle,
17
18
  onClose,
18
19
  sidebarData,
20
+ basePath,
19
21
  }) => {
20
22
  // Prevent body scroll when mobile menu is open
21
23
  useEffect(() => {
@@ -87,7 +89,7 @@ export const HamburgerMenu: React.FC<HamburgerMenuProps> = ({
87
89
  <Cross2Icon width='18' height='18' />
88
90
  </IconButton>
89
91
  </Flex>
90
- <Sidebar data={sidebarData} />
92
+ <Sidebar data={sidebarData} basePath={basePath} />
91
93
  </Box>
92
94
  </>
93
95
  )}
@@ -1,3 +1,5 @@
1
- export const MissingSchema = () => {
1
+ import type { React } from '#dep/react/index'
2
+
3
+ export const MissingSchema: React.FC = () => {
2
4
  return <div>No content to show. There is no schema to work with.</div>
3
5
  }
@@ -1,16 +1,8 @@
1
- import type { ReactNode } from 'react'
1
+ import { Api } from '#api/iso'
2
+ import type { React } from '#dep/react/index'
2
3
  import { useVersionPath } from '../hooks/useVersionPath.js'
3
4
  import { Link } from './Link.js'
4
5
 
5
- interface Props {
6
- /** The GraphQL type name */
7
- type: string
8
- /** Optional field name for field-specific links */
9
- field?: string
10
- /** Link content */
11
- children: ReactNode
12
- }
13
-
14
6
  /**
15
7
  * Link component for GraphQL schema references that preserves version context
16
8
  *
@@ -18,13 +10,22 @@ interface Props {
18
10
  * <ReferenceLink type="User">User</ReferenceLink>
19
11
  * <ReferenceLink type="User" field="name">User.name</ReferenceLink>
20
12
  */
21
- export const ReferenceLink = ({ type, field, children }: Props) => {
13
+ export const ReferenceLink: React.FC<{
14
+ /** The GraphQL type name */
15
+ type: string
16
+ /** Optional field name for field-specific links */
17
+ field?: string
18
+ /** Link content */
19
+ children: React.ReactNode
20
+ }> = ({ type, field, children }) => {
22
21
  const versionPath = useVersionPath()
23
22
 
24
- let path = `/reference/${versionPath}${type}`
25
- if (field) {
26
- path += `/${field}`
27
- }
23
+ const path = Api.Schema.Routing.joinSegmentsAndPaths(
24
+ Api.Schema.Routing.segmentLiterals.reference,
25
+ versionPath,
26
+ type,
27
+ field,
28
+ )
28
29
 
29
30
  return (
30
31
  <Link to={path}>
@@ -0,0 +1,67 @@
1
+ import type { React } from '#dep/react/index'
2
+ import { Box, Flex } from '@radix-ui/themes'
3
+ import { useSnapshot } from 'valtio'
4
+ import { Stores } from '../stores/$.js'
5
+ import { ToastItem } from './ToastItem.js'
6
+
7
+ export const ToastContainer: React.FC = () => {
8
+ const snap = useSnapshot(Stores.Toast.store)
9
+
10
+ return (
11
+ <>
12
+ <style>
13
+ {`
14
+ @keyframes slideIn {
15
+ from {
16
+ transform: translateX(100%);
17
+ opacity: 0;
18
+ }
19
+ to {
20
+ transform: translateX(0);
21
+ opacity: 1;
22
+ }
23
+ }
24
+
25
+ @keyframes slideOut {
26
+ from {
27
+ transform: translateX(0);
28
+ opacity: 1;
29
+ }
30
+ to {
31
+ transform: translateX(100%);
32
+ opacity: 0;
33
+ }
34
+ }
35
+
36
+ @keyframes timerCountdown {
37
+ from {
38
+ width: 100%;
39
+ }
40
+ to {
41
+ width: 0%;
42
+ }
43
+ }
44
+ `}
45
+ </style>
46
+ <Box
47
+ position='fixed'
48
+ bottom='0'
49
+ right='0'
50
+ p='4'
51
+ style={{
52
+ zIndex: 9999,
53
+ pointerEvents: 'none',
54
+ }}
55
+ >
56
+ <Flex
57
+ direction='column'
58
+ gap='2'
59
+ align='end'
60
+ style={{ pointerEvents: 'auto' }}
61
+ >
62
+ {snap.toasts.map(toast => <ToastItem key={toast.id} toast={toast} />)}
63
+ </Flex>
64
+ </Box>
65
+ </>
66
+ )
67
+ }
@@ -0,0 +1,119 @@
1
+ import type { React } from '#dep/react/index'
2
+ import {
3
+ CheckCircledIcon,
4
+ Cross2Icon,
5
+ CrossCircledIcon,
6
+ ExclamationTriangleIcon,
7
+ InfoCircledIcon,
8
+ } from '@radix-ui/react-icons'
9
+ import { Box, Button, Card, Flex, IconButton, Text } from '@radix-ui/themes'
10
+ import type { TextProps } from '@radix-ui/themes'
11
+ import type { ReadonlyDeep } from 'type-fest'
12
+ import { Stores } from '../stores/$.js'
13
+
14
+ const toastVariants = {
15
+ info: {
16
+ icon: <InfoCircledIcon />,
17
+ color: 'blue',
18
+ },
19
+ success: {
20
+ icon: <CheckCircledIcon />,
21
+ color: 'green',
22
+ },
23
+ warning: {
24
+ icon: <ExclamationTriangleIcon />,
25
+ color: 'amber',
26
+ },
27
+ error: {
28
+ icon: <CrossCircledIcon />,
29
+ color: 'red',
30
+ },
31
+ } satisfies Record<Stores.Toast.Type, {
32
+ icon: React.ReactElement
33
+ color: NonNullable<TextProps['color']>
34
+ }>
35
+
36
+ export const ToastItem: React.FC<{ toast: ReadonlyDeep<Stores.Toast.Toast> }> = ({ toast }) => {
37
+ const handleClose = () => Stores.toast.remove(toast.id)
38
+ const duration = toast.duration ?? 5000
39
+ const showTimer = duration > 0
40
+ const type: Stores.Toast.Type = toast.type || 'info'
41
+
42
+ return (
43
+ <Card
44
+ size={'2'}
45
+ style={{
46
+ animation: 'slideIn 0.2s ease-out',
47
+ position: 'relative',
48
+ }}
49
+ >
50
+ <Flex gap='3' align='start' maxWidth={'400px'}>
51
+ <Text
52
+ as='div'
53
+ size='4'
54
+ color={toastVariants[type].color}
55
+ >
56
+ {toastVariants[type].icon}
57
+ </Text>
58
+ <Box style={{ flex: 1 }}>
59
+ <Flex align='baseline' gap='2' wrap='wrap'>
60
+ <Text weight='medium' size='2'>
61
+ {toast.message}
62
+ </Text>
63
+ {toast.actions.map((action) => (
64
+ <Button
65
+ id={action.label}
66
+ size='1'
67
+ variant='soft'
68
+ onClick={() => {
69
+ action.onClick()
70
+ handleClose()
71
+ }}
72
+ >
73
+ {action.label}
74
+ </Button>
75
+ ))}
76
+ </Flex>
77
+
78
+ {toast.description && (
79
+ <Text size='1' color='gray' mt='1' style={{ display: 'block' }}>
80
+ {toast.description}
81
+ </Text>
82
+ )}
83
+ </Box>
84
+
85
+ <IconButton
86
+ size='1'
87
+ variant='ghost'
88
+ color='gray'
89
+ onClick={handleClose}
90
+ style={{ flexShrink: 0 }}
91
+ >
92
+ <Cross2Icon />
93
+ </IconButton>
94
+ </Flex>
95
+
96
+ {showTimer && (
97
+ <Box
98
+ style={{
99
+ position: 'absolute',
100
+ bottom: 0,
101
+ left: 0,
102
+ right: 0,
103
+ height: '2px',
104
+ backgroundColor: `var(--${toastVariants[toast.type || 'info'].color}-a3)`,
105
+ overflow: 'hidden',
106
+ }}
107
+ >
108
+ <Box
109
+ style={{
110
+ height: '100%',
111
+ backgroundColor: `var(--${toastVariants[toast.type || 'info'].color}-a6)`,
112
+ animation: `timerCountdown ${duration}ms linear forwards`,
113
+ }}
114
+ />
115
+ </Box>
116
+ )}
117
+ </Card>
118
+ )
119
+ }
@@ -1,17 +1,13 @@
1
+ import type { React } from '#dep/react/index'
1
2
  import { Text } from '@radix-ui/themes'
2
3
  import type { GraphQLType } from 'graphql'
3
4
  import { isInputObjectType, isListType, isNamedType, isNonNullType, isScalarType } from 'graphql'
4
- import type { FC } from 'react'
5
5
  import { ReferenceLink } from './ReferenceLink.js'
6
6
 
7
- export interface Props {
8
- type: GraphQLType // Can be either GraphQLInputType or GraphQLOutputType
9
- }
10
-
11
7
  /**
12
8
  * Renders a GraphQL type recursively, with links for named types
13
9
  */
14
- export const TypeAnnotation: FC<Props> = ({ type }) => {
10
+ export const TypeAnnotation: React.FC<{ type: GraphQLType }> = ({ type }) => {
15
11
  // Handle NonNull type wrapper
16
12
  if (isNonNullType(type)) {
17
13
  return (