asasvirtuais 0.6.6 → 0.7.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 (74) hide show
  1. package/package.json +14 -5
  2. package/actions/draw.ts +0 -20
  3. package/components/OAuthCard.tsx +0 -346
  4. package/components/icons.tsx +0 -11
  5. package/components/markdown.tsx +0 -18
  6. package/components/stack/list.tsx +0 -21
  7. package/components/stack/menu.tsx +0 -40
  8. package/components/stack/nav.tsx +0 -39
  9. package/components/table/fixed.tsx +0 -59
  10. package/components/table/key-value.tsx +0 -19
  11. package/components/ui/color-mode.tsx +0 -108
  12. package/components/ui/provider.tsx +0 -15
  13. package/components/ui/toaster.tsx +0 -43
  14. package/components/ui/tooltip.tsx +0 -46
  15. package/hooks/useBoolean.tsx +0 -11
  16. package/hooks/useForwardAs.tsx +0 -29
  17. package/hooks/useHash copy.tsx +0 -27
  18. package/hooks/useHash.tsx +0 -27
  19. package/hooks/useIsMobile.tsx +0 -6
  20. package/hooks/useOAuthTokens.ts +0 -97
  21. package/hooks/useOpenRouterModels.ts +0 -80
  22. package/index.ts +0 -1
  23. package/lib/blob.ts +0 -3
  24. package/lib/client-token-storage.ts +0 -216
  25. package/lib/date-utils.ts +0 -139
  26. package/lib/oauth-tokens.ts +0 -85
  27. package/lib/personality-systems.ts +0 -94
  28. package/lib/push-notification.ts +0 -80
  29. package/lib/summarize.ts +0 -175
  30. package/lib/tools.ts +0 -124
  31. package/next-env.d.ts +0 -6
  32. package/next.config.ts +0 -23
  33. package/packages/airtable/index.ts +0 -189
  34. package/packages/airtable/types.ts +0 -722
  35. package/packages/auth0.ts +0 -43
  36. package/packages/blob.ts +0 -97
  37. package/packages/chat/components/dialog.tsx +0 -46
  38. package/packages/chat/components/header/delete-dialog.tsx +0 -48
  39. package/packages/chat/components/header/menu.tsx +0 -56
  40. package/packages/chat/components/header/title.tsx +0 -33
  41. package/packages/chat/components/header/wrapper.tsx +0 -12
  42. package/packages/chat/components/input/index.tsx +0 -52
  43. package/packages/chat/components/input/menu.tsx +0 -34
  44. package/packages/chat/components/input/send.tsx +0 -20
  45. package/packages/chat/components/input/textarea.tsx +0 -22
  46. package/packages/chat/components/input/wrapper.tsx +0 -11
  47. package/packages/chat/components/layout.tsx +0 -0
  48. package/packages/chat/components/messages/index.tsx +0 -4
  49. package/packages/chat/components/messages/wrapper.tsx +0 -21
  50. package/packages/chat/components/settings/dialog.tsx +0 -31
  51. package/packages/chat/components/settings/model-selector.tsx +0 -83
  52. package/packages/chat/components/settings/temperature-slider.tsx +0 -67
  53. package/packages/dexie.ts +0 -126
  54. package/packages/env.ts +0 -8
  55. package/packages/fetch-interface.ts +0 -75
  56. package/packages/fields.tsx +0 -169
  57. package/packages/firebase.ts +0 -13
  58. package/packages/firestore.ts +0 -51
  59. package/packages/form.tsx +0 -66
  60. package/packages/hooks.tsx +0 -123
  61. package/packages/interface.ts +0 -79
  62. package/packages/message/components/edit.tsx +0 -48
  63. package/packages/message/components/menu.tsx +0 -52
  64. package/packages/message/components/message.tsx +0 -41
  65. package/packages/message/components/tool-results.tsx +0 -32
  66. package/packages/next-interface.ts +0 -121
  67. package/packages/next.ts +0 -64
  68. package/packages/novelai.ts +0 -101
  69. package/packages/openrouter.ts +0 -4
  70. package/packages/react-interface.tsx +0 -373
  71. package/packages/wretch.ts +0 -22
  72. package/packages/yaml.ts +0 -163
  73. package/pnpm-workspace.yaml +0 -4
  74. package/tsconfig.json +0 -44
package/package.json CHANGED
@@ -1,20 +1,29 @@
1
1
  {
2
2
  "name": "asasvirtuais",
3
3
  "type": "module",
4
- "version": "0.6.6",
4
+ "version": "0.7.0",
5
5
  "directories": {
6
6
  "packages": "./packages"
7
7
  },
8
+ "files": [
9
+ "dist"
10
+ ],
8
11
  "exports": {
9
- ".": "./index.ts",
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
10
16
  "./package.json": "./package.json",
11
- "./*": "./packages/*",
12
- "./*/*": "./packages/*/*"
17
+ "./*": {
18
+ "import": "./dist/packages/*",
19
+ "types": "./dist/packages/*"
20
+ }
13
21
  },
14
22
  "scripts": {
15
23
  "code": "tmux new-session -d 'termux-wake-lock && sh dev-tunnel.sh'",
16
24
  "dev": "next dev --port 3000 --hostname 0.0.0.0",
17
- "build": "next build",
25
+ "build:packages": "tsc -p tsconfig.build.json",
26
+ "build": "pnpm run build:packages && next build",
18
27
  "start": "next start",
19
28
  "lint": "next lint",
20
29
  "claude": "claude --dangerously-skip-permissions --mcp-config ./mcp.json",
package/actions/draw.ts DELETED
@@ -1,20 +0,0 @@
1
- 'use server'
2
- import { uploadBuffer } from '@/packages/blob'
3
- import { generateImage } from '@/packages/novelai'
4
-
5
- export interface DrawParams {
6
- prompt?: string
7
- orientation?: 'portrait' | 'landscape' | 'square'
8
- }
9
-
10
- export async function drawAction({ prompt, orientation = 'square' }: DrawParams) {
11
- const buffer = await generateImage({ prompt, orientation })
12
-
13
- // Use filename from zip entry if available, otherwise generate one
14
- const filenameBase = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}.png`
15
- const filename = `novelai/${filenameBase}`
16
-
17
- // Upload to configured bucket and return public URL
18
- const publicUrl = await uploadBuffer(buffer, filename, 'image/png')
19
- return publicUrl
20
- }
@@ -1,346 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useEffect } from 'react'
4
- import { useSearchParams } from 'next/navigation'
5
- import {
6
- Card,
7
- VStack,
8
- HStack,
9
- Heading,
10
- Text,
11
- Button,
12
- Badge,
13
- Icon,
14
- Box,
15
- Code,
16
- Collapsible,
17
- IconButton
18
- } from '@chakra-ui/react'
19
- import {
20
- FaGoogle,
21
- FaFacebook,
22
- FaInstagram,
23
- FaChartLine,
24
- FaLink,
25
- FaUnlink,
26
- FaSync,
27
- FaCopy,
28
- FaChevronDown,
29
- FaChevronUp
30
- } from 'react-icons/fa'
31
- import { IconType } from 'react-icons'
32
- import { toaster } from '@/components/ui/toaster'
33
- import { clientTokenStorage } from '@/lib/client-token-storage'
34
-
35
- const iconMap: Record<string, IconType> = {
36
- FaGoogle,
37
- FaFacebook,
38
- FaInstagram,
39
- FaChartLine
40
- }
41
-
42
- interface Platform {
43
- id: string
44
- name: string
45
- icon: string
46
- description: string
47
- scopes: string[]
48
- color: string
49
- }
50
-
51
- interface OAuthCardProps {
52
- platform: Platform
53
- userEmail?: string
54
- }
55
-
56
- export default function OAuthCard({ platform, userEmail }: OAuthCardProps) {
57
- const [isConnected, setIsConnected] = useState(false)
58
- const [isLoading, setIsLoading] = useState(false)
59
- const [token, setToken] = useState<string | null>(null)
60
- const [showToken, setShowToken] = useState(false)
61
- const searchParams = useSearchParams()
62
-
63
- const IconComponent = iconMap[platform.icon] || FaLink
64
-
65
- useEffect(() => {
66
- const success = searchParams.get('success')
67
- const error = searchParams.get('error')
68
- const connectedPlatform = searchParams.get('platform')
69
- const encodedToken = searchParams.get('token')
70
-
71
- if (success === 'true' && connectedPlatform === platform.id) {
72
- setIsConnected(true)
73
-
74
- // Store token in IndexedDB if provided
75
- if (encodedToken) {
76
- try {
77
- const tokenData = JSON.parse(Buffer.from(encodedToken, 'base64').toString())
78
- clientTokenStorage.storeToken({
79
- id: platform.id,
80
- platform: platform.name,
81
- accessToken: tokenData.accessToken,
82
- expiresAt: tokenData.expiresAt,
83
- lastRefreshed: new Date().toISOString()
84
- })
85
- setToken(tokenData.accessToken)
86
- } catch (err) {
87
- console.error('Failed to store token:', err)
88
- }
89
- }
90
-
91
- toaster.create({
92
- title: 'Connected successfully',
93
- description: `${platform.name} has been connected`,
94
- type: 'success',
95
- duration: 3000,
96
- })
97
- }
98
-
99
- if (error && connectedPlatform === platform.id) {
100
- toaster.create({
101
- title: 'Connection failed',
102
- description: `Failed to connect ${platform.name}: ${error}`,
103
- type: 'error',
104
- duration: 3000,
105
- })
106
- }
107
- }, [searchParams, platform])
108
-
109
- // Load token from IndexedDB on mount
110
- useEffect(() => {
111
- const loadToken = async () => {
112
- try {
113
- const storedToken = await clientTokenStorage.getToken(platform.id)
114
- if (storedToken) {
115
- setToken(storedToken.accessToken)
116
- setIsConnected(true)
117
- }
118
- } catch (err) {
119
- console.error('Failed to load token:', err)
120
- }
121
- }
122
- loadToken()
123
- }, [platform.id])
124
-
125
- const handleConnect = async () => {
126
- setIsLoading(true)
127
- try {
128
- const params = new URLSearchParams({
129
- platform: platform.id,
130
- scopes: platform.scopes.join(','),
131
- userEmail: userEmail || ''
132
- })
133
-
134
- window.location.href = `/api/oauth/connect?${params.toString()}`
135
- } catch (error) {
136
- toaster.create({
137
- title: 'Connection failed',
138
- description: 'Unable to initiate OAuth connection',
139
- type: 'error',
140
- duration: 3000,
141
- })
142
- setIsLoading(false)
143
- }
144
- }
145
-
146
- const handleDisconnect = async () => {
147
- setIsLoading(true)
148
- try {
149
- const response = await fetch(`/api/oauth/disconnect`, {
150
- method: 'POST',
151
- headers: { 'Content-Type': 'application/json' },
152
- body: JSON.stringify({ platform: platform.id })
153
- })
154
-
155
- if (!response.ok) throw new Error('Disconnection failed')
156
-
157
- setIsConnected(false)
158
- setToken(null)
159
-
160
- // Remove token from IndexedDB
161
- await clientTokenStorage.removeToken(platform.id)
162
-
163
- toaster.create({
164
- title: 'Disconnected',
165
- description: `${platform.name} has been disconnected`,
166
- type: 'success',
167
- duration: 3000,
168
- })
169
- } catch (error) {
170
- toaster.create({
171
- title: 'Disconnection failed',
172
- description: 'Unable to disconnect platform',
173
- type: 'error',
174
- duration: 3000,
175
- })
176
- } finally {
177
- setIsLoading(false)
178
- }
179
- }
180
-
181
- const handleRefreshToken = async () => {
182
- setIsLoading(true)
183
- try {
184
- const response = await fetch(`/api/oauth/refresh`, {
185
- method: 'POST',
186
- headers: { 'Content-Type': 'application/json' },
187
- body: JSON.stringify({ platform: platform.id })
188
- })
189
-
190
- if (!response.ok) throw new Error('Token refresh failed')
191
-
192
- const data = await response.json()
193
- setToken(data.accessToken)
194
-
195
- // Update token in IndexedDB
196
- await clientTokenStorage.storeToken({
197
- id: platform.id,
198
- platform: platform.name,
199
- accessToken: data.accessToken,
200
- expiresAt: data.expiresIn ?
201
- new Date(Date.now() + data.expiresIn * 1000).toISOString() :
202
- undefined,
203
- lastRefreshed: new Date().toISOString()
204
- })
205
-
206
- toaster.create({
207
- title: 'Token refreshed',
208
- description: 'Your access token has been refreshed',
209
- type: 'success',
210
- duration: 3000,
211
- })
212
- } catch (error) {
213
- toaster.create({
214
- title: 'Refresh failed',
215
- description: 'Unable to refresh token',
216
- type: 'error',
217
- duration: 3000,
218
- })
219
- } finally {
220
- setIsLoading(false)
221
- }
222
- }
223
-
224
- const copyToken = () => {
225
- if (token) {
226
- navigator.clipboard.writeText(token)
227
- toaster.create({
228
- title: 'Copied!',
229
- description: 'Token copied to clipboard',
230
- type: 'success',
231
- duration: 2000,
232
- })
233
- }
234
- }
235
-
236
- return (
237
- <Card.Root variant="outline" size="lg">
238
- <Card.Header>
239
- <HStack justify="space-between">
240
- <HStack gap={3}>
241
- <Icon as={IconComponent} boxSize={6} color={platform.color} />
242
- <Heading size="md">{platform.name}</Heading>
243
- </HStack>
244
- <Badge colorScheme={isConnected ? 'green' : 'gray'}>
245
- {isConnected ? 'Connected' : 'Not Connected'}
246
- </Badge>
247
- </HStack>
248
- </Card.Header>
249
-
250
- <Card.Body>
251
- <VStack align="stretch" gap={4}>
252
- <Text color="fg.muted" fontSize="sm">
253
- {platform.description}
254
- </Text>
255
-
256
- <Box>
257
- <Text fontSize="sm" fontWeight="medium" mb={1}>Scopes:</Text>
258
- <Text fontSize="xs" color="fg.muted" lineClamp={2}>
259
- {platform.scopes.join(', ')}
260
- </Text>
261
- </Box>
262
-
263
- <HStack gap={2}>
264
- {!isConnected ? (
265
- <Button
266
- colorScheme="blue"
267
- onClick={handleConnect}
268
- loading={isLoading}
269
- loadingText="Connecting..."
270
- size="sm"
271
- width="full"
272
- >
273
- <FaLink />
274
- Connect
275
- </Button>
276
- ) : (
277
- <>
278
- <Button
279
- variant="outline"
280
- onClick={handleRefreshToken}
281
- loading={isLoading}
282
- size="sm"
283
- flex={1}
284
- >
285
- <FaSync />
286
- Refresh
287
- </Button>
288
- <Button
289
- variant="outline"
290
- colorScheme="red"
291
- onClick={handleDisconnect}
292
- loading={isLoading}
293
- size="sm"
294
- flex={1}
295
- >
296
- <FaUnlink />
297
- Disconnect
298
- </Button>
299
- </>
300
- )}
301
- </HStack>
302
-
303
- {isConnected && token && (
304
- <Box>
305
- <HStack justify="space-between" mb={2}>
306
- <Text fontSize="sm" fontWeight="medium">Access Token:</Text>
307
- <HStack gap={1}>
308
- <IconButton
309
- aria-label="Copy token"
310
- size="xs"
311
- variant="ghost"
312
- onClick={copyToken}
313
- >
314
- <FaCopy />
315
- </IconButton>
316
- <IconButton
317
- aria-label="Toggle token visibility"
318
- size="xs"
319
- variant="ghost"
320
- onClick={() => setShowToken(!showToken)}
321
- >
322
- {showToken ? <FaChevronUp /> : <FaChevronDown />}
323
- </IconButton>
324
- </HStack>
325
- </HStack>
326
- <Collapsible.Root open={showToken}>
327
- <Collapsible.Content>
328
- <Code
329
- p={3}
330
- borderRadius="md"
331
- fontSize="xs"
332
- display="block"
333
- overflowX="auto"
334
- whiteSpace="pre"
335
- >
336
- {token}
337
- </Code>
338
- </Collapsible.Content>
339
- </Collapsible.Root>
340
- </Box>
341
- )}
342
- </VStack>
343
- </Card.Body>
344
- </Card.Root>
345
- )
346
- }
@@ -1,11 +0,0 @@
1
- 'use client'
2
-
3
- import { forwardRef } from 'react'
4
-
5
- export const AirtableIcon = forwardRef<SVGSVGElement>((props, ref) => (
6
- <svg ref={ref} viewBox='0 0 20 16' xmlns='http://www.w3.org/2000/svg' {...props}><path d='m8.50297526.20100591-7.09941044 2.93764625c-.39480037.16338794-.39071029.72415946.00656565.88162754l7.12911731 2.82710645c.62642805.24841855 1.32400201.24841855 1.95032242 0l7.129225-2.82710645c.3971683-.15746808.401366-.7182396.006458-.88162754l-7.0993028-2.93764625c-.6477395-.26800788-1.37534322-.26800788-2.02297514 0' fill='#ffbf00'/><path d='m10.1469076 8.39120841v7.06249209c0 .3359247.3387232.565938.6509686.4421592l7.9440119-3.0834899c.1813628-.0718993.300298-.2471269.300298-.4421592v-7.06249207c0-.33592474-.3387232-.56593793-.6509685-.44215918l-7.944012 3.08348988c-.1812551.07189931-.300298.24712699-.300298.44215918' fill='#26b5f8'/><path d='m8.29192714 8.75561302-2.35760833 1.13833392-.23937732.11570616-4.97676647 2.3846244c-.31547434.152194-.71813197-.0777115-.71813197-.4281668v-6.62872832c0-.12679249.06501075-.23625595.15219404-.31870335.03638019-.03648782.07760389-.06651762.1204421-.09030467.11893522-.07136113.28856591-.09041229.43279506-.03336644l7.54684367 2.99017147c.38360647.15219408.41374392.68971668.03960922.87043363' fill='#ed3049'/><path d='m8.29192714 8.75561302-2.35760833 1.13833392-5.78208172-4.87526791c.03638019-.03648782.07760389-.06651762.1204421-.09030467.11893522-.07136113.28856591-.09041229.43279506-.03336644l7.54684367 2.99017147c.38360647.15219408.41374392.68971668.03960922.87043363' fillOpacity='.25'/></svg>
7
- ))
8
-
9
- export const LinkedInIcon = forwardRef<SVGSVGElement>((props, ref) => (
10
- <svg ref={ref} height='72' viewBox='0 0 72 72' width='72' xmlns='http://www.w3.org/2000/svg' {...props}><g fill='none' fillRule='evenodd'><path d='M8,72 L64,72 C68.418278,72 72,68.418278 72,64 L72,8 C72,3.581722 68.418278,-8.11624501e-16 64,0 L8,0 C3.581722,8.11624501e-16 -5.41083001e-16,3.581722 0,8 L0,64 C5.41083001e-16,68.418278 3.581722,72 8,72 Z' fill='#007EBB'/><path d='M62,62 L51.315625,62 L51.315625,43.8021149 C51.315625,38.8127542 49.4197917,36.0245323 45.4707031,36.0245323 C41.1746094,36.0245323 38.9300781,38.9261103 38.9300781,43.8021149 L38.9300781,62 L28.6333333,62 L28.6333333,27.3333333 L38.9300781,27.3333333 L38.9300781,32.0029283 C38.9300781,32.0029283 42.0260417,26.2742151 49.3825521,26.2742151 C56.7356771,26.2742151 62,30.7644705 62,40.051212 L62,62 Z M16.349349,22.7940133 C12.8420573,22.7940133 10,19.9296567 10,16.3970067 C10,12.8643566 12.8420573,10 16.349349,10 C19.8566406,10 22.6970052,12.8643566 22.6970052,16.3970067 C22.6970052,19.9296567 19.8566406,22.7940133 16.349349,22.7940133 Z M11.0325521,62 L21.769401,62 L21.769401,27.3333333 L11.0325521,27.3333333 L11.0325521,62 Z' fill='#FFF'/></g></svg>
11
- ))
@@ -1,18 +0,0 @@
1
- 'use client'
2
- import ReactMarkdown from 'react-markdown'
3
- import gfm from 'remark-gfm'
4
- import breaks from 'remark-breaks'
5
- import { Link, Text } from '@chakra-ui/react'
6
-
7
- export default function Markdown({ children } : {children: string}) {
8
- return (
9
- <ReactMarkdown
10
- components={{
11
- a: props => <Link target='_blank' {...props}/>,
12
- // @ts-expect-error
13
- em: props => <Text as='i' fontStyle='italic' {...props} />,
14
- }}
15
- remarkPlugins={[breaks, gfm]}
16
- >{children}</ReactMarkdown>
17
- )
18
- }
@@ -1,21 +0,0 @@
1
- 'use client'
2
- import { forwardRef } from 'react'
3
- import { List, Stack, HStack, VStack } from '@chakra-ui/react'
4
- import useForwardAs from '@/hooks/useForwardAs'
5
-
6
- export type StackListProps = List.RootProps
7
-
8
- export const StackList = forwardRef<typeof Stack, StackListProps>(({ as, ...props }, ref) => (
9
- <List.Root
10
- // @ts-expect-error
11
- ref={ref}
12
- as={useForwardAs(Stack, as)} {...props} />
13
- ))
14
-
15
- export const HList = forwardRef<typeof HStack, StackListProps>(({ as, ...props }, ref) => (
16
- <StackList ref={ref} as={useForwardAs(HStack, as)} {...props} />
17
- ))
18
-
19
- export const VList = forwardRef<typeof HStack, StackListProps>(({ as, ...props }, ref) => (
20
- <StackList ref={ref} as={useForwardAs(VStack, as)} {...props} />
21
- ))
@@ -1,40 +0,0 @@
1
- 'use client'
2
- import { ElementType, forwardRef } from 'react'
3
- import { StackList, VList, HList, StackListProps } from '@/components/stack/list'
4
- import useForwardAs from '@/hooks/useForwardAs'
5
-
6
- export type StackMenuProps = StackListProps
7
-
8
- export const StackMenu = forwardRef<typeof StackList, StackMenuProps>(({ children, as, ...props }, ref) => (
9
- <StackList
10
- // @ts-expect-error
11
- ref={ref}
12
- as={as ? useForwardAs(as, 'menu') : 'menu'}
13
- // List Defaults
14
- p={0} m={0} listStyleType='none'
15
- // Alignment
16
- justifyContent='space-between'
17
- {...props}>{children}</StackList>
18
- ))
19
-
20
- export const HMenu = forwardRef<typeof HList, StackMenuProps>(({ children, ...props }, ref) => (
21
- <StackMenu ref={ref} as={HList} {...props}>{children}</StackMenu>
22
- ))
23
-
24
- export const VMenu = forwardRef<typeof VList, StackMenuProps>(({ children, ...props }, ref) => (
25
- <StackMenu ref={ref} as={VList} {...props}>{children}</StackMenu>
26
- ))
27
-
28
- // Menu Item, keep it here in this file
29
- import { Button, ButtonProps, ListItem } from '@chakra-ui/react'
30
-
31
- export type MenuItemProps = ButtonProps
32
- export const MenuItem = forwardRef<ElementType, MenuItemProps>(({ children, ...props }, ref) => (
33
- <ListItem
34
- // @ts-expect-error
35
- ref={ref}>
36
- <Button size='sm' variant='ghost' {...props}>
37
- {children}
38
- </Button>
39
- </ListItem>
40
- ))
@@ -1,39 +0,0 @@
1
- 'use client'
2
- import { forwardRef } from 'react'
3
- import { StackList, VList, HList, StackListProps } from '@/components/stack/list'
4
- import useForwardAs from '@/hooks/useForwardAs'
5
-
6
- export type StackNavProps = StackListProps
7
-
8
- export const StackNav = forwardRef<typeof StackList, StackListProps>(({ children, as, ...props }, ref) => (
9
- <StackList
10
- // @ts-expect-error
11
- ref={ref}
12
- as={as ? useForwardAs(as, 'nav') : 'nav'}
13
- // List Defaults
14
- p={0} m={0} listStyleType='none'
15
- // Alignment
16
- justifyContent='space-between'
17
- {...props}>{children}</StackList>
18
- ))
19
-
20
- export const HNav = forwardRef<typeof HList, StackListProps>(({ children, ...props }, ref) => (
21
- <StackNav ref={ref} as={HList} {...props}>{children}</StackNav>
22
- ))
23
-
24
- export const VNav = forwardRef<typeof VList, StackListProps>(({ children, ...props }, ref) => (
25
- <StackNav ref={ref} as={VList} {...props}>{children}</StackNav>
26
- ))
27
-
28
- import { ListItem, ListItemProps, Link, LinkProps } from '@chakra-ui/react'
29
-
30
- export type NavItemProps = LinkProps
31
-
32
- export const NavItem = forwardRef<typeof Link, NavItemProps>(({ children, as, ...props }, ref) => (
33
- <ListItem
34
- // @ts-expect-error
35
- ref={ref}
36
- {...props}>
37
- <Link {...props}>{children}</Link>
38
- </ListItem>
39
- ))
@@ -1,59 +0,0 @@
1
- import { Table, TableCell, TableColumnHeader, TableColumnProps, TableRow } from '@chakra-ui/react/table'
2
- import { FunctionComponent, PropsWithChildren, ReactNode } from 'react'
3
-
4
- export type FixedTableProps = Table.RootProps & { guide: ReactNode }
5
-
6
- export default function FixedTable( { children, guide, ...props } : FixedTableProps ) {
7
-
8
- return (
9
- <Table.ScrollArea>
10
- <Table.Root tableLayout='fixed' {...props}>
11
- <Table.Header position='sticky' top={0} zIndex={2}>
12
- {guide}
13
- </Table.Header>
14
- <Table.Body zIndex={1}>
15
- {children}
16
- </Table.Body>
17
- <Table.Footer position='sticky' bottom={0} zIndex={2}>
18
- {guide}
19
- </Table.Footer>
20
- </Table.Root>
21
- </Table.ScrollArea>
22
- )
23
- }
24
-
25
- type TitleSizes = {
26
- [KEY in string]: {
27
- label: string,
28
- width: TableColumnProps['w'],
29
- }
30
- }
31
-
32
- type FixedTableComponents<T extends TitleSizes> = {
33
- Components: {
34
- [K in keyof T] : {
35
- Header: FunctionComponent,
36
- Data: FunctionComponent<PropsWithChildren>
37
- }
38
- },
39
- HeadersRow: FunctionComponent,
40
- }
41
- export const makeFixedTableComponents = <T extends TitleSizes>(titleSizes: T): FixedTableComponents<T> => {
42
- const Components = Object.fromEntries(
43
- Object.entries(titleSizes).map(([key, {label, width}]) => [key, {
44
- Header: () => <TableColumnHeader w={width}>{label}</TableColumnHeader>,
45
- Data: ({children}: PropsWithChildren) => <TableCell w={width}>{children}</TableCell>,
46
- }])
47
- )
48
- const HeadersRow = () => (
49
- <TableRow>
50
- {Object.entries(Components).map(([key, { Header }], i) => (
51
- <Header key={key + i}/>
52
- ))}
53
- </TableRow>
54
- )
55
- return {
56
- Components,
57
- HeadersRow,
58
- } as unknown as FixedTableComponents<T>
59
- }
@@ -1,19 +0,0 @@
1
- import { Table } from '@chakra-ui/react/table'
2
-
3
- export type KeyValueTableProps = Table.RootProps & { values: { [K in string | number]: string | number } }
4
-
5
- export default function KeyValueTable( { children, ...props } : KeyValueTableProps ) {
6
-
7
- return (
8
- <Table.Root variant='outline' {...props}>
9
- <Table.Body zIndex={1}>
10
- {Object.entries(props.values).map(([key, value]) => (
11
- <Table.Row key={key}>
12
- <Table.ColumnHeader>{key}</Table.ColumnHeader>
13
- <Table.Cell>{value}</Table.Cell>
14
- </Table.Row>
15
- ))}
16
- </Table.Body>
17
- </Table.Root>
18
- )
19
- }