@geenius/tools 0.1.0 → 0.3.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.
- package/package.json +62 -3
- package/packages/convex/shared/README.md +1 -1
- package/packages/devtools/dist/index.d.ts +204 -0
- package/packages/devtools/dist/index.js +186 -0
- package/packages/devtools/dist/index.js.map +1 -0
- package/packages/devtools/react/README.md +1 -1
- package/packages/devtools/solidjs/README.md +1 -1
- package/packages/devtools/solidjs/dist/index.js +1830 -0
- package/packages/devtools/solidjs/dist/index.js.map +1 -0
- package/packages/env/dist/index.d.ts +151 -0
- package/packages/env/dist/index.js +93 -0
- package/packages/env/dist/index.js.map +1 -0
- package/packages/errors/dist/index.d.ts +177 -0
- package/packages/errors/dist/index.js +187 -0
- package/packages/errors/dist/index.js.map +1 -0
- package/packages/errors/react/README.md +1 -1
- package/packages/errors/solidjs/README.md +1 -1
- package/packages/logger/dist/index.d.ts +171 -0
- package/packages/logger/dist/index.js +216 -0
- package/packages/logger/dist/index.js.map +1 -0
- package/packages/logger/react/README.md +1 -1
- package/packages/logger/solidjs/README.md +1 -1
- package/packages/perf/dist/index.d.ts +168 -0
- package/packages/perf/dist/index.js +265 -0
- package/packages/perf/dist/index.js.map +1 -0
- package/packages/perf/react/README.md +1 -1
- package/packages/perf/solidjs/README.md +1 -1
- package/packages/shared/dist/index.d.ts +253 -0
- package/packages/shared/dist/index.js +278 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.env.example +0 -2
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.node-version +0 -1
- package/.nvmrc +0 -1
- package/.prettierrc +0 -7
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -26
- package/CONTRIBUTING.md +0 -69
- package/SECURITY.md +0 -18
- package/SUPPORT.md +0 -14
- package/packages/convex/shared/package.json +0 -42
- package/packages/convex/shared/src/audit/index.ts +0 -5
- package/packages/convex/shared/src/audit/presets.ts +0 -165
- package/packages/convex/shared/src/audit/schema.ts +0 -85
- package/packages/convex/shared/src/audit/write.ts +0 -102
- package/packages/convex/shared/src/extract.ts +0 -75
- package/packages/convex/shared/src/index.ts +0 -41
- package/packages/convex/shared/src/messages.ts +0 -45
- package/packages/convex/shared/src/security.ts +0 -112
- package/packages/convex/shared/src/throw.ts +0 -184
- package/packages/convex/shared/src/types.ts +0 -57
- package/packages/convex/shared/src/utils.ts +0 -58
- package/packages/convex/shared/tsconfig.json +0 -28
- package/packages/convex/shared/tsup.config.ts +0 -12
- package/packages/devtools/package.json +0 -27
- package/packages/devtools/react/package.json +0 -53
- package/packages/devtools/react/src/components/DesignPreview.tsx +0 -59
- package/packages/devtools/react/src/components/DesignSwitcherDropdown.tsx +0 -99
- package/packages/devtools/react/src/components/DevSidebar.tsx +0 -247
- package/packages/devtools/react/src/components/DevToolbar.tsx +0 -242
- package/packages/devtools/react/src/components/GitHubIssueDialog.tsx +0 -402
- package/packages/devtools/react/src/components/InspectorOverlay.tsx +0 -312
- package/packages/devtools/react/src/components/PageLoadWaterfall.tsx +0 -144
- package/packages/devtools/react/src/components/PerformancePanel.tsx +0 -330
- package/packages/devtools/react/src/context/DevModeContext.tsx +0 -226
- package/packages/devtools/react/src/context/PerformanceContext.tsx +0 -143
- package/packages/devtools/react/src/data/designs.ts +0 -13
- package/packages/devtools/react/src/hooks/useGitHubLabels.ts +0 -47
- package/packages/devtools/react/src/hooks/useVirtualList.ts +0 -124
- package/packages/devtools/react/src/index.ts +0 -77
- package/packages/devtools/react/src/panels/ConvexSpy.tsx +0 -130
- package/packages/devtools/react/src/panels/DatabaseSeeder.tsx +0 -116
- package/packages/devtools/react/src/panels/DevModePhase2.tsx +0 -191
- package/packages/devtools/react/src/panels/DevModePhase3.tsx +0 -234
- package/packages/devtools/react/src/panels/FeatureFlagsToggle.tsx +0 -104
- package/packages/devtools/react/src/panels/QuickRouteJump.tsx +0 -152
- package/packages/devtools/react/src/services/github-service.ts +0 -247
- package/packages/devtools/react/tsconfig.json +0 -31
- package/packages/devtools/react/tsup.config.ts +0 -18
- package/packages/devtools/solidjs/package.json +0 -49
- package/packages/devtools/solidjs/src/components/DesignPreview.tsx +0 -51
- package/packages/devtools/solidjs/src/components/DesignSwitcherDropdown.tsx +0 -95
- package/packages/devtools/solidjs/src/components/DevSidebar.tsx +0 -247
- package/packages/devtools/solidjs/src/components/DevToolbar.tsx +0 -242
- package/packages/devtools/solidjs/src/components/GitHubIssueDialog.tsx +0 -400
- package/packages/devtools/solidjs/src/components/InspectorOverlay.tsx +0 -311
- package/packages/devtools/solidjs/src/components/PageLoadWaterfall.tsx +0 -144
- package/packages/devtools/solidjs/src/components/PerformancePanel.tsx +0 -330
- package/packages/devtools/solidjs/src/context/DevModeContext.tsx +0 -216
- package/packages/devtools/solidjs/src/context/PerformanceContext.tsx +0 -135
- package/packages/devtools/solidjs/src/data/designs.ts +0 -13
- package/packages/devtools/solidjs/src/hooks/createGitHubLabels.ts +0 -47
- package/packages/devtools/solidjs/src/index.ts +0 -64
- package/packages/devtools/solidjs/src/services/github-service.ts +0 -247
- package/packages/devtools/solidjs/tsconfig.json +0 -21
- package/packages/devtools/src/index.ts +0 -377
- package/packages/devtools/tsup.config.ts +0 -12
- package/packages/env/package.json +0 -30
- package/packages/env/src/index.ts +0 -264
- package/packages/env/tsup.config.ts +0 -12
- package/packages/errors/package.json +0 -27
- package/packages/errors/react/package.json +0 -72
- package/packages/errors/react/src/analytics.ts +0 -16
- package/packages/errors/react/src/components/ErrorBoundary.tsx +0 -248
- package/packages/errors/react/src/components/ErrorDisplay.tsx +0 -328
- package/packages/errors/react/src/components/ValidationErrors.tsx +0 -102
- package/packages/errors/react/src/config.ts +0 -199
- package/packages/errors/react/src/constants.ts +0 -74
- package/packages/errors/react/src/hooks/useErrorBoundary.ts +0 -92
- package/packages/errors/react/src/hooks/useErrorHandler.ts +0 -87
- package/packages/errors/react/src/index.ts +0 -96
- package/packages/errors/react/src/types.ts +0 -102
- package/packages/errors/react/src/utils/errorMessages.ts +0 -35
- package/packages/errors/react/src/utils/errorPolicy.ts +0 -139
- package/packages/errors/react/src/utils/extractAppError.ts +0 -174
- package/packages/errors/react/src/utils/formatError.ts +0 -112
- package/packages/errors/react/tsconfig.json +0 -25
- package/packages/errors/react/tsup.config.ts +0 -24
- package/packages/errors/solidjs/package.json +0 -46
- package/packages/errors/solidjs/src/components/ErrorDisplay.tsx +0 -179
- package/packages/errors/solidjs/src/config.ts +0 -98
- package/packages/errors/solidjs/src/hooks/createErrorHandler.ts +0 -107
- package/packages/errors/solidjs/src/index.ts +0 -61
- package/packages/errors/solidjs/src/types.ts +0 -34
- package/packages/errors/solidjs/src/utils/errorPolicy.ts +0 -56
- package/packages/errors/solidjs/src/utils/extractAppError.ts +0 -94
- package/packages/errors/solidjs/src/utils/formatError.ts +0 -33
- package/packages/errors/solidjs/tsconfig.json +0 -26
- package/packages/errors/solidjs/tsup.config.ts +0 -21
- package/packages/errors/src/index.ts +0 -320
- package/packages/errors/tsup.config.ts +0 -12
- package/packages/logger/package.json +0 -27
- package/packages/logger/react/package.json +0 -46
- package/packages/logger/react/src/index.ts +0 -4
- package/packages/logger/react/src/useMetrics.ts +0 -42
- package/packages/logger/react/src/usePerformanceLog.ts +0 -61
- package/packages/logger/react/tsconfig.json +0 -31
- package/packages/logger/react/tsup.config.ts +0 -12
- package/packages/logger/solidjs/package.json +0 -45
- package/packages/logger/solidjs/src/createMetrics.ts +0 -37
- package/packages/logger/solidjs/src/createPerformanceLog.ts +0 -58
- package/packages/logger/solidjs/src/index.ts +0 -4
- package/packages/logger/solidjs/tsconfig.json +0 -32
- package/packages/logger/solidjs/tsup.config.ts +0 -12
- package/packages/logger/src/index.ts +0 -363
- package/packages/logger/tsup.config.ts +0 -12
- package/packages/perf/package.json +0 -27
- package/packages/perf/react/package.json +0 -59
- package/packages/perf/react/src/components/PerformanceDashboard.tsx +0 -257
- package/packages/perf/react/src/hooks/useMonitoredQuery.ts +0 -89
- package/packages/perf/react/src/hooks/usePerformanceMetrics.ts +0 -78
- package/packages/perf/react/src/index.ts +0 -33
- package/packages/perf/react/src/services/PerformanceMonitor.ts +0 -313
- package/packages/perf/react/src/types.ts +0 -77
- package/packages/perf/react/tsconfig.json +0 -25
- package/packages/perf/react/tsup.config.ts +0 -19
- package/packages/perf/solidjs/package.json +0 -41
- package/packages/perf/solidjs/src/components/PerformanceDashboard.tsx +0 -207
- package/packages/perf/solidjs/src/hooks/createPerformanceMetrics.ts +0 -73
- package/packages/perf/solidjs/src/index.ts +0 -31
- package/packages/perf/solidjs/src/services/PerformanceMonitor.ts +0 -134
- package/packages/perf/solidjs/src/types.ts +0 -78
- package/packages/perf/solidjs/tsconfig.json +0 -26
- package/packages/perf/solidjs/tsup.config.ts +0 -14
- package/packages/perf/src/index.ts +0 -410
- package/packages/perf/tsup.config.ts +0 -12
- package/pnpm-workspace.yaml +0 -2
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-react — components/DesignPreview.tsx
|
|
2
|
-
import { useRef, useEffect } from 'react'
|
|
3
|
-
import type { Design } from '../data/designs'
|
|
4
|
-
|
|
5
|
-
export type DesignPreviewProps = {
|
|
6
|
-
designNumber: number
|
|
7
|
-
showGrid?: boolean
|
|
8
|
-
theme?: 'light' | 'dark'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* DesignPreview — renders an HTML design file in an iframe with grid overlay + theme control.
|
|
13
|
-
*
|
|
14
|
-
* Uses Tailwind CSS utility classes.
|
|
15
|
-
*/
|
|
16
|
-
export function DesignPreview({
|
|
17
|
-
designNumber,
|
|
18
|
-
showGrid = false,
|
|
19
|
-
theme = 'light',
|
|
20
|
-
}: DesignPreviewProps) {
|
|
21
|
-
const iframeRef = useRef<HTMLIFrameElement>(null)
|
|
22
|
-
|
|
23
|
-
const applyTheme = () => {
|
|
24
|
-
try {
|
|
25
|
-
const iframe = iframeRef.current
|
|
26
|
-
if (iframe?.contentDocument) {
|
|
27
|
-
const action = theme === 'dark' ? 'add' : 'remove'
|
|
28
|
-
iframe.contentDocument.documentElement.classList[action]('dark')
|
|
29
|
-
iframe.contentDocument.body?.classList[action]('dark')
|
|
30
|
-
}
|
|
31
|
-
} catch {
|
|
32
|
-
// Cross-origin restrictions
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
useEffect(applyTheme, [theme, designNumber])
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="relative w-full h-screen">
|
|
40
|
-
{showGrid && (
|
|
41
|
-
<div className="absolute inset-0 pointer-events-none z-[100] flex justify-between px-4 max-w-[1400px] mx-auto w-full">
|
|
42
|
-
{Array.from({ length: 12 }).map((_, i) => (
|
|
43
|
-
<div
|
|
44
|
-
key={i}
|
|
45
|
-
className="h-full w-[calc(100%/12)] border-x border-red-500/20 bg-red-500/5 mx-2"
|
|
46
|
-
/>
|
|
47
|
-
))}
|
|
48
|
-
</div>
|
|
49
|
-
)}
|
|
50
|
-
<iframe
|
|
51
|
-
ref={iframeRef}
|
|
52
|
-
src={`/designs/design-${designNumber}.html`}
|
|
53
|
-
className="w-full h-full border-0"
|
|
54
|
-
title={`Design ${designNumber} Preview`}
|
|
55
|
-
onLoad={applyTheme}
|
|
56
|
-
/>
|
|
57
|
-
</div>
|
|
58
|
-
)
|
|
59
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-react — components/DesignSwitcherDropdown.tsx
|
|
2
|
-
import { useState, useRef, useEffect } from 'react'
|
|
3
|
-
|
|
4
|
-
export type DesignSwitcherDropdownProps = {
|
|
5
|
-
/** Current active path — used to highlight the active design */
|
|
6
|
-
currentPath: string
|
|
7
|
-
/** Called when user selects a design */
|
|
8
|
-
onNavigate: (path: string) => void
|
|
9
|
-
/** Total number of designs */
|
|
10
|
-
designCount?: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* DesignSwitcherDropdown — dropdown menu for switching between design previews.
|
|
15
|
-
*
|
|
16
|
-
* Router-agnostic: caller provides currentPath and onNavigate.
|
|
17
|
-
* Uses Tailwind CSS utility classes.
|
|
18
|
-
*/
|
|
19
|
-
export function DesignSwitcherDropdown({
|
|
20
|
-
currentPath,
|
|
21
|
-
onNavigate,
|
|
22
|
-
designCount = 21,
|
|
23
|
-
}: DesignSwitcherDropdownProps) {
|
|
24
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
25
|
-
const dropdownRef = useRef<HTMLDivElement>(null)
|
|
26
|
-
|
|
27
|
-
const getCurrentDesign = () => {
|
|
28
|
-
const match = currentPath.match(/\/dev\/design\/(\d+)/)
|
|
29
|
-
return match ? `Design ${match[1]}` : 'Current Design'
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const currentDesign = getCurrentDesign()
|
|
33
|
-
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
36
|
-
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
37
|
-
setIsOpen(false)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
document.addEventListener('mousedown', handleClickOutside)
|
|
41
|
-
return () => document.removeEventListener('mousedown', handleClickOutside)
|
|
42
|
-
}, [])
|
|
43
|
-
|
|
44
|
-
const handleDesignChange = (path: string) => {
|
|
45
|
-
onNavigate(path)
|
|
46
|
-
setIsOpen(false)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const designs = [
|
|
50
|
-
{ label: 'Current Design', path: '/' },
|
|
51
|
-
...Array.from({ length: designCount }, (_, i) => ({
|
|
52
|
-
label: `Design ${i + 1}`,
|
|
53
|
-
path: `/dev/design/${i + 1}`,
|
|
54
|
-
})),
|
|
55
|
-
]
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div ref={dropdownRef} className="relative">
|
|
59
|
-
<button
|
|
60
|
-
type="button"
|
|
61
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
62
|
-
aria-label="Switch Design"
|
|
63
|
-
className="flex items-center gap-2 px-3 py-2 rounded-lg text-foreground hover:bg-bg-muted transition-colors text-sm font-medium"
|
|
64
|
-
>
|
|
65
|
-
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}><circle cx="13.5" cy="6.5" r="0.5" /><circle cx="17.5" cy="10.5" r="0.5" /><circle cx="8.5" cy="7.5" r="0.5" /><circle cx="6.5" cy="12" r="0.5" /><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" /></svg>
|
|
66
|
-
<span className="hidden sm:inline">{currentDesign}</span>
|
|
67
|
-
<svg
|
|
68
|
-
className={`w-4 h-4 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
|
|
69
|
-
fill="none"
|
|
70
|
-
stroke="currentColor"
|
|
71
|
-
viewBox="0 0 24 24"
|
|
72
|
-
>
|
|
73
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
74
|
-
</svg>
|
|
75
|
-
</button>
|
|
76
|
-
|
|
77
|
-
{isOpen && (
|
|
78
|
-
<div className="absolute right-0 mt-2 py-2 bg-card border border-border rounded-lg shadow-xl overflow-hidden min-w-[180px] max-h-[400px] overflow-y-auto z-50">
|
|
79
|
-
{designs.map((design) => (
|
|
80
|
-
<button
|
|
81
|
-
key={design.path}
|
|
82
|
-
type="button"
|
|
83
|
-
onClick={() => handleDesignChange(design.path)}
|
|
84
|
-
className={`w-full px-4 py-2.5 text-left text-sm transition-colors ${currentDesign === design.label
|
|
85
|
-
? 'bg-primary/10 text-primary font-medium'
|
|
86
|
-
: 'hover:bg-bg-muted text-foreground'
|
|
87
|
-
}`}
|
|
88
|
-
>
|
|
89
|
-
{design.label}
|
|
90
|
-
{currentDesign === design.label && (
|
|
91
|
-
<span className="ml-2 text-primary">✓</span>
|
|
92
|
-
)}
|
|
93
|
-
</button>
|
|
94
|
-
))}
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
</div>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-react — src/components/DevSidebar.tsx
|
|
2
|
-
|
|
3
|
-
import { memo, useState, useEffect, useMemo } from 'react'
|
|
4
|
-
import { cn } from '@geenius-ui/react'
|
|
5
|
-
import {
|
|
6
|
-
Bug,
|
|
7
|
-
Lightbulb,
|
|
8
|
-
ExternalLink,
|
|
9
|
-
Clock,
|
|
10
|
-
X,
|
|
11
|
-
RefreshCw,
|
|
12
|
-
Maximize2,
|
|
13
|
-
Minimize2,
|
|
14
|
-
} from 'lucide-react'
|
|
15
|
-
import { useDevModeOptional } from '../context/DevModeContext'
|
|
16
|
-
import {
|
|
17
|
-
getGitHubIssues,
|
|
18
|
-
getGitHubConfig,
|
|
19
|
-
getIssueType,
|
|
20
|
-
formatRelativeTime,
|
|
21
|
-
type GitHubIssueListItem,
|
|
22
|
-
} from '../services/github-service'
|
|
23
|
-
|
|
24
|
-
interface IssueCardProps {
|
|
25
|
-
issue: GitHubIssueListItem
|
|
26
|
-
expandedView: boolean
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const IssueCard = memo(function IssueCard({
|
|
30
|
-
issue,
|
|
31
|
-
expandedView,
|
|
32
|
-
}: IssueCardProps) {
|
|
33
|
-
const issueType = getIssueType(issue)
|
|
34
|
-
|
|
35
|
-
const linkedComponent = useMemo(() => {
|
|
36
|
-
if (!issue.body) return null
|
|
37
|
-
const match = issue.body.match(/\*\*Name:\*\*\s*`([^`]+)`/)
|
|
38
|
-
return match ? match[1] : null
|
|
39
|
-
}, [issue.body])
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<a
|
|
43
|
-
href={issue.html_url}
|
|
44
|
-
target="_blank"
|
|
45
|
-
rel="noopener noreferrer"
|
|
46
|
-
className={cn(
|
|
47
|
-
'block p-3 rounded-lg border transition-all duration-200',
|
|
48
|
-
'hover:bg-white/5 hover:border-white/20',
|
|
49
|
-
'border-white/10 bg-white/[0.02]',
|
|
50
|
-
)}
|
|
51
|
-
>
|
|
52
|
-
<div className="flex items-start gap-3">
|
|
53
|
-
<div
|
|
54
|
-
className={cn(
|
|
55
|
-
'flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center',
|
|
56
|
-
issueType === 'bug' && 'bg-red-500/10 text-red-500',
|
|
57
|
-
issueType === 'feature' && 'bg-emerald-500/10 text-emerald-500',
|
|
58
|
-
issueType === 'other' && 'bg-blue-500/10 text-blue-500',
|
|
59
|
-
)}
|
|
60
|
-
>
|
|
61
|
-
{issueType === 'bug' ? (
|
|
62
|
-
<Bug className="w-4 h-4" />
|
|
63
|
-
) : (
|
|
64
|
-
<Lightbulb className="w-4 h-4" />
|
|
65
|
-
)}
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
<div className="flex-1 min-w-0">
|
|
69
|
-
<p className="font-medium text-sm text-white line-clamp-2">
|
|
70
|
-
{issue.title}
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
{linkedComponent && (
|
|
74
|
-
<span className="inline-flex items-center gap-1 mt-1 text-[10px] px-1.5 py-0.5 bg-white/5 border border-white/10 rounded text-white/60">
|
|
75
|
-
{linkedComponent}
|
|
76
|
-
</span>
|
|
77
|
-
)}
|
|
78
|
-
|
|
79
|
-
<div className="flex items-center gap-3 mt-2 text-xs text-white/40">
|
|
80
|
-
<span>#{issue.number}</span>
|
|
81
|
-
<span className="flex items-center gap-1">
|
|
82
|
-
<Clock className="w-3 h-3" />
|
|
83
|
-
{formatRelativeTime(issue.updated_at)}
|
|
84
|
-
</span>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
{expandedView && issue.body && (
|
|
88
|
-
<div className="mt-3 text-xs text-white/40 border-l-2 border-white/10 pl-2 line-clamp-6 whitespace-pre-line font-mono bg-white/[0.02] p-2 rounded-sm">
|
|
89
|
-
{issue.body.substring(0, 300)}
|
|
90
|
-
{issue.body.length > 300 ? '...' : ''}
|
|
91
|
-
</div>
|
|
92
|
-
)}
|
|
93
|
-
</div>
|
|
94
|
-
<ExternalLink className="w-4 h-4 text-white/30 flex-shrink-0" />
|
|
95
|
-
</div>
|
|
96
|
-
</a>
|
|
97
|
-
)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
export const DevSidebar = memo(function DevSidebar() {
|
|
101
|
-
const devMode = useDevModeOptional()
|
|
102
|
-
const [issues, setIssues] = useState<GitHubIssueListItem[]>([])
|
|
103
|
-
const [loading, setLoading] = useState(false)
|
|
104
|
-
const [tab, setTab] = useState<'bugs' | 'features'>('bugs')
|
|
105
|
-
const [isExpanded, setIsExpanded] = useState(false)
|
|
106
|
-
|
|
107
|
-
const isSidebarOpen = devMode?.isSidebarOpen ?? false
|
|
108
|
-
const setSidebarOpen = devMode?.setSidebarOpen ?? (() => { })
|
|
109
|
-
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
if (isSidebarOpen && issues.length === 0 && !loading) {
|
|
112
|
-
fetchIssues()
|
|
113
|
-
}
|
|
114
|
-
}, [isSidebarOpen])
|
|
115
|
-
|
|
116
|
-
const fetchIssues = async () => {
|
|
117
|
-
setLoading(true)
|
|
118
|
-
try {
|
|
119
|
-
const result = await getGitHubIssues('all', 'open')
|
|
120
|
-
setIssues(result)
|
|
121
|
-
} catch {
|
|
122
|
-
// Silently fail
|
|
123
|
-
} finally {
|
|
124
|
-
setLoading(false)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const handleRefresh = () => fetchIssues()
|
|
129
|
-
const toggleExpand = () => setIsExpanded((prev) => !prev)
|
|
130
|
-
|
|
131
|
-
const { bugs, features } = useMemo(() => {
|
|
132
|
-
const bugs: GitHubIssueListItem[] = []
|
|
133
|
-
const features: GitHubIssueListItem[] = []
|
|
134
|
-
|
|
135
|
-
issues.forEach((issue) => {
|
|
136
|
-
const type = getIssueType(issue)
|
|
137
|
-
if (type === 'bug') bugs.push(issue)
|
|
138
|
-
else features.push(issue)
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
return { bugs, features }
|
|
142
|
-
}, [issues])
|
|
143
|
-
|
|
144
|
-
const currentIssues = tab === 'bugs' ? bugs : features
|
|
145
|
-
|
|
146
|
-
if (!devMode || !isSidebarOpen) return null
|
|
147
|
-
|
|
148
|
-
const config = getGitHubConfig()
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<div
|
|
152
|
-
data-dev-tool="true"
|
|
153
|
-
className={cn(
|
|
154
|
-
'fixed top-0 right-0 h-full z-50',
|
|
155
|
-
'flex flex-col',
|
|
156
|
-
'bg-gradient-to-b from-slate-900/98 to-slate-950/98',
|
|
157
|
-
'backdrop-blur-xl border-l border-white/10',
|
|
158
|
-
'shadow-2xl shadow-black/50',
|
|
159
|
-
'transition-all duration-300 ease-in-out',
|
|
160
|
-
isExpanded ? 'w-full sm:max-w-[50vw]' : 'w-full sm:max-w-md',
|
|
161
|
-
'animate-in slide-in-from-right duration-300',
|
|
162
|
-
)}
|
|
163
|
-
>
|
|
164
|
-
{/* Header */}
|
|
165
|
-
<div className="flex items-center justify-between px-4 py-3 border-b border-white/10">
|
|
166
|
-
<div className="flex items-center gap-2">
|
|
167
|
-
<Bug className="w-4 h-4 text-primary" />
|
|
168
|
-
<span className="text-sm font-bold text-white">GitHub Issues</span>
|
|
169
|
-
<span className="text-xs text-white/40">
|
|
170
|
-
({config.owner}/{config.repo})
|
|
171
|
-
</span>
|
|
172
|
-
</div>
|
|
173
|
-
<div className="flex items-center gap-1">
|
|
174
|
-
<button
|
|
175
|
-
onClick={handleRefresh}
|
|
176
|
-
disabled={loading}
|
|
177
|
-
className={cn(
|
|
178
|
-
'p-1.5 text-white/40 hover:text-white hover:bg-white/10 rounded-lg transition-colors',
|
|
179
|
-
loading && 'animate-spin',
|
|
180
|
-
)}
|
|
181
|
-
>
|
|
182
|
-
<RefreshCw className="w-3.5 h-3.5" />
|
|
183
|
-
</button>
|
|
184
|
-
<button
|
|
185
|
-
onClick={toggleExpand}
|
|
186
|
-
className="hidden sm:block p-1.5 text-white/40 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
187
|
-
>
|
|
188
|
-
{isExpanded ? (
|
|
189
|
-
<Minimize2 className="w-3.5 h-3.5" />
|
|
190
|
-
) : (
|
|
191
|
-
<Maximize2 className="w-3.5 h-3.5" />
|
|
192
|
-
)}
|
|
193
|
-
</button>
|
|
194
|
-
<button
|
|
195
|
-
onClick={() => setSidebarOpen(false)}
|
|
196
|
-
className="p-1.5 text-white/40 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
197
|
-
>
|
|
198
|
-
<X className="w-4 h-4" />
|
|
199
|
-
</button>
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
{/* Tabs */}
|
|
204
|
-
<div className="flex border-b border-white/10">
|
|
205
|
-
<button
|
|
206
|
-
onClick={() => setTab('bugs')}
|
|
207
|
-
className={cn(
|
|
208
|
-
'flex-1 px-4 py-2.5 text-xs font-medium transition-colors',
|
|
209
|
-
tab === 'bugs'
|
|
210
|
-
? 'text-red-400 border-b-2 border-red-500'
|
|
211
|
-
: 'text-white/40 hover:text-white/70',
|
|
212
|
-
)}
|
|
213
|
-
>
|
|
214
|
-
🐛 Bugs ({bugs.length})
|
|
215
|
-
</button>
|
|
216
|
-
<button
|
|
217
|
-
onClick={() => setTab('features')}
|
|
218
|
-
className={cn(
|
|
219
|
-
'flex-1 px-4 py-2.5 text-xs font-medium transition-colors',
|
|
220
|
-
tab === 'features'
|
|
221
|
-
? 'text-emerald-400 border-b-2 border-emerald-500'
|
|
222
|
-
: 'text-white/40 hover:text-white/70',
|
|
223
|
-
)}
|
|
224
|
-
>
|
|
225
|
-
✨ Features ({features.length})
|
|
226
|
-
</button>
|
|
227
|
-
</div>
|
|
228
|
-
|
|
229
|
-
{/* Content */}
|
|
230
|
-
<div className="flex-1 overflow-y-auto p-3 space-y-2">
|
|
231
|
-
{loading ? (
|
|
232
|
-
<div className="flex items-center justify-center py-12">
|
|
233
|
-
<div className="w-6 h-6 border-2 border-white/20 border-t-primary rounded-full animate-spin" />
|
|
234
|
-
</div>
|
|
235
|
-
) : currentIssues.length === 0 ? (
|
|
236
|
-
<div className="text-center py-12 text-sm text-white/30">
|
|
237
|
-
No {tab === 'bugs' ? 'bugs' : 'features'} found
|
|
238
|
-
</div>
|
|
239
|
-
) : (
|
|
240
|
-
currentIssues.map((issue) => (
|
|
241
|
-
<IssueCard key={issue.id} issue={issue} expandedView={isExpanded} />
|
|
242
|
-
))
|
|
243
|
-
)}
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
)
|
|
247
|
-
})
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-react — src/components/DevToolbar.tsx
|
|
2
|
-
|
|
3
|
-
import { memo, useState, useRef, useEffect } from 'react'
|
|
4
|
-
import { cn } from '@geenius-ui/react'
|
|
5
|
-
import {
|
|
6
|
-
Power,
|
|
7
|
-
PanelRight,
|
|
8
|
-
Bug,
|
|
9
|
-
Lightbulb,
|
|
10
|
-
Target,
|
|
11
|
-
Activity,
|
|
12
|
-
} from 'lucide-react'
|
|
13
|
-
import { useDevModeOptional, useIsDevAllowed } from '../context/DevModeContext'
|
|
14
|
-
import { usePerformanceContextOptional } from '../context/PerformanceContext'
|
|
15
|
-
import { GitHubIssueDialog } from './GitHubIssueDialog'
|
|
16
|
-
import { PerformancePanel } from './PerformancePanel'
|
|
17
|
-
|
|
18
|
-
interface ToolbarButtonProps {
|
|
19
|
-
icon: React.ReactNode
|
|
20
|
-
label: string
|
|
21
|
-
onClick?: () => void
|
|
22
|
-
active?: boolean
|
|
23
|
-
variant?: 'default' | 'primary' | 'success' | 'danger'
|
|
24
|
-
showLabel?: boolean
|
|
25
|
-
disabled?: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const ToolbarButton = memo(function ToolbarButton({
|
|
29
|
-
icon,
|
|
30
|
-
label,
|
|
31
|
-
onClick,
|
|
32
|
-
active = false,
|
|
33
|
-
variant = 'default',
|
|
34
|
-
showLabel = true,
|
|
35
|
-
disabled = false,
|
|
36
|
-
}: ToolbarButtonProps) {
|
|
37
|
-
const variantStyles = {
|
|
38
|
-
default: active
|
|
39
|
-
? 'bg-white/20 text-white'
|
|
40
|
-
: 'text-white/70 hover:text-white hover:bg-white/10',
|
|
41
|
-
primary: active
|
|
42
|
-
? 'bg-primary/30 text-primary-foreground'
|
|
43
|
-
: 'text-white/70 hover:text-primary hover:bg-primary/10',
|
|
44
|
-
success: 'text-white/70 hover:text-emerald-400 hover:bg-emerald-500/10',
|
|
45
|
-
danger: 'text-white/70 hover:text-red-400 hover:bg-red-500/10',
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const content = (
|
|
49
|
-
<>
|
|
50
|
-
{icon}
|
|
51
|
-
{showLabel && (
|
|
52
|
-
<span className="hidden sm:inline text-xs font-medium">{label}</span>
|
|
53
|
-
)}
|
|
54
|
-
</>
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
const className = cn(
|
|
58
|
-
'flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200',
|
|
59
|
-
'focus:outline-none focus:ring-2 focus:ring-white/20',
|
|
60
|
-
disabled
|
|
61
|
-
? 'opacity-40 cursor-not-allowed text-white'
|
|
62
|
-
: variantStyles[variant],
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<button
|
|
67
|
-
type="button"
|
|
68
|
-
onClick={disabled ? undefined : onClick}
|
|
69
|
-
className={cn(className, !disabled && 'cursor-pointer')}
|
|
70
|
-
title={label}
|
|
71
|
-
disabled={disabled}
|
|
72
|
-
>
|
|
73
|
-
{content}
|
|
74
|
-
</button>
|
|
75
|
-
)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
interface ExpandableSectionProps {
|
|
79
|
-
show: boolean
|
|
80
|
-
children: React.ReactNode
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const ExpandableSection = memo(function ExpandableSection({
|
|
84
|
-
show,
|
|
85
|
-
children,
|
|
86
|
-
}: ExpandableSectionProps) {
|
|
87
|
-
const contentRef = useRef<HTMLDivElement>(null)
|
|
88
|
-
const [width, setWidth] = useState(0)
|
|
89
|
-
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
if (contentRef.current) {
|
|
92
|
-
setWidth(show ? contentRef.current.scrollWidth : 0)
|
|
93
|
-
}
|
|
94
|
-
}, [show, children])
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<div
|
|
98
|
-
className="overflow-hidden transition-all duration-300 ease-out"
|
|
99
|
-
style={{ width: show ? width : 0, opacity: show ? 1 : 0 }}
|
|
100
|
-
>
|
|
101
|
-
<div
|
|
102
|
-
ref={contentRef}
|
|
103
|
-
className={cn(
|
|
104
|
-
'flex items-center gap-1 whitespace-nowrap',
|
|
105
|
-
'transition-transform duration-300 ease-out',
|
|
106
|
-
show ? 'translate-x-0' : '-translate-x-2',
|
|
107
|
-
)}
|
|
108
|
-
>
|
|
109
|
-
{children}
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
export interface DevToolbarProps {
|
|
116
|
-
/** Whether dev tools are allowed. Default: auto-detects from env */
|
|
117
|
-
isAllowed?: boolean
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export const DevToolbar = memo(function DevToolbar({
|
|
121
|
-
isAllowed,
|
|
122
|
-
}: DevToolbarProps = {}) {
|
|
123
|
-
const isDevAllowed = useIsDevAllowed(isAllowed)
|
|
124
|
-
const devMode = useDevModeOptional()
|
|
125
|
-
const performanceContext = usePerformanceContextOptional()
|
|
126
|
-
|
|
127
|
-
const [isReady, setIsReady] = useState(false)
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
const timer = setTimeout(() => setIsReady(true), 1000)
|
|
130
|
-
return () => clearTimeout(timer)
|
|
131
|
-
}, [])
|
|
132
|
-
|
|
133
|
-
if (!isDevAllowed || !devMode) return null
|
|
134
|
-
|
|
135
|
-
const {
|
|
136
|
-
isDevMode,
|
|
137
|
-
isSidebarOpen,
|
|
138
|
-
toggleDevMode,
|
|
139
|
-
toggleSidebar,
|
|
140
|
-
openIssueDialog,
|
|
141
|
-
issueDialog,
|
|
142
|
-
closeIssueDialog,
|
|
143
|
-
} = devMode
|
|
144
|
-
|
|
145
|
-
const showContent = isDevMode && isReady
|
|
146
|
-
|
|
147
|
-
return (
|
|
148
|
-
<>
|
|
149
|
-
{/* Floating Toolbar */}
|
|
150
|
-
<div
|
|
151
|
-
data-dev-tool="true"
|
|
152
|
-
className={cn(
|
|
153
|
-
'fixed bottom-4 left-1/2 -translate-x-1/2 z-50',
|
|
154
|
-
'flex items-center px-2 py-1',
|
|
155
|
-
showContent ? 'gap-2' : 'gap-0',
|
|
156
|
-
'rounded-2xl border border-white/10',
|
|
157
|
-
'bg-gradient-to-r from-slate-900/95 via-slate-800/95 to-slate-900/95',
|
|
158
|
-
'backdrop-blur-xl shadow-2xl shadow-black/50',
|
|
159
|
-
'transition-all duration-300 ease-out',
|
|
160
|
-
)}
|
|
161
|
-
>
|
|
162
|
-
{/* Power / Toggle Dev Mode */}
|
|
163
|
-
<ToolbarButton
|
|
164
|
-
icon={<Power className="w-4 h-4" />}
|
|
165
|
-
label={isDevMode ? 'Dev Mode On' : 'Dev Mode Off'}
|
|
166
|
-
onClick={toggleDevMode}
|
|
167
|
-
active={isDevMode}
|
|
168
|
-
variant={isDevMode ? 'primary' : 'default'}
|
|
169
|
-
/>
|
|
170
|
-
|
|
171
|
-
<ExpandableSection show={showContent}>
|
|
172
|
-
{/* Separator */}
|
|
173
|
-
<div className="shrink-0 w-px h-6 bg-white/20 mx-1 my-2" />
|
|
174
|
-
|
|
175
|
-
{/* Inspector Mode Toggle */}
|
|
176
|
-
<ToolbarButton
|
|
177
|
-
icon={<Target className="w-4 h-4" />}
|
|
178
|
-
label="Inspector"
|
|
179
|
-
onClick={devMode.toggleInspector}
|
|
180
|
-
active={devMode.isInspectorMode}
|
|
181
|
-
variant={devMode.isInspectorMode ? 'primary' : 'default'}
|
|
182
|
-
/>
|
|
183
|
-
|
|
184
|
-
{/* Performance Monitor Toggle */}
|
|
185
|
-
{performanceContext && (
|
|
186
|
-
<ToolbarButton
|
|
187
|
-
icon={<Activity className="w-4 h-4" />}
|
|
188
|
-
label="Perf"
|
|
189
|
-
onClick={performanceContext.togglePerformancePanel}
|
|
190
|
-
active={performanceContext.isPerformancePanelOpen}
|
|
191
|
-
variant={
|
|
192
|
-
performanceContext.isPerformancePanelOpen
|
|
193
|
-
? 'primary'
|
|
194
|
-
: 'default'
|
|
195
|
-
}
|
|
196
|
-
/>
|
|
197
|
-
)}
|
|
198
|
-
|
|
199
|
-
{/* Sidebar Toggle (Desktop only) */}
|
|
200
|
-
<div className="hidden md:block">
|
|
201
|
-
<ToolbarButton
|
|
202
|
-
icon={<PanelRight className="w-4 h-4" />}
|
|
203
|
-
label="Issues"
|
|
204
|
-
onClick={toggleSidebar}
|
|
205
|
-
active={isSidebarOpen}
|
|
206
|
-
/>
|
|
207
|
-
</div>
|
|
208
|
-
|
|
209
|
-
{/* Create Bug */}
|
|
210
|
-
<ToolbarButton
|
|
211
|
-
icon={<Bug className="w-4 h-4" />}
|
|
212
|
-
label="Bug"
|
|
213
|
-
onClick={() => openIssueDialog('bug')}
|
|
214
|
-
variant="danger"
|
|
215
|
-
/>
|
|
216
|
-
|
|
217
|
-
{/* Create Feature */}
|
|
218
|
-
<ToolbarButton
|
|
219
|
-
icon={<Lightbulb className="w-4 h-4" />}
|
|
220
|
-
label="Feature"
|
|
221
|
-
onClick={() => openIssueDialog('feature')}
|
|
222
|
-
variant="success"
|
|
223
|
-
/>
|
|
224
|
-
</ExpandableSection>
|
|
225
|
-
</div>
|
|
226
|
-
|
|
227
|
-
{/* Performance Panel */}
|
|
228
|
-
{performanceContext && <PerformancePanel />}
|
|
229
|
-
|
|
230
|
-
{/* Issue Dialog */}
|
|
231
|
-
<div data-dev-tool="true">
|
|
232
|
-
<GitHubIssueDialog
|
|
233
|
-
open={issueDialog.isOpen}
|
|
234
|
-
onOpenChange={(open) => !open && closeIssueDialog()}
|
|
235
|
-
initialType={issueDialog.type}
|
|
236
|
-
initialDescription={issueDialog.initialDescription}
|
|
237
|
-
componentDetails={issueDialog.componentDetails}
|
|
238
|
-
/>
|
|
239
|
-
</div>
|
|
240
|
-
</>
|
|
241
|
-
)
|
|
242
|
-
})
|