@weaverclub/render 0.0.2 → 0.0.4
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/dist/entrypoint +0 -0
- package/package.json +6 -2
- package/.github/workflows/publish.yml +0 -44
- package/biome.json +0 -42
- package/build.ts +0 -62
- package/bun.lock +0 -733
- package/bunfig.toml +0 -3
- package/ideas.md +0 -11
- package/publish.ts +0 -62
- package/src/cli/command/renderCommand.ts +0 -112
- package/src/cli/entrypoint.ts +0 -25
- package/src/core/bundler.ts +0 -180
- package/src/core/control/arrayControl.ts +0 -15
- package/src/core/control/booleanControl.ts +0 -15
- package/src/core/control/control.ts +0 -7
- package/src/core/control/controlBuilder.ts +0 -87
- package/src/core/control/numberControl.ts +0 -15
- package/src/core/control/stringControl.ts +0 -15
- package/src/core/control/variantControl.ts +0 -18
- package/src/core/css/css.ts +0 -50
- package/src/core/css/tailwind.ts +0 -172
- package/src/core/html.ts +0 -63
- package/src/core/pkg.ts +0 -92
- package/src/core/story.ts +0 -52
- package/src/core/tsconfig.ts +0 -46
- package/src/react/react.ts +0 -2
- package/src/react/reactControlBuilder.ts +0 -130
- package/src/react/reactStory.ts +0 -36
- package/src/server/api/getStories.ts +0 -44
- package/src/server/api/renderIframe.ts +0 -66
- package/src/server/backend.ts +0 -104
- package/src/server/streaming.ts +0 -16
- package/src/ui/api.ts +0 -16
- package/src/ui/app.tsx +0 -23
- package/src/ui/cn.ts +0 -6
- package/src/ui/components/appSidebar.tsx +0 -76
- package/src/ui/components/button.stories.tsx +0 -32
- package/src/ui/components/button.tsx +0 -55
- package/src/ui/components/command.tsx +0 -187
- package/src/ui/components/contextMenu.tsx +0 -261
- package/src/ui/components/dialog.tsx +0 -153
- package/src/ui/components/input.tsx +0 -23
- package/src/ui/components/inputGroup.tsx +0 -157
- package/src/ui/components/kdb.tsx +0 -26
- package/src/ui/components/searchCommand.tsx +0 -5
- package/src/ui/components/separator.tsx +0 -22
- package/src/ui/components/sheet.tsx +0 -131
- package/src/ui/components/sidebar.tsx +0 -725
- package/src/ui/components/skeleton.tsx +0 -13
- package/src/ui/components/spinner.tsx +0 -15
- package/src/ui/components/tabButton.tsx +0 -80
- package/src/ui/components/tabContent.tsx +0 -20
- package/src/ui/components/tabList.tsx +0 -53
- package/src/ui/components/textarea.tsx +0 -17
- package/src/ui/components/tooltip.tsx +0 -67
- package/src/ui/frontend.tsx +0 -68
- package/src/ui/hooks/useMobile.ts +0 -23
- package/src/ui/index.html +0 -12
- package/src/ui/routeTree.gen.ts +0 -35
- package/src/ui/routes/__root.tsx +0 -9
- package/src/ui/styles.css +0 -123
- package/src/ui/tabs.tsx +0 -89
- package/tsconfig.json +0 -25
- package/tsr.config.json +0 -6
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { cn } from '../cn'
|
|
2
|
-
|
|
3
|
-
function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
|
|
4
|
-
return (
|
|
5
|
-
<div
|
|
6
|
-
data-slot="skeleton"
|
|
7
|
-
className={cn('bg-muted rounded-md animate-pulse', className)}
|
|
8
|
-
{...props}
|
|
9
|
-
/>
|
|
10
|
-
)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export { Skeleton }
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Loader2Icon } from 'lucide-react'
|
|
2
|
-
import { cn } from '../cn'
|
|
3
|
-
|
|
4
|
-
function Spinner({ className, ...props }: React.ComponentProps<'svg'>) {
|
|
5
|
-
return (
|
|
6
|
-
<Loader2Icon
|
|
7
|
-
role="status"
|
|
8
|
-
aria-label="Loading"
|
|
9
|
-
className={cn('size-4 animate-spin', className)}
|
|
10
|
-
{...props}
|
|
11
|
-
/>
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export { Spinner }
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps } from 'react'
|
|
2
|
-
import { useActiveTab, useNewTab, useReplaceTab, useTabs } from '#ui/tabs'
|
|
3
|
-
import {
|
|
4
|
-
ContextMenu,
|
|
5
|
-
ContextMenuContent,
|
|
6
|
-
ContextMenuItem,
|
|
7
|
-
ContextMenuTrigger
|
|
8
|
-
} from './contextMenu'
|
|
9
|
-
import { SidebarMenuButton } from './sidebar'
|
|
10
|
-
|
|
11
|
-
export function TabButton({ story, ...props }: TabButtonProps) {
|
|
12
|
-
const [tabs] = useTabs()
|
|
13
|
-
const { activeTab, setActiveTab } = useActiveTab()
|
|
14
|
-
const newTab = useNewTab()
|
|
15
|
-
const replaceTab = useReplaceTab()
|
|
16
|
-
|
|
17
|
-
function handleOpen(state: 'temporary' | 'permanent') {
|
|
18
|
-
return () => {
|
|
19
|
-
const existingTab = tabs.find((tab) => tab.path === story.id)
|
|
20
|
-
|
|
21
|
-
if (existingTab) {
|
|
22
|
-
return setActiveTab(existingTab.id)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (activeTab?.temporary) {
|
|
26
|
-
return replaceTab(activeTab.id, {
|
|
27
|
-
name: story.name,
|
|
28
|
-
path: story.id,
|
|
29
|
-
temporary: state === 'temporary'
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return newTab({
|
|
34
|
-
name: story.name,
|
|
35
|
-
path: story.id,
|
|
36
|
-
temporary: state === 'temporary'
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function handleOpenInNewTab() {
|
|
42
|
-
return () => {
|
|
43
|
-
newTab({
|
|
44
|
-
name: story.name,
|
|
45
|
-
path: story.id,
|
|
46
|
-
temporary: false
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<ContextMenu>
|
|
53
|
-
<ContextMenuTrigger
|
|
54
|
-
render={
|
|
55
|
-
<SidebarMenuButton
|
|
56
|
-
onClick={handleOpen('temporary')}
|
|
57
|
-
onDoubleClick={handleOpen('permanent')}
|
|
58
|
-
{...props}
|
|
59
|
-
/>
|
|
60
|
-
}
|
|
61
|
-
/>
|
|
62
|
-
|
|
63
|
-
<ContextMenuContent>
|
|
64
|
-
<ContextMenuItem onSelect={handleOpen('permanent')}>
|
|
65
|
-
Open
|
|
66
|
-
</ContextMenuItem>
|
|
67
|
-
<ContextMenuItem onSelect={handleOpenInNewTab()}>
|
|
68
|
-
Open in New Tab
|
|
69
|
-
</ContextMenuItem>
|
|
70
|
-
</ContextMenuContent>
|
|
71
|
-
</ContextMenu>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
type TabButtonProps = ComponentProps<typeof SidebarMenuButton> & {
|
|
76
|
-
story: {
|
|
77
|
-
name: string
|
|
78
|
-
id: string
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Tabs } from '@base-ui/react'
|
|
2
|
-
import { useTabs } from '#ui/tabs'
|
|
3
|
-
|
|
4
|
-
export function TabContent() {
|
|
5
|
-
const [tabs] = useTabs()
|
|
6
|
-
|
|
7
|
-
return (
|
|
8
|
-
<>
|
|
9
|
-
{tabs.map((tab) => (
|
|
10
|
-
<Tabs.Panel key={tab.id} value={tab.id}>
|
|
11
|
-
<iframe
|
|
12
|
-
src={`/iframe/${tab.path}`}
|
|
13
|
-
className="w-full h-full border-none bg-white"
|
|
14
|
-
title={tab.name}
|
|
15
|
-
/>
|
|
16
|
-
</Tabs.Panel>
|
|
17
|
-
))}
|
|
18
|
-
</>
|
|
19
|
-
)
|
|
20
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Tabs } from '@base-ui/react/tabs'
|
|
2
|
-
import { ArrowLeftIcon, ArrowRightIcon, XIcon } from 'lucide-react'
|
|
3
|
-
import { useCloseTab, useMarkTabAsPermanent, useTabs } from '#ui/tabs'
|
|
4
|
-
import { Button } from './button'
|
|
5
|
-
|
|
6
|
-
export function TabList() {
|
|
7
|
-
const [tabs] = useTabs()
|
|
8
|
-
const markTabAsPermanent = useMarkTabAsPermanent()
|
|
9
|
-
const closeTab = useCloseTab()
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Tabs.List className="border-b h-8 bg-sidebar flex w-full">
|
|
13
|
-
{tabs.length > 0 && (
|
|
14
|
-
<div className="flex h-full items-center px-1.5 gap-0.5 border-r">
|
|
15
|
-
<Button variant="ghost" size="icon-sm">
|
|
16
|
-
<ArrowLeftIcon />
|
|
17
|
-
</Button>
|
|
18
|
-
<Button variant="ghost" size="icon-sm">
|
|
19
|
-
<ArrowRightIcon />
|
|
20
|
-
</Button>
|
|
21
|
-
</div>
|
|
22
|
-
)}
|
|
23
|
-
{tabs.map((tab) => (
|
|
24
|
-
<Tabs.Tab
|
|
25
|
-
nativeButton={false}
|
|
26
|
-
render={<div />}
|
|
27
|
-
key={tab.id}
|
|
28
|
-
value={tab.id}
|
|
29
|
-
className="px-6 h-8 border-r text-xs flex items-center justify-center relative group data-[temporary=true]:italic select-none"
|
|
30
|
-
data-temporary={tab.temporary}
|
|
31
|
-
onClick={() => {
|
|
32
|
-
if (tab.temporary) {
|
|
33
|
-
markTabAsPermanent(tab.id)
|
|
34
|
-
}
|
|
35
|
-
}}
|
|
36
|
-
>
|
|
37
|
-
{tab.name}
|
|
38
|
-
<Button
|
|
39
|
-
size="icon-xs"
|
|
40
|
-
variant="ghost"
|
|
41
|
-
className="absolute right-1 invisible opacity-0 group-hover:visible group-hover:opacity-100 transition-opacity duration-200 p-0"
|
|
42
|
-
onClick={(e) => {
|
|
43
|
-
e.stopPropagation()
|
|
44
|
-
closeTab(tab.id)
|
|
45
|
-
}}
|
|
46
|
-
>
|
|
47
|
-
<XIcon />
|
|
48
|
-
</Button>
|
|
49
|
-
</Tabs.Tab>
|
|
50
|
-
))}
|
|
51
|
-
</Tabs.List>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type * as React from 'react'
|
|
2
|
-
import { cn } from '../cn'
|
|
3
|
-
|
|
4
|
-
function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
|
|
5
|
-
return (
|
|
6
|
-
<textarea
|
|
7
|
-
data-slot="textarea"
|
|
8
|
-
className={cn(
|
|
9
|
-
'border-input bg-input/20 dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-md border px-2 py-2 text-sm transition-colors focus-visible:ring-2 aria-invalid:ring-2 md:text-xs/relaxed placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
10
|
-
className
|
|
11
|
-
)}
|
|
12
|
-
{...props}
|
|
13
|
-
/>
|
|
14
|
-
)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export { Textarea }
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip'
|
|
2
|
-
import { cn } from '../cn'
|
|
3
|
-
|
|
4
|
-
function TooltipProvider({
|
|
5
|
-
delay = 0,
|
|
6
|
-
...props
|
|
7
|
-
}: TooltipPrimitive.Provider.Props) {
|
|
8
|
-
return (
|
|
9
|
-
<TooltipPrimitive.Provider
|
|
10
|
-
data-slot="tooltip-provider"
|
|
11
|
-
delay={delay}
|
|
12
|
-
{...props}
|
|
13
|
-
/>
|
|
14
|
-
)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
|
|
18
|
-
return (
|
|
19
|
-
<TooltipProvider>
|
|
20
|
-
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
21
|
-
</TooltipProvider>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
|
|
26
|
-
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function TooltipContent({
|
|
30
|
-
className,
|
|
31
|
-
side = 'top',
|
|
32
|
-
sideOffset = 4,
|
|
33
|
-
align = 'center',
|
|
34
|
-
alignOffset = 0,
|
|
35
|
-
children,
|
|
36
|
-
...props
|
|
37
|
-
}: TooltipPrimitive.Popup.Props &
|
|
38
|
-
Pick<
|
|
39
|
-
TooltipPrimitive.Positioner.Props,
|
|
40
|
-
'align' | 'alignOffset' | 'side' | 'sideOffset'
|
|
41
|
-
>) {
|
|
42
|
-
return (
|
|
43
|
-
<TooltipPrimitive.Portal>
|
|
44
|
-
<TooltipPrimitive.Positioner
|
|
45
|
-
align={align}
|
|
46
|
-
alignOffset={alignOffset}
|
|
47
|
-
side={side}
|
|
48
|
-
sideOffset={sideOffset}
|
|
49
|
-
className="isolate z-50"
|
|
50
|
-
>
|
|
51
|
-
<TooltipPrimitive.Popup
|
|
52
|
-
data-slot="tooltip-content"
|
|
53
|
-
className={cn(
|
|
54
|
-
'data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 rounded-md px-3 py-1.5 text-xs **:data-[slot=kbd]:rounded-md bg-foreground text-background z-50 w-fit max-w-xs origin-(--transform-origin)',
|
|
55
|
-
className
|
|
56
|
-
)}
|
|
57
|
-
{...props}
|
|
58
|
-
>
|
|
59
|
-
{children}
|
|
60
|
-
<TooltipPrimitive.Arrow className="size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
|
|
61
|
-
</TooltipPrimitive.Popup>
|
|
62
|
-
</TooltipPrimitive.Positioner>
|
|
63
|
-
</TooltipPrimitive.Portal>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
package/src/ui/frontend.tsx
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createRoot, type Root } from 'react-dom/client'
|
|
2
|
-
import './styles.css'
|
|
3
|
-
import { App } from './app'
|
|
4
|
-
|
|
5
|
-
const elem = document.getElementById('root')
|
|
6
|
-
|
|
7
|
-
if (!elem) throw new Error('Root element not found')
|
|
8
|
-
|
|
9
|
-
// HMR WebSocket client
|
|
10
|
-
function setupHMR() {
|
|
11
|
-
let reconnectAttempts = 0
|
|
12
|
-
const maxReconnectAttempts = 10
|
|
13
|
-
|
|
14
|
-
function refreshIframes() {
|
|
15
|
-
// Find all iframes and refresh them by updating their src
|
|
16
|
-
const iframes = document.querySelectorAll('iframe')
|
|
17
|
-
iframes.forEach((iframe) => {
|
|
18
|
-
const currentSrc = iframe.src
|
|
19
|
-
// Add or update a cache-busting param
|
|
20
|
-
const url = new URL(currentSrc)
|
|
21
|
-
url.searchParams.set('_hmr', Date.now().toString())
|
|
22
|
-
iframe.src = url.toString()
|
|
23
|
-
})
|
|
24
|
-
console.log(`[HMR] Refreshed ${iframes.length} iframe(s)`)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function connect() {
|
|
28
|
-
const ws = new WebSocket(`ws://${location.host}/__hmr`)
|
|
29
|
-
|
|
30
|
-
ws.onopen = () => {
|
|
31
|
-
console.log('[HMR] Connected')
|
|
32
|
-
reconnectAttempts = 0
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
ws.onmessage = (event) => {
|
|
36
|
-
const data = JSON.parse(event.data)
|
|
37
|
-
if (data.type === 'reload') {
|
|
38
|
-
console.log('[HMR] Reloading iframes...')
|
|
39
|
-
refreshIframes()
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
ws.onclose = () => {
|
|
44
|
-
console.log('[HMR] Disconnected')
|
|
45
|
-
if (reconnectAttempts < maxReconnectAttempts) {
|
|
46
|
-
reconnectAttempts++
|
|
47
|
-
setTimeout(connect, 1000 * Math.min(reconnectAttempts, 5))
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
ws.onerror = () => ws.close()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
connect()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (import.meta.hot) {
|
|
58
|
-
let root: Root = import.meta.hot.data.root
|
|
59
|
-
|
|
60
|
-
if (!root) root = import.meta.hot.data.root = createRoot(elem)
|
|
61
|
-
|
|
62
|
-
root.render(<App />)
|
|
63
|
-
} else {
|
|
64
|
-
createRoot(elem).render(<App />)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Always set up our custom WebSocket HMR
|
|
68
|
-
setupHMR()
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
|
|
11
|
-
const onChange = () => {
|
|
12
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
mql.addEventListener('change', onChange)
|
|
16
|
-
|
|
17
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
18
|
-
|
|
19
|
-
return () => mql.removeEventListener('change', onChange)
|
|
20
|
-
}, [])
|
|
21
|
-
|
|
22
|
-
return !!isMobile
|
|
23
|
-
}
|
package/src/ui/index.html
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Render</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="./frontend.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|
package/src/ui/routeTree.gen.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
|
|
3
|
-
// @ts-nocheck
|
|
4
|
-
|
|
5
|
-
// noinspection JSUnusedGlobalSymbols
|
|
6
|
-
|
|
7
|
-
// This file was automatically generated by TanStack Router.
|
|
8
|
-
// You should NOT make any changes in this file as it will be overwritten.
|
|
9
|
-
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
10
|
-
|
|
11
|
-
import { Route as rootRouteImport } from './routes/__root'
|
|
12
|
-
|
|
13
|
-
export interface FileRoutesByFullPath {}
|
|
14
|
-
export interface FileRoutesByTo {}
|
|
15
|
-
export interface FileRoutesById {
|
|
16
|
-
__root__: typeof rootRouteImport
|
|
17
|
-
}
|
|
18
|
-
export interface FileRouteTypes {
|
|
19
|
-
fileRoutesByFullPath: FileRoutesByFullPath
|
|
20
|
-
fullPaths: never
|
|
21
|
-
fileRoutesByTo: FileRoutesByTo
|
|
22
|
-
to: never
|
|
23
|
-
id: '__root__'
|
|
24
|
-
fileRoutesById: FileRoutesById
|
|
25
|
-
}
|
|
26
|
-
export interface RootRouteChildren {}
|
|
27
|
-
|
|
28
|
-
declare module '@tanstack/react-router' {
|
|
29
|
-
interface FileRoutesByPath {}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const rootRouteChildren: RootRouteChildren = {}
|
|
33
|
-
export const routeTree = rootRouteImport
|
|
34
|
-
._addFileChildren(rootRouteChildren)
|
|
35
|
-
._addFileTypes<FileRouteTypes>()
|
package/src/ui/routes/__root.tsx
DELETED
package/src/ui/styles.css
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "tw-animate-css";
|
|
3
|
-
|
|
4
|
-
@custom-variant dark (&:is(.dark *));
|
|
5
|
-
|
|
6
|
-
:root {
|
|
7
|
-
--background: oklch(1 0 0);
|
|
8
|
-
--foreground: oklch(0.145 0 0);
|
|
9
|
-
--card: oklch(1 0 0);
|
|
10
|
-
--card-foreground: oklch(0.145 0 0);
|
|
11
|
-
--popover: oklch(1 0 0);
|
|
12
|
-
--popover-foreground: oklch(0.145 0 0);
|
|
13
|
-
--primary: oklch(0.205 0 0);
|
|
14
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
15
|
-
--secondary: oklch(0.97 0 0);
|
|
16
|
-
--secondary-foreground: oklch(0.205 0 0);
|
|
17
|
-
--muted: oklch(0.97 0 0);
|
|
18
|
-
--muted-foreground: oklch(0.556 0 0);
|
|
19
|
-
--accent: oklch(0.97 0 0);
|
|
20
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
21
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
22
|
-
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
23
|
-
--border: oklch(0.922 0 0);
|
|
24
|
-
--input: oklch(0.922 0 0);
|
|
25
|
-
--ring: oklch(0.708 0 0);
|
|
26
|
-
--chart-1: oklch(0.646 0.222 41.116);
|
|
27
|
-
--chart-2: oklch(0.6 0.118 184.704);
|
|
28
|
-
--chart-3: oklch(0.398 0.07 227.392);
|
|
29
|
-
--chart-4: oklch(0.828 0.189 84.429);
|
|
30
|
-
--chart-5: oklch(0.769 0.188 70.08);
|
|
31
|
-
--radius: 0.625rem;
|
|
32
|
-
--sidebar: oklch(0.985 0 0);
|
|
33
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
34
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
35
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
36
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
37
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
38
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
39
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.dark {
|
|
43
|
-
--background: oklch(0.145 0 0);
|
|
44
|
-
--foreground: oklch(0.985 0 0);
|
|
45
|
-
--card: oklch(0.145 0 0);
|
|
46
|
-
--card-foreground: oklch(0.985 0 0);
|
|
47
|
-
--popover: oklch(0.145 0 0);
|
|
48
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
49
|
-
--primary: oklch(0.985 0 0);
|
|
50
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
51
|
-
--secondary: oklch(0.269 0 0);
|
|
52
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
53
|
-
--muted: oklch(0.269 0 0);
|
|
54
|
-
--muted-foreground: oklch(0.708 0 0);
|
|
55
|
-
--accent: oklch(0.269 0 0);
|
|
56
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
57
|
-
--destructive: oklch(0.396 0.141 25.723);
|
|
58
|
-
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
59
|
-
--border: oklch(0.269 0 0);
|
|
60
|
-
--input: oklch(0.269 0 0);
|
|
61
|
-
--ring: oklch(0.439 0 0);
|
|
62
|
-
--chart-1: oklch(0.488 0.243 264.376);
|
|
63
|
-
--chart-2: oklch(0.696 0.17 162.48);
|
|
64
|
-
--chart-3: oklch(0.769 0.188 70.08);
|
|
65
|
-
--chart-4: oklch(0.627 0.265 303.9);
|
|
66
|
-
--chart-5: oklch(0.645 0.246 16.439);
|
|
67
|
-
--sidebar: oklch(0.205 0 0);
|
|
68
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
69
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
70
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
71
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
72
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
73
|
-
--sidebar-border: oklch(0.269 0 0);
|
|
74
|
-
--sidebar-ring: oklch(0.439 0 0);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
@theme inline {
|
|
78
|
-
--color-background: var(--background);
|
|
79
|
-
--color-foreground: var(--foreground);
|
|
80
|
-
--color-card: var(--card);
|
|
81
|
-
--color-card-foreground: var(--card-foreground);
|
|
82
|
-
--color-popover: var(--popover);
|
|
83
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
84
|
-
--color-primary: var(--primary);
|
|
85
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
86
|
-
--color-secondary: var(--secondary);
|
|
87
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
88
|
-
--color-muted: var(--muted);
|
|
89
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
90
|
-
--color-accent: var(--accent);
|
|
91
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
92
|
-
--color-destructive: var(--destructive);
|
|
93
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
94
|
-
--color-border: var(--border);
|
|
95
|
-
--color-input: var(--input);
|
|
96
|
-
--color-ring: var(--ring);
|
|
97
|
-
--color-chart-1: var(--chart-1);
|
|
98
|
-
--color-chart-2: var(--chart-2);
|
|
99
|
-
--color-chart-3: var(--chart-3);
|
|
100
|
-
--color-chart-4: var(--chart-4);
|
|
101
|
-
--color-chart-5: var(--chart-5);
|
|
102
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
103
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
104
|
-
--radius-lg: var(--radius);
|
|
105
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
106
|
-
--color-sidebar: var(--sidebar);
|
|
107
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
108
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
109
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
110
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
111
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
112
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
113
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
@layer base {
|
|
117
|
-
* {
|
|
118
|
-
@apply border-border outline-ring/50;
|
|
119
|
-
}
|
|
120
|
-
body {
|
|
121
|
-
@apply bg-background text-foreground;
|
|
122
|
-
}
|
|
123
|
-
}
|
package/src/ui/tabs.tsx
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { createMemoryHistory, type RouterHistory } from '@tanstack/react-router'
|
|
2
|
-
import { atom, useAtom } from 'jotai'
|
|
3
|
-
import { atomWithStorage } from 'jotai/utils'
|
|
4
|
-
|
|
5
|
-
export const activeTabIdAtom = atomWithStorage<string | null>(
|
|
6
|
-
'activeTabId',
|
|
7
|
-
null
|
|
8
|
-
)
|
|
9
|
-
export const tabsAtom = atomWithStorage<Tab[]>('tabs', [])
|
|
10
|
-
export const tabsHistoryAtom = atom<Record<string, RouterHistory>>((get) =>
|
|
11
|
-
get(tabsAtom).reduce(
|
|
12
|
-
(acc, tab) => {
|
|
13
|
-
acc[tab.id] = createMemoryHistory({
|
|
14
|
-
initialEntries: [tab.path]
|
|
15
|
-
})
|
|
16
|
-
return acc
|
|
17
|
-
},
|
|
18
|
-
{} as Record<string, RouterHistory>
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
export function useTabs() {
|
|
23
|
-
return useAtom(tabsAtom)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function useActiveTab() {
|
|
27
|
-
const [tabs] = useAtom(tabsAtom)
|
|
28
|
-
const [activeTabId, setActiveTab] = useAtom(activeTabIdAtom)
|
|
29
|
-
const [tabsHistory] = useAtom(tabsHistoryAtom)
|
|
30
|
-
|
|
31
|
-
const activeTab = tabs.find((tab) => tab.id === activeTabId) ?? null
|
|
32
|
-
const tabHistory = activeTabId ? tabsHistory[activeTabId] : null
|
|
33
|
-
|
|
34
|
-
return { activeTab, setActiveTab, tabHistory }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function useNewTab() {
|
|
38
|
-
const [, setTabs] = useAtom(tabsAtom)
|
|
39
|
-
const [, setActiveTab] = useAtom(activeTabIdAtom)
|
|
40
|
-
|
|
41
|
-
return (tab: Omit<Tab, 'id'>) => {
|
|
42
|
-
const id = crypto.randomUUID()
|
|
43
|
-
|
|
44
|
-
setTabs((tabs) => [...tabs, { ...tab, id }])
|
|
45
|
-
setActiveTab(id)
|
|
46
|
-
|
|
47
|
-
return id
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function useMarkTabAsPermanent() {
|
|
52
|
-
const [tabs, setTabs] = useAtom(tabsAtom)
|
|
53
|
-
|
|
54
|
-
return (id: string) => {
|
|
55
|
-
setTabs(
|
|
56
|
-
tabs.map((tab) => (tab.id === id ? { ...tab, temporary: false } : tab))
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function useCloseTab() {
|
|
62
|
-
const [tabs, setTabs] = useAtom(tabsAtom)
|
|
63
|
-
const [activeTabId, setActiveTab] = useAtom(activeTabIdAtom)
|
|
64
|
-
|
|
65
|
-
return (id: string) => {
|
|
66
|
-
setTabs(tabs.filter((tab) => tab.id !== id))
|
|
67
|
-
|
|
68
|
-
if (activeTabId === id) {
|
|
69
|
-
const tabIndex = tabs.findIndex((tab) => tab.id === id)
|
|
70
|
-
const newActiveTab = tabs[tabIndex - 1] || tabs[tabIndex + 1] || null
|
|
71
|
-
setActiveTab(newActiveTab ? newActiveTab.id : null)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function useReplaceTab() {
|
|
77
|
-
const [tabs, setTabs] = useAtom(tabsAtom)
|
|
78
|
-
|
|
79
|
-
return (id: string, newTab: Omit<Tab, 'id'>) => {
|
|
80
|
-
setTabs(tabs.map((tab) => (tab.id === id ? { ...newTab, id } : tab)))
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type Tab = {
|
|
85
|
-
id: string
|
|
86
|
-
name: string
|
|
87
|
-
path: string
|
|
88
|
-
temporary: boolean
|
|
89
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "ESNext",
|
|
4
|
-
"target": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"noUncheckedIndexedAccess": true,
|
|
8
|
-
"baseUrl": ".",
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"noFallthroughCasesInSwitch": true,
|
|
11
|
-
"noImplicitOverride": true,
|
|
12
|
-
"lib": ["ESNext", "DOM"],
|
|
13
|
-
"moduleDetection": "force",
|
|
14
|
-
"jsx": "react-jsx",
|
|
15
|
-
"paths": {
|
|
16
|
-
"#*": ["./src/*"]
|
|
17
|
-
},
|
|
18
|
-
"plugins": [
|
|
19
|
-
{
|
|
20
|
-
"name": "@effect/language-service"
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
"exclude": ["dist", "node_modules"]
|
|
25
|
-
}
|