@sntlr/registry-shell 1.0.0 → 1.1.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 (36) hide show
  1. package/README.md +2 -5
  2. package/dist/adapter/custom.d.ts +1 -1
  3. package/dist/adapter/default.d.ts +3 -3
  4. package/dist/adapter/default.js +3 -3
  5. package/dist/cli/init.js +0 -3
  6. package/dist/cli/init.js.map +1 -1
  7. package/dist/cli/shared.js +0 -5
  8. package/dist/cli/shared.js.map +1 -1
  9. package/dist/config-loader.d.ts +0 -2
  10. package/dist/config-loader.js +0 -1
  11. package/dist/define-config.d.ts +0 -6
  12. package/package.json +1 -1
  13. package/src/adapter/custom.ts +1 -1
  14. package/src/adapter/default.ts +3 -3
  15. package/src/cli/init.ts +0 -3
  16. package/src/cli/shared.ts +0 -4
  17. package/src/config-loader.ts +0 -3
  18. package/src/define-config.ts +0 -7
  19. package/src/next-app/app/globals.css +329 -329
  20. package/src/next-app/app/page.tsx +1 -1
  21. package/src/next-app/components/component-icon.tsx +140 -140
  22. package/src/next-app/components/heading-anchor.tsx +52 -52
  23. package/src/next-app/{fallback → components}/homepage.tsx +2 -3
  24. package/src/next-app/components/navigation-progress.tsx +62 -62
  25. package/src/next-app/components/resizable-preview.tsx +101 -101
  26. package/src/next-app/components/sidebar-provider.tsx +75 -75
  27. package/src/next-app/hooks/use-controls.ts +72 -72
  28. package/src/next-app/lib/i18n.tsx +630 -630
  29. package/src/next-app/lib/registry-adapter.ts +6 -32
  30. package/src/next-app/lib/utils.ts +6 -6
  31. package/src/next-app/next-env.d.ts +6 -6
  32. package/src/next-app/next.config.ts +0 -5
  33. package/src/next-app/postcss.config.mjs +7 -7
  34. package/src/next-app/user-aliases.d.ts +0 -7
  35. package/src/next-app/app/_user-global.css +0 -6
  36. package/src/next-app/app/_user-sources.css +0 -9
@@ -1,101 +1,101 @@
1
- "use client"
2
-
3
- import { useCallback, useRef, useState, useEffect } from "react"
4
-
5
- const STORAGE_KEY = "preview-height"
6
- const DEFAULT_HEIGHT_DESKTOP = 384
7
- const DEFAULT_HEIGHT_MOBILE = 600
8
- const MIN_HEIGHT = 200
9
- const MAX_HEIGHT = 1000
10
-
11
- function getDefaultHeight(): number {
12
- if (typeof window === "undefined") return DEFAULT_HEIGHT_DESKTOP
13
- return window.matchMedia("(max-width: 767px)").matches
14
- ? DEFAULT_HEIGHT_MOBILE
15
- : DEFAULT_HEIGHT_DESKTOP
16
- }
17
-
18
- function getStoredHeight(): number {
19
- if (typeof window === "undefined") return DEFAULT_HEIGHT_DESKTOP
20
- const stored = sessionStorage.getItem(STORAGE_KEY)
21
- if (stored) {
22
- const n = Number(stored)
23
- if (!isNaN(n)) return Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, n))
24
- }
25
- return getDefaultHeight()
26
- }
27
-
28
- export function ResizablePreview({ children }: { children: React.ReactNode }) {
29
- const [height, setHeight] = useState(getStoredHeight)
30
- const dragging = useRef(false)
31
- const startY = useRef(0)
32
- const startH = useRef(0)
33
-
34
- useEffect(() => {
35
- sessionStorage.setItem(STORAGE_KEY, String(height))
36
- }, [height])
37
-
38
- const onMouseDown = useCallback((e: React.MouseEvent) => {
39
- e.preventDefault()
40
- dragging.current = true
41
- startY.current = e.clientY
42
- startH.current = height
43
- document.body.style.cursor = "row-resize"
44
- document.body.style.userSelect = "none"
45
-
46
- function onMouseMove(ev: MouseEvent) {
47
- if (!dragging.current) return
48
- const newH = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, startH.current + (ev.clientY - startY.current)))
49
- setHeight(newH)
50
- }
51
-
52
- function onMouseUp() {
53
- dragging.current = false
54
- document.body.style.cursor = ""
55
- document.body.style.userSelect = ""
56
- document.removeEventListener("mousemove", onMouseMove)
57
- document.removeEventListener("mouseup", onMouseUp)
58
- }
59
-
60
- document.addEventListener("mousemove", onMouseMove)
61
- document.addEventListener("mouseup", onMouseUp)
62
- }, [height])
63
-
64
- const onTouchStart = useCallback((e: React.TouchEvent) => {
65
- if (e.touches.length !== 1) return
66
- dragging.current = true
67
- startY.current = e.touches[0].clientY
68
- startH.current = height
69
-
70
- function onTouchMove(ev: TouchEvent) {
71
- if (!dragging.current || ev.touches.length !== 1) return
72
- ev.preventDefault()
73
- const newH = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, startH.current + (ev.touches[0].clientY - startY.current)))
74
- setHeight(newH)
75
- }
76
-
77
- function onTouchEnd() {
78
- dragging.current = false
79
- document.removeEventListener("touchmove", onTouchMove)
80
- document.removeEventListener("touchend", onTouchEnd)
81
- }
82
-
83
- document.addEventListener("touchmove", onTouchMove, { passive: false })
84
- document.addEventListener("touchend", onTouchEnd)
85
- }, [height])
86
-
87
- return (
88
- <div>
89
- <div style={{ height }}>
90
- {children}
91
- </div>
92
- <div
93
- className="h-3 md:h-2 cursor-row-resize flex items-center justify-center hover:bg-muted/50 active:bg-muted/50 transition-colors group touch-none"
94
- onMouseDown={onMouseDown}
95
- onTouchStart={onTouchStart}
96
- >
97
- <div className="w-8 h-0.5 rounded-full bg-border group-hover:bg-muted-foreground transition-colors" />
98
- </div>
99
- </div>
100
- )
101
- }
1
+ "use client"
2
+
3
+ import { useCallback, useRef, useState, useEffect } from "react"
4
+
5
+ const STORAGE_KEY = "preview-height"
6
+ const DEFAULT_HEIGHT_DESKTOP = 384
7
+ const DEFAULT_HEIGHT_MOBILE = 600
8
+ const MIN_HEIGHT = 200
9
+ const MAX_HEIGHT = 1000
10
+
11
+ function getDefaultHeight(): number {
12
+ if (typeof window === "undefined") return DEFAULT_HEIGHT_DESKTOP
13
+ return window.matchMedia("(max-width: 767px)").matches
14
+ ? DEFAULT_HEIGHT_MOBILE
15
+ : DEFAULT_HEIGHT_DESKTOP
16
+ }
17
+
18
+ function getStoredHeight(): number {
19
+ if (typeof window === "undefined") return DEFAULT_HEIGHT_DESKTOP
20
+ const stored = sessionStorage.getItem(STORAGE_KEY)
21
+ if (stored) {
22
+ const n = Number(stored)
23
+ if (!isNaN(n)) return Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, n))
24
+ }
25
+ return getDefaultHeight()
26
+ }
27
+
28
+ export function ResizablePreview({ children }: { children: React.ReactNode }) {
29
+ const [height, setHeight] = useState(getStoredHeight)
30
+ const dragging = useRef(false)
31
+ const startY = useRef(0)
32
+ const startH = useRef(0)
33
+
34
+ useEffect(() => {
35
+ sessionStorage.setItem(STORAGE_KEY, String(height))
36
+ }, [height])
37
+
38
+ const onMouseDown = useCallback((e: React.MouseEvent) => {
39
+ e.preventDefault()
40
+ dragging.current = true
41
+ startY.current = e.clientY
42
+ startH.current = height
43
+ document.body.style.cursor = "row-resize"
44
+ document.body.style.userSelect = "none"
45
+
46
+ function onMouseMove(ev: MouseEvent) {
47
+ if (!dragging.current) return
48
+ const newH = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, startH.current + (ev.clientY - startY.current)))
49
+ setHeight(newH)
50
+ }
51
+
52
+ function onMouseUp() {
53
+ dragging.current = false
54
+ document.body.style.cursor = ""
55
+ document.body.style.userSelect = ""
56
+ document.removeEventListener("mousemove", onMouseMove)
57
+ document.removeEventListener("mouseup", onMouseUp)
58
+ }
59
+
60
+ document.addEventListener("mousemove", onMouseMove)
61
+ document.addEventListener("mouseup", onMouseUp)
62
+ }, [height])
63
+
64
+ const onTouchStart = useCallback((e: React.TouchEvent) => {
65
+ if (e.touches.length !== 1) return
66
+ dragging.current = true
67
+ startY.current = e.touches[0].clientY
68
+ startH.current = height
69
+
70
+ function onTouchMove(ev: TouchEvent) {
71
+ if (!dragging.current || ev.touches.length !== 1) return
72
+ ev.preventDefault()
73
+ const newH = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, startH.current + (ev.touches[0].clientY - startY.current)))
74
+ setHeight(newH)
75
+ }
76
+
77
+ function onTouchEnd() {
78
+ dragging.current = false
79
+ document.removeEventListener("touchmove", onTouchMove)
80
+ document.removeEventListener("touchend", onTouchEnd)
81
+ }
82
+
83
+ document.addEventListener("touchmove", onTouchMove, { passive: false })
84
+ document.addEventListener("touchend", onTouchEnd)
85
+ }, [height])
86
+
87
+ return (
88
+ <div>
89
+ <div style={{ height }}>
90
+ {children}
91
+ </div>
92
+ <div
93
+ className="h-3 md:h-2 cursor-row-resize flex items-center justify-center hover:bg-muted/50 active:bg-muted/50 transition-colors group touch-none"
94
+ onMouseDown={onMouseDown}
95
+ onTouchStart={onTouchStart}
96
+ >
97
+ <div className="w-8 h-0.5 rounded-full bg-border group-hover:bg-muted-foreground transition-colors" />
98
+ </div>
99
+ </div>
100
+ )
101
+ }
@@ -1,75 +1,75 @@
1
- "use client"
2
-
3
- import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useState, type ReactNode } from "react"
4
-
5
- interface SidebarContextValue {
6
- open: boolean
7
- toggle: () => void
8
- close: () => void
9
- collapsed: boolean
10
- setCollapsed: (v: boolean) => void
11
- }
12
-
13
- const SidebarContext = createContext<SidebarContextValue>({
14
- open: false,
15
- toggle: () => {},
16
- close: () => {},
17
- collapsed: false,
18
- setCollapsed: () => {},
19
- })
20
-
21
- /**
22
- * Runs synchronously after DOM commit and *before* paint, so we can swap
23
- * client-only state into the tree post-hydration without ever rendering a
24
- * mismatched DOM. On the server it's a no-op alias to `useEffect`.
25
- */
26
- const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect
27
-
28
- export function SidebarProvider({ children }: { children: ReactNode }) {
29
- // Always start with the SSR-safe defaults so the server HTML and the first
30
- // client render are identical. Reading from sessionStorage / matchMedia in
31
- // a `useState` initializer caused a hydration mismatch on the Header (which
32
- // builds className strings from `collapsed`), and React's mismatch recovery
33
- // discards the affected subtree — which restarts the bento card CSS
34
- // animations on the homepage. We restore the persisted state in a layout
35
- // effect that runs before the first paint, so users never see a flash.
36
- const [open, setOpen] = useState(false)
37
- const [collapsed, setCollapsedState] = useState(false)
38
-
39
- useIsomorphicLayoutEffect(() => {
40
- // Sidebar nav: only restore on desktop (mobile always starts closed).
41
- const isMobile = window.matchMedia("(max-width: 767px)").matches
42
- if (!isMobile) {
43
- const storedOpen = sessionStorage.getItem("sidebar-nav-open") === "true"
44
- if (storedOpen) setOpen(true)
45
- }
46
- // Preview fullscreen.
47
- const storedCollapsed = sessionStorage.getItem("preview-fullscreen") === "true"
48
- if (storedCollapsed) setCollapsedState(true)
49
- }, [])
50
-
51
- const toggle = useCallback(() => {
52
- setOpen((o) => {
53
- sessionStorage.setItem("sidebar-nav-open", String(!o))
54
- return !o
55
- })
56
- }, [])
57
- const close = useCallback(() => {
58
- setOpen(false)
59
- sessionStorage.setItem("sidebar-nav-open", "false")
60
- }, [])
61
- const setCollapsed = useCallback((v: boolean) => {
62
- setCollapsedState(v)
63
- sessionStorage.setItem("preview-fullscreen", String(v))
64
- }, [])
65
-
66
- return (
67
- <SidebarContext.Provider value={{ open, toggle, close, collapsed, setCollapsed }}>
68
- {children}
69
- </SidebarContext.Provider>
70
- )
71
- }
72
-
73
- export function useMobileSidebar() {
74
- return useContext(SidebarContext)
75
- }
1
+ "use client"
2
+
3
+ import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useState, type ReactNode } from "react"
4
+
5
+ interface SidebarContextValue {
6
+ open: boolean
7
+ toggle: () => void
8
+ close: () => void
9
+ collapsed: boolean
10
+ setCollapsed: (v: boolean) => void
11
+ }
12
+
13
+ const SidebarContext = createContext<SidebarContextValue>({
14
+ open: false,
15
+ toggle: () => {},
16
+ close: () => {},
17
+ collapsed: false,
18
+ setCollapsed: () => {},
19
+ })
20
+
21
+ /**
22
+ * Runs synchronously after DOM commit and *before* paint, so we can swap
23
+ * client-only state into the tree post-hydration without ever rendering a
24
+ * mismatched DOM. On the server it's a no-op alias to `useEffect`.
25
+ */
26
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect
27
+
28
+ export function SidebarProvider({ children }: { children: ReactNode }) {
29
+ // Always start with the SSR-safe defaults so the server HTML and the first
30
+ // client render are identical. Reading from sessionStorage / matchMedia in
31
+ // a `useState` initializer caused a hydration mismatch on the Header (which
32
+ // builds className strings from `collapsed`), and React's mismatch recovery
33
+ // discards the affected subtree — which restarts the bento card CSS
34
+ // animations on the homepage. We restore the persisted state in a layout
35
+ // effect that runs before the first paint, so users never see a flash.
36
+ const [open, setOpen] = useState(false)
37
+ const [collapsed, setCollapsedState] = useState(false)
38
+
39
+ useIsomorphicLayoutEffect(() => {
40
+ // Sidebar nav: only restore on desktop (mobile always starts closed).
41
+ const isMobile = window.matchMedia("(max-width: 767px)").matches
42
+ if (!isMobile) {
43
+ const storedOpen = sessionStorage.getItem("sidebar-nav-open") === "true"
44
+ if (storedOpen) setOpen(true)
45
+ }
46
+ // Preview fullscreen.
47
+ const storedCollapsed = sessionStorage.getItem("preview-fullscreen") === "true"
48
+ if (storedCollapsed) setCollapsedState(true)
49
+ }, [])
50
+
51
+ const toggle = useCallback(() => {
52
+ setOpen((o) => {
53
+ sessionStorage.setItem("sidebar-nav-open", String(!o))
54
+ return !o
55
+ })
56
+ }, [])
57
+ const close = useCallback(() => {
58
+ setOpen(false)
59
+ sessionStorage.setItem("sidebar-nav-open", "false")
60
+ }, [])
61
+ const setCollapsed = useCallback((v: boolean) => {
62
+ setCollapsedState(v)
63
+ sessionStorage.setItem("preview-fullscreen", String(v))
64
+ }, [])
65
+
66
+ return (
67
+ <SidebarContext.Provider value={{ open, toggle, close, collapsed, setCollapsed }}>
68
+ {children}
69
+ </SidebarContext.Provider>
70
+ )
71
+ }
72
+
73
+ export function useMobileSidebar() {
74
+ return useContext(SidebarContext)
75
+ }
@@ -1,72 +1,72 @@
1
- "use client"
2
-
3
- import { useState } from "react"
4
-
5
- interface SelectControl {
6
- type: "select"
7
- options: string[]
8
- default: string
9
- }
10
-
11
- interface BooleanControl {
12
- type: "boolean"
13
- default: boolean
14
- }
15
-
16
- interface TextControl {
17
- type: "text"
18
- default: string
19
- }
20
-
21
- interface NumberControl {
22
- type: "number"
23
- default: number
24
- min?: number
25
- max?: number
26
- }
27
-
28
- type ControlDef = SelectControl | BooleanControl | TextControl | NumberControl
29
-
30
- export type ControlDefs = Record<string, ControlDef>
31
-
32
- type ControlValues<T extends ControlDefs> = {
33
- [K in keyof T]: T[K] extends SelectControl
34
- ? string
35
- : T[K] extends BooleanControl
36
- ? boolean
37
- : T[K] extends TextControl
38
- ? string
39
- : T[K] extends NumberControl
40
- ? number
41
- : never
42
- }
43
-
44
- export interface ControlEntry {
45
- name: string
46
- def: ControlDef
47
- value: unknown
48
- onChange: (value: unknown) => void
49
- }
50
-
51
- export function useControls<T extends ControlDefs>(defs: T) {
52
- const [values, setValues] = useState<Record<string, unknown>>(() => {
53
- const initial: Record<string, unknown> = {}
54
- for (const [key, def] of Object.entries(defs)) {
55
- initial[key] = def.default
56
- }
57
- return initial
58
- })
59
-
60
- const entries: ControlEntry[] = Object.entries(defs).map(([name, def]) => ({
61
- name,
62
- def,
63
- value: values[name],
64
- onChange: (value: unknown) =>
65
- setValues((prev) => ({ ...prev, [name]: value })),
66
- }))
67
-
68
- return {
69
- values: values as ControlValues<T>,
70
- entries,
71
- }
72
- }
1
+ "use client"
2
+
3
+ import { useState } from "react"
4
+
5
+ interface SelectControl {
6
+ type: "select"
7
+ options: string[]
8
+ default: string
9
+ }
10
+
11
+ interface BooleanControl {
12
+ type: "boolean"
13
+ default: boolean
14
+ }
15
+
16
+ interface TextControl {
17
+ type: "text"
18
+ default: string
19
+ }
20
+
21
+ interface NumberControl {
22
+ type: "number"
23
+ default: number
24
+ min?: number
25
+ max?: number
26
+ }
27
+
28
+ type ControlDef = SelectControl | BooleanControl | TextControl | NumberControl
29
+
30
+ export type ControlDefs = Record<string, ControlDef>
31
+
32
+ type ControlValues<T extends ControlDefs> = {
33
+ [K in keyof T]: T[K] extends SelectControl
34
+ ? string
35
+ : T[K] extends BooleanControl
36
+ ? boolean
37
+ : T[K] extends TextControl
38
+ ? string
39
+ : T[K] extends NumberControl
40
+ ? number
41
+ : never
42
+ }
43
+
44
+ export interface ControlEntry {
45
+ name: string
46
+ def: ControlDef
47
+ value: unknown
48
+ onChange: (value: unknown) => void
49
+ }
50
+
51
+ export function useControls<T extends ControlDefs>(defs: T) {
52
+ const [values, setValues] = useState<Record<string, unknown>>(() => {
53
+ const initial: Record<string, unknown> = {}
54
+ for (const [key, def] of Object.entries(defs)) {
55
+ initial[key] = def.default
56
+ }
57
+ return initial
58
+ })
59
+
60
+ const entries: ControlEntry[] = Object.entries(defs).map(([name, def]) => ({
61
+ name,
62
+ def,
63
+ value: values[name],
64
+ onChange: (value: unknown) =>
65
+ setValues((prev) => ({ ...prev, [name]: value })),
66
+ }))
67
+
68
+ return {
69
+ values: values as ControlValues<T>,
70
+ entries,
71
+ }
72
+ }