@sntlr/registry-shell 1.0.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.
Files changed (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/adapter/custom.d.ts +47 -0
  4. package/dist/adapter/custom.js +53 -0
  5. package/dist/adapter/custom.js.map +1 -0
  6. package/dist/adapter/default.d.ts +40 -0
  7. package/dist/adapter/default.js +202 -0
  8. package/dist/adapter/default.js.map +1 -0
  9. package/dist/cli/build.d.ts +1 -0
  10. package/dist/cli/build.js +31 -0
  11. package/dist/cli/build.js.map +1 -0
  12. package/dist/cli/dev.d.ts +1 -0
  13. package/dist/cli/dev.js +26 -0
  14. package/dist/cli/dev.js.map +1 -0
  15. package/dist/cli/index.d.ts +12 -0
  16. package/dist/cli/index.js +49 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/cli/init.d.ts +1 -0
  19. package/dist/cli/init.js +70 -0
  20. package/dist/cli/init.js.map +1 -0
  21. package/dist/cli/shared.d.ts +33 -0
  22. package/dist/cli/shared.js +278 -0
  23. package/dist/cli/shared.js.map +1 -0
  24. package/dist/cli/start.d.ts +1 -0
  25. package/dist/cli/start.js +24 -0
  26. package/dist/cli/start.js.map +1 -0
  27. package/dist/config-loader.d.ts +49 -0
  28. package/dist/config-loader.js +140 -0
  29. package/dist/define-config.d.ts +188 -0
  30. package/dist/define-config.js +21 -0
  31. package/dist/index.d.ts +11 -0
  32. package/dist/index.js +9 -0
  33. package/package.json +124 -0
  34. package/src/adapter/custom.ts +90 -0
  35. package/src/adapter/default.ts +241 -0
  36. package/src/cli/build.ts +38 -0
  37. package/src/cli/dev.ts +38 -0
  38. package/src/cli/index.ts +52 -0
  39. package/src/cli/init.ts +76 -0
  40. package/src/cli/shared.ts +306 -0
  41. package/src/cli/start.ts +28 -0
  42. package/src/config-loader.ts +190 -0
  43. package/src/define-config.ts +206 -0
  44. package/src/index.ts +17 -0
  45. package/src/next-app/app/[...asset]/route.ts +81 -0
  46. package/src/next-app/app/_user-global.css +6 -0
  47. package/src/next-app/app/_user-sources.css +9 -0
  48. package/src/next-app/app/a11y/[name]/route.ts +19 -0
  49. package/src/next-app/app/api/search-index/route.ts +19 -0
  50. package/src/next-app/app/components/[name]/page.tsx +61 -0
  51. package/src/next-app/app/components/layout.tsx +18 -0
  52. package/src/next-app/app/docs/[slug]/page.tsx +53 -0
  53. package/src/next-app/app/docs/layout.tsx +18 -0
  54. package/src/next-app/app/globals.css +329 -0
  55. package/src/next-app/app/layout.tsx +102 -0
  56. package/src/next-app/app/page.tsx +9 -0
  57. package/src/next-app/app/preview-snapshot/[name]/page.tsx +20 -0
  58. package/src/next-app/app/preview-snapshot/layout.tsx +17 -0
  59. package/src/next-app/app/props/[name]/route.ts +19 -0
  60. package/src/next-app/app/r/[name]/route.ts +14 -0
  61. package/src/next-app/app/tests/[name]/route.ts +19 -0
  62. package/src/next-app/components/a11y-info.tsx +287 -0
  63. package/src/next-app/components/a11y-provider.tsx +39 -0
  64. package/src/next-app/components/component-breadcrumb.tsx +55 -0
  65. package/src/next-app/components/component-icon.tsx +140 -0
  66. package/src/next-app/components/component-preview.tsx +13 -0
  67. package/src/next-app/components/component-tabs.tsx +209 -0
  68. package/src/next-app/components/docs-toc.tsx +86 -0
  69. package/src/next-app/components/global-mobile-sidebar.tsx +35 -0
  70. package/src/next-app/components/header.tsx +188 -0
  71. package/src/next-app/components/heading-anchor.tsx +52 -0
  72. package/src/next-app/components/homepage-demo.tsx +180 -0
  73. package/src/next-app/components/locale-toggle.tsx +35 -0
  74. package/src/next-app/components/localized-mdx-client.tsx +14 -0
  75. package/src/next-app/components/localized-mdx.tsx +27 -0
  76. package/src/next-app/components/mobile-sidebar.tsx +22 -0
  77. package/src/next-app/components/nav-data-provider.tsx +37 -0
  78. package/src/next-app/components/navigation-progress.tsx +62 -0
  79. package/src/next-app/components/preview-canvas.tsx +368 -0
  80. package/src/next-app/components/preview-controls.tsx +94 -0
  81. package/src/next-app/components/preview-layout.tsx +218 -0
  82. package/src/next-app/components/props-table.tsx +134 -0
  83. package/src/next-app/components/resizable-preview.tsx +101 -0
  84. package/src/next-app/components/search.tsx +177 -0
  85. package/src/next-app/components/settings-modal.tsx +98 -0
  86. package/src/next-app/components/shell-ui/accordion.tsx +70 -0
  87. package/src/next-app/components/shell-ui/backdrop.tsx +29 -0
  88. package/src/next-app/components/shell-ui/badge.tsx +55 -0
  89. package/src/next-app/components/shell-ui/breadcrumb.tsx +120 -0
  90. package/src/next-app/components/shell-ui/button.tsx +64 -0
  91. package/src/next-app/components/shell-ui/card.tsx +127 -0
  92. package/src/next-app/components/shell-ui/checkbox.tsx +33 -0
  93. package/src/next-app/components/shell-ui/dialog.tsx +171 -0
  94. package/src/next-app/components/shell-ui/empty-state.tsx +66 -0
  95. package/src/next-app/components/shell-ui/input.tsx +27 -0
  96. package/src/next-app/components/shell-ui/kbd.tsx +30 -0
  97. package/src/next-app/components/shell-ui/label.tsx +25 -0
  98. package/src/next-app/components/shell-ui/select.tsx +204 -0
  99. package/src/next-app/components/shell-ui/separator.tsx +32 -0
  100. package/src/next-app/components/shell-ui/skeleton.tsx +18 -0
  101. package/src/next-app/components/shell-ui/table.tsx +124 -0
  102. package/src/next-app/components/shell-ui/tabs.tsx +102 -0
  103. package/src/next-app/components/shell-ui/toggle.tsx +56 -0
  104. package/src/next-app/components/sidebar-layout.tsx +37 -0
  105. package/src/next-app/components/sidebar-provider.tsx +75 -0
  106. package/src/next-app/components/sidebar.tsx +222 -0
  107. package/src/next-app/components/snapshot-preview.tsx +28 -0
  108. package/src/next-app/components/test-info.tsx +155 -0
  109. package/src/next-app/components/theme-provider.tsx +16 -0
  110. package/src/next-app/components/theme-toggle.tsx +21 -0
  111. package/src/next-app/components/translated-text.tsx +8 -0
  112. package/src/next-app/fallback/homepage.tsx +112 -0
  113. package/src/next-app/fallback/previews.ts +17 -0
  114. package/src/next-app/hooks/use-active-section.ts +23 -0
  115. package/src/next-app/hooks/use-controls.ts +72 -0
  116. package/src/next-app/hooks/use-mobile.ts +19 -0
  117. package/src/next-app/lib/branding.ts +52 -0
  118. package/src/next-app/lib/components-nav.ts +8 -0
  119. package/src/next-app/lib/docs.ts +16 -0
  120. package/src/next-app/lib/github.ts +38 -0
  121. package/src/next-app/lib/i18n.tsx +630 -0
  122. package/src/next-app/lib/locales.ts +17 -0
  123. package/src/next-app/lib/preview-loader.ts +7 -0
  124. package/src/next-app/lib/registry-adapter.ts +199 -0
  125. package/src/next-app/lib/utils.ts +6 -0
  126. package/src/next-app/next-env.d.ts +6 -0
  127. package/src/next-app/next.config.ts +101 -0
  128. package/src/next-app/postcss.config.mjs +7 -0
  129. package/src/next-app/public/favicon.ico +0 -0
  130. package/src/next-app/public/favicon_dark.svg +3 -0
  131. package/src/next-app/public/favicon_light.svg +3 -0
  132. package/src/next-app/registry.config.ts +50 -0
  133. package/src/next-app/tsconfig.json +29 -0
  134. package/src/next-app/user-aliases.d.ts +17 -0
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Client-safe branding. Populated by the CLI via NEXT_PUBLIC_SHELL_* env vars
3
+ * that Next.js inlines at build time. Values fall back to sensible defaults
4
+ * when no config is wired, so client code never crashes.
5
+ */
6
+ import type { BrandingConfig, GithubConfig } from "@shell/lib/registry-adapter"
7
+
8
+ const DEFAULT_BRANDING = {
9
+ siteName: "UI Registry",
10
+ shortName: "UI",
11
+ siteUrl: "",
12
+ description: "",
13
+ ogImage: "",
14
+ twitterHandle: "",
15
+ logoAlt: "UI",
16
+ faviconDark: "/favicon_dark.svg",
17
+ faviconLight: "/favicon_light.svg",
18
+ faviconIco: "/favicon.ico",
19
+ } as const
20
+
21
+ function pick(key: string, fallback: string): string {
22
+ const value = process.env[`NEXT_PUBLIC_SHELL_${key}`]
23
+ return value && value.length > 0 ? value : fallback
24
+ }
25
+
26
+ const githubOwner = pick("GITHUB_OWNER", "")
27
+ const githubRepo = pick("GITHUB_REPO", "")
28
+ const github: GithubConfig | undefined =
29
+ githubOwner && githubRepo
30
+ ? {
31
+ owner: githubOwner,
32
+ repo: githubRepo,
33
+ label: pick("GITHUB_LABEL", "Github"),
34
+ showStars: process.env.NEXT_PUBLIC_SHELL_GITHUB_SHOW_STARS !== "false",
35
+ }
36
+ : undefined
37
+
38
+ export const branding: Required<Omit<BrandingConfig, "github">> & {
39
+ github: GithubConfig | undefined
40
+ } = {
41
+ siteName: pick("SITE_NAME", DEFAULT_BRANDING.siteName),
42
+ shortName: pick("SHORT_NAME", DEFAULT_BRANDING.shortName),
43
+ siteUrl: pick("SITE_URL", DEFAULT_BRANDING.siteUrl),
44
+ description: pick("DESCRIPTION", DEFAULT_BRANDING.description),
45
+ ogImage: pick("OG_IMAGE", DEFAULT_BRANDING.ogImage),
46
+ twitterHandle: pick("TWITTER_HANDLE", DEFAULT_BRANDING.twitterHandle),
47
+ github,
48
+ logoAlt: pick("LOGO_ALT", DEFAULT_BRANDING.logoAlt),
49
+ faviconDark: pick("FAVICON_DARK", DEFAULT_BRANDING.faviconDark),
50
+ faviconLight: pick("FAVICON_LIGHT", DEFAULT_BRANDING.faviconLight),
51
+ faviconIco: pick("FAVICON_ICO", DEFAULT_BRANDING.faviconIco),
52
+ }
@@ -0,0 +1,8 @@
1
+ import { registry } from "@shell/registry.config"
2
+ import type { ComponentMeta } from "./registry-adapter"
3
+
4
+ export type { ComponentMeta }
5
+
6
+ export function getAllComponents(): ComponentMeta[] {
7
+ return registry?.getAllComponents() ?? []
8
+ }
@@ -0,0 +1,16 @@
1
+ import { registry } from "@shell/registry.config"
2
+ import type { DocMeta } from "./registry-adapter"
3
+
4
+ export type { DocMeta }
5
+
6
+ export function getAllDocs(): DocMeta[] {
7
+ return registry?.getAllDocs() ?? []
8
+ }
9
+
10
+ export function getDocBySlug(slug: string, locale?: string) {
11
+ return registry?.getDocBySlug(slug, locale) ?? null
12
+ }
13
+
14
+ export function getDocAllLocales(slug: string): Record<string, string> {
15
+ return registry?.getDocAllLocales(slug) ?? {}
16
+ }
@@ -0,0 +1,38 @@
1
+ import { branding } from "@shell/lib/branding"
2
+
3
+ export const GITHUB_URL = branding.github
4
+ ? `https://github.com/${branding.github.owner}/${branding.github.repo}`
5
+ : ""
6
+
7
+ interface RepoResponse {
8
+ stargazers_count?: number
9
+ }
10
+
11
+ /**
12
+ * Server-side fetch of the repository star count with a 1-hour Next.js
13
+ * revalidation window. Returns `null` when no GitHub config is set, when
14
+ * the registry opted out of stars, or on any API failure so callers can
15
+ * render the bare icon without throwing.
16
+ */
17
+ export async function getGithubStars(): Promise<number | null> {
18
+ const gh = branding.github
19
+ if (!gh || gh.showStars === false) return null
20
+ try {
21
+ const res = await fetch(`https://api.github.com/repos/${gh.owner}/${gh.repo}`, {
22
+ next: { revalidate: 3600 },
23
+ headers: { Accept: "application/vnd.github+json" },
24
+ })
25
+ if (!res.ok) return null
26
+ const data = (await res.json()) as RepoResponse
27
+ return typeof data.stargazers_count === "number" ? data.stargazers_count : null
28
+ } catch {
29
+ return null
30
+ }
31
+ }
32
+
33
+ /** Compact star count: 1234 → "1.2k", 12345 → "12k", anything < 1000 stays as-is. */
34
+ export function formatStarCount(count: number): string {
35
+ if (count < 1000) return String(count)
36
+ if (count < 10000) return `${(count / 1000).toFixed(1).replace(/\.0$/, "")}k`
37
+ return `${Math.round(count / 1000)}k`
38
+ }