@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.
Files changed (177) hide show
  1. package/package.json +62 -3
  2. package/packages/convex/shared/README.md +1 -1
  3. package/packages/devtools/dist/index.d.ts +204 -0
  4. package/packages/devtools/dist/index.js +186 -0
  5. package/packages/devtools/dist/index.js.map +1 -0
  6. package/packages/devtools/react/README.md +1 -1
  7. package/packages/devtools/solidjs/README.md +1 -1
  8. package/packages/devtools/solidjs/dist/index.js +1830 -0
  9. package/packages/devtools/solidjs/dist/index.js.map +1 -0
  10. package/packages/env/dist/index.d.ts +151 -0
  11. package/packages/env/dist/index.js +93 -0
  12. package/packages/env/dist/index.js.map +1 -0
  13. package/packages/errors/dist/index.d.ts +177 -0
  14. package/packages/errors/dist/index.js +187 -0
  15. package/packages/errors/dist/index.js.map +1 -0
  16. package/packages/errors/react/README.md +1 -1
  17. package/packages/errors/solidjs/README.md +1 -1
  18. package/packages/logger/dist/index.d.ts +171 -0
  19. package/packages/logger/dist/index.js +216 -0
  20. package/packages/logger/dist/index.js.map +1 -0
  21. package/packages/logger/react/README.md +1 -1
  22. package/packages/logger/solidjs/README.md +1 -1
  23. package/packages/perf/dist/index.d.ts +168 -0
  24. package/packages/perf/dist/index.js +265 -0
  25. package/packages/perf/dist/index.js.map +1 -0
  26. package/packages/perf/react/README.md +1 -1
  27. package/packages/perf/solidjs/README.md +1 -1
  28. package/packages/shared/dist/index.d.ts +253 -0
  29. package/packages/shared/dist/index.js +278 -0
  30. package/packages/shared/dist/index.js.map +1 -0
  31. package/.changeset/config.json +0 -11
  32. package/.env.example +0 -2
  33. package/.github/CODEOWNERS +0 -1
  34. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
  35. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
  36. package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
  37. package/.github/dependabot.yml +0 -11
  38. package/.github/workflows/ci.yml +0 -23
  39. package/.github/workflows/release.yml +0 -29
  40. package/.node-version +0 -1
  41. package/.nvmrc +0 -1
  42. package/.prettierrc +0 -7
  43. package/.project/ACCOUNT.yaml +0 -4
  44. package/.project/IDEAS.yaml +0 -7
  45. package/.project/PROJECT.yaml +0 -11
  46. package/.project/ROADMAP.yaml +0 -15
  47. package/CODE_OF_CONDUCT.md +0 -26
  48. package/CONTRIBUTING.md +0 -69
  49. package/SECURITY.md +0 -18
  50. package/SUPPORT.md +0 -14
  51. package/packages/convex/shared/package.json +0 -42
  52. package/packages/convex/shared/src/audit/index.ts +0 -5
  53. package/packages/convex/shared/src/audit/presets.ts +0 -165
  54. package/packages/convex/shared/src/audit/schema.ts +0 -85
  55. package/packages/convex/shared/src/audit/write.ts +0 -102
  56. package/packages/convex/shared/src/extract.ts +0 -75
  57. package/packages/convex/shared/src/index.ts +0 -41
  58. package/packages/convex/shared/src/messages.ts +0 -45
  59. package/packages/convex/shared/src/security.ts +0 -112
  60. package/packages/convex/shared/src/throw.ts +0 -184
  61. package/packages/convex/shared/src/types.ts +0 -57
  62. package/packages/convex/shared/src/utils.ts +0 -58
  63. package/packages/convex/shared/tsconfig.json +0 -28
  64. package/packages/convex/shared/tsup.config.ts +0 -12
  65. package/packages/devtools/package.json +0 -27
  66. package/packages/devtools/react/package.json +0 -53
  67. package/packages/devtools/react/src/components/DesignPreview.tsx +0 -59
  68. package/packages/devtools/react/src/components/DesignSwitcherDropdown.tsx +0 -99
  69. package/packages/devtools/react/src/components/DevSidebar.tsx +0 -247
  70. package/packages/devtools/react/src/components/DevToolbar.tsx +0 -242
  71. package/packages/devtools/react/src/components/GitHubIssueDialog.tsx +0 -402
  72. package/packages/devtools/react/src/components/InspectorOverlay.tsx +0 -312
  73. package/packages/devtools/react/src/components/PageLoadWaterfall.tsx +0 -144
  74. package/packages/devtools/react/src/components/PerformancePanel.tsx +0 -330
  75. package/packages/devtools/react/src/context/DevModeContext.tsx +0 -226
  76. package/packages/devtools/react/src/context/PerformanceContext.tsx +0 -143
  77. package/packages/devtools/react/src/data/designs.ts +0 -13
  78. package/packages/devtools/react/src/hooks/useGitHubLabels.ts +0 -47
  79. package/packages/devtools/react/src/hooks/useVirtualList.ts +0 -124
  80. package/packages/devtools/react/src/index.ts +0 -77
  81. package/packages/devtools/react/src/panels/ConvexSpy.tsx +0 -130
  82. package/packages/devtools/react/src/panels/DatabaseSeeder.tsx +0 -116
  83. package/packages/devtools/react/src/panels/DevModePhase2.tsx +0 -191
  84. package/packages/devtools/react/src/panels/DevModePhase3.tsx +0 -234
  85. package/packages/devtools/react/src/panels/FeatureFlagsToggle.tsx +0 -104
  86. package/packages/devtools/react/src/panels/QuickRouteJump.tsx +0 -152
  87. package/packages/devtools/react/src/services/github-service.ts +0 -247
  88. package/packages/devtools/react/tsconfig.json +0 -31
  89. package/packages/devtools/react/tsup.config.ts +0 -18
  90. package/packages/devtools/solidjs/package.json +0 -49
  91. package/packages/devtools/solidjs/src/components/DesignPreview.tsx +0 -51
  92. package/packages/devtools/solidjs/src/components/DesignSwitcherDropdown.tsx +0 -95
  93. package/packages/devtools/solidjs/src/components/DevSidebar.tsx +0 -247
  94. package/packages/devtools/solidjs/src/components/DevToolbar.tsx +0 -242
  95. package/packages/devtools/solidjs/src/components/GitHubIssueDialog.tsx +0 -400
  96. package/packages/devtools/solidjs/src/components/InspectorOverlay.tsx +0 -311
  97. package/packages/devtools/solidjs/src/components/PageLoadWaterfall.tsx +0 -144
  98. package/packages/devtools/solidjs/src/components/PerformancePanel.tsx +0 -330
  99. package/packages/devtools/solidjs/src/context/DevModeContext.tsx +0 -216
  100. package/packages/devtools/solidjs/src/context/PerformanceContext.tsx +0 -135
  101. package/packages/devtools/solidjs/src/data/designs.ts +0 -13
  102. package/packages/devtools/solidjs/src/hooks/createGitHubLabels.ts +0 -47
  103. package/packages/devtools/solidjs/src/index.ts +0 -64
  104. package/packages/devtools/solidjs/src/services/github-service.ts +0 -247
  105. package/packages/devtools/solidjs/tsconfig.json +0 -21
  106. package/packages/devtools/src/index.ts +0 -377
  107. package/packages/devtools/tsup.config.ts +0 -12
  108. package/packages/env/package.json +0 -30
  109. package/packages/env/src/index.ts +0 -264
  110. package/packages/env/tsup.config.ts +0 -12
  111. package/packages/errors/package.json +0 -27
  112. package/packages/errors/react/package.json +0 -72
  113. package/packages/errors/react/src/analytics.ts +0 -16
  114. package/packages/errors/react/src/components/ErrorBoundary.tsx +0 -248
  115. package/packages/errors/react/src/components/ErrorDisplay.tsx +0 -328
  116. package/packages/errors/react/src/components/ValidationErrors.tsx +0 -102
  117. package/packages/errors/react/src/config.ts +0 -199
  118. package/packages/errors/react/src/constants.ts +0 -74
  119. package/packages/errors/react/src/hooks/useErrorBoundary.ts +0 -92
  120. package/packages/errors/react/src/hooks/useErrorHandler.ts +0 -87
  121. package/packages/errors/react/src/index.ts +0 -96
  122. package/packages/errors/react/src/types.ts +0 -102
  123. package/packages/errors/react/src/utils/errorMessages.ts +0 -35
  124. package/packages/errors/react/src/utils/errorPolicy.ts +0 -139
  125. package/packages/errors/react/src/utils/extractAppError.ts +0 -174
  126. package/packages/errors/react/src/utils/formatError.ts +0 -112
  127. package/packages/errors/react/tsconfig.json +0 -25
  128. package/packages/errors/react/tsup.config.ts +0 -24
  129. package/packages/errors/solidjs/package.json +0 -46
  130. package/packages/errors/solidjs/src/components/ErrorDisplay.tsx +0 -179
  131. package/packages/errors/solidjs/src/config.ts +0 -98
  132. package/packages/errors/solidjs/src/hooks/createErrorHandler.ts +0 -107
  133. package/packages/errors/solidjs/src/index.ts +0 -61
  134. package/packages/errors/solidjs/src/types.ts +0 -34
  135. package/packages/errors/solidjs/src/utils/errorPolicy.ts +0 -56
  136. package/packages/errors/solidjs/src/utils/extractAppError.ts +0 -94
  137. package/packages/errors/solidjs/src/utils/formatError.ts +0 -33
  138. package/packages/errors/solidjs/tsconfig.json +0 -26
  139. package/packages/errors/solidjs/tsup.config.ts +0 -21
  140. package/packages/errors/src/index.ts +0 -320
  141. package/packages/errors/tsup.config.ts +0 -12
  142. package/packages/logger/package.json +0 -27
  143. package/packages/logger/react/package.json +0 -46
  144. package/packages/logger/react/src/index.ts +0 -4
  145. package/packages/logger/react/src/useMetrics.ts +0 -42
  146. package/packages/logger/react/src/usePerformanceLog.ts +0 -61
  147. package/packages/logger/react/tsconfig.json +0 -31
  148. package/packages/logger/react/tsup.config.ts +0 -12
  149. package/packages/logger/solidjs/package.json +0 -45
  150. package/packages/logger/solidjs/src/createMetrics.ts +0 -37
  151. package/packages/logger/solidjs/src/createPerformanceLog.ts +0 -58
  152. package/packages/logger/solidjs/src/index.ts +0 -4
  153. package/packages/logger/solidjs/tsconfig.json +0 -32
  154. package/packages/logger/solidjs/tsup.config.ts +0 -12
  155. package/packages/logger/src/index.ts +0 -363
  156. package/packages/logger/tsup.config.ts +0 -12
  157. package/packages/perf/package.json +0 -27
  158. package/packages/perf/react/package.json +0 -59
  159. package/packages/perf/react/src/components/PerformanceDashboard.tsx +0 -257
  160. package/packages/perf/react/src/hooks/useMonitoredQuery.ts +0 -89
  161. package/packages/perf/react/src/hooks/usePerformanceMetrics.ts +0 -78
  162. package/packages/perf/react/src/index.ts +0 -33
  163. package/packages/perf/react/src/services/PerformanceMonitor.ts +0 -313
  164. package/packages/perf/react/src/types.ts +0 -77
  165. package/packages/perf/react/tsconfig.json +0 -25
  166. package/packages/perf/react/tsup.config.ts +0 -19
  167. package/packages/perf/solidjs/package.json +0 -41
  168. package/packages/perf/solidjs/src/components/PerformanceDashboard.tsx +0 -207
  169. package/packages/perf/solidjs/src/hooks/createPerformanceMetrics.ts +0 -73
  170. package/packages/perf/solidjs/src/index.ts +0 -31
  171. package/packages/perf/solidjs/src/services/PerformanceMonitor.ts +0 -134
  172. package/packages/perf/solidjs/src/types.ts +0 -78
  173. package/packages/perf/solidjs/tsconfig.json +0 -26
  174. package/packages/perf/solidjs/tsup.config.ts +0 -14
  175. package/packages/perf/src/index.ts +0 -410
  176. package/packages/perf/tsup.config.ts +0 -12
  177. 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
- })